Annotation of XNU/iokit/Kernel/IOLib.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.