Annotation of XNU/iokit/Kernel/IOUserClient.cpp, 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:  * 14 Aug 98 sdouglas created.
                     28:  * 08 Dec 98 sdouglas cpp.
                     29:  */
                     30: 
                     31: #include <IOKit/IOKitServer.h>
                     32: #include <IOKit/IOUserClient.h>
                     33: #include <IOKit/IOService.h>
                     34: #include <IOKit/IORegistryEntry.h>
                     35: #include <IOKit/IOCatalogue.h>
                     36: #include <IOKit/IOMemoryDescriptor.h>
                     37: #include <IOKit/IOLib.h>
                     38: 
                     39: #include "../bsddev/IOKitBSDInit.h"
                     40: 
                     41: #include <IOKit/assert.h>
                     42: 
                     43: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     44: 
                     45: // definitions we should get from osfmk
                     46: 
                     47: //typedef struct ipc_port * ipc_port_t;
                     48: typedef natural_t ipc_kobject_type_t;
                     49: 
                     50: #define IKOT_IOKIT_SPARE       27
                     51: #define IKOT_IOKIT_CONNECT     29
                     52: #define IKOT_IOKIT_OBJECT      30
                     53: 
                     54: extern "C" {
                     55: 
                     56: extern ipc_port_t iokit_alloc_object_port( io_object_t obj,
                     57:                        ipc_kobject_type_t type );
                     58: 
                     59: extern kern_return_t iokit_destroy_object_port( ipc_port_t port );
                     60: 
                     61: extern mach_port_name_t iokit_make_send_right( task_t task,
                     62:                                io_object_t obj, ipc_kobject_type_t type );
                     63: 
                     64: extern ipc_port_t master_device_port;
                     65: 
                     66: extern vm_size_t msg_ool_size_small;
                     67: 
                     68: extern kern_return_t   vm_map_copyin_common(
                     69:                                vm_map_t        src_map,
                     70:                                vm_offset_t     src_addr,
                     71:                                vm_size_t       len,
                     72:                                boolean_t       src_destroy,
                     73:                                boolean_t       src_volatile,
                     74:                                vm_map_copy_t   *copy_result,   /* OUT */
                     75:                                boolean_t       use_maxprot);
                     76: 
                     77: #define        vm_map_copyin(src_map, src_addr, len, src_destroy, copy_result) \
                     78:                vm_map_copyin_common(src_map, src_addr, len, src_destroy, \
                     79:                                        FALSE, copy_result, FALSE)
                     80: 
                     81: extern kern_return_t   vm_map_copyout(
                     82:                                vm_map_t        dst_map,
                     83:                                vm_offset_t     *dst_addr,      /* OUT */
                     84:                                vm_map_copy_t   copy);
                     85: 
                     86: } /* extern "C" */
                     87: 
                     88: 
                     89: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                     90: 
                     91: // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject.
                     92: 
                     93: class IOMachPort : public OSObject
                     94: {
                     95:     OSDeclareDefaultStructors(IOMachPort)
                     96: public:
                     97:     OSObject * object;
                     98:     ipc_port_t port;
                     99: 
                    100:     static IOMachPort * portForObject( OSObject * obj,
                    101:                                ipc_kobject_type_t type );
                    102:     static void releasePortForObject( OSObject * obj,
                    103:                                ipc_kobject_type_t type );
                    104:     static OSDictionary * dictForType( ipc_kobject_type_t type );
                    105: 
                    106:     static mach_port_name_t makeSendRightForTask( task_t task,
                    107:                                io_object_t obj, ipc_kobject_type_t type );
                    108: 
                    109:     virtual void free();
                    110: };
                    111: 
                    112: #define super OSObject
                    113: OSDefineMetaClassAndStructors(IOMachPort, OSObject)
                    114: 
                    115: static IOLock *                gIOObjectPortLock;
                    116: 
                    117: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    118: 
                    119: // not in dictForType() for debugging ease
                    120: static OSDictionary *  gIOObjectPorts;
                    121: static OSDictionary *  gIOConnectPorts;
                    122: 
                    123: OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type )
                    124: {
                    125:     OSDictionary **            dict;
                    126: 
                    127:     if( IKOT_IOKIT_OBJECT == type )
                    128:        dict = &gIOObjectPorts;
                    129:     else if( IKOT_IOKIT_CONNECT == type )
                    130:        dict = &gIOConnectPorts;
                    131:     else
                    132:        return( 0 );
                    133: 
                    134:     if( 0 == *dict)
                    135:         *dict = OSDictionary::withCapacity( 1 );
                    136: 
                    137:     return( *dict );
                    138: }
                    139: 
                    140: IOMachPort * IOMachPort::portForObject ( OSObject * obj,
                    141:                                ipc_kobject_type_t type )
                    142: {
                    143:     IOMachPort *       inst = 0;
                    144:     OSDictionary *     dict;
                    145: 
                    146:     IOTakeLock( gIOObjectPortLock);
                    147: 
                    148:     do {
                    149: 
                    150:        dict = dictForType( type );
                    151:        if( !dict)
                    152:            continue;
                    153: 
                    154:         if( (inst = (IOMachPort *)
                    155:                 dict->getObject( (const OSSymbol *) obj )))
                    156:             continue;
                    157: 
                    158:         inst = new IOMachPort;
                    159:         if( inst && !inst->init()) {
                    160:             inst = 0;
                    161:             continue;
                    162:        }
                    163: 
                    164:         inst->port = iokit_alloc_object_port( obj, type );
                    165:         if( inst->port) {
                    166:            // retains obj
                    167:             dict->setObject( (const OSSymbol *) obj, inst );
                    168:             inst->release();   // one more to free port => release obj
                    169: 
                    170:         } else {
                    171:             inst->release();
                    172:             inst = 0;
                    173:         }
                    174: 
                    175:     } while( false );
                    176: 
                    177:     IOUnlock( gIOObjectPortLock);
                    178: 
                    179:     return( inst );
                    180: }
                    181: 
                    182: void IOMachPort::releasePortForObject( OSObject * obj,
                    183:                                ipc_kobject_type_t type )
                    184: {
                    185:     OSDictionary *     dict;
                    186: 
                    187:     IOTakeLock( gIOObjectPortLock);
                    188: 
                    189:     if( (dict = dictForType( type )))
                    190:         dict->removeObject( (const OSSymbol *) obj );
                    191: 
                    192:     IOUnlock( gIOObjectPortLock);
                    193: }
                    194: 
                    195: void IOUserClient::destroyUserReferences( OSObject * obj )
                    196: {
                    197:     IOMachPort::releasePortForObject( obj, IKOT_IOKIT_OBJECT );
                    198:     IOMachPort::releasePortForObject( obj, IKOT_IOKIT_CONNECT );
                    199: }
                    200: 
                    201: mach_port_name_t IOMachPort::makeSendRightForTask( task_t task,
                    202:                                io_object_t obj, ipc_kobject_type_t type )
                    203: {
                    204:     return( iokit_make_send_right( task, obj, type ));
                    205: }
                    206: 
                    207: void IOMachPort::free( void )
                    208: {
                    209:     if( port)
                    210:        iokit_destroy_object_port( port );
                    211:     super::free();
                    212: }
                    213: 
                    214: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    215: 
                    216: extern "C" {
                    217: 
                    218: // functions called from osfmk/device/iokit_rpc.c
                    219: 
                    220: void
                    221: iokit_add_reference( io_object_t obj )
                    222: {
                    223:     if( obj)
                    224:        obj->retain();
                    225: }
                    226: 
                    227: void
                    228: iokit_remove_reference( io_object_t obj )
                    229: {
                    230:     if( obj)
                    231:        obj->release();
                    232: }
                    233: 
                    234: ipc_port_t
                    235: iokit_port_for_object( io_object_t obj, ipc_kobject_type_t type )
                    236: {
                    237:     IOMachPort * machPort;
                    238: 
                    239:     if( (machPort = IOMachPort::portForObject( obj, type )))
                    240:        return( machPort->port );
                    241:     else
                    242:        return( 0 );
                    243: }
                    244: 
                    245: kern_return_t
                    246: iokit_client_died( io_object_t obj, ipc_port_t /* port */,
                    247:                        ipc_kobject_type_t type )
                    248: {
                    249:     IOUserClient *     client;
                    250: 
                    251:     if( (IKOT_IOKIT_CONNECT == type)
                    252:      && (client = OSDynamicCast( IOUserClient, obj )))
                    253:        client->clientDied();
                    254: 
                    255:     IOMachPort::releasePortForObject( obj, type );
                    256: 
                    257:     return( kIOReturnSuccess);
                    258: }
                    259: 
                    260: };     /* extern "C" */
                    261: 
                    262: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    263: 
                    264: class IOUserNotification : public OSIterator
                    265: {
                    266:     OSDeclareDefaultStructors(IOUserNotification)
                    267: 
                    268:     struct PingMsg {
                    269:         mach_msg_header_t      msgHdr;
                    270:         OSNotificationHeader   notifyHeader;
                    271:     };
                    272: 
                    273:     PingMsg    *       pingMsg;
                    274:     vm_size_t          msgSize;
                    275:     IONotifier         *       holdNotify;
                    276:     IOLock     *       lock;
                    277: 
                    278: public:
                    279: 
                    280:     virtual bool init( mach_port_t port, natural_t type,
                    281:                        OSAsyncReference reference,
                    282:                        vm_size_t messageSize );
                    283:     virtual void free();
                    284: 
                    285:     virtual void setNotification( IONotifier * obj );
                    286: 
                    287:     virtual void reset();
                    288:     virtual bool isValid();
                    289: };
                    290: 
                    291: class IOServiceUserNotification : public IOUserNotification
                    292: {
                    293:     OSDeclareDefaultStructors(IOServiceUserNotification)
                    294: 
                    295:     enum { kMaxOutstanding = 256 };
                    296: 
                    297:     OSArray    *       newSet;
                    298:     OSObject   *       lastEntry;
                    299:     bool               armed;
                    300: 
                    301: public:
                    302: 
                    303:     virtual bool init( mach_port_t port, natural_t type,
                    304:                        OSAsyncReference reference );
                    305:     virtual void free();
                    306: 
                    307:     static bool _handler( void * target,
                    308:                           void * ref, IOService * newService );
                    309:     virtual bool handler( void * ref, IOService * newService );
                    310: 
                    311:     virtual OSObject * getNextObject();
                    312: };
                    313: 
                    314: class IOServiceMessageUserNotification : public IOUserNotification
                    315: {
                    316:     OSDeclareDefaultStructors(IOServiceMessageUserNotification)
                    317: 
                    318: public:
                    319: 
                    320:     virtual bool init( mach_port_t port, natural_t type,
                    321:                        OSAsyncReference reference, vm_size_t extraSize );
                    322:     virtual void free();
                    323:     
                    324:     static IOReturn _handler( void * target, void * ref,
                    325:                               UInt32 messageType, IOService * provider,
                    326:                               void * messageArgument, vm_size_t argSize );
                    327:     virtual IOReturn handler( void * ref,
                    328:                               UInt32 messageType, IOService * provider,
                    329:                               void * messageArgument, vm_size_t argSize );
                    330: 
                    331:     virtual OSObject * getNextObject();
                    332: };
                    333: 
                    334: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    335: 
                    336: #undef super
                    337: #define super OSIterator
                    338: OSDefineMetaClass( IOUserNotification, OSIterator )
                    339: OSDefineAbstractStructors( IOUserNotification, OSIterator )
                    340: 
                    341: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    342: 
                    343: bool IOUserNotification::init( mach_port_t port, natural_t type,
                    344:                                OSAsyncReference reference, vm_size_t extraSize )
                    345: {
                    346:     if( !super::init())
                    347:        return( false );
                    348: 
                    349:     lock = IOLockAlloc();
                    350:     if( !lock)
                    351:         return( false );
                    352: 
                    353:     msgSize = sizeof( PingMsg) + extraSize;
                    354:     pingMsg = (PingMsg *) IOMalloc( msgSize);
                    355:     if( !pingMsg)
                    356:         return( false );
                    357: 
                    358:     bzero( pingMsg, msgSize);
                    359: 
                    360:     pingMsg->msgHdr.msgh_remote_port   = port;
                    361:     pingMsg->msgHdr.msgh_bits          = MACH_MSGH_BITS(
                    362:                                             MACH_MSG_TYPE_COPY_SEND,
                    363:                                             MACH_MSG_TYPE_COPY_SEND );
                    364:     pingMsg->msgHdr.msgh_size          = msgSize;
                    365:     pingMsg->msgHdr.msgh_id            = kOSNotificationMessageID;
                    366: 
                    367:     pingMsg->notifyHeader.size = extraSize;
                    368:     pingMsg->notifyHeader.type = type;
                    369:     bcopy( reference, pingMsg->notifyHeader.reference, sizeof(OSAsyncReference) );
                    370: 
                    371:     return( true );
                    372: }
                    373: 
                    374: void IOUserNotification::free( void )
                    375: {
                    376:     if( holdNotify)
                    377:        holdNotify->remove();
                    378:     // can't be in handler now
                    379: 
                    380:     if( pingMsg)
                    381:         IOFree( pingMsg, msgSize);
                    382: 
                    383:     if( lock)
                    384:        IOLockFree( lock );
                    385: 
                    386:     super::free();
                    387: }
                    388: 
                    389: 
                    390: void IOUserNotification::setNotification( IONotifier * notify )
                    391: {
                    392:     if( holdNotify)
                    393:        holdNotify->remove();
                    394: 
                    395:     holdNotify = notify;
                    396: }
                    397: 
                    398: void IOUserNotification::reset()
                    399: {
                    400:     // ?
                    401: }
                    402: 
                    403: bool IOUserNotification::isValid()
                    404: {
                    405:     return( true );
                    406: }
                    407: 
                    408: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    409: 
                    410: #undef super
                    411: #define super IOUserNotification
                    412: OSDefineMetaClassAndStructors(IOServiceUserNotification, IOUserNotification)
                    413: 
                    414: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    415: 
                    416: bool IOServiceUserNotification::init( mach_port_t port, natural_t type,
                    417:                                 OSAsyncReference reference )
                    418: {
                    419:     newSet = OSArray::withCapacity( 1 );
                    420:     if( !newSet)
                    421:         return( false );
                    422: 
                    423:     return( super::init( port, type, reference, 0) );
                    424: }
                    425: 
                    426: void IOServiceUserNotification::free( void )
                    427: {
                    428:     if( lastEntry)
                    429:         lastEntry->release();
                    430: 
                    431:     if( newSet)
                    432:         newSet->release();
                    433: 
                    434:     super::free();
                    435: }
                    436: 
                    437: bool IOServiceUserNotification::_handler( void * target,
                    438:                                     void * ref, IOService * newService )
                    439: {
                    440:     return( ((IOServiceUserNotification *) target)->handler( ref, newService ));
                    441: }
                    442: 
                    443: bool IOServiceUserNotification::handler( void * /* ref */,
                    444:                                 IOService * newService )
                    445: {
                    446:     unsigned int       count;
                    447:     kern_return_t      kr;
                    448:     IOMachPort *       machPort;
                    449:     bool               sendPing = false;
                    450: 
                    451:     IOTakeLock( lock );
                    452: 
                    453:     count = newSet->getCount();
                    454:     if( count < kMaxOutstanding) {
                    455: 
                    456:         newSet->setObject( newService );
                    457:         if( (sendPing = (armed && (0 == count))))
                    458:             armed = false;
                    459:     }
                    460: 
                    461:     IOUnlock( lock );
                    462: 
                    463:     if( sendPing) {
                    464:         if( (0 == pingMsg->msgHdr.msgh_local_port)
                    465:          && (machPort = IOMachPort::portForObject( this, IKOT_IOKIT_OBJECT ) ))
                    466:             pingMsg->msgHdr.msgh_local_port = machPort->port;
                    467: 
                    468:         kr = mach_msg_send_from_kernel( &pingMsg->msgHdr,
                    469:                                         pingMsg->msgHdr.msgh_size);
                    470:         if( KERN_SUCCESS != kr)
                    471:             IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
                    472:     }
                    473: 
                    474:     return( true );
                    475: }
                    476: 
                    477: OSObject * IOServiceUserNotification::getNextObject()
                    478: {
                    479:     unsigned int       count;
                    480:     OSObject *         result;
                    481: 
                    482:     IOTakeLock( lock );
                    483: 
                    484:     if( lastEntry)
                    485:         lastEntry->release();
                    486: 
                    487:     count = newSet->getCount();
                    488:     if( count ) {
                    489:         result = newSet->getObject( count - 1 );
                    490:         result->retain();
                    491:         newSet->removeObject( count - 1);
                    492:     } else {
                    493:         result = 0;
                    494:         armed = true;
                    495:     }
                    496:     lastEntry = result;
                    497: 
                    498:     IOUnlock( lock );
                    499: 
                    500:     return( result );
                    501: }
                    502: 
                    503: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    504: 
                    505: OSDefineMetaClassAndStructors(IOServiceMessageUserNotification, IOUserNotification)
                    506: 
                    507: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    508: 
                    509: bool IOServiceMessageUserNotification::init( mach_port_t port, natural_t type,
                    510:                        OSAsyncReference reference, vm_size_t extraSize )
                    511: {
                    512:     return( super::init( port, type, reference,
                    513:                        sizeof(IOServiceInterestContent) + extraSize) );
                    514: }
                    515: 
                    516: void IOServiceMessageUserNotification::free( void )
                    517: {
                    518:     super::free();
                    519: }
                    520: 
                    521: IOReturn IOServiceMessageUserNotification::_handler( void * target, void * ref,
                    522:                                             UInt32 messageType, IOService * provider,
                    523:                                             void * argument, vm_size_t argSize )
                    524: {
                    525:     return( ((IOServiceMessageUserNotification *) target)->handler(
                    526:                                 ref, messageType, provider, argument, argSize));
                    527: }
                    528: 
                    529: IOReturn IOServiceMessageUserNotification::handler( void * ref,
                    530:                                     UInt32 messageType, IOService * provider,
                    531:                                     void * messageArgument, vm_size_t argSize )
                    532: {
                    533:     kern_return_t              kr;
                    534:     IOMachPort *               machPort;
                    535:     IOServiceInterestContent *         data = (IOServiceInterestContent *)
                    536:                                        pingMsg->notifyHeader.content;
                    537: 
                    538:     data->messageType = messageType;
                    539:     if( argSize == 0) {
                    540:         argSize = sizeof( messageArgument);
                    541:         data->messageArgument[0] = messageArgument;
                    542:     } else {
                    543:         if( argSize > kIOUserNotifyMaxMessageSize)
                    544:             argSize = kIOUserNotifyMaxMessageSize;
                    545:         bcopy( messageArgument, data->messageArgument, argSize );
                    546:     }
                    547:     pingMsg->msgHdr.msgh_size = sizeof( PingMsg)
                    548:         + sizeof( IOServiceInterestContent )
                    549:         - sizeof( data->messageArgument)
                    550:         + argSize;
                    551: 
                    552:     if( (machPort = IOMachPort::portForObject( provider, IKOT_IOKIT_OBJECT ) ))
                    553:         pingMsg->msgHdr.msgh_local_port = machPort->port;
                    554:     else
                    555:         pingMsg->msgHdr.msgh_local_port = MACH_PORT_NULL;
                    556:     
                    557:     kr = mach_msg_send_from_kernel( &pingMsg->msgHdr,
                    558:                                     pingMsg->msgHdr.msgh_size);
                    559:     if( KERN_SUCCESS != kr)
                    560:         IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
                    561: 
                    562:     return( kIOReturnSuccess );
                    563: }
                    564: 
                    565: OSObject * IOServiceMessageUserNotification::getNextObject()
                    566: {
                    567:     return( 0 );
                    568: }
                    569: 
                    570: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    571: 
                    572: #undef super
                    573: #define super IOService
                    574: OSDefineMetaClass( IOUserClient, IOService )
                    575: OSDefineAbstractStructors( IOUserClient, IOService )
                    576: 
                    577: void IOUserClient::initialize( void )
                    578: {
                    579:     gIOObjectPortLock = IOLockAlloc();
                    580: 
                    581:     assert( gIOObjectPortLock );
                    582: }
                    583: 
                    584: IOReturn IOUserClient::clientDied( void )
                    585: {
                    586:     return( clientClose());
                    587: }
                    588: 
                    589: IOReturn IOUserClient::clientClose( void )
                    590: {
                    591:     return( kIOReturnUnsupported );
                    592: }
                    593: 
                    594: IOService * IOUserClient::getService( void )
                    595: {
                    596:     return( 0 );
                    597: }
                    598: 
                    599: IOReturn IOUserClient::registerNotificationPort(
                    600:                mach_port_t     /* port */,
                    601:                UInt32          /* type */,
                    602:                 UInt32         /* refCon */)
                    603: {
                    604:     return( kIOReturnUnsupported);
                    605: }
                    606: 
                    607: IOReturn IOUserClient::getNotificationSemaphore( UInt32 notification_type,
                    608:                                     semaphore_t * semaphore )
                    609: {
                    610:     return( kIOReturnUnsupported);
                    611: }
                    612: 
                    613: IOReturn IOUserClient::connectClient( IOUserClient * /* client */ )
                    614: {
                    615:     return( kIOReturnUnsupported);
                    616: }
                    617: 
                    618: IOReturn IOUserClient::clientMemoryForType( UInt32 type,
                    619:                                IOOptionBits * options,
                    620:                                IOMemoryDescriptor ** memory )
                    621: {
                    622:     return( kIOReturnUnsupported);
                    623: }
                    624: 
                    625: IOMemoryMap * IOUserClient::mapClientMemory( 
                    626:        IOOptionBits            type,
                    627:        task_t                  task,
                    628:        IOOptionBits            mapFlags = kIOMapAnywhere,
                    629:        IOVirtualAddress        atAddress = 0 )
                    630: {
                    631:     IOReturn           err;
                    632:     IOOptionBits       options = 0;
                    633:     IOMemoryDescriptor * memory;
                    634:     IOMemoryMap *      map = 0;
                    635: 
                    636:     err = clientMemoryForType( (UInt32) type, &options, &memory );
                    637: 
                    638:     if( memory && (kIOReturnSuccess == err)) {
                    639: 
                    640:         options = (options & ~kIOMapUserOptionsMask)
                    641:                | (mapFlags & kIOMapUserOptionsMask);
                    642:        map = memory->map( task, atAddress, options );
                    643:        memory->release();
                    644:     }
                    645: 
                    646:     return( map );
                    647: }
                    648: 
                    649: IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */)
                    650: {
                    651:     return( 0 );
                    652: }
                    653: 
                    654: IOExternalAsyncMethod * IOUserClient::getExternalAsyncMethodForIndex( UInt32 /* index */)
                    655: {
                    656:     return( 0 );
                    657: }
                    658: 
                    659: IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference,
                    660:                                        IOReturn result, void *args[], UInt32 numArgs)
                    661: {
                    662:     struct ReplyMsg {
                    663:         mach_msg_header_t      msgHdr;
                    664:         OSNotificationHeader   notifyHdr;
                    665:         IOAsyncCompletionContent asyncContent;
                    666:         void *                 args[kMaxAsyncArgs];
                    667:     };
                    668:     ReplyMsg replyMsg;
                    669:     mach_port_t        replyPort;
                    670:     kern_return_t kr;
                    671: 
                    672:     // If no reply port, do nothing.
                    673:     replyPort = (mach_port_t) reference[0];
                    674:     if(replyPort == MACH_PORT_NULL)
                    675:         return kIOReturnSuccess;
                    676:     
                    677:     if(numArgs > kMaxAsyncArgs)
                    678:         return kIOReturnMessageTooLarge;
                    679:     replyMsg.msgHdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0);
                    680:     replyMsg.msgHdr.msgh_size =
                    681:         sizeof(replyMsg) - (kMaxAsyncArgs-numArgs)*sizeof(void *);
                    682:     replyMsg.msgHdr.msgh_remote_port = replyPort;
                    683:     replyMsg.msgHdr.msgh_local_port = 0;
                    684:     replyMsg.msgHdr.msgh_id = kOSNotificationMessageID;
                    685: 
                    686:     replyMsg.notifyHdr.size = sizeof(IOAsyncCompletionContent)
                    687:                             + numArgs*sizeof(void *);
                    688:     replyMsg.notifyHdr.type = kIOAsyncCompletionNotificationType;
                    689:     bcopy( reference, replyMsg.notifyHdr.reference, sizeof(OSAsyncReference));
                    690: 
                    691:     replyMsg.asyncContent.result = result;
                    692:     if(numArgs > 0)
                    693:         bcopy(args, replyMsg.args, sizeof(void *)*numArgs);
                    694:      kr = mach_msg_send_from_kernel( &replyMsg.msgHdr,
                    695:             replyMsg.msgHdr.msgh_size);
                    696:     if( KERN_SUCCESS != kr)
                    697:         IOLog("%s: mach_msg_send_from_kernel {%x}\n", __FILE__, kr );
                    698:     return kr;
                    699: }
                    700: 
                    701: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    702: 
                    703: #include <IOKit/pci/IOPCIDevice.h>
                    704: 
                    705: static void makeMatchingCompatible( OSDictionary * dict )
                    706: {
                    707:     const char *       key;
                    708:     const char *       newKey;
                    709:     OSObject *         value;
                    710:     int                        i = 0;
                    711: 
                    712:     static const char * gratuitousNameChanges[] = {
                    713:        "IOImports",            kIOProviderClassKey,
                    714:        "IOClass Names",        kIOClassKey,
                    715:        "IOProbe Score",        kIOProbeScoreKey,
                    716:        "IOKit Debug",          kIOKitDebugKey,
                    717:        "IONeededResources",    kIOResourceMatchKey,
                    718:        "IOName Match",         kIONameMatchKey,
                    719:        "IOPCI Match",          kIOPCIMatchKey,
                    720:        "IOPCI Primary Match",  kIOPCIPrimaryMatchKey,
                    721:        "IOPCI Secondary Match",kIOPCISecondaryMatchKey,
                    722:        "IOPCI Class Match",    kIOPCIClassMatchKey,
                    723:        0
                    724:     };
                    725: 
                    726:     while( (key = gratuitousNameChanges[i++])) {
                    727:        newKey = gratuitousNameChanges[i++];
                    728:         if( (value = dict->getObject( key))
                    729:          && (0 == dict->getObject( newKey))) {
                    730:             IOLog("Must change soon: %s to %s\n", key, newKey);
                    731:             dict->setObject( newKey, value);
                    732:             dict->removeObject( key);
                    733:        }
                    734:     }
                    735: }
                    736: 
                    737: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                    738: 
                    739: extern "C" {
                    740: 
                    741: #define CHECK(cls,obj,out)                     \
                    742:        cls * out;                              \
                    743:        if( !(out = OSDynamicCast( cls, obj)))  \
                    744:            return( kIOReturnBadArgument )
                    745: 
                    746: /* Routine io_object_get_class */
                    747: kern_return_t is_io_object_get_class(
                    748:        io_object_t object,
                    749:        io_name_t className )
                    750: {
                    751:     strcpy( className, object->getMetaClass()->getClassName());
                    752:     return( kIOReturnSuccess );
                    753: }
                    754: 
                    755: /* Routine io_object_conforms_to */
                    756: kern_return_t is_io_object_conforms_to(
                    757:        io_object_t object,
                    758:        io_name_t className,
                    759:        boolean_t *conforms )
                    760: {
                    761:     *conforms = (0 != object->metaCast( className ));
                    762:     return( kIOReturnSuccess );
                    763: }
                    764: 
                    765: /* Routine io_object_get_retain_count */
                    766: kern_return_t is_io_object_get_retain_count(
                    767:        io_object_t object,
                    768:        int *retainCount )
                    769: {
                    770:     *retainCount = object->getRetainCount();
                    771:     return( kIOReturnSuccess );
                    772: }
                    773: 
                    774: /* Routine io_iterator_next */
                    775: kern_return_t is_io_iterator_next(
                    776:        io_object_t iterator,
                    777:        io_object_t *object )
                    778: {
                    779:     OSObject * obj;
                    780: 
                    781:     CHECK( OSIterator, iterator, iter );
                    782: 
                    783:     obj = iter->getNextObject();
                    784:     if( obj) {
                    785:        obj->retain();
                    786:        *object = obj;
                    787:         return( kIOReturnSuccess );
                    788:     } else
                    789:         return( kIOReturnNoDevice );
                    790: }
                    791: 
                    792: /* Routine io_iterator_reset */
                    793: kern_return_t is_io_iterator_reset(
                    794:        io_object_t iterator )
                    795: {
                    796:     CHECK( OSIterator, iterator, iter );
                    797: 
                    798:     iter->reset();
                    799: 
                    800:     return( kIOReturnSuccess );
                    801: }
                    802: 
                    803: /* Routine io_iterator_is_valid */
                    804: kern_return_t is_io_iterator_is_valid(
                    805:        io_object_t iterator,
                    806:        boolean_t *is_valid )
                    807: {
                    808:     CHECK( OSIterator, iterator, iter );
                    809: 
                    810:     *is_valid = iter->isValid();
                    811: 
                    812:     return( kIOReturnSuccess );
                    813: }
                    814: 
                    815: /* Routine io_service_match_property_table */
                    816: kern_return_t is_io_service_match_property_table(
                    817:        io_service_t _service,
                    818:        io_string_t matching,
                    819:        boolean_t *matches )
                    820: {
                    821:     CHECK( IOService, _service, service );
                    822: 
                    823:     kern_return_t      kr;
                    824:     OSObject *         obj;
                    825:     OSDictionary *     dict;
                    826: 
                    827:     obj = OSUnserializeXML( matching );
                    828: 
                    829:     if( (dict = OSDynamicCast( OSDictionary, obj))) {
                    830:         *matches = service->passiveMatch( dict );
                    831:        kr = kIOReturnSuccess;
                    832:     } else
                    833:        kr = kIOReturnBadArgument;
                    834: 
                    835:     if( obj)
                    836:         obj->release();
                    837: 
                    838:     return( kr );
                    839: }
                    840: 
                    841: /* Routine io_service_get_matching_services */
                    842: kern_return_t is_io_service_get_matching_services(
                    843:        mach_port_t master_port,
                    844:        io_string_t matching,
                    845:        io_iterator_t *existing )
                    846: {
                    847:     kern_return_t      kr;
                    848:     OSObject *         obj;
                    849:     OSDictionary *     dict;
                    850: 
                    851:     if( master_port != master_device_port)
                    852:         return( kIOReturnNotPrivileged);
                    853: 
                    854:     obj = OSUnserializeXML( matching );
                    855: 
                    856:     if( (dict = OSDynamicCast( OSDictionary, obj))) {
                    857:        makeMatchingCompatible( dict ); // temp for binary compatibility
                    858:         *existing = IOService::getMatchingServices( dict );
                    859:        kr = kIOReturnSuccess;
                    860:     } else
                    861:        kr = kIOReturnBadArgument;
                    862: 
                    863:     if( obj)
                    864:         obj->release();
                    865: 
                    866:     return( kr );
                    867: }
                    868: 
                    869: /* Routine io_service_add_notification */
                    870: kern_return_t is_io_service_add_notification(
                    871:        mach_port_t master_port,
                    872:        io_name_t notification_type,
                    873:        io_string_t matching,
                    874:        mach_port_t port,
                    875:        io_async_ref_t reference,
                    876:        mach_msg_type_number_t referenceCnt,
                    877:        io_object_t * notification )
                    878: {
                    879: 
                    880:     IOServiceUserNotification *        userNotify = 0;
                    881:     IONotifier *               notify = 0;
                    882:     const OSSymbol *           sym;
                    883:     OSDictionary *             dict;
                    884:     IOReturn                   err;
                    885:     unsigned long int          userMsgType;
                    886: 
                    887: 
                    888:     if( master_port != master_device_port)
                    889:         return( kIOReturnNotPrivileged);
                    890: 
                    891:     do {
                    892:         err = kIOReturnNoResources;
                    893: 
                    894:         if( !(sym = OSSymbol::withCString( notification_type )))
                    895:            err = kIOReturnNoResources;
                    896: 
                    897:         if( !(dict = OSDynamicCast( OSDictionary,
                    898:                     OSUnserializeXML( matching )))) {
                    899:             err = kIOReturnBadArgument;
                    900:            continue;
                    901:        }
                    902:        makeMatchingCompatible( dict ); // temp for binary compatibility
                    903: 
                    904:        if( (sym == gIOPublishNotification)
                    905:         || (sym == gIOFirstPublishNotification))
                    906:            userMsgType = kIOServicePublishNotificationType;
                    907:        else if( (sym == gIOMatchedNotification)
                    908:              || (sym == gIOFirstMatchNotification))
                    909:            userMsgType = kIOServiceMatchedNotificationType;
                    910:        else if( sym == gIOTerminatedNotification)
                    911:            userMsgType = kIOServiceTerminatedNotificationType;
                    912:        else
                    913:            userMsgType = kLastIOKitNotificationType;
                    914: 
                    915:         userNotify = new IOServiceUserNotification;
                    916: 
                    917:         if( userNotify && !userNotify->init( port, userMsgType,
                    918:                                              reference)) {
                    919:             userNotify->release();
                    920:             userNotify = 0;
                    921:         }
                    922:         if( !userNotify)
                    923:            continue;
                    924: 
                    925:         notify = IOService::addNotification( sym, dict,
                    926:                                              &userNotify->_handler, userNotify );
                    927:        if( notify) {
                    928:             dict = 0;
                    929:             *notification = userNotify;
                    930:            userNotify->setNotification( notify );
                    931:            err = kIOReturnSuccess;
                    932:        } else
                    933:            err = kIOReturnUnsupported;
                    934: 
                    935:     } while( false );
                    936: 
                    937:     if( sym)
                    938:        sym->release();
                    939:     if( dict)
                    940:        dict->release();
                    941: 
                    942:     return( err );
                    943: }
                    944: 
                    945: /* Routine io_service_add_notification_old */
                    946: kern_return_t is_io_service_add_notification_old(
                    947:        mach_port_t master_port,
                    948:        io_name_t notification_type,
                    949:        io_string_t matching,
                    950:        mach_port_t port,
                    951:        natural_t ref,
                    952:        io_object_t * notification )
                    953: {
                    954:     return( is_io_service_add_notification( master_port, notification_type,
                    955:             matching, port, &ref, 1, notification ));
                    956: }
                    957: 
                    958: /* Routine io_service_add_message_notification */
                    959: kern_return_t is_io_service_add_interest_notification(
                    960:         io_object_t _service,
                    961:         io_name_t type_of_interest,
                    962:         mach_port_t port,
                    963:        io_async_ref_t reference,
                    964:        mach_msg_type_number_t referenceCnt,
                    965:         io_object_t * notification )
                    966: {
                    967: 
                    968:     IOServiceMessageUserNotification * userNotify = 0;
                    969:     IONotifier *                       notify = 0;
                    970:     const OSSymbol *                   sym;
                    971:     IOReturn                           err;
                    972: 
                    973:     CHECK( IOService, _service, service );
                    974: 
                    975:     err = kIOReturnNoResources;
                    976:     if( (sym = OSSymbol::withCString( type_of_interest ))) do {
                    977: 
                    978:         userNotify = new IOServiceMessageUserNotification;
                    979: 
                    980:         if( userNotify && !userNotify->init( port, kIOServiceMessageNotificationType,
                    981:                                              reference, kIOUserNotifyMaxMessageSize )) {
                    982:             userNotify->release();
                    983:             userNotify = 0;
                    984:         }
                    985:         if( !userNotify)
                    986:             continue;
                    987: 
                    988:         notify = service->registerInterest( sym,
                    989:                                     &userNotify->_handler, userNotify );
                    990:         if( notify) {
                    991:             *notification = userNotify;
                    992:             userNotify->setNotification( notify );
                    993:             err = kIOReturnSuccess;
                    994:         } else
                    995:             err = kIOReturnUnsupported;
                    996: 
                    997:     } while( false );
                    998: 
                    999:     return( err );
                   1000: }
                   1001: 
                   1002: /* Routine io_service_acknowledge_notification */
                   1003: kern_return_t is_io_service_acknowledge_notification(
                   1004:        io_object_t _service,
                   1005:        natural_t notify_ref,
                   1006:        natural_t response )
                   1007: {
                   1008:     CHECK( IOService, _service, service );
                   1009: 
                   1010:     return( service->acknowledgeNotification( (IONotificationRef) notify_ref,
                   1011:                                               (IOOptionBits) response ));
                   1012:     
                   1013: }
                   1014: 
                   1015: /* Routine io_connect_get_semaphore */
                   1016: kern_return_t is_io_connect_get_notification_semaphore(
                   1017:        io_connect_t connection,
                   1018:        natural_t notification_type,
                   1019:        semaphore_t *semaphore )
                   1020: {
                   1021:     CHECK( IOUserClient, connection, client );
                   1022: 
                   1023:     return( client->getNotificationSemaphore( (UInt32) notification_type,
                   1024:                                               semaphore ));
                   1025: }
                   1026: 
                   1027: /* Routine io_registry_get_root_entry */
                   1028: kern_return_t is_io_registry_get_root_entry(
                   1029:        mach_port_t master_port,
                   1030:        io_object_t *root )
                   1031: {
                   1032:     IORegistryEntry *  entry;
                   1033: 
                   1034:     if( master_port != master_device_port)
                   1035:         return( kIOReturnNotPrivileged);
                   1036: 
                   1037:     entry = IORegistryEntry::getRegistryRoot();
                   1038:     if( entry)
                   1039:        entry->retain();
                   1040:     *root = entry;
                   1041: 
                   1042:     return( kIOReturnSuccess );
                   1043: }
                   1044: 
                   1045: /* Routine io_registry_create_iterator */
                   1046: kern_return_t is_io_registry_create_iterator(
                   1047:        mach_port_t master_port,
                   1048:        io_name_t plane,
                   1049:        int options,
                   1050:        io_object_t *iterator )
                   1051: {
                   1052:     if( master_port != master_device_port)
                   1053:         return( kIOReturnNotPrivileged);
                   1054: 
                   1055:     *iterator = IORegistryIterator::iterateOver(
                   1056:        IORegistryEntry::getPlane( plane ), options );
                   1057: 
                   1058:     return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
                   1059: }
                   1060: 
                   1061: /* Routine io_registry_entry_create_iterator */
                   1062: kern_return_t is_io_registry_entry_create_iterator(
                   1063:        io_object_t registry_entry,
                   1064:        io_name_t plane,
                   1065:        int options,
                   1066:        io_object_t *iterator )
                   1067: {
                   1068:     CHECK( IORegistryEntry, registry_entry, entry );
                   1069: 
                   1070:     *iterator = IORegistryIterator::iterateOver( entry,
                   1071:        IORegistryEntry::getPlane( plane ), options );
                   1072: 
                   1073:     return( *iterator ? kIOReturnSuccess : kIOReturnBadArgument );
                   1074: }
                   1075: 
                   1076: /* Routine io_registry_iterator_enter */
                   1077: kern_return_t is_io_registry_iterator_enter_entry(
                   1078:        io_object_t iterator )
                   1079: {
                   1080:     CHECK( IORegistryIterator, iterator, iter );
                   1081: 
                   1082:     iter->enterEntry();
                   1083: 
                   1084:     return( kIOReturnSuccess );
                   1085: }
                   1086: 
                   1087: /* Routine io_registry_iterator_exit */
                   1088: kern_return_t is_io_registry_iterator_exit_entry(
                   1089:        io_object_t iterator )
                   1090: {
                   1091:     bool       didIt;
                   1092: 
                   1093:     CHECK( IORegistryIterator, iterator, iter );
                   1094: 
                   1095:     didIt = iter->exitEntry();
                   1096: 
                   1097:     return( didIt ? kIOReturnSuccess : kIOReturnNoDevice );
                   1098: }
                   1099: 
                   1100: /* Routine io_registry_entry_from_path */
                   1101: kern_return_t is_io_registry_entry_from_path(
                   1102:        mach_port_t master_port,
                   1103:        io_string_t path,
                   1104:        io_object_t *registry_entry )
                   1105: {
                   1106:     IORegistryEntry *  entry;
                   1107: 
                   1108:     if( master_port != master_device_port)
                   1109:         return( kIOReturnNotPrivileged);
                   1110: 
                   1111:     entry = IORegistryEntry::fromPath( path );
                   1112: 
                   1113:     *registry_entry = entry;
                   1114: 
                   1115:     return( kIOReturnSuccess );
                   1116: }
                   1117: 
                   1118: /* Routine io_registry_entry_in_plane */
                   1119: kern_return_t is_io_registry_entry_in_plane(
                   1120:        io_object_t registry_entry,
                   1121:        io_name_t plane,
                   1122:        boolean_t *inPlane )
                   1123: {
                   1124:     CHECK( IORegistryEntry, registry_entry, entry );
                   1125: 
                   1126:     *inPlane = entry->inPlane( IORegistryEntry::getPlane( plane ));
                   1127: 
                   1128:     return( kIOReturnSuccess );
                   1129: }
                   1130: 
                   1131: 
                   1132: /* Routine io_registry_entry_get_path */
                   1133: kern_return_t is_io_registry_entry_get_path(
                   1134:        io_object_t registry_entry,
                   1135:        io_name_t plane,
                   1136:        io_string_t path )
                   1137: {
                   1138:     int                length;
                   1139:     CHECK( IORegistryEntry, registry_entry, entry );
                   1140: 
                   1141:     length = sizeof( io_string_t);
                   1142:     if( entry->getPath( path, &length, IORegistryEntry::getPlane( plane )))
                   1143:        return( kIOReturnSuccess );
                   1144:     else
                   1145:        return( kIOReturnBadArgument );
                   1146: }
                   1147: 
                   1148: 
                   1149: /* Routine io_registry_entry_get_name */
                   1150: kern_return_t is_io_registry_entry_get_name(
                   1151:        io_object_t registry_entry,
                   1152:        io_name_t name )
                   1153: {
                   1154:     CHECK( IORegistryEntry, registry_entry, entry );
                   1155: 
                   1156:     strncpy( name, entry->getName(), sizeof( io_name_t));
                   1157: 
                   1158:     return( kIOReturnSuccess );
                   1159: }
                   1160: 
                   1161: /* Routine io_registry_entry_get_name_in_plane */
                   1162: kern_return_t is_io_registry_entry_get_name_in_plane(
                   1163:        io_object_t registry_entry,
                   1164:        io_name_t plane,
                   1165:        io_name_t name )
                   1166: {
                   1167:     CHECK( IORegistryEntry, registry_entry, entry );
                   1168: 
                   1169:     strncpy( name, entry->getName( IORegistryEntry::getPlane( plane )),
                   1170:                sizeof( io_name_t));
                   1171: 
                   1172:     return( kIOReturnSuccess );
                   1173: }
                   1174: 
                   1175: // Create a vm_map_copy_t or kalloc'ed data for memory
                   1176: // to be copied out. ipc will free after the copyout.
                   1177: 
                   1178: static kern_return_t copyoutkdata( void * data, vm_size_t len,
                   1179:                                     io_buf_ptr_t * buf )
                   1180: {
                   1181:     kern_return_t      err;
                   1182:     void *             kdata;
                   1183:     vm_map_copy_t      copy;
                   1184:     bool               ool;
                   1185: 
                   1186:     ool = (len >= msg_ool_size_small);
                   1187: 
                   1188:     if( ool ) {
                   1189: 
                   1190:        err = vm_allocate( kernel_map, (vm_offset_t *) &kdata, len, true );
                   1191:        assert( err == KERN_SUCCESS );
                   1192:        if( err)
                   1193:            return( err );
                   1194: 
                   1195:         bcopy( data, kdata, len );
                   1196: 
                   1197:        err = vm_map_copyin( kernel_map, (vm_offset_t) kdata, len,
                   1198:                        true /* src_destroy */, &copy);
                   1199: 
                   1200:        assert( err == KERN_SUCCESS );
                   1201:        if( err == KERN_SUCCESS )
                   1202:             *buf = (char *) copy;
                   1203:        else
                   1204:            vm_deallocate( kernel_map, (vm_offset_t ) kdata, len );
                   1205: 
                   1206:     } else {
                   1207: 
                   1208:         kdata = (void *) kalloc( len );
                   1209:         assert( kdata );
                   1210:        if( kdata) {
                   1211:             *buf = (char *) kdata;
                   1212:             bcopy( data, kdata, len );
                   1213:            err = kIOReturnSuccess;
                   1214:        } else
                   1215:            err = kIOReturnNoMemory;
                   1216:     }
                   1217: 
                   1218:     return( err );
                   1219: }
                   1220: 
                   1221: 
                   1222: /* Routine io_registry_entry_get_properties */
                   1223: kern_return_t is_io_registry_entry_get_properties(
                   1224:        io_object_t registry_entry,
                   1225:        io_buf_ptr_t *properties,
                   1226:        mach_msg_type_number_t *propertiesCnt )
                   1227: {
                   1228:     kern_return_t      err;
                   1229:     vm_size_t          len;
                   1230: 
                   1231:     CHECK( IORegistryEntry, registry_entry, entry );
                   1232: 
                   1233:     OSSerialize * s = OSSerialize::withCapacity(4096);
                   1234: 
                   1235:     if( !s)
                   1236:        return( kIOReturnNoMemory );
                   1237: 
                   1238:     s->clearText();
                   1239: 
                   1240:     if( entry->serializeProperties( s )) {
                   1241:         len = s->getLength();
                   1242:         *propertiesCnt = len;
                   1243:         err = copyoutkdata( s->text(), len, properties );
                   1244: 
                   1245:     } else
                   1246:         err = kIOReturnUnsupported;
                   1247: 
                   1248:         s->release();
                   1249: 
                   1250:     return( err );
                   1251: }
                   1252: 
                   1253: /* Routine io_registry_entry_set_properties */
                   1254: kern_return_t is_io_registry_entry_set_properties
                   1255: (
                   1256:        io_object_t registry_entry,
                   1257:        io_buf_ptr_t properties,
                   1258:        mach_msg_type_number_t propertiesCnt
                   1259: )
                   1260: {
                   1261:     OSObject * obj;
                   1262:     IOReturn   err;
                   1263:     vm_offset_t data;
                   1264: 
                   1265:     CHECK( IORegistryEntry, registry_entry, entry );
                   1266: 
                   1267:     err = vm_map_copyout( kernel_map, &data, (vm_map_copy_t) properties );
                   1268: 
                   1269:     if( KERN_SUCCESS == err) {
                   1270: 
                   1271:         obj = OSUnserializeXML( (const char *) data );
                   1272:        vm_deallocate( kernel_map, data, propertiesCnt );
                   1273: 
                   1274:         if( obj) {
                   1275:             err = entry->setProperties( obj );
                   1276:             obj->release();
                   1277:         } else
                   1278:             err = kIOReturnBadArgument;
                   1279:     }
                   1280: 
                   1281:     return( err );
                   1282: }
                   1283: 
                   1284: 
                   1285: /* Routine io_registry_entry_get_property */
                   1286: kern_return_t is_io_registry_entry_get_property(
                   1287:        io_object_t registry_entry,
                   1288:        io_name_t property_name,
                   1289:        io_scalar_inband_t buf,
                   1290:        mach_msg_type_number_t *dataCnt )
                   1291: {
                   1292:     OSObject   *       obj;
                   1293:     OSData     *       data;
                   1294:     OSString   *       str;
                   1295:     OSBoolean  *       boo;
                   1296:     OSNumber   *       off;
                   1297:     UInt64             offsetBytes;
                   1298:     unsigned int       len = 0;
                   1299:     const void *       bytes = 0;
                   1300:     IOReturn           ret = kIOReturnSuccess;
                   1301: 
                   1302:     CHECK( IORegistryEntry, registry_entry, entry );
                   1303: 
                   1304:     obj = entry->getProperty( property_name );
                   1305:     if( !obj)
                   1306:         return( kIOReturnNoResources );
                   1307: 
                   1308:     // One day OSData will be a common container base class
                   1309:     // until then...
                   1310:     if( (data = OSDynamicCast( OSData, obj ))) {
                   1311:        len = data->getLength();
                   1312:        bytes = data->getBytesNoCopy();
                   1313: 
                   1314:     } else if( (str = OSDynamicCast( OSString, obj ))) {
                   1315:        len = str->getLength() + 1;
                   1316:        bytes = str->getCStringNoCopy();
                   1317: 
                   1318:     } else if( (boo = OSDynamicCast( OSBoolean, obj ))) {
                   1319:        len = boo->isTrue() ? sizeof("Yes") : sizeof("No");
                   1320:        bytes = boo->isTrue() ? "Yes" : "No";
                   1321: 
                   1322:     } else if( (off = OSDynamicCast( OSNumber, obj ))) {
                   1323:        offsetBytes = off->unsigned64BitValue();
                   1324:        len = off->numberOfBytes();
                   1325:        bytes = &offsetBytes;
                   1326: #if __BIG_ENDIAN__
                   1327:        bytes = (const void *)
                   1328:                (((UInt32) bytes) + (sizeof( UInt64) - len));
                   1329: #endif
                   1330: 
                   1331:     } else
                   1332:        ret = kIOReturnBadArgument;
                   1333: 
                   1334:     if( bytes) {
                   1335:        if( *dataCnt < len)
                   1336:            ret = kIOReturnIPCError;
                   1337:        else {
                   1338:             *dataCnt = len;
                   1339:             bcopy( bytes, buf, len );
                   1340:        }
                   1341:     }
                   1342: 
                   1343:     return( ret );
                   1344: }
                   1345: 
                   1346: 
                   1347: /* Routine io_registry_entry_get_child_iterator */
                   1348: kern_return_t is_io_registry_entry_get_child_iterator(
                   1349:        io_object_t registry_entry,
                   1350:        io_name_t plane,
                   1351:        io_object_t *iterator )
                   1352: {
                   1353:     CHECK( IORegistryEntry, registry_entry, entry );
                   1354: 
                   1355:     *iterator = entry->getChildIterator(
                   1356:        IORegistryEntry::getPlane( plane ));
                   1357: 
                   1358:     return( kIOReturnSuccess );
                   1359: }
                   1360: 
                   1361: /* Routine io_registry_entry_get_parent_iterator */
                   1362: kern_return_t is_io_registry_entry_get_parent_iterator(
                   1363:        io_object_t registry_entry,
                   1364:        io_name_t plane,
                   1365:        io_object_t *iterator)
                   1366: {
                   1367:     CHECK( IORegistryEntry, registry_entry, entry );
                   1368: 
                   1369:     *iterator = entry->getParentIterator(
                   1370:        IORegistryEntry::getPlane( plane ));
                   1371: 
                   1372:     return( kIOReturnSuccess );
                   1373: }
                   1374: 
                   1375: /* Routine io_service_get_busy_state */
                   1376: kern_return_t is_io_service_get_busy_state(
                   1377:        io_object_t _service,
                   1378:        int *busyState )
                   1379: {
                   1380:     CHECK( IOService, _service, service );
                   1381: 
                   1382:     *busyState = service->getBusyState();
                   1383: 
                   1384:     return( kIOReturnSuccess );
                   1385: }
                   1386: 
                   1387: /* Routine io_service_wait_quiet */
                   1388: kern_return_t is_io_service_wait_quiet(
                   1389:        io_object_t _service,
                   1390:        mach_timespec_t wait_time )
                   1391: {
                   1392:     CHECK( IOService, _service, service );
                   1393: 
                   1394:     return( service->waitQuiet( &wait_time ));
                   1395: }
                   1396: 
                   1397: /* Routine io_service_request_probe */
                   1398: kern_return_t is_io_service_request_probe(
                   1399:        io_object_t _service,
                   1400:        int options )
                   1401: {
                   1402:     CHECK( IOService, _service, service );
                   1403: 
                   1404:     return( service->requestProbe( options ));
                   1405: }
                   1406: 
                   1407: 
                   1408: /* Routine io_service_open */
                   1409: kern_return_t is_io_service_open(
                   1410:        io_object_t _service,
                   1411:        task_t owningTask,
                   1412:        int connect_type,
                   1413:        io_object_t *connection )
                   1414: {
                   1415:     IOUserClient       *       client;
                   1416:     IOReturn                   err;
                   1417:     unsigned int               token[2];
                   1418: 
                   1419:     CHECK( IOService, _service, service );
                   1420: 
                   1421:     err = service->newUserClient( owningTask, token,
                   1422:                connect_type, &client );
                   1423: 
                   1424:     if( err == kIOReturnSuccess) {
                   1425:        assert( OSDynamicCast(IOUserClient, client) );
                   1426:        *connection = client;
                   1427:     }
                   1428: 
                   1429:     return( err);
                   1430: }
                   1431: 
                   1432: /* Routine io_service_close */
                   1433: kern_return_t is_io_service_close(
                   1434:        io_object_t connection )
                   1435: {
                   1436:     CHECK( IOUserClient, connection, client );
                   1437: 
                   1438:     client->clientClose();
                   1439: 
                   1440:     return( kIOReturnSuccess );
                   1441: }
                   1442: 
                   1443: /* Routine io_connect_get_service */
                   1444: kern_return_t is_io_connect_get_service(
                   1445:        io_object_t connection,
                   1446:        io_object_t *service )
                   1447: {
                   1448:     IOService * theService;
                   1449: 
                   1450:     CHECK( IOUserClient, connection, client );
                   1451: 
                   1452:     theService = client->getService();
                   1453:     if( theService)
                   1454:        theService->retain();
                   1455: 
                   1456:     *service = theService;
                   1457: 
                   1458:     return( theService ? kIOReturnSuccess : kIOReturnUnsupported );
                   1459: }
                   1460: 
                   1461: /* Routine io_connect_set_notification_port */
                   1462: kern_return_t is_io_connect_set_notification_port(
                   1463:        io_object_t connection,
                   1464:        int notification_type,
                   1465:        mach_port_t port,
                   1466:        int reference)
                   1467: {
                   1468:     CHECK( IOUserClient, connection, client );
                   1469: 
                   1470:     return( client->registerNotificationPort( port, notification_type,
                   1471:                                                reference ));
                   1472: }
                   1473: 
                   1474: kern_return_t is_io_connect_map_memory(
                   1475:        io_object_t     connect,
                   1476:        int             type,
                   1477:        task_t          task,
                   1478:        vm_address_t *  mapAddr,
                   1479:        vm_size_t    *  mapSize,
                   1480:        int             flags )
                   1481: {
                   1482:     IOReturn           err;
                   1483:     IOMemoryMap *      map;
                   1484:     mach_port_name_t   name;
                   1485: 
                   1486:     CHECK( IOUserClient, connect, client );
                   1487: 
                   1488:     map = client->mapClientMemory( type, task, flags, *mapAddr );
                   1489: 
                   1490:     if( map) {
                   1491:         *mapAddr = map->getVirtualAddress();
                   1492:         if( mapSize)
                   1493:             *mapSize = map->getLength();
                   1494:         // push a name out to the task owning the map,
                   1495:         // so we can clean up maps
                   1496:         name = IOMachPort::makeSendRightForTask( task, map, IKOT_IOKIT_OBJECT );
                   1497:         assert( name );
                   1498:        err = kIOReturnSuccess;
                   1499: 
                   1500:     } else
                   1501:        err = kIOReturnBadArgument;
                   1502: 
                   1503:     return( err );
                   1504: }
                   1505: 
                   1506: /* Routine io_connect_add_client */
                   1507: kern_return_t is_io_connect_add_client(
                   1508:        io_object_t connection,
                   1509:        io_object_t connect_to)
                   1510: {
                   1511:     CHECK( IOUserClient, connection, client );
                   1512:     CHECK( IOUserClient, connect_to, to );
                   1513: 
                   1514:     return( client->connectClient( to ) );
                   1515: }
                   1516: 
                   1517: 
                   1518: /* Routine io_connect_set_properties */
                   1519: kern_return_t is_io_connect_set_properties(
                   1520:        io_object_t connection,
                   1521:        io_buf_ptr_t properties,
                   1522:        mach_msg_type_number_t propertiesCnt )
                   1523: {
                   1524:     return( is_io_registry_entry_set_properties( connection, properties, propertiesCnt ));
                   1525: }
                   1526: 
                   1527: 
                   1528: /* Routine io_connect_method_scalarI_scalarO */
                   1529: kern_return_t is_io_connect_method_scalarI_scalarO(
                   1530:        io_object_t     connect,
                   1531:        UInt32          index,
                   1532:         void *         input[],
                   1533:         IOByteCount    inputCount,
                   1534:         void *         output[],
                   1535:         IOByteCount *  outputCount )
                   1536: {
                   1537:     IOReturn           err;
                   1538:     IOExternalMethod * method;
                   1539:     IOService *                object;
                   1540:     IOMethod           func;
                   1541: 
                   1542:     CHECK( IOUserClient, connect, client);
                   1543:     if( (method = client->getExternalMethodForIndex(index))) {
                   1544:       do {
                   1545:         err = kIOReturnBadArgument;
                   1546:        if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
                   1547:            continue;
                   1548:        if( inputCount != method->count0)
                   1549:            continue;
                   1550:        if( *outputCount != method->count1)
                   1551:            continue;
                   1552: 
                   1553:        func = method->func;
                   1554:        object = method->object;
                   1555: 
                   1556:        switch( inputCount) {
                   1557: 
                   1558:            case 6:
                   1559:                err = (object->*func)(  input[0], input[1], input[2],
                   1560:                                        input[3], input[4], input[5] );
                   1561:                break;
                   1562:            case 5:
                   1563:                err = (object->*func)(  input[0], input[1], input[2],
                   1564:                                        input[3], input[4], 
                   1565:                                        &output[0] );
                   1566:                break;
                   1567:            case 4:
                   1568:                err = (object->*func)(  input[0], input[1], input[2],
                   1569:                                        input[3],
                   1570:                                        &output[0], &output[1] );
                   1571:                break;
                   1572:            case 3:
                   1573:                err = (object->*func)(  input[0], input[1], input[2],
                   1574:                                        &output[0], &output[1], &output[2] );
                   1575:                break;
                   1576:            case 2:
                   1577:                err = (object->*func)(  input[0], input[1],
                   1578:                                        &output[0], &output[1], &output[2],
                   1579:                                        &output[3] );
                   1580:                break;
                   1581:            case 1:
                   1582:                err = (object->*func)(  input[0],
                   1583:                                        &output[0], &output[1], &output[2],
                   1584:                                        &output[3], &output[4] );
                   1585:                break;
                   1586:            case 0:
                   1587:                err = (object->*func)(  &output[0], &output[1], &output[2],
                   1588:                                        &output[3], &output[4], &output[5] );
                   1589:                break;
                   1590: 
                   1591:            default:
                   1592:                IOLog("%s: Bad method table\n", client->getName());
                   1593:        }
                   1594:       } while( false);
                   1595: 
                   1596:     } else
                   1597:         err = kIOReturnUnsupported;
                   1598: 
                   1599:     return( err);
                   1600: }
                   1601: 
                   1602: /* Routine io_connect_method_scalarI_structureO */
                   1603: kern_return_t is_io_connect_method_scalarI_structureO(
                   1604:        io_object_t     connect,
                   1605:        UInt32          index,
                   1606:         void *         input[],
                   1607:         IOByteCount    inputCount,
                   1608:         void *         output,
                   1609:         IOByteCount *  outputCount )
                   1610: {
                   1611:     IOReturn           err;
                   1612:     IOExternalMethod * method;
                   1613:     IOService *                object;
                   1614:     IOMethod           func;
                   1615: 
                   1616:     CHECK( IOUserClient, connect, client);
                   1617: 
                   1618:     if( (method = client->getExternalMethodForIndex(index))) {
                   1619:       do {
                   1620:         err = kIOReturnBadArgument;
                   1621:        if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
                   1622:            continue;
                   1623:        if( inputCount != method->count0)
                   1624:            continue;
                   1625:        if( (0xffffffff != method->count1)
                   1626:                && (*outputCount != method->count1))
                   1627:            continue;
                   1628: 
                   1629:        func = method->func;
                   1630:        object = method->object;
                   1631: 
                   1632:        switch( inputCount) {
                   1633: 
                   1634:            case 5:
                   1635:                err = (object->*func)(  input[0], input[1], input[2],
                   1636:                                         input[3], input[4],
                   1637:                                         output );
                   1638:                break;
                   1639:            case 4:
                   1640:                err = (object->*func)(  input[0], input[1], input[2],
                   1641:                                        input[3],
                   1642:                                        output, (void *)outputCount );
                   1643:                break;
                   1644:            case 3:
                   1645:                err = (object->*func)(  input[0], input[1], input[2],
                   1646:                                        output, (void *)outputCount, 0 );
                   1647:                break;
                   1648:            case 2:
                   1649:                err = (object->*func)(  input[0], input[1],
                   1650:                                        output, (void *)outputCount, 0, 0 );
                   1651:                break;
                   1652:            case 1:
                   1653:                err = (object->*func)(  input[0],
                   1654:                                        output, (void *)outputCount, 0, 0, 0 );
                   1655:                break;
                   1656:            case 0:
                   1657:                err = (object->*func)(  output, (void *)outputCount, 0, 0, 0, 0 );
                   1658:                break;
                   1659: 
                   1660:            default:
                   1661:                IOLog("%s: Bad method table\n", client->getName());
                   1662:        }
                   1663:       } while( false);
                   1664: 
                   1665:     } else
                   1666:         err = kIOReturnUnsupported;
                   1667: 
                   1668:     return( err);
                   1669: }
                   1670: 
                   1671: /* Routine io_connect_method_scalarI_structureI */
                   1672: kern_return_t is_io_connect_method_scalarI_structureI(
                   1673:        io_connect_t    connect,
                   1674:        UInt32          index,
                   1675:         void *         input[],
                   1676:         IOByteCount    inputCount,
                   1677:         UInt8 *                inputStruct,
                   1678:         IOByteCount    inputStructCount )
                   1679: {
                   1680:     IOReturn           err;
                   1681:     IOExternalMethod * method;
                   1682:     IOService *                object;
                   1683:     IOMethod           func;
                   1684: 
                   1685:     CHECK( IOUserClient, connect, client);
                   1686: 
                   1687:     if( (method = client->getExternalMethodForIndex(index))) {
                   1688:       do {
                   1689:         err = kIOReturnBadArgument;
                   1690:        if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
                   1691:            continue;
                   1692:        if( (0xffffffff != method->count0)
                   1693:                && (inputCount != method->count0))
                   1694:            continue;
                   1695:        if( (0xffffffff != method->count1)
                   1696:                && (inputStructCount != method->count1))
                   1697:            continue;
                   1698: 
                   1699:        func = method->func;
                   1700:        object = method->object;
                   1701: 
                   1702:        switch( inputCount) {
                   1703: 
                   1704:            case 5:
                   1705:                err = (object->*func)( input[0], input[1], input[2],
                   1706:                                        input[3], input[4], 
                   1707:                                        inputStruct );
                   1708:                break;
                   1709:            case 4:
                   1710:                err = (object->*func)( input[0], input[1], input[2],
                   1711:                                        input[3],
                   1712:                                        inputStruct, (void *)inputStructCount );
                   1713:                break;
                   1714:            case 3:
                   1715:                err = (object->*func)( input[0], input[1], input[2],
                   1716:                                        inputStruct, (void *)inputStructCount,
                   1717:                                        0 );
                   1718:                break;
                   1719:            case 2:
                   1720:                err = (object->*func)( input[0], input[1],
                   1721:                                        inputStruct, (void *)inputStructCount,
                   1722:                                        0, 0 );
                   1723:                break;
                   1724:            case 1:
                   1725:                err = (object->*func)( input[0],
                   1726:                                        inputStruct, (void *)inputStructCount,
                   1727:                                        0, 0, 0 );
                   1728:                break;
                   1729:            case 0:
                   1730:                err = (object->*func)( inputStruct, (void *)inputStructCount,
                   1731:                                        0, 0, 0, 0 );
                   1732:                break;
                   1733: 
                   1734:            default:
                   1735:                IOLog("%s: Bad method table\n", client->getName());
                   1736:        }
                   1737:       } while( false);
                   1738: 
                   1739:     } else
                   1740:         err = kIOReturnUnsupported;
                   1741: 
                   1742:     return( err);
                   1743: }
                   1744: 
                   1745: /* Routine io_connect_method_structureI_structureO */
                   1746: kern_return_t is_io_connect_method_structureI_structureO(
                   1747:        io_object_t     connect,
                   1748:        UInt32          index,
                   1749:         UInt8 *                input,
                   1750:         IOByteCount    inputCount,
                   1751:         UInt8 *                output,
                   1752:         IOByteCount *  outputCount )
                   1753: {
                   1754:     IOReturn           err;
                   1755:     IOExternalMethod * method;
                   1756:     IOService *                object;
                   1757:     IOMethod           func;
                   1758: 
                   1759:     CHECK( IOUserClient, connect, client);
                   1760: 
                   1761:     if( (method = client->getExternalMethodForIndex(index))) {
                   1762:       do {
                   1763:         err = kIOReturnBadArgument;
                   1764:        if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
                   1765:            continue;
                   1766:        if( (0xffffffff != method->count0)
                   1767:                && (inputCount != method->count0))
                   1768:            continue;
                   1769:        if( (0xffffffff != method->count1)
                   1770:                && (*outputCount != method->count1))
                   1771:            continue;
                   1772: 
                   1773:        func = method->func;
                   1774:        object = method->object;
                   1775: 
                   1776:        if( method->count1) {
                   1777:            if( method->count0) {
                   1778:                err = (object->*func)( input, output,
                   1779:                                        (void *)inputCount, outputCount, 0, 0 );
                   1780:            } else {
                   1781:                err = (object->*func)( output, outputCount, 0, 0, 0, 0 );
                   1782:            }
                   1783:        } else {
                   1784:                err = (object->*func)( input, (void *)inputCount, 0, 0, 0, 0 );
                   1785:        }
                   1786: 
                   1787:       } while( false);
                   1788: 
                   1789:     } else
                   1790:         err = kIOReturnUnsupported;
                   1791: 
                   1792:     return( err);
                   1793: }
                   1794: 
                   1795: kern_return_t is_io_async_method_scalarI_scalarO(
                   1796:         io_object_t    connect,
                   1797:         mach_port_t    wakePort,
                   1798:        io_async_ref_t          reference,
                   1799:        mach_msg_type_number_t  referenceCnt,
                   1800:         UInt32         index,
                   1801:         void *         input[],
                   1802:         IOByteCount    inputCount,
                   1803:         void *         output[],
                   1804:         IOByteCount *  outputCount )
                   1805: {
                   1806:     IOReturn           err;
                   1807:     IOExternalAsyncMethod *method;
                   1808:     IOService *                object;
                   1809:     IOAsyncMethod      func;
                   1810: 
                   1811:     CHECK( IOUserClient, connect, client);
                   1812:     if( (method = client->getExternalAsyncMethodForIndex(index))) {
                   1813:       do {
                   1814:         err = kIOReturnBadArgument;
                   1815:         if( kIOUCScalarIScalarO != (method->flags & kIOUCTypeMask))
                   1816:             continue;
                   1817:         if( inputCount != method->count0)
                   1818:             continue;
                   1819:         if( *outputCount != method->count1)
                   1820:             continue;
                   1821: 
                   1822:         reference[0] = (natural_t) wakePort;
                   1823:         func = method->func;
                   1824:         object = method->object;
                   1825: 
                   1826:         switch( inputCount) {
                   1827: 
                   1828:             case 6:
                   1829:                 err = (object->*func)( reference,
                   1830:                                         input[0], input[1], input[2],
                   1831:                                         input[3], input[4], input[5] );
                   1832:                 break;
                   1833:             case 5:
                   1834:                 err = (object->*func)(  reference,
                   1835:                                         input[0], input[1], input[2],
                   1836:                                         input[3], input[4],
                   1837:                                         &output[0] );
                   1838:                 break;
                   1839:             case 4:
                   1840:                 err = (object->*func)(  reference,
                   1841:                                         input[0], input[1], input[2],
                   1842:                                         input[3],
                   1843:                                         &output[0], &output[1] );
                   1844:                 break;
                   1845:             case 3:
                   1846:                 err = (object->*func)(  reference,
                   1847:                                         input[0], input[1], input[2],
                   1848:                                         &output[0], &output[1], &output[2] );
                   1849:                 break;
                   1850:             case 2:
                   1851:                 err = (object->*func)(  reference,
                   1852:                                         input[0], input[1],
                   1853:                                         &output[0], &output[1], &output[2],
                   1854:                                         &output[3] );
                   1855:                 break;
                   1856:             case 1:
                   1857:                 err = (object->*func)(  reference,
                   1858:                                         input[0],
                   1859:                                         &output[0], &output[1], &output[2],
                   1860:                                         &output[3], &output[4] );
                   1861:                 break;
                   1862:             case 0:
                   1863:                 err = (object->*func)(  reference,
                   1864:                                         &output[0], &output[1], &output[2],
                   1865:                                         &output[3], &output[4], &output[5] );
                   1866:                 break;
                   1867: 
                   1868:             default:
                   1869:                 IOLog("%s: Bad method table\n", client->getName());
                   1870:         }
                   1871:       } while( false);
                   1872: 
                   1873:     } else
                   1874:         err = kIOReturnUnsupported;
                   1875: 
                   1876:     return( err);
                   1877: }
                   1878: 
                   1879: kern_return_t is_io_async_method_scalarI_structureO(
                   1880:         io_object_t    connect,
                   1881:         mach_port_t    wakePort,
                   1882:        io_async_ref_t          reference,
                   1883:        mach_msg_type_number_t  referenceCnt,
                   1884:         UInt32         index,
                   1885:         void *         input[],
                   1886:         IOByteCount    inputCount,
                   1887:         void *         output,
                   1888:         IOByteCount *  outputCount )
                   1889: {
                   1890:     IOReturn           err;
                   1891:     IOExternalAsyncMethod *method;
                   1892:     IOService *                object;
                   1893:     IOAsyncMethod      func;
                   1894: 
                   1895:     CHECK( IOUserClient, connect, client);
                   1896: 
                   1897:     if( (method = client->getExternalAsyncMethodForIndex(index))) {
                   1898:       do {
                   1899:         err = kIOReturnBadArgument;
                   1900:         if( kIOUCScalarIStructO != (method->flags & kIOUCTypeMask))
                   1901:             continue;
                   1902:         if( inputCount != method->count0)
                   1903:             continue;
                   1904:         if( (0xffffffff != method->count1)
                   1905:                 && (*outputCount != method->count1))
                   1906:             continue;
                   1907: 
                   1908:         reference[0] = (natural_t) wakePort;
                   1909:         func = method->func;
                   1910:         object = method->object;
                   1911: 
                   1912:         switch( inputCount) {
                   1913: 
                   1914:             case 5:
                   1915:                 err = (object->*func)( reference,
                   1916:                                         input[0], input[1], input[2],
                   1917:                                         input[3], input[4],
                   1918:                                         output );
                   1919:                 break;
                   1920:             case 4:
                   1921:                 err = (object->*func)( reference,
                   1922:                                         input[0], input[1], input[2],
                   1923:                                         input[3],
                   1924:                                         output, (void *)outputCount );
                   1925:                 break;
                   1926:             case 3:
                   1927:                 err = (object->*func)( reference,
                   1928:                                         input[0], input[1], input[2],
                   1929:                                         output, (void *)outputCount, 0 );
                   1930:                 break;
                   1931:             case 2:
                   1932:                 err = (object->*func)( reference,
                   1933:                                         input[0], input[1],
                   1934:                                         output, (void *)outputCount, 0, 0 );
                   1935:                 break;
                   1936:             case 1:
                   1937:                 err = (object->*func)( reference,
                   1938:                                         input[0],
                   1939:                                         output, (void *)outputCount, 0, 0, 0 );
                   1940:                 break;
                   1941:             case 0:
                   1942:                 err = (object->*func)( reference,
                   1943:                                         output, (void *)outputCount, 0, 0, 0, 0 );
                   1944:                 break;
                   1945: 
                   1946:             default:
                   1947:                 IOLog("%s: Bad method table\n", client->getName());
                   1948:         }
                   1949:       } while( false);
                   1950: 
                   1951:     } else
                   1952:         err = kIOReturnUnsupported;
                   1953: 
                   1954:     return( err);
                   1955: }
                   1956: 
                   1957: kern_return_t is_io_async_method_scalarI_structureI(
                   1958:             io_connect_t       connect,
                   1959:             mach_port_t                wakePort,
                   1960:            io_async_ref_t          reference,
                   1961:            mach_msg_type_number_t  referenceCnt,
                   1962:             UInt32             index,
                   1963:             void *             input[],
                   1964:             IOByteCount        inputCount,
                   1965:             UInt8 *            inputStruct,
                   1966:             IOByteCount        inputStructCount )
                   1967: {
                   1968:     IOReturn           err;
                   1969:     IOExternalAsyncMethod *method;
                   1970:     IOService *                object;
                   1971:     IOAsyncMethod      func;
                   1972: 
                   1973:     CHECK( IOUserClient, connect, client);
                   1974: 
                   1975:     if( (method = client->getExternalAsyncMethodForIndex(index))) {
                   1976:       do {
                   1977:         err = kIOReturnBadArgument;
                   1978:         if( kIOUCScalarIStructI != (method->flags & kIOUCTypeMask))
                   1979:             continue;
                   1980:         if( (0xffffffff != method->count0)
                   1981:                 && (inputCount != method->count0))
                   1982:             continue;
                   1983:         if( (0xffffffff != method->count1)
                   1984:                 && (inputStructCount != method->count1))
                   1985:             continue;
                   1986: 
                   1987:         reference[0] = (natural_t) wakePort;
                   1988:         func = method->func;
                   1989:         object = method->object;
                   1990: 
                   1991:         switch( inputCount) {
                   1992: 
                   1993:             case 5:
                   1994:                 err = (object->*func)( reference,
                   1995:                                         input[0], input[1], input[2],
                   1996:                                         input[3], input[4],
                   1997:                                         inputStruct );
                   1998:                 break;
                   1999:             case 4:
                   2000:                 err = (object->*func)( reference,
                   2001:                                         input[0], input[1], input[2],
                   2002:                                         input[3],
                   2003:                                         inputStruct, (void *)inputStructCount );
                   2004:                 break;
                   2005:             case 3:
                   2006:                 err = (object->*func)( reference,
                   2007:                                         input[0], input[1], input[2],
                   2008:                                         inputStruct, (void *)inputStructCount,
                   2009:                                         0 );
                   2010:                 break;
                   2011:             case 2:
                   2012:                 err = (object->*func)( reference,
                   2013:                                         input[0], input[1],
                   2014:                                         inputStruct, (void *)inputStructCount,
                   2015:                                         0, 0 );
                   2016:                 break;
                   2017:             case 1:
                   2018:                 err = (object->*func)( reference,
                   2019:                                         input[0],
                   2020:                                         inputStruct, (void *)inputStructCount,
                   2021:                                         0, 0, 0 );
                   2022:                 break;
                   2023:             case 0:
                   2024:                 err = (object->*func)( reference,
                   2025:                                         inputStruct, (void *)inputStructCount,
                   2026:                                         0, 0, 0, 0 );
                   2027:                 break;
                   2028: 
                   2029:             default:
                   2030:                 IOLog("%s: Bad method table\n", client->getName());
                   2031:         }
                   2032:       } while( false);
                   2033: 
                   2034:     } else
                   2035:         err = kIOReturnUnsupported;
                   2036: 
                   2037:     return( err);
                   2038: }
                   2039: 
                   2040: kern_return_t is_io_async_method_structureI_structureO(
                   2041:         io_object_t    connect,
                   2042:         mach_port_t wakePort,
                   2043:        io_async_ref_t          reference,
                   2044:        mach_msg_type_number_t  referenceCnt,
                   2045:         UInt32         index,
                   2046:         UInt8 *                input,
                   2047:         IOByteCount    inputCount,
                   2048:         UInt8 *                output,
                   2049:         IOByteCount *  outputCount )
                   2050: {
                   2051:     IOReturn           err;
                   2052:     IOExternalAsyncMethod *method;
                   2053:     IOService *                object;
                   2054:     IOAsyncMethod      func;
                   2055: 
                   2056:     CHECK( IOUserClient, connect, client);
                   2057: 
                   2058:     if( (method = client->getExternalAsyncMethodForIndex(index))) {
                   2059:       do {
                   2060:         err = kIOReturnBadArgument;
                   2061:         if( kIOUCStructIStructO != (method->flags & kIOUCTypeMask))
                   2062:             continue;
                   2063:         if( (0xffffffff != method->count0)
                   2064:                 && (inputCount != method->count0))
                   2065:             continue;
                   2066:         if( (0xffffffff != method->count1)
                   2067:                 && (*outputCount != method->count1))
                   2068:             continue;
                   2069: 
                   2070:         reference[0] = (natural_t) wakePort;
                   2071:         func = method->func;
                   2072:         object = method->object;
                   2073: 
                   2074:         if( method->count1) {
                   2075:             if( method->count0) {
                   2076:                 err = (object->*func)( reference,
                   2077:                                        input, output,
                   2078:                                         (void *)inputCount, outputCount, 0, 0 );
                   2079:             } else {
                   2080:                 err = (object->*func)( reference,
                   2081:                                        output, outputCount, 0, 0, 0, 0 );
                   2082:             }
                   2083:         } else {
                   2084:                 err = (object->*func)( reference,
                   2085:                                        input, (void *)inputCount, 0, 0, 0, 0 );
                   2086:         }
                   2087: 
                   2088:       } while( false);
                   2089: 
                   2090:     } else
                   2091:         err = kIOReturnUnsupported;
                   2092: 
                   2093:     return( err);
                   2094: }
                   2095: /* Routine io_make_matching */
                   2096: kern_return_t is_io_make_matching(
                   2097:        mach_port_t     master_port,
                   2098:        UInt32          type,
                   2099:        IOOptionBits    options,
                   2100:         UInt8 *                input,
                   2101:         IOByteCount    inputCount,
                   2102:        io_string_t     matching )
                   2103: {
                   2104:     OSSerialize *      s;
                   2105:     IOReturn           err = kIOReturnSuccess;
                   2106:     OSDictionary *     dict;
                   2107: 
                   2108:     if( master_port != master_device_port)
                   2109:         return( kIOReturnNotPrivileged);
                   2110: 
                   2111:     switch( type) {
                   2112: 
                   2113:        case kIOServiceMatching:
                   2114:             dict = IOService::serviceMatching( gIOServiceKey );
                   2115:            break;
                   2116: 
                   2117:        case kIOBSDNameMatching:
                   2118:            dict = IOBSDNameMatching( (const char *) input );
                   2119:            break;
                   2120: 
                   2121:        case kIOOFPathMatching:
                   2122:            /* need to look up path, get device type,
                   2123:               call matching help based on device type */
                   2124:            dict = IODiskMatching( (const char *) input,
                   2125:                                     matching, sizeof( io_string_t));
                   2126:            break;
                   2127: 
                   2128:        default:
                   2129:            dict = 0;
                   2130:     }
                   2131: 
                   2132:     if( !dict)
                   2133:        return( kIOReturnUnsupported);
                   2134: 
                   2135:     do {
                   2136:         s = OSSerialize::withCapacity(4096);
                   2137:         if( !s) {
                   2138:             err = kIOReturnNoMemory;
                   2139:            continue;
                   2140:        }
                   2141:         s->clearText();
                   2142:         if( !dict->serialize( s )) {
                   2143:             err = kIOReturnUnsupported;
                   2144:            continue;
                   2145:         }
                   2146: 
                   2147:         if( s->getLength() > sizeof( io_string_t)) {
                   2148:             err = kIOReturnNoMemory;
                   2149:            continue;
                   2150:         } else
                   2151:             strcpy( matching, s->text());
                   2152: 
                   2153:     } while( false);
                   2154: 
                   2155:     if( s)
                   2156:        s->release();
                   2157:     if( dict)
                   2158:        dict->release();
                   2159: 
                   2160:     return( err);
                   2161: }
                   2162: 
                   2163: /* Routine io_catalog_send_data */
                   2164: kern_return_t is_io_catalog_send_data(
                   2165:         mach_port_t            master_port,
                   2166:         int                     flag,
                   2167:         io_buf_ptr_t           inData,
                   2168:         mach_msg_type_number_t         inDataCount
                   2169: )
                   2170: {
                   2171:     OSObject * obj = 0;
                   2172:     vm_offset_t data;
                   2173:     kern_return_t kr = kIOReturnSuccess;
                   2174: 
                   2175:     //printf("io_catalog_send_data called. flag: %d\n", flag);
                   2176:     
                   2177:     if( master_port != master_device_port)
                   2178:         return kIOReturnNotPrivileged;
                   2179: 
                   2180:     if ( !inData || !inDataCount )
                   2181:         return kIOReturnBadArgument;
                   2182:     
                   2183:     kr = vm_map_copyout( kernel_map, &data, (vm_map_copy_t)inData );
                   2184:     if ( kr != kIOReturnSuccess )
                   2185:         return kr;
                   2186: 
                   2187:     if ( inDataCount ) {
                   2188:         obj = (OSObject *)OSUnserializeXML((const char *)data);
                   2189:         vm_deallocate( kernel_map, data, inDataCount );
                   2190:         if ( !obj )
                   2191:             return kIOReturnNoMemory;
                   2192:     }
                   2193: 
                   2194:     switch ( flag ) {
                   2195:         case kIOCatalogAddDrivers: 
                   2196:         case kIOCatalogAddDriversNoMatch: {
                   2197:                 OSArray * array;
                   2198: 
                   2199:                 array = OSDynamicCast(OSArray, obj);
                   2200:                 if ( array ) {
                   2201: //--
                   2202:     OSDictionary * dict;
                   2203:     int i = 0;
                   2204:         while( (dict = OSDynamicCast(OSDictionary, array->getObject(i++))))
                   2205:             makeMatchingCompatible( dict );
                   2206: //--
                   2207:                     if ( !gIOCatalogue->addDrivers( array , 
                   2208:                                           flag == kIOCatalogAddDrivers) ) {
                   2209:                         kr = kIOReturnError;
                   2210:                     }
                   2211:                 }
                   2212:                 else {
                   2213:                     kr = kIOReturnBadArgument;
                   2214:                 }
                   2215:             }
                   2216:             break;
                   2217: 
                   2218:         case kIOCatalogRemoveDrivers: 
                   2219:         case kIOCatalogRemoveDriversNoMatch: {
                   2220:                 OSDictionary * dict;
                   2221: 
                   2222:                 dict = OSDynamicCast(OSDictionary, obj);
                   2223:                 if ( dict ) {
                   2224:                    makeMatchingCompatible( dict );
                   2225:                     if ( !gIOCatalogue->removeDrivers( dict, 
                   2226:                                           flag == kIOCatalogRemoveDrivers ) ) {
                   2227:                         kr = kIOReturnError;
                   2228:                     }
                   2229:                 }
                   2230:                 else {
                   2231:                     kr = kIOReturnBadArgument;
                   2232:                 }
                   2233:             }
                   2234:             break;
                   2235: 
                   2236:         case kIOCatalogStartMatching: {
                   2237:                 OSDictionary * dict;
                   2238: 
                   2239:                 dict = OSDynamicCast(OSDictionary, obj);
                   2240:                 if ( dict ) {
                   2241:                    makeMatchingCompatible( dict );
                   2242:                     if ( !gIOCatalogue->startMatching( dict ) ) {
                   2243:                         kr = kIOReturnError;
                   2244:                     }
                   2245:                 }
                   2246:                 else {
                   2247:                     kr = kIOReturnBadArgument;
                   2248:                 }
                   2249:             }
                   2250:             break;
                   2251:             
                   2252:         default:
                   2253:             kr = kIOReturnBadArgument;
                   2254:             break;
                   2255:     }
                   2256:     obj->release();
                   2257:     
                   2258:     return kr;
                   2259: }
                   2260: 
                   2261: /* Routine io_catalog_terminate */
                   2262: kern_return_t is_io_catalog_terminate(
                   2263:        mach_port_t master_port,
                   2264:        int flag,
                   2265:        io_name_t name )
                   2266: {
                   2267:     kern_return_t      kr;
                   2268: 
                   2269:     if( master_port != master_device_port )
                   2270:         return kIOReturnNotPrivileged;
                   2271: 
                   2272:     kr = kIOReturnSuccess;
                   2273:     switch ( flag ) {
                   2274:         case kIOCatalogServiceTerminate:
                   2275:             OSIterator *       iter;
                   2276:             IOService *                service;
                   2277: 
                   2278:             iter = IORegistryIterator::iterateOver(gIOServicePlane,
                   2279:                                         kIORegistryIterateRecursively);
                   2280:             if ( !iter )
                   2281:                 return kIOReturnNoMemory;
                   2282: 
                   2283:             do {
                   2284:                 iter->reset();
                   2285:                 while( (service = (IOService *)iter->getNextObject()) ) {
                   2286:                     if( service->metaCast(name)) {
                   2287:                         if ( !service->terminate(kIOServiceRequired) ) {
                   2288:                             kr = kIOReturnUnsupported;
                   2289:                             break;
                   2290:                         }
                   2291:                     }
                   2292:                 }
                   2293:             } while( !service && !iter->isValid());
                   2294:             iter->release();
                   2295:             break;
                   2296: 
                   2297:         case kIOCatalogModuleUnload:
                   2298:         case kIOCatalogModuleTerminate:
                   2299:             kr = gIOCatalogue->terminateDriversForModule(name,
                   2300:                                         flag == kIOCatalogModuleUnload);
                   2301:             break;
                   2302: 
                   2303:         default:
                   2304:             kr = kIOReturnBadArgument;
                   2305:             break;
                   2306:     }
                   2307: 
                   2308:     return( kr );
                   2309: }
                   2310: 
                   2311: /* Routine io_catalog_get_data */
                   2312: kern_return_t is_io_catalog_get_data(
                   2313:         mach_port_t            master_port,
                   2314:         int                     flag,
                   2315:         io_buf_ptr_t           *outData,
                   2316:         mach_msg_type_number_t         *outDataCount)
                   2317: {
                   2318:     kern_return_t kr = kIOReturnSuccess;
                   2319:     OSSerialize * s;
                   2320:     
                   2321:     if( master_port != master_device_port)
                   2322:         return kIOReturnNotPrivileged;
                   2323: 
                   2324:     //printf("io_catalog_get_data called. flag: %d\n", flag);
                   2325:     
                   2326:     s = OSSerialize::withCapacity(4096);
                   2327:     if ( !s )
                   2328:         return kIOReturnNoMemory;
                   2329: 
                   2330:     s->clearText();
                   2331:     switch ( flag ) {
                   2332:         case kIOCatalogGetContents:
                   2333:             if ( !gIOCatalogue->serialize(s) ) {
                   2334:                 kr = kIOReturnNoMemory;
                   2335:             }
                   2336:             break;
                   2337: 
                   2338:         default:
                   2339:             kr = kIOReturnBadArgument;
                   2340:             break;
                   2341:     }
                   2342: 
                   2343:     if ( kr == kIOReturnSuccess ) {
                   2344:         vm_offset_t data;
                   2345:         vm_map_copy_t copy;
                   2346:         vm_size_t size;
                   2347: 
                   2348:         size = s->getLength();
                   2349:         kr = vm_allocate(kernel_map, &data, size, true);
                   2350:         if ( kr == kIOReturnSuccess ) {
                   2351:             bcopy(s->text(), (void *)data, size);
                   2352:             kr = vm_map_copyin(kernel_map, data, size, true, &copy);
                   2353:             *outData = (char *)copy;
                   2354:             *outDataCount = size;
                   2355:         }
                   2356:     }
                   2357: 
                   2358:     s->release();
                   2359: 
                   2360:     return kr;
                   2361: }
                   2362: 
                   2363: /* Routine io_catalog_get_gen_count */
                   2364: kern_return_t is_io_catalog_get_gen_count(
                   2365:         mach_port_t            master_port,
                   2366:         int                     *genCount)
                   2367: {
                   2368:     if( master_port != master_device_port)
                   2369:         return kIOReturnNotPrivileged;
                   2370: 
                   2371:     //printf("io_catalog_get_gen_count called.\n");
                   2372: 
                   2373:     if ( !genCount )
                   2374:         return kIOReturnBadArgument;
                   2375: 
                   2376:     *genCount = gIOCatalogue->getGenerationCount();
                   2377:     
                   2378:     return kIOReturnSuccess;
                   2379: }
                   2380: 
                   2381: /* Routine io_catalog_module_loaded */
                   2382: kern_return_t is_io_catalog_module_loaded(
                   2383:         mach_port_t            master_port,
                   2384:         io_name_t               name)
                   2385: {
                   2386:     if( master_port != master_device_port)
                   2387:         return kIOReturnNotPrivileged;
                   2388: 
                   2389:     //printf("io_catalog_module_loaded called. name %s\n", name);
                   2390:     
                   2391:     if ( !name )
                   2392:         return kIOReturnBadArgument;
                   2393:     
                   2394:     gIOCatalogue->moduleHasLoaded(name);
                   2395:     
                   2396:     return kIOReturnSuccess;
                   2397: }
                   2398: 
                   2399: kern_return_t is_io_catalog_reset(
                   2400:        mach_port_t             master_port,
                   2401:        int                     flag)
                   2402: {
                   2403:     if( master_port != master_device_port)
                   2404:         return kIOReturnNotPrivileged;
                   2405: 
                   2406:     switch ( flag ) {
                   2407:         case kIOCatalogResetDefault:
                   2408:             gIOCatalogue->reset();
                   2409:             break;
                   2410: 
                   2411:         default:
                   2412:             return kIOReturnBadArgument;
                   2413:     }
                   2414:     
                   2415:     return kIOReturnSuccess;
                   2416: }
                   2417: 
                   2418: };     /* extern "C" */
                   2419: 
                   2420: 

unix.superglobalmegacorp.com

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