Annotation of XNU/iokit/Kernel/IOLib.c, revision 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.