|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* ! 25: * Copyright 1994 NeXT Computer, Inc. ! 26: * All rights reserved. ! 27: * ! 28: */ ! 29: ! 30: #if NOTYET ! 31: ! 32: /* Clean this up later. */ ! 33: #define KERNEL_PRIVATE 1 ! 34: #define ARCH_PRIVATE 1 ! 35: ! 36: #import <driverkit/IOBuffer.h> ! 37: #import <driverkit/generalFuncs.h> ! 38: #import <vm/vm_map.h> ! 39: #import <mach/vm_param.h> ! 40: ! 41: #define MIN(a,b) ((a) < (b) ? (a) : (b)) ! 42: ! 43: /* ! 44: * Helper functions ! 45: */ ! 46: static BOOL checkAlignmentFromVirtual( ! 47: IOVirtualAddress vaddr, ! 48: IOAddressMap map, ! 49: int size, ! 50: IOAlignment align ! 51: ); ! 52: static BOOL checkAlignmentFromPhysical( ! 53: IOPhysicalAddress paddr, ! 54: int size, ! 55: IOAlignment align ! 56: ); ! 57: static BOOL checkAlignmentFromSize( ! 58: int size, ! 59: IOAlignment align ! 60: ); ! 61: static unsigned int ! 62: maskFromAlignment( ! 63: IOAlignment align ! 64: ); ! 65: static unsigned int ! 66: alignmentFromAddress( ! 67: IOVirtualAddress addr ! 68: ); ! 69: static void ! 70: copyData( ! 71: IOVirtualAddress src, ! 72: IOAddressMap srcMap, ! 73: IOVirtualAddress dst, ! 74: IOAddressMap dstMap, ! 75: unsigned int totalLength ! 76: ); ! 77: ! 78: ! 79: ! 80: @implementation IOBuffer ! 81: ! 82: -initWithSize:(unsigned int)newSize ! 83: { ! 84: return [self initWithSize:newSize attributes:IOBuf_None ! 85: alignment:IOBufferAlignMin]; ! 86: } ! 87: ! 88: -initWithSize:(unsigned int)newSize ! 89: attributes:(IOBufferAttributes)newAttrs ! 90: alignment:(IOAlignment)align ! 91: { ! 92: if (checkAlignmentFromSize(newSize, align) == NO) { ! 93: return nil; ! 94: } ! 95: ! 96: size = newSize; ! 97: alignment = align; ! 98: if ([[self class] allocMemoryWithSize:newSize ! 99: attributes:newAttrs ! 100: alignment:align ! 101: allocedAddress:&allocedData ! 102: dataAddress:(IOVirtualAddress *)&data ! 103: allocedSize:&allocedSize ! 104: newAttributes:&attributes ! 105: newMap:&map] == NO) { ! 106: return nil; ! 107: } ! 108: ! 109: attributes = newAttrs | IOBuf_Wired | IOBuf_Contiguous | IOBuf_WiredStatic; ! 110: ! 111: map = (IOAddressMap)IOVmTaskSelf(); ! 112: ! 113: return self; ! 114: } ! 115: ! 116: ! 117: -initFromVirtualAddress:(IOVirtualAddress)addr ! 118: addressMap:(IOAddressMap)newMap ! 119: size:(unsigned int)newSize ! 120: { ! 121: data = (void *)addr; ! 122: map = newMap; ! 123: ! 124: alignment = MIN(alignmentFromAddress(addr), ! 125: alignmentFromAddress(newSize)); ! 126: size = newSize; ! 127: ! 128: return self; ! 129: } ! 130: ! 131: ! 132: -initFromPhysicalAddress:(IOPhysicalAddress)addr ! 133: size:(unsigned int)newSize ! 134: { ! 135: data = (void *)addr; ! 136: ! 137: alignment = MIN(alignmentFromAddress(addr), ! 138: alignmentFromAddress(newSize)); ! 139: return nil; ! 140: } ! 141: ! 142: -free ! 143: { ! 144: (void)[self unwireMemory]; ! 145: if (allocedData) { ! 146: [[self class] freeMemory:allocedData ! 147: size:allocedSize ! 148: map:map ! 149: attributes:attributes]; ! 150: } ! 151: return [super free]; ! 152: } ! 153: ! 154: -(BOOL)copyFromBuffer:(IOBuffer *)sourceBuffer ! 155: { ! 156: int length, sourceSize; ! 157: BOOL rtn; ! 158: IORange source, dest; ! 159: ! 160: sourceSize = [sourceBuffer size]; ! 161: source.size = dest.size = MIN(sourceSize, size); ! 162: source.start = dest.start = 0; ! 163: rtn = [self copyFromBuffer:sourceBuffer ! 164: source:source ! 165: destination:dest]; ! 166: if ((rtn == YES) && (sourceSize < source.size)) { ! 167: bzero((char *)data + sourceSize, source.size - sourceSize); ! 168: } ! 169: return rtn; ! 170: } ! 171: ! 172: -(BOOL)copyFromBuffer:(IOBuffer *)sourceBuffer ! 173: source:(IORange)srcRange ! 174: destination:(IORange)dstRange ! 175: { ! 176: int sourceSize, destSize; ! 177: IOVirtualRange sourceAddrRange, destAddrRange; ! 178: ! 179: if ([self isWired] == NO || [sourceBuffer isWired] == NO) ! 180: return NO; ! 181: ! 182: sourceSize = [sourceBuffer size] - srcRange.start; ! 183: destSize = [self size] - dstRange.start; ! 184: if ((srcRange.size > sourceSize) || (srcRange.size > destSize)) ! 185: return NO; ! 186: ! 187: if ([sourceBuffer getVirtualAddress:&sourceAddrRange ! 188: at:srcRange.start] == NO) { ! 189: return NO; ! 190: } ! 191: if ([self getVirtualAddress:&destAddrRange ! 192: at:dstRange.start] == NO) { ! 193: return NO; ! 194: } ! 195: copyData(sourceAddrRange.start, [sourceBuffer addressMap], ! 196: destAddrRange.start, map, srcRange.size); ! 197: ! 198: return YES; ! 199: } ! 200: ! 201: -(IOAddressMap)addressMap ! 202: { ! 203: return map; ! 204: } ! 205: ! 206: ! 207: -(BOOL)wireMemory ! 208: { ! 209: if ([self isWired]) ! 210: return YES; ! 211: ! 212: if (vm_map_pageable(map, trunc_page((char *)data), ! 213: round_page((char *)data + size), FALSE) ! 214: == KERN_SUCCESS) { ! 215: attributes |= IOBuf_Wired; ! 216: return YES; ! 217: } ! 218: ! 219: return NO; ! 220: } ! 221: ! 222: -(BOOL)unwireMemory ! 223: { ! 224: if ([self isWired] == NO) ! 225: return YES; ! 226: if (!(attributes & IOBuf_WiredStatic) && ! 227: (vm_map_pageable(map, trunc_page((char *)data), ! 228: round_page((char *)data + size), TRUE) ! 229: == KERN_SUCCESS)) { ! 230: attributes &= ~IOBuf_Wired; ! 231: return YES; ! 232: } ! 233: return NO; ! 234: } ! 235: ! 236: -(BOOL)getVirtualAddress:(IOVirtualRange *)virtualRangePtr ! 237: at:(unsigned int)offset ! 238: { ! 239: if (offset >= size) ! 240: return NO; ! 241: if (virtualRangePtr != NULL) { ! 242: virtualRangePtr->start = (IOVirtualAddress)((char *)data + offset); ! 243: virtualRangePtr->size = size - offset; ! 244: } ! 245: return YES; ! 246: } ! 247: ! 248: -(BOOL)getPhysicalAddress:(IOPhysicalRange *)physicalRangePtr ! 249: at:(unsigned int)offset ! 250: { ! 251: IOPhysicalAddress paddr; ! 252: char *vaddr; ! 253: int cbytes = 0; ! 254: IOPhysicalAddress nextContPage, nextPhysPage; ! 255: char *nextVirtPage, *curVirtPage; ! 256: int bytesLeftInPage, curByteCount; ! 257: ! 258: if ((offset >= size) || ![self isWired]) ! 259: return NO; ! 260: ! 261: vaddr = (char *)data + offset; ! 262: paddr = (IOPhysicalAddress) pmap_resident_extract( ! 263: vm_map_pmap((vm_map_t)map), vaddr); ! 264: ! 265: if (physicalRangePtr != NULL) { ! 266: curByteCount = size - offset; ! 267: curVirtPage = (char *)trunc_page(vaddr); ! 268: nextContPage = (IOPhysicalAddress)trunc_page(paddr) + PAGE_SIZE; ! 269: bytesLeftInPage = nextContPage - paddr; ! 270: ! 271: while (curByteCount > 0) { ! 272: if (bytesLeftInPage >= curByteCount ){ ! 273: cbytes += curByteCount; ! 274: break; ! 275: } else { ! 276: cbytes += bytesLeftInPage; ! 277: ! 278: nextPhysPage = (IOPhysicalAddress) pmap_resident_extract( ! 279: vm_map_pmap((vm_map_t)map), ! 280: (curVirtPage + PAGE_SIZE)); ! 281: ! 282: if (nextPhysPage == nextContPage){ ! 283: curByteCount -= bytesLeftInPage; ! 284: bytesLeftInPage = PAGE_SIZE; ! 285: curVirtPage += PAGE_SIZE; ! 286: nextContPage += PAGE_SIZE; ! 287: } else { ! 288: break; ! 289: } ! 290: } ! 291: } ! 292: } ! 293: if (physicalRangePtr != NULL) { ! 294: physicalRangePtr->start = paddr; ! 295: physicalRangePtr->size = cbytes; ! 296: } ! 297: return YES; ! 298: } ! 299: ! 300: -(IOBufferAttributes)attributes ! 301: { ! 302: return attributes; ! 303: } ! 304: ! 305: -(BOOL)isContiguous ! 306: { ! 307: return ((attributes & IOBuf_Contiguous) ? YES : NO); ! 308: } ! 309: ! 310: -(BOOL)isWired ! 311: { ! 312: return ((attributes & IOBuf_Wired) ? YES : NO); ! 313: } ! 314: ! 315: -(unsigned int)size ! 316: { ! 317: return size; ! 318: } ! 319: ! 320: -(void *)data ! 321: { ! 322: return data; ! 323: } ! 324: ! 325: -(IOAlignment)alignment ! 326: { ! 327: return alignment; ! 328: } ! 329: ! 330: -(IORange)range ! 331: { ! 332: return userRange; ! 333: } ! 334: ! 335: ! 336: -(void)setRange:(IORange)newRange ! 337: { ! 338: userRange = newRange; ! 339: } ! 340: ! 341: ! 342: +(BOOL)allocMemoryWithSize:(int)memSize ! 343: attributes:(IOBufferAttributes)attr ! 344: alignment:(IOAlignment)align ! 345: allocedAddress:(IOVirtualAddress *)allocPtr ! 346: dataAddress:(IOVirtualAddress *)dataPtr ! 347: allocedSize:(int *)sizePtr ! 348: newAttributes:(IOBufferAttributes *)newAttrPtr ! 349: newMap:(IOAddressMap *)mapPtr ! 350: { ! 351: IOVirtualAddress vaddr; ! 352: int alignSize, newSize; ! 353: ! 354: alignSize = IOAlignmentToSize(align); ! 355: newSize = memSize + 2 * alignSize; ! 356: ! 357: /* an optimization that relies on IOMalloc returning aligned pages. */ ! 358: if (newSize > PAGE_SIZE && memSize <= PAGE_SIZE) ! 359: newSize = PAGE_SIZE; ! 360: ! 361: vaddr = (IOVirtualAddress)IOMalloc(newSize); ! 362: if (vaddr == 0) ! 363: return FALSE; ! 364: ! 365: *allocPtr = vaddr; ! 366: if (newSize != memSize) ! 367: *dataPtr = (vaddr + alignSize - 1) & ~(alignSize - 1); ! 368: else ! 369: *dataPtr = vaddr; ! 370: *sizePtr = newSize; ! 371: *newAttrPtr = IOBuf_Wired | IOBuf_WiredStatic | IOBuf_Contiguous; ! 372: *mapPtr = (IOAddressMap)IOVmTaskSelf(); ! 373: return TRUE; ! 374: } ! 375: ! 376: ! 377: +(BOOL)freeMemory:(IOVirtualAddress)addr ! 378: size:(int)memsize ! 379: map:(IOAddressMap)memmap ! 380: attributes:(IOBufferAttributes)attr ! 381: { ! 382: IOFree((void *)addr, memsize); ! 383: return TRUE; ! 384: } ! 385: ! 386: @end ! 387: ! 388: /* ! 389: * Helper functions ! 390: */ ! 391: ! 392: /* ! 393: * Returns TRUE if the address meets the specified aligment requirement. ! 394: */ ! 395: static BOOL checkAlignmentFromVirtual( ! 396: IOVirtualAddress vaddr, ! 397: IOAddressMap map, ! 398: int size, ! 399: IOAlignment align ! 400: ) ! 401: { ! 402: IOPhysicalAddress paddr; ! 403: ! 404: paddr = (IOPhysicalAddress) pmap_resident_extract( ! 405: vm_map_pmap((vm_map_t)map), vaddr); ! 406: ! 407: return checkAlignmentFromPhysical(paddr, size, align); ! 408: } ! 409: ! 410: static BOOL checkAlignmentFromPhysical( ! 411: IOPhysicalAddress paddr, ! 412: int size, ! 413: IOAlignment align ! 414: ) ! 415: { ! 416: unsigned int mask; ! 417: ! 418: if (align > IOBufferAlignMax) ! 419: return NO; ! 420: ! 421: mask = maskFromAlignment(align); ! 422: if ((paddr & mask) || (size & mask)) ! 423: return NO; ! 424: ! 425: return YES; ! 426: } ! 427: ! 428: static BOOL checkAlignmentFromSize( ! 429: int size, ! 430: IOAlignment align ! 431: ) ! 432: { ! 433: unsigned int mask; ! 434: if (align > IOBufferAlignMax) ! 435: return NO; ! 436: mask = maskFromAlignment(align); ! 437: if (size & mask) ! 438: return NO; ! 439: return YES; ! 440: } ! 441: ! 442: static unsigned int ! 443: maskFromAlignment( ! 444: IOAlignment align ! 445: ) ! 446: { ! 447: unsigned int mask; ! 448: ! 449: for (mask = 0; align; align--) { ! 450: mask = (mask << 1) | 1; ! 451: } ! 452: return mask; ! 453: } ! 454: ! 455: static unsigned int ! 456: alignmentFromAddress( ! 457: unsigned int addr ! 458: ) ! 459: { ! 460: unsigned int alignment; ! 461: ! 462: for (alignment=0; alignment < PAGE_SHIFT; alignment++) { ! 463: if (addr & 0x01) ! 464: return alignment; ! 465: addr >>= 1; ! 466: } ! 467: return alignment; ! 468: } ! 469: ! 470: static void ! 471: copyData( ! 472: IOVirtualAddress src, ! 473: IOAddressMap srcMap, ! 474: IOVirtualAddress dst, ! 475: IOAddressMap dstMap, ! 476: unsigned int totalLength ! 477: ) ! 478: { ! 479: IOPhysicalAddress physSrc, physDst; ! 480: int currentLength; ! 481: int leftInSrc, leftInDst; ! 482: const unsigned int pageMask = PAGE_SIZE - 1; ! 483: ! 484: while (totalLength) { ! 485: physSrc = (IOPhysicalAddress) pmap_resident_extract( ! 486: vm_map_pmap((vm_map_t)srcMap), src); ! 487: physDst = (IOPhysicalAddress) pmap_resident_extract( ! 488: vm_map_pmap((vm_map_t)dstMap), dst); ! 489: leftInSrc = PAGE_SIZE - (physSrc & pageMask); ! 490: leftInDst = PAGE_SIZE - (physDst & pageMask); ! 491: currentLength = MIN(leftInSrc, leftInDst); ! 492: currentLength = MIN(totalLength, currentLength); ! 493: bcopy(pmap_phys_to_kern(physSrc), ! 494: pmap_phys_to_kern(physDst), ! 495: currentLength); ! 496: totalLength -= currentLength; ! 497: src += currentLength; ! 498: dst += currentLength; ! 499: } ! 500: } ! 501: ! 502: #endif NOTYET ! 503:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.