|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * ! 27: * 17-Apr-91 Portions from libIO.m, Doug Mitchell at NeXT. ! 28: * 17-Nov-98 cpp ! 29: * ! 30: */ ! 31: ! 32: #include <IOKit/system.h> ! 33: #include <mach/sync_policy.h> ! 34: #include <machine/machine_routines.h> ! 35: #include <libkern/c++/OSCPPDebug.h> ! 36: ! 37: #include <IOKit/assert.h> ! 38: ! 39: #include <IOKit/IOReturn.h> ! 40: #include <IOKit/IOLib.h> ! 41: #include <IOKit/IOKitDebug.h> ! 42: ! 43: mach_timespec_t IOZeroTvalspec = { 0, 0 }; ! 44: ! 45: /* ! 46: * Static variables for this module. ! 47: */ ! 48: ! 49: static IOThreadFunc threadArgFcn; ! 50: static void * threadArgArg; ! 51: static lock_t * threadArgLock; ! 52: ! 53: void IOLibInit(void) ! 54: { ! 55: static bool libInitialized; ! 56: ! 57: if(libInitialized) ! 58: return; ! 59: ! 60: threadArgLock = lock_alloc( true, NULL, NULL ); ! 61: ! 62: libInitialized = true; ! 63: } ! 64: ! 65: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 66: ! 67: /* ! 68: * We pass an argument to a new thread by saving fcn and arg in some ! 69: * locked variables and starting the thread at ioThreadStart(). This ! 70: * function retrives fcn and arg and makes the appropriate call. ! 71: * ! 72: */ ! 73: ! 74: static void ioThreadStart( void ) ! 75: { ! 76: IOThreadFunc fcn; ! 77: void * arg; ! 78: ! 79: fcn = threadArgFcn; ! 80: arg = threadArgArg; ! 81: lock_done( threadArgLock); ! 82: ! 83: (*fcn)(arg); ! 84: ! 85: IOExitThread(); ! 86: } ! 87: ! 88: IOThread IOCreateThread(IOThreadFunc fcn, void *arg) ! 89: { ! 90: IOThread thread; ! 91: ! 92: lock_write( threadArgLock); ! 93: threadArgFcn = fcn; ! 94: threadArgArg = arg; ! 95: ! 96: thread = kernel_thread( kernel_task, ioThreadStart); ! 97: ! 98: return(thread); ! 99: } ! 100: ! 101: ! 102: volatile void IOExitThread() ! 103: { ! 104: (void) thread_terminate(current_act()); ! 105: } ! 106: ! 107: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 108: ! 109: ! 110: void * IOMalloc(vm_size_t size) ! 111: { ! 112: void * address; ! 113: ! 114: address = (void *)kalloc(size); ! 115: #ifdef DEBUG ! 116: if (address) ! 117: debug_iomalloc_size += size; ! 118: #endif ! 119: return address; ! 120: } ! 121: ! 122: void IOFree(void * address, vm_size_t size) ! 123: { ! 124: if (address) { ! 125: kfree((vm_offset_t)address, size); ! 126: #ifdef DEBUG ! 127: debug_iomalloc_size -= size; ! 128: #endif ! 129: } ! 130: } ! 131: ! 132: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 133: ! 134: #define KMA_HERE 0x01 ! 135: #define KMA_NOPAGEWAIT 0x02 ! 136: #define KMA_KOBJECT 0x04 ! 137: ! 138: extern kern_return_t ! 139: kernel_memory_allocate( ! 140: register vm_map_t map, ! 141: register vm_offset_t *addrp, ! 142: register vm_size_t size, ! 143: register vm_offset_t mask, ! 144: int flags); ! 145: ! 146: extern void ! 147: kmem_free( ! 148: vm_map_t map, ! 149: vm_offset_t addr, ! 150: vm_size_t size); ! 151: ! 152: void * IOMallocAligned(vm_size_t size, vm_size_t alignment) ! 153: { ! 154: kern_return_t kr; ! 155: vm_address_t address; ! 156: vm_address_t allocationAddress; ! 157: vm_size_t adjustedSize; ! 158: vm_offset_t alignMask = alignment - 1; ! 159: ! 160: if (size == 0) return 0; ! 161: ! 162: adjustedSize = size + sizeof(vm_size_t) + sizeof(vm_address_t); ! 163: if (adjustedSize >= page_size) { ! 164: ! 165: kr = kernel_memory_allocate(kernel_map, &address, ! 166: size, alignMask, KMA_KOBJECT); ! 167: if (KERN_SUCCESS != kr) { ! 168: IOLog("Failed %08x, %08x\n", size, alignment); ! 169: address = 0; ! 170: } ! 171: } else { ! 172: ! 173: adjustedSize += alignMask; ! 174: allocationAddress = (vm_address_t) kalloc(adjustedSize); ! 175: ! 176: if (allocationAddress) { ! 177: address = (allocationAddress + alignMask ! 178: + (sizeof(vm_size_t) + sizeof(vm_address_t))) ! 179: & (~alignMask); ! 180: ! 181: *((vm_size_t *)(address - sizeof(vm_size_t) ! 182: - sizeof(vm_address_t))) = adjustedSize; ! 183: *((vm_address_t *)(address - sizeof(vm_address_t))) ! 184: = allocationAddress; ! 185: } else ! 186: address = 0; ! 187: } ! 188: ! 189: assert(0 == (address & alignMask)); ! 190: ! 191: #ifdef DEBUG ! 192: if( address) ! 193: debug_iomalloc_size += size; ! 194: #endif ! 195: ! 196: return (void *) address; ! 197: } ! 198: ! 199: void IOFreeAligned(void * address, vm_size_t size) ! 200: { ! 201: vm_address_t allocationAddress; ! 202: vm_size_t adjustedSize; ! 203: ! 204: if( !address) ! 205: return; ! 206: ! 207: assert(size); ! 208: ! 209: adjustedSize = size + sizeof(vm_size_t) + sizeof(vm_address_t); ! 210: if (adjustedSize >= page_size) { ! 211: ! 212: kmem_free( kernel_map, (vm_address_t) address, size); ! 213: ! 214: } else { ! 215: adjustedSize = *((vm_size_t *)( (vm_address_t) address ! 216: - sizeof(vm_address_t) - sizeof(vm_size_t))); ! 217: allocationAddress = *((vm_address_t *)( (vm_address_t) address ! 218: - sizeof(vm_address_t) )); ! 219: ! 220: kfree((vm_offset_t) allocationAddress, adjustedSize); ! 221: } ! 222: ! 223: #ifdef DEBUG ! 224: debug_iomalloc_size -= size; ! 225: #endif ! 226: } ! 227: ! 228: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 229: ! 230: extern kern_return_t kmem_alloc_contig( ! 231: vm_map_t map, ! 232: vm_offset_t *addrp, ! 233: vm_size_t size, ! 234: vm_offset_t mask, ! 235: int flags); ! 236: ! 237: void * IOMallocContiguous(vm_size_t size, vm_size_t alignment, ! 238: IOPhysicalAddress * physicalAddress) ! 239: { ! 240: kern_return_t kr; ! 241: vm_address_t address; ! 242: vm_address_t allocationAddress; ! 243: vm_size_t adjustedSize; ! 244: vm_offset_t alignMask; ! 245: ! 246: if (size == 0) return 0; ! 247: if (alignment == 0) alignment = 1; ! 248: ! 249: alignMask = alignment - 1; ! 250: adjustedSize = (2 * size) + sizeof(vm_size_t) + sizeof(vm_address_t); ! 251: if (adjustedSize >= page_size) { ! 252: ! 253: kr = kmem_alloc_contig(kernel_map, &address, size, ! 254: alignMask, KMA_KOBJECT); ! 255: if (KERN_SUCCESS != kr) ! 256: address = 0; ! 257: ! 258: } else { ! 259: ! 260: adjustedSize += alignMask; ! 261: allocationAddress = (vm_address_t) ! 262: kalloc(adjustedSize); ! 263: if (allocationAddress) { ! 264: ! 265: address = (allocationAddress + alignMask ! 266: + (sizeof(vm_size_t) + sizeof(vm_address_t))) ! 267: & (~alignMask); ! 268: ! 269: if (atop(address) != atop(address + size - 1)) ! 270: address = round_page(address); ! 271: ! 272: *((vm_size_t *)(address - sizeof(vm_size_t) ! 273: - sizeof(vm_address_t))) = adjustedSize; ! 274: *((vm_address_t *)(address - sizeof(vm_address_t))) ! 275: = allocationAddress; ! 276: } else ! 277: address = 0; ! 278: } ! 279: ! 280: if( address && physicalAddress) ! 281: *physicalAddress = (IOPhysicalAddress) pmap_extract( kernel_pmap, ! 282: address ); ! 283: ! 284: assert(0 == (address & alignMask)); ! 285: ! 286: #ifdef DEBUG ! 287: if( address) ! 288: debug_iomalloc_size += size; ! 289: #endif ! 290: ! 291: return (void *) address; ! 292: } ! 293: ! 294: void IOFreeContiguous(void * address, vm_size_t size) ! 295: { ! 296: vm_address_t allocationAddress; ! 297: vm_size_t adjustedSize; ! 298: ! 299: if( !address) ! 300: return; ! 301: ! 302: assert(size); ! 303: ! 304: adjustedSize = (2 * size) + sizeof(vm_size_t) + sizeof(vm_address_t); ! 305: if (adjustedSize >= page_size) { ! 306: ! 307: kmem_free( kernel_map, (vm_address_t) address, size); ! 308: ! 309: } else { ! 310: adjustedSize = *((vm_size_t *)( (vm_address_t) address ! 311: - sizeof(vm_address_t) - sizeof(vm_size_t))); ! 312: allocationAddress = *((vm_address_t *)( (vm_address_t) address ! 313: - sizeof(vm_address_t) )); ! 314: ! 315: kfree((vm_offset_t) allocationAddress, adjustedSize); ! 316: } ! 317: ! 318: #ifdef DEBUG ! 319: debug_iomalloc_size -= size; ! 320: #endif ! 321: } ! 322: ! 323: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 324: ! 325: extern kern_return_t IOMapPages(vm_map_t map, vm_offset_t va, vm_offset_t pa, ! 326: vm_size_t length, unsigned int options); ! 327: ! 328: IOReturn IOSetProcessorCacheMode( task_t task, IOVirtualAddress address, ! 329: IOByteCount length, IOOptionBits cacheMode ) ! 330: { ! 331: IOReturn ret = kIOReturnSuccess; ! 332: vm_offset_t physAddr; ! 333: ! 334: if( task != kernel_task) ! 335: return( kIOReturnUnsupported ); ! 336: ! 337: length = round_page(address + length) - trunc_page( address ); ! 338: address = trunc_page( address ); ! 339: ! 340: // make map mode ! 341: cacheMode = (cacheMode << kIOMapCacheShift) & kIOMapCacheMask; ! 342: ! 343: while( (kIOReturnSuccess == ret) && (length > 0) ) { ! 344: ! 345: physAddr = pmap_extract( kernel_pmap, address ); ! 346: if( physAddr) ! 347: ret = IOMapPages( get_task_map(task), address, physAddr, page_size, cacheMode ); ! 348: else ! 349: ret = kIOReturnVMError; ! 350: ! 351: length -= page_size; ! 352: } ! 353: ! 354: return( ret ); ! 355: } ! 356: ! 357: ! 358: IOReturn IOFlushProcessorCache( task_t task, IOVirtualAddress address, ! 359: IOByteCount length ) ! 360: { ! 361: if( task != kernel_task) ! 362: return( kIOReturnUnsupported ); ! 363: ! 364: #if __ppc__ ! 365: flush_dcache( (vm_offset_t) address, (unsigned) length, false ); ! 366: #endif ! 367: ! 368: return( kIOReturnSuccess ); ! 369: } ! 370: ! 371: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 372: ! 373: SInt32 OSKernelStackRemaining( void ) ! 374: { ! 375: SInt32 stack; ! 376: ! 377: stack = (((SInt32) &stack) & (KERNEL_STACK_SIZE - 1)); ! 378: ! 379: return( stack ); ! 380: } ! 381: ! 382: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 383: ! 384: void IOSleep(unsigned milliseconds) ! 385: { ! 386: assert_wait_timeout(milliseconds, THREAD_INTERRUPTIBLE); ! 387: thread_block((void (*)(void))0); ! 388: thread_cancel_timer(); ! 389: } ! 390: ! 391: /* ! 392: * Spin for indicated number of microseconds. ! 393: */ ! 394: void IODelay(unsigned microseconds) ! 395: { ! 396: extern void delay(int usec); ! 397: ! 398: delay(microseconds); ! 399: } ! 400: ! 401: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 402: ! 403: void IOLog(const char *format, ...) ! 404: { ! 405: va_list ap; ! 406: extern void conslog_putc(char); ! 407: extern void logwakeup(); ! 408: ! 409: va_start(ap, format); ! 410: _doprnt(format, &ap, conslog_putc, 16); ! 411: va_end(ap); ! 412: logwakeup(); ! 413: } ! 414: ! 415: void IOPanic(const char *reason) ! 416: { ! 417: panic(reason); ! 418: } ! 419: ! 420: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 421: ! 422: /* ! 423: * Convert a integer constant (typically a #define or enum) to a string. ! 424: */ ! 425: static char noValue[80]; // that's pretty ! 426: ! 427: const char *IOFindNameForValue(int value, const IONamedValue *regValueArray) ! 428: { ! 429: for( ; regValueArray->name; regValueArray++) { ! 430: if(regValueArray->value == value) ! 431: return(regValueArray->name); ! 432: } ! 433: sprintf(noValue, "%d(d) (UNDEFINED)", value); ! 434: return((const char *)noValue); ! 435: } ! 436: ! 437: IOReturn IOFindValueForName(const char *string, ! 438: const IONamedValue *regValueArray, ! 439: int *value) ! 440: { ! 441: for( ; regValueArray->name; regValueArray++) { ! 442: if(!strcmp(regValueArray->name, string)) { ! 443: *value = regValueArray->value; ! 444: return kIOReturnSuccess; ! 445: } ! 446: } ! 447: return kIOReturnBadArgument; ! 448: } ! 449: ! 450: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 451: ! 452: IOAlignment IOSizeToAlignment(unsigned int size) ! 453: { ! 454: register int shift; ! 455: const int intsize = sizeof(unsigned int) * 8; ! 456: ! 457: for (shift = 1; shift < intsize; shift++) { ! 458: if (size & 0x80000000) ! 459: return (IOAlignment)(intsize - shift); ! 460: size <<= 1; ! 461: } ! 462: return 0; ! 463: } ! 464: ! 465: unsigned int IOAlignmentToSize(IOAlignment align) ! 466: { ! 467: unsigned int size; ! 468: ! 469: for (size = 1; align; align--) { ! 470: size <<= 1; ! 471: } ! 472: return size; ! 473: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.