Annotation of driverkit/libDriver/IODevice.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
                     25:  *
                     26:  * IODevice.m - Implementation of IODevice superclass
                     27:  *
                     28:  * HISTORY
                     29:  * 13-Jan-98   Martin Minow at Apple
                     30:  *     Added createMachPort
                     31:  * 20-Jan-93   Doug Mitchell
                     32:  *     Implemented the Walrath Changes.
                     33:  * 29-Jan-91    Doug Mitchell at NeXT
                     34:  *      Created.
                     35:  */
                     36: 
                     37: /*
                     38:  * FIXME - should global parameter stuff be KERNEL only?
                     39:  */
                     40:  
                     41: #import <bsd/sys/types.h>
                     42: #import <mach/kern_return.h>
                     43: #import <mach/message.h>
                     44: #import <driverkit/IODevice.h>
                     45: #import <driverkit/Device_ddm.h>
                     46: 
                     47: #ifdef KERNEL
                     48: #import <kernserv/prototypes.h>
                     49: #import <mach/mach_interface.h>
                     50: #else  KERNEL
                     51: #import <mach/mach.h>
                     52: #import <bsd/string.h>
                     53: #endif KERNEL
                     54: 
                     55: #import <machkit/NXLock.h>
                     56: #import <bsd/sys/errno.h>
                     57: 
                     58: #import <driverkit/generalFuncs.h>
                     59: #import <driverkit/IODeviceParams.h>
                     60: #import <driverkit/IODeviceDescription.h>
                     61: #import <driverkit/IODeviceDescriptionPrivate.h>
                     62: #import <driverkit/IODeviceKernPrivate.h>
                     63: #ifdef KERNEL
                     64: #import <driverkit/KernStringList.h>
                     65: #endif
                     66: #import <kernserv/queue.h>
                     67: #import <objc/List.h>
                     68: 
                     69: /*
                     70:  * For stringFromReturn:.
                     71:  */
                     72: static IONamedValue IOReturn_values[] = { 
                     73:         {IO_R_SUCCESS,                 "Success"                       },
                     74:         {IO_R_NO_MEMORY,               "Memory Allocation error"       },
                     75:         {IO_R_RESOURCE,                        "Resource Shortage"             },
                     76:         {IO_R_IPC_FAILURE,             "Mach IPC Failure"              },
                     77:         {IO_R_NO_DEVICE,               "No Such Device"                },
                     78:         {IO_R_PRIVILEGE,               "Privilege Violation"           },
                     79:         {IO_R_INVALID_ARG,             "Invalid Argument"              },
                     80:         {IO_R_LOCKED_READ,             "Device Read Locked"            },
                     81:         {IO_R_LOCKED_WRITE,            "Device Write Locked"           },
                     82:         {IO_R_EXCLUSIVE_ACCESS,                "Exclusive Access Device"       },
                     83:         {IO_R_BAD_MSG_ID,              "Bad IPC Message ID"            },
                     84:         {IO_R_UNSUPPORTED,             "Unsupported Function"          },
                     85:         {IO_R_VM_FAILURE,              "Virtual Memory error"          },
                     86:         {IO_R_INTERNAL,                        "Internal Driver error"         },
                     87:         {IO_R_IO,                      "I/O error"                     },
                     88:         {IO_R_CANT_LOCK,               "Can\'t Acquire Desired Lock"   },
                     89:         {IO_R_NOT_OPEN,                        "Device Not Open"               },
                     90:         {IO_R_NOT_READABLE,            "Device Not Readable"           },
                     91:         {IO_R_NOT_WRITABLE,            "Device Not Writeable"          },
                     92:        {IO_R_ALIGN,                    "DMA ALignment error"           },
                     93:        {IO_R_MEDIA,                    "Media error"                   },
                     94:        {IO_R_OPEN,                     "Device(s) still open"          },
                     95:        {IO_R_RLD,                      "rld failure"                   },
                     96:        {IO_R_DMA,                      "DMA failure"                   },
                     97:        {IO_R_BUSY,                     "Device Busy"                   },
                     98:        {IO_R_TIMEOUT,                  "I/O Timeout"                   },
                     99:        {IO_R_OFFLINE,                  "Device Offline"                },
                    100:        {IO_R_NOT_READY,                "Not Ready"                     },
                    101:        {IO_R_NOT_ATTACHED,             "Device/Channel not attached"   },
                    102:        {IO_R_NO_CHANNELS,              "No DMA Channels Available"     },
                    103:        {IO_R_NO_SPACE,                 "No Address Space for Mapping"  },
                    104:        {IO_R_PORT_EXISTS,              "Device Port Already Exists"    },
                    105:        {IO_R_CANT_WIRE,                "Can\'t Wire Physical Memory"   },
                    106:        {IO_R_NO_INTERRUPT,             "No Interrupt Port Attached"    },
                    107:        {IO_R_NO_FRAMES,                "No DMA Frames Enqueued"        },
                    108:         {IO_R_INVALID,                 "INVALID STATUS (Internal Error)" },
                    109:        {0,                             NULL                            }
                    110: };
                    111: 
                    112: /*
                    113:  * Struct to map "global Object number" to id.
                    114:  */
                    115: typedef struct {
                    116:        id              instance;
                    117:        int             objectNumber;
                    118:        queue_chain_t   link;
                    119: } objectListEntry;
                    120: 
                    121: /*
                    122:  * Struct to maintain IODevice class list.
                    123:  */
                    124: typedef struct {
                    125:        id              classId;
                    126:        int             classNumber;
                    127:        int             bmajor;
                    128:        int             cmajor;
                    129:        id              originalDeviceDescription;
                    130:        queue_chain_t   link;
                    131: } classListEntry;
                    132: 
                    133: /*
                    134:  * ObjectNumber-to-id mapping info. 
                    135:  */
                    136: static int globalObjectCounter;
                    137: static queue_head_t objectList;                // queue of objectListEntry's
                    138: static NXLock *objectListLock;         // protects both of the above
                    139: 
                    140: /*
                    141:  * IODevice class list.
                    142:  */
                    143: static int classCounter;
                    144: static queue_head_t classList;
                    145: static NXLock *classListLock;
                    146: 
                    147: /*
                    148:  * Static function prototypes.
                    149:  */
                    150: static IOReturn objectNumToId(IOObjectNumber objectNum, id *instance);
                    151: static IOReturn deviceNameToId(IOString name, 
                    152:        id *instance,
                    153:        IOObjectNumber *objectNum);
                    154: static objectListEntry *getObjectListEntry(id object);
                    155: static IOReturn getClassListEntryForId(
                    156:        id classId,
                    157:        classListEntry  **entry);
                    158: static IOReturn getClassListEntry(unsigned classNumber,
                    159:        classListEntry  **entry);
                    160: 
                    161: @implementation IODevice
                    162: 
                    163: static BOOL IODeviceInitFlag = NO;
                    164: 
                    165: /* Shouldn't this be somewhere else? */
                    166: static inline int _atoi(const char *string)
                    167: {
                    168:     int sum = 0;
                    169:     while(*string && (*string >= '0' && *string <= '9'))
                    170:        sum = (sum * 10) + (*string++ - '0');
                    171:     return sum;
                    172: }
                    173: 
                    174: + initialize
                    175: {
                    176:        if(self != objc_getClass("IODevice")) {
                    177:                /*
                    178:                 * This is someone else's. Register them.
                    179:                 */
                    180:                [IODevice registerClass:self];
                    181:        }
                    182: 
                    183:        if(IODeviceInitFlag) {
                    184:                /*
                    185:                 * We've already been here. This shouldn't happen unless
                    186:                 * someone calls [IODevice initialize] explicitly.
                    187:                 */
                    188:                return self;
                    189:        }
                    190:        
                    191:        /*
                    192:         * Init objectNumber-to-id list.
                    193:         */
                    194: 
                    195:        objectListLock = [NXLock new];
                    196:        globalObjectCounter = 0;
                    197:        queue_init(&objectList);
                    198:        
                    199:        /* 
                    200:         * Init class list.
                    201:         */
                    202:        queue_init(&classList);
                    203:        classListLock = [NXLock new];
                    204:        IODeviceInitFlag = YES;
                    205:        return self;
                    206: }
                    207: 
                    208: /*
                    209:  * Probe method used by direct, indirect, and pseudo devices. 
                    210:  * Implemented by most (not all) subclasses.
                    211:  * 
                    212:  * Create an instance of subclass to be associated with specified 
                    213:  * deviceDescription. Returns a pointer to a nil-terminated array of 
                    214:  * id's of instantiated device objects if successful, else returns nil.
                    215:  */
                    216: + (BOOL)probe : (id)deviceDescription
                    217: {
                    218:        return NO;
                    219: }
                    220: 
                    221: /*
                    222:  * Report basic style of driver (direct, indirect, or pseudo). Must be 
                    223:  * implemented by subclass.
                    224:  */
                    225: + (IODeviceStyle)deviceStyle
                    226: {
                    227:        return IO_PseudoDevice;         // just a place holder
                    228: }
                    229: 
                    230: /*
                    231:  * Report protocols needed. Kernel-level indirect devices must implement
                    232:  * this.
                    233:  */
                    234: + (Protocol **)requiredProtocols
                    235: {
                    236:        return NULL;
                    237: }
                    238: 
                    239: /*
                    240:  * Called from leaf subclass's +initialize method. 
                    241:  */
                    242: + (void)registerClass : classId
                    243: {
                    244:        classListEntry *listEntry;
                    245:        
                    246:        listEntry = IOMalloc(sizeof(classListEntry));
                    247:        listEntry->classId = classId;
                    248:        listEntry->bmajor = listEntry->cmajor = -1;
                    249:        listEntry->originalDeviceDescription = nil;
                    250:        [classListLock lock];
                    251:        listEntry->classNumber = classCounter++;
                    252:        queue_enter(&classList, listEntry, classListEntry *, link);
                    253:        [classListLock unlock];
                    254: }
                    255: 
                    256: /*
                    257:  * Called if/when a class is being removed from an executable's address
                    258:  * space.
                    259:  */
                    260: + (void)unregisterClass : classId
                    261: {
                    262:        classListEntry *classEntry;
                    263:        
                    264:        [classListLock lock];
                    265:        classEntry = (classListEntry *)queue_first(&classList);
                    266:        while(!queue_end(&classList, (queue_t)classEntry)) {
                    267:                if(classEntry->classId == classId) {
                    268:                        queue_remove(&classList,
                    269:                                classEntry,
                    270:                                classListEntry *,
                    271:                                link);
                    272:                        break;
                    273:                }
                    274:                classEntry = (classListEntry *)classEntry->link.next;
                    275:        }
                    276:        [classListLock unlock];
                    277: }
                    278: 
                    279: /*
                    280:  * Initialize  common instance variables. Typically invoked
                    281:  * via [super init:] in subclass's init: method.
                    282:  */
                    283: - init
                    284: {
                    285:        xpr_dev("IODevice init:\n", 1,2,3,4,5);
                    286:        return [super init];
                    287: }
                    288: 
                    289: /* 
                    290:  * Initialize per specified deviceDescription. Returns nil on error. 
                    291:  * This is actually a nop at the IODevice level; subclasses may do with it 
                    292:  * as they see fit.
                    293:  */
                    294: - initFromDeviceDescription : deviceDescription
                    295: {
                    296:     if( [[self class] deviceStyle] == IO_IndirectDevice)
                    297:         __deviceDescription = [deviceDescription directDevice];
                    298:     else
                    299:         __deviceDescription = deviceDescription;
                    300:     return self;
                    301: }
                    302: 
                    303: - deviceDescription
                    304: {
                    305:     if( [[self class] deviceStyle] == IO_IndirectDevice)
                    306:        return nil;
                    307:     else
                    308:         return __deviceDescription;
                    309: }
                    310: 
                    311: - (void)setDeviceDescription : deviceDescription
                    312: {
                    313:     if( [[self class] deviceStyle] == IO_IndirectDevice)
                    314:         __deviceDescription = [deviceDescription directDevice];
                    315:     else
                    316:         __deviceDescription = deviceDescription;
                    317: }
                    318: 
                    319: /*
                    320:  * Returns a string representation of the hardware's location.
                    321:  * Indirect drivers return the direct device's path they were probed on.
                    322:  */
                    323: - getDevicePath:(char *)path maxLength:(int)maxLen useAlias:(BOOL)doAlias
                    324: {
                    325:     if( [__deviceDescription respondsTo:@selector(getDevicePath:maxLength:useAlias:)])
                    326:         return( [__deviceDescription getDevicePath:path maxLength:maxLen useAlias:doAlias]);
                    327: 
                    328:     return( nil);
                    329: }
                    330: 
                    331: /*
                    332:  * Returns the tail of the matchPath parameter if the head matches the
                    333:  * device's path, else returns nil. Indirect drivers match on the
                    334:  * direct device's path they were probed on.
                    335:  */
                    336: - (char *) matchDevicePath:(char *)matchPath
                    337: {
                    338:     if( [__deviceDescription respondsTo:@selector(matchDevicePath:)])
                    339:         return( [__deviceDescription matchDevicePath:matchPath]);
                    340: 
                    341:     return( NULL);
                    342: }
                    343: 
                    344: - lookUpProperty:(const char *)propertyName
                    345:        value:(unsigned char *)value
                    346:        length:(unsigned int *)length
                    347:        selector:(SEL)selector
                    348:        isString:(BOOL)isString
                    349: {
                    350:     id         rtn = nil, prtn = nil;
                    351: 
                    352:     if( __deviceDescription)
                    353:         prtn = [__deviceDescription lookUpProperty:propertyName value:value length:length
                    354:                selector:(SEL)selector isString:isString];
                    355: 
                    356:     if( [self respondsTo:selector]) {
                    357:        // guarantee a minimal size so most methods don't have to check
                    358:        if( (isString == NO) || ((strlen( value) + 32) <= *length))
                    359:             rtn = objc_msgSend( self, selector, value, length );
                    360:     }
                    361: 
                    362:     return( prtn ? prtn : rtn);
                    363: }
                    364: 
                    365: - lookUpProperty:(const char *)propertyName
                    366:        value:(unsigned char *)value
                    367:        length:(unsigned int *)length
                    368: 
                    369: {
                    370:     char                       selName[ 64 ];
                    371:     SEL                        selector;
                    372:     unsigned int       len = 4;
                    373: 
                    374:     *value = 0;
                    375:     sprintf( selName, "property_%s:length:", propertyName);
                    376:     selector = sel_getUid( selName);
                    377: 
                    378:     return( [self lookUpProperty:propertyName value:value length:length
                    379:                selector:selector isString:NO]);
                    380: }
                    381: 
                    382: - lookUpStringProperty:(const char *)propertyName
                    383:        value:(char *)value
                    384:        length:(unsigned int)maxLength
                    385: {
                    386:     char               selName[ 64 ];
                    387:     SEL                selector;
                    388: 
                    389:     *value = 0;
                    390:     sprintf( selName, "property_%s:length:", propertyName);
                    391:     selector = sel_getUid( selName);
                    392: 
                    393:     return( [self lookUpProperty:propertyName value:value length:&maxLength
                    394:                selector:selector isString:YES]);
                    395: }
                    396: 
                    397: - property_IODriverNames:(char *)classes length:(unsigned int *)maxLen
                    398: {
                    399:     if( *classes)
                    400:        strcat( classes, " ");
                    401:     strcat( classes, [self name]);
                    402:     return( self);
                    403: }
                    404: 
                    405: - property_IODevicePath:(char *)path length:(unsigned int *)maxLen
                    406: {
                    407:     return( [self getDevicePath:path maxLength:*maxLen useAlias:YES]);
                    408: }
                    409: 
                    410: #ifdef KERNEL
                    411: - getStringPropertyList:(const char *)names
                    412:        results:(char *) results
                    413:        maxLength:(unsigned int)length
                    414: {
                    415:     int                        index, maxLen, nameLen, nextLen;
                    416:     KernStringList *   nameList;
                    417:     char *             nextValue;
                    418:     const char *               name;
                    419: 
                    420:     nameList = [[KernStringList alloc]
                    421:                         initWithWhitespaceDelimitedString:names];
                    422:     if( nameList) {
                    423:         nextValue = results;
                    424:         maxLen = length - (4 + 2);
                    425: 
                    426:         for (index = 0; index < [nameList count]; index++) {
                    427:             name = [nameList stringAt:index];
                    428:             nameLen = strlen( name);
                    429:             nextLen = maxLen - nameLen;
                    430: 
                    431:             if( [self lookUpStringProperty:name value:(nextValue + nameLen + 4) length:nextLen]) {
                    432: 
                    433:                 sprintf( nextValue, "\"%s\"=", name);
                    434:                 nextValue += nameLen + 3;
                    435:                 *nextValue++ = '\"';
                    436:                 nextLen = strlen( nextValue) + 2;
                    437:                 nextValue += nextLen;
                    438:                 strcpy( nextValue - 2, "\";");
                    439:                 maxLen -= nextLen + nameLen + 4;
                    440:             }
                    441:         }
                    442:         [nameList free];
                    443:     }
                    444: 
                    445:     *nextValue = 0;
                    446:     return( self);
                    447: }
                    448: 
                    449: - matchStringPropertyList:(char *)values
                    450: {
                    451:     enum {             kValueMaxSize = 256 };
                    452:     char *             valueBuf;
                    453:     KernStringList *   valueList, * lookList;
                    454:     int                        look, value;
                    455:     id                 rtn;
                    456:     char *             next, * end;
                    457:     BOOL               found, lookingName = YES;
                    458: 
                    459:     next = values;
                    460:     valueList = lookList = nil;
                    461:     valueBuf = IOMalloc( kValueMaxSize);
                    462:     if( !valueBuf)
                    463:        return( nil);
                    464: 
                    465:     while(
                    466:             (next = (char *) strchr( next, '\"'))
                    467:             &&
                    468:             (end = (char *) strchr( ++next, '\"'))     ) {
                    469: 
                    470:        found = NO;
                    471:         *end = 0;              // yikes - modify caller's string
                    472: 
                    473:        if( lookingName) {
                    474: 
                    475:             rtn = [self lookUpStringProperty:next value:valueBuf length:kValueMaxSize];
                    476:             *end = '\"';       // restore caller's string
                    477:             if( !rtn)
                    478:                 break;
                    479:            [valueList free];
                    480:             valueList = [[KernStringList alloc]
                    481:                             initWithWhitespaceDelimitedString:valueBuf];
                    482:             if( !valueList)
                    483:                 break;
                    484: 
                    485:        } else {
                    486: 
                    487:            [lookList free];
                    488:             lookList = [[KernStringList alloc]
                    489:                             initWithWhitespaceDelimitedString:next];
                    490:             *end = '\"';       // restore caller's string
                    491:             if( !lookList)
                    492:                 break;
                    493: 
                    494:             found = YES;
                    495:            for( look = 0; found && (look < [lookList count]); look++) {
                    496:                found = NO;
                    497:                 for( value = 0; !found && (value < [valueList count]); value++)
                    498:                    found = (0 == strcmp( [lookList stringAt:look], [valueList stringAt:value] ));
                    499:            }
                    500:            if( !found)
                    501:                break;
                    502:        }
                    503: 
                    504:        next = end + 1;
                    505:        lookingName ^= YES;
                    506:     }
                    507:     [valueList free];
                    508:     [lookList free];
                    509:     IOFree( valueBuf, kValueMaxSize);
                    510:     return( found ? self : nil);
                    511: }
                    512: 
                    513: #else  /* !KERNEL */
                    514: 
                    515: - getStringPropertyList:(const char *)names
                    516:        results:(char *) results
                    517:        maxLength:(unsigned int)length
                    518: {
                    519:     return( nil);
                    520: }
                    521: - matchStringPropertyList:(char *)values
                    522: {
                    523:     return( nil);
                    524: }
                    525: 
                    526: #endif         /* KERNEL */
                    527: 
                    528: 
                    529: /*
                    530:  * Free up resources used by this device; invoke Object's free. Instance 
                    531:  * will be "gone" upon return.
                    532:  */
                    533: - free
                    534: {
                    535:        [self unregisterDevice];
                    536:        return([super free]);
                    537: }
                    538: 
                    539: - registerLoudly
                    540: {
                    541:     return( self);
                    542: }
                    543: 
                    544: /*
                    545:  * Register instance with nmserver (or IOServer or ...). _deviceName and
                    546:  * _deviceKind must be valid; _location must be valid or NULL.
                    547:  */
                    548: - registerDevice
                    549: {
                    550:        objectListEntry *objectEntry;
                    551:        
                    552:        xpr_dev("IODevice register\n", 1,2,3,4,5);
                    553: 
                    554:        if( [self registerLoudly]) {
                    555: 
                    556:             IOLog("Registering: %s", _deviceName);
                    557: 
                    558:             if(_location[0])
                    559:                     IOLog(" at %s", _location);
                    560: 
                    561:             if( (_deviceName[ 0 ] != '/')
                    562:                 && [__deviceDescription respondsTo:@selector(nodeName)]
                    563:                && [__deviceDescription nodeName] ) {
                    564: 
                    565:                    char        slotName[ 32 ];
                    566: 
                    567:                     IOLog("   [%s", [__deviceDescription nodeName]);
                    568: 
                    569:                    if( [self lookUpStringProperty:IOPropSlotName
                    570:                        value:slotName length:sizeof( slotName)])
                    571:                             IOLog(", slot %s", slotName);
                    572:                     IOLog( "]");
                    573:            }
                    574:             IOLog( "\n");
                    575:        }
                    576: 
                    577:        /*
                    578:         * Create a objectNum-to-id map entry for this instance.
                    579:         */
                    580:        objectEntry = IOMalloc(sizeof(*objectEntry));
                    581:        objectEntry->instance = self;
                    582:        [objectListLock lock];
                    583:        objectEntry->objectNumber = globalObjectCounter++;
                    584:        queue_enter(&objectList,
                    585:                objectEntry,
                    586:                objectListEntry *,
                    587:                link);
                    588:        [objectListLock unlock];
                    589: 
                    590:        /*
                    591:         * See if any indirect devices are interested in this object's
                    592:         * protocol.
                    593:         */
                    594:        [IODevice connectToIndirectDevices:self];
                    595:        return self;
                    596: }
                    597: 
                    598: - (void)unregisterDevice
                    599: {
                    600:        objectListEntry *objectEntry;
                    601:        
                    602:        xpr_dev("IODevice unregister %s\n", _deviceName, 2,3,4,5);
                    603: 
                    604:        /*
                    605:         * Remove this device's objectNum-to-id map entry. This creates a 
                    606:         * hole in the global objectNumber space which never gets filled 
                    607:         * (in the current implementation).
                    608:         */
                    609:        [objectListLock lock];
                    610:        objectEntry = getObjectListEntry(self);
                    611:        if(objectEntry != NULL) {
                    612:                 if( [self registerLoudly])
                    613:                     IOLog("Unregistering Device: %s\n", _deviceName);
                    614:                queue_remove(&objectList, 
                    615:                        objectEntry, 
                    616:                        objectListEntry *, 
                    617:                        link);
                    618:                IOFree(objectEntry, sizeof(*objectEntry));
                    619:        }
                    620:        [objectListLock unlock];
                    621:        
                    622: }
                    623: 
                    624: /*
                    625:  * Obtain public instance variables.
                    626:  */
                    627: - (const char *)name
                    628: {
                    629:        return((const char *)_deviceName);
                    630: }
                    631: 
                    632: - (void)setName        : (const char *)name
                    633: {
                    634:        int len;
                    635:        
                    636:        len = strlen((char *)name);
                    637:        if(len >= IO_STRING_LENGTH)
                    638:                len = IO_STRING_LENGTH - 1;
                    639:        strncpy(_deviceName, name, len);
                    640:        _deviceName[len] = '\0';                
                    641: }
                    642: 
                    643: - (const char *)deviceKind
                    644: {
                    645:        return((const char *)_deviceKind);
                    646: }
                    647: 
                    648: - (void)setDeviceKind  : (const char *)type
                    649: {
                    650:        int len;
                    651:        
                    652:        len = strlen((char *)type);
                    653:        if(len >= IO_STRING_LENGTH)
                    654:                len = IO_STRING_LENGTH - 1;
                    655:        strncpy(_deviceKind, type, len);
                    656:        _deviceKind[len] = '\0';                
                    657: }
                    658: 
                    659: - (const char *)location
                    660: {
                    661:        return((const char *)_location);
                    662: }
                    663: 
                    664: - (void)setLocation            : (const char *)location
                    665: {
                    666:        int len;
                    667:        
                    668:        if(location == NULL) {
                    669:                _location[0] = '\0';
                    670:        }
                    671:        else {
                    672:                len = strlen((char *)location);
                    673:                if(len >= IO_STRING_LENGTH)
                    674:                        len = IO_STRING_LENGTH - 1;
                    675:                strncpy(_location, location, len);
                    676:                _location[len] = '\0';          
                    677:        }
                    678: }
                    679: 
                    680: - (u_int)unit
                    681: {
                    682:        return(_unit);
                    683: }
                    684: 
                    685: - (void)setUnit                : (u_int)unit
                    686: {
                    687:        _unit = unit;
                    688: }
                    689: 
                    690: + (int)blockMajor
                    691: {
                    692:     classListEntry *classEntry;
                    693:     if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
                    694:        return classEntry->bmajor;
                    695:     else
                    696:        return -1;
                    697: }
                    698: 
                    699: + (void)setBlockMajor  : (int)bmajor
                    700: {
                    701:     classListEntry *classEntry;
                    702:     if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
                    703:        classEntry->bmajor = bmajor;
                    704: }
                    705: 
                    706: + (int)characterMajor
                    707: {
                    708:     classListEntry *classEntry;
                    709:     if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
                    710:        return classEntry->cmajor;
                    711:     else
                    712:        return -1;
                    713: }
                    714: 
                    715: + (void)setCharacterMajor : (int)cmajor
                    716: {
                    717:     classListEntry *classEntry;
                    718:     if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
                    719:        classEntry->cmajor = cmajor;
                    720: }
                    721: 
                    722: #if KERNEL
                    723: 
                    724: + (BOOL)addToCdevswFromDescription: (id) deviceDescription
                    725:     open:      (IOSwitchFunc) openFunc
                    726:     close:     (IOSwitchFunc) closeFunc
                    727:     read:      (IOSwitchFunc) readFunc
                    728:     write:     (IOSwitchFunc) writeFunc
                    729:     ioctl:     (IOSwitchFunc) ioctlFunc
                    730:     stop:      (IOSwitchFunc) stopFunc
                    731:     reset:     (IOSwitchFunc) resetFunc
                    732:     select:    (IOSwitchFunc) selectFunc
                    733:     mmap:      (IOSwitchFunc) mmapFunc
                    734:     getc:      (IOSwitchFunc) getcFunc
                    735:     putc:      (IOSwitchFunc) putcFunc
                    736: {
                    737:        const char *majorString;
                    738:        int major, result;
                    739: 
                    740:        majorString = [[deviceDescription configTable]
                    741:                        valueForStringKey:"Character Major"];
                    742:        if (majorString) {
                    743:            major = _atoi(majorString);
                    744:        } else {
                    745:            major = -1;
                    746:        }
                    747:        result = IOAddToCdevswAt(
                    748:            major,
                    749:            openFunc,
                    750:            closeFunc,
                    751:            readFunc,
                    752:            writeFunc,
                    753:            ioctlFunc,
                    754:            stopFunc,
                    755:            resetFunc,
                    756:            selectFunc,
                    757:            mmapFunc,
                    758:            getcFunc,
                    759:            putcFunc);
                    760:        if (result < 0) { 
                    761:            if (major < 0)
                    762:                IOLog ("%s: could not add to cdevsw table at any major\n",
                    763:                    [self name]);
                    764:            else
                    765:                IOLog ("%s: could not add to cdevsw table at major %d\n",
                    766:                    [self name], major);
                    767:            return NO;
                    768:        }
                    769:        [self setCharacterMajor: result];
                    770:        return YES;
                    771: }
                    772: 
                    773: + (BOOL) addToBdevswFromDescription: (id) deviceDescription
                    774:     open:      (IOSwitchFunc) openFunc
                    775:     close:     (IOSwitchFunc) closeFunc
                    776:     strategy:  (IOSwitchFunc) strategyFunc
                    777:     ioctl:     (IOSwitchFunc) ioctlFunc
                    778:     dump:      (IOSwitchFunc) dumpFunc
                    779:     psize:     (IOSwitchFunc) sizeFunc
                    780:     isTape:    (BOOL) isTape
                    781: {
                    782:        const char *majorString;
                    783:        int major, result;
                    784: 
                    785:        majorString = [[deviceDescription configTable]
                    786:                        valueForStringKey:"Block Major"];
                    787:        if (majorString) {
                    788:            major = _atoi(majorString);
                    789:        } else {
                    790:            major = -1;
                    791:        }
                    792:        result = IOAddToBdevswAt(
                    793:            major,
                    794:            openFunc,
                    795:            closeFunc,
                    796:            strategyFunc,
                    797:            ioctlFunc,
                    798:            dumpFunc,
                    799:            sizeFunc,
                    800:            isTape);
                    801:        if (result < 0) { 
                    802:            if (major < 0)
                    803:                IOLog ("%s: could not add to bdevsw table at any major\n",
                    804:                    [self name]);
                    805:            else
                    806:                IOLog ("%s: could not add to bdevsw table at major %d\n",
                    807:                    [self name], major);
                    808:            return NO;
                    809:        }
                    810:        [self setBlockMajor: result];
                    811:        return YES;
                    812: }
                    813: 
                    814: + (BOOL) removeFromCdevsw
                    815: {
                    816:     int major = [self characterMajor];
                    817:     if (major == -1)
                    818:        return NO;
                    819: 
                    820:     IORemoveFromCdevsw(major);
                    821:     [self setCharacterMajor: -1];
                    822:     return YES;
                    823: }
                    824: 
                    825: + (BOOL) removeFromBdevsw
                    826: {
                    827:     int major = [self blockMajor];
                    828:     if (major == -1)
                    829:        return NO;
                    830:     
                    831:     IORemoveFromBdevsw(major);
                    832:     [self setBlockMajor: -1];
                    833:     return YES;
                    834: }
                    835: 
                    836: - (IOReturn) serverConnect: (port_t *)   machPort   // out in IOTask space
                    837:                  taskPort: (port_t)     taskPort;  // in actually ipc_port_t
                    838: {
                    839:     *machPort = PORT_NULL;
                    840:     return IO_R_UNSUPPORTED;
                    841: }
                    842: 
                    843: #else /* !KERNEL */
                    844: 
                    845: + (BOOL)addToCdevswFromDescription: (id) deviceDescription
                    846:     open:      (IOSwitchFunc) openFunc
                    847:     close:     (IOSwitchFunc) closeFunc
                    848:     read:      (IOSwitchFunc) readFunc
                    849:     write:     (IOSwitchFunc) writeFunc
                    850:     ioctl:     (IOSwitchFunc) ioctlFunc
                    851:     stop:      (IOSwitchFunc) stopFunc
                    852:     reset:     (IOSwitchFunc) resetFunc
                    853:     select:    (IOSwitchFunc) selectFunc
                    854:     mmap:      (IOSwitchFunc) mmapFunc
                    855:     getc:      (IOSwitchFunc) getcFunc
                    856:     putc:      (IOSwitchFunc) putcFunc
                    857: {
                    858:     return FALSE;
                    859: }
                    860: 
                    861: + (BOOL) addToBdevswFromDescription: (id) deviceDescription
                    862:     open:      (IOSwitchFunc) openFunc
                    863:     close:     (IOSwitchFunc) closeFunc
                    864:     strategy:  (IOSwitchFunc) strategyFunc
                    865:     ioctl:     (IOSwitchFunc) ioctlFunc
                    866:     dump:      (IOSwitchFunc) dumpFunc
                    867:     psize:     (IOSwitchFunc) sizeFunc
                    868:     isTape:    (BOOL) isTape
                    869: {
                    870:     return FALSE;
                    871: }
                    872: 
                    873: + (BOOL) removeFromCdevsw
                    874: {
                    875:        return FALSE;
                    876: }
                    877: 
                    878: + (BOOL) removeFromBdevsw
                    879: {
                    880:        return FALSE;
                    881: }
                    882: 
                    883: - (IOReturn) serverConnect: (port_t *)   machPort   // out in IOTask space
                    884:                  taskPort: (port_t)     taskPort;  // in actually ipc_port_t
                    885: {
                    886:     return IO_R_UNSUPPORTED;
                    887: }
                    888: 
                    889: #endif /* KERNEL */
                    890: 
                    891: + (int) driverKitVersion
                    892: {
                    893:     return IO_DRIVERKIT_VERSION;
                    894: }
                    895: 
                    896: #define VERSION_CLASS "Version"
                    897: #define VERSION_METHOD "driverKitVersionFor"
                    898: 
                    899: + (int) driverKitVersionForDriverNamed:(char *)driverName
                    900: {
                    901:     char *nameBuf;
                    902:     int size, ret;
                    903:     id versionClass;
                    904:     SEL versionMethod;
                    905:     
                    906:     size = strlen(driverName) + strlen(VERSION_CLASS) + 1;
                    907:     nameBuf = IOMalloc(size);
                    908:     if (nameBuf == NULL)
                    909:        return -1;
                    910:     strcpy(nameBuf, driverName);
                    911:     strcat(nameBuf,VERSION_CLASS);
                    912:     versionClass = objc_getClass(nameBuf);
                    913:     IOFree(nameBuf, size);
                    914:     if (versionClass == nil)
                    915:        return -1;
                    916:     size = strlen(driverName) + strlen(VERSION_METHOD) + 1;
                    917:     nameBuf = IOMalloc(size);
                    918:     if (nameBuf == NULL)
                    919:        return -1;
                    920:     strcpy(nameBuf, VERSION_METHOD);
                    921:     strcat(nameBuf, driverName);
                    922:     versionMethod = sel_getUid(nameBuf);
                    923:     if ([versionClass respondsTo:versionMethod])
                    924:        ret = (int)[versionClass perform:versionMethod];
                    925:     else
                    926:        ret = -1;
                    927:     IOFree(nameBuf, size);
                    928:     return ret;
                    929: }
                    930: 
                    931: 
                    932: 
                    933: /*
                    934:  * Get/set parameters.
                    935:  */
                    936: - (IOReturn)getIntValues               : (unsigned *)parameterArray
                    937:                           forParameter : (IOParameterName)parameterName
                    938:                                  count : (unsigned *)count     // in/out
                    939: {
                    940:        if(strcmp(parameterName, IO_UNIT) == 0) {
                    941:                parameterArray[0] = _unit;
                    942:                *count = 1;
                    943:                return IO_R_SUCCESS;
                    944:        } else if(strcmp(parameterName, IO_BLOCK_MAJOR) == 0) {
                    945:                classListEntry *classEntry;
                    946:                if (getClassListEntryForId([self class], &classEntry) ==
                    947:                        IO_R_SUCCESS) {
                    948:                    parameterArray[0] = classEntry->bmajor;
                    949:                    *count = 1;
                    950:                    return IO_R_SUCCESS;
                    951:                } else
                    952:                    return IO_R_UNSUPPORTED;
                    953:        } else if(strcmp(parameterName, IO_CHARACTER_MAJOR) == 0) {
                    954:                classListEntry *classEntry;
                    955:                if (getClassListEntryForId([self class], &classEntry) ==
                    956:                        IO_R_SUCCESS) {
                    957:                    parameterArray[0] = classEntry->cmajor;
                    958:                    *count = 1;
                    959:                    return IO_R_SUCCESS;
                    960:                } else
                    961:                    return IO_R_UNSUPPORTED;
                    962:        }
                    963:        return IO_R_UNSUPPORTED;
                    964: }
                    965: 
                    966: - (IOReturn)getCharValues              : (unsigned char *)parameterArray
                    967:                           forParameter : (IOParameterName)parameterName
                    968:                                  count : (unsigned *)count     // in/out
                    969: {
                    970:        const char *name;
                    971:        unsigned length;
                    972:        int maxCount = *count;
                    973:        
                    974:        if(maxCount == 0) {
                    975:                maxCount = IO_MAX_PARAMETER_ARRAY_LENGTH;
                    976:        }
                    977:        if(strcmp(parameterName, IO_CLASS_NAME) == 0) {
                    978:                name = [[self class] name];
                    979:                goto name_out;
                    980:        }
                    981:        else if(strcmp(parameterName, IO_DEVICE_NAME) == 0) {
                    982:                name = _deviceName;
                    983:                goto name_out;
                    984:        }
                    985:        else if(strcmp(parameterName, IO_DEVICE_KIND) == 0){
                    986:                name = _deviceKind;
                    987: name_out:
                    988:                length = strlen(name);
                    989:                if(length >= maxCount) {
                    990:                        length = maxCount - 1;
                    991:                }
                    992:                *count = length + 1;
                    993:                strncpy(parameterArray, name, length);
                    994:                parameterArray[length] = '\0';
                    995:                return IO_R_SUCCESS;
                    996:        }
                    997:        else {
                    998:                return IO_R_UNSUPPORTED;
                    999:        }
                   1000: }
                   1001:                
                   1002: - (IOReturn)setIntValues               : (unsigned *)parameterArray
                   1003:                           forParameter : (IOParameterName)parameterName
                   1004:                                  count : (unsigned)count
                   1005: {
                   1006:        return IO_R_UNSUPPORTED;
                   1007: }
                   1008: 
                   1009: - (IOReturn)setCharValues              : (unsigned char *)parameterArray
                   1010:                           forParameter : (IOParameterName)parameterName
                   1011:                                  count : (unsigned)count
                   1012: {
                   1013:        return IO_R_UNSUPPORTED;
                   1014: }
                   1015: 
                   1016: /*
                   1017:  * Convert an IOReturn to text. Subclasses which add additional
                   1018:  * IOReturn's should override this method and call 
                   1019:  * [super stringFromReturn] if the desired value is not found.
                   1020:  */
                   1021: - (const char *)stringFromReturn : (IOReturn)rtn
                   1022: {
                   1023:        return [IODevice stringFromReturn:rtn];
                   1024: }
                   1025: 
                   1026: + (const char *)stringFromReturn : (IOReturn)rtn
                   1027: {
                   1028:        return IOFindNameForValue(rtn, IOReturn_values);
                   1029: }
                   1030: 
                   1031: /*
                   1032:  * Convert an IOReturn to an errno.
                   1033:  */
                   1034: - (int)errnoFromReturn : (IOReturn)rtn
                   1035: {
                   1036:        switch(rtn) {
                   1037:            case IO_R_SUCCESS:
                   1038:                return(0);
                   1039:            case IO_R_NO_MEMORY:
                   1040:            case IO_R_RESOURCE:
                   1041:                return(ENOMEM);
                   1042:            case IO_R_NO_DEVICE:
                   1043:                return(ENXIO);
                   1044:            case IO_R_PRIVILEGE:
                   1045:            case IO_R_LOCKED_READ:
                   1046:            case IO_R_LOCKED_WRITE:
                   1047:            case IO_R_EXCLUSIVE_ACCESS:
                   1048:            case IO_R_CANT_LOCK:
                   1049:            case IO_R_NOT_READABLE:
                   1050:            case IO_R_NOT_OPEN:
                   1051:                return(EACCES);
                   1052:            case IO_R_INVALID_ARG:
                   1053:                return(EINVAL);
                   1054:            case IO_R_UNSUPPORTED:
                   1055:                return(EOPNOTSUPP);
                   1056:            case IO_R_IO:
                   1057:            case IO_R_MEDIA:
                   1058:            case IO_R_DMA:
                   1059:                return(EIO);
                   1060:            case IO_R_NOT_WRITABLE:
                   1061:                return(EROFS);
                   1062:            case IO_R_OPEN:
                   1063:            case IO_R_BUSY:
                   1064:                return(EBUSY);
                   1065:            default:
                   1066:                return(EIO);
                   1067:        }
                   1068: }
                   1069: 
                   1070: @end   /* IODevice */
                   1071: 
                   1072: @implementation IODevice(Internal)
                   1073: 
                   1074: @end   /* IODevice(Internal) */
                   1075: 
                   1076: /*
                   1077:  * Get/set parameter RPC support. In the kernel, these methods are mainly 
                   1078:  * called by the driverServer (although they cal be used by anyone); they 
                   1079:  * map an objectNumber to an id and invoke the appropriate methods. Usage in
                   1080:  * user space TBD.
                   1081:  */
                   1082:  
                   1083: @implementation IODevice(GlobalParameter)
                   1084: 
                   1085: #if KERNEL
                   1086: + (IOReturn) serverConnect: (port_t *)       machPort   // out - IOTask space
                   1087:              objectNumber: (IOObjectNumber) objectNumber
                   1088:                  taskPort: (port_t)         taskPort;  // in  - ipc_port_t
                   1089: {
                   1090:     IODevice *instance;
                   1091:     IOReturn rtn = IO_R_SUCCESS;
                   1092: 
                   1093:     [objectListLock lock];
                   1094:     rtn = objectNumToId(objectNumber, (id) &instance);
                   1095:     [objectListLock unlock];
                   1096: 
                   1097:     if (rtn == IO_R_SUCCESS)
                   1098:        rtn = [instance serverConnect: machPort taskPort: taskPort];
                   1099: 
                   1100:     return rtn;
                   1101: }
                   1102: #endif /* KERNEL */
                   1103: 
                   1104: /*
                   1105:  * Lookup by IOObjectNumber.
                   1106:  */
                   1107: + (IOReturn)lookupByObjectNumber        : (IOObjectNumber)objectNumber
                   1108:                              deviceKind : (IOString *)deviceKind
                   1109:                              deviceName : (IOString *)deviceName;
                   1110: {
                   1111:        id instance;
                   1112:        IOReturn rtn = IO_R_SUCCESS;
                   1113:        
                   1114:        [objectListLock lock];
                   1115:        rtn = objectNumToId(objectNumber, &instance);
                   1116:        [objectListLock unlock];
                   1117:        if(rtn == IO_R_SUCCESS)  {
                   1118:                strncpy(*deviceKind, [instance deviceKind], IO_STRING_LENGTH);
                   1119:                strncpy(*deviceName, [instance name], IO_STRING_LENGTH);
                   1120:        }
                   1121:        return rtn;
                   1122: }
                   1123: 
                   1124: + (IOReturn)lookupByObjectNumber       : (IOObjectNumber)objectNumber
                   1125:                               instance : (id *)instance
                   1126: {
                   1127:        IOReturn rtn;
                   1128:        
                   1129:        [objectListLock lock];
                   1130:        rtn = objectNumToId(objectNumber, instance);
                   1131:        [objectListLock unlock];
                   1132:        return rtn;
                   1133: }
                   1134: 
                   1135: /*
                   1136:  * Lookup by deviceName.
                   1137:  */
                   1138: + (IOReturn)lookupByDeviceName         : (IOString)deviceName
                   1139:                           objectNumber : (IOObjectNumber *)objectNumber
                   1140:                             deviceKind : (IOString *)deviceKind;
                   1141: {
                   1142:        id instance;
                   1143:        IOReturn rtn = IO_R_SUCCESS;
                   1144:        
                   1145:        [objectListLock lock];
                   1146:        rtn = deviceNameToId(deviceName, &instance, objectNumber);
                   1147:        [objectListLock unlock];
                   1148:        if(rtn == IO_R_SUCCESS)  {
                   1149:                strncpy(*deviceKind, [instance deviceKind], IO_STRING_LENGTH);
                   1150:        }
                   1151:        return rtn;
                   1152: }
                   1153: 
                   1154: + (IOReturn) lookUpByStringPropertyList:(char *)values
                   1155:        results:(char *)results
                   1156:        maxLength:(unsigned int)length
                   1157: {
                   1158:     IOReturn           err;
                   1159:     int                        objectNum = 0;
                   1160:     id                 dev;
                   1161:     const char *       newName;
                   1162: 
                   1163:     *results = 0;
                   1164:     [objectListLock lock];
                   1165:     do {
                   1166:         err = objectNumToId(objectNum++, &dev);
                   1167:         if( err != IO_R_SUCCESS)
                   1168:             continue;
                   1169: 
                   1170:         if( [dev matchStringPropertyList:values]) {
                   1171: 
                   1172:            newName = [dev name];
                   1173:            if( (1 + 1 + strlen( newName)) < length) {          // space & zero chars
                   1174:                if( results[ 0 ]) {
                   1175:                     strcat( results, " ");
                   1176:                    length--;
                   1177:                }
                   1178:                 strcat( results, newName );
                   1179:                length -= strlen( newName);
                   1180:            } else
                   1181:                err = IO_R_RESOURCE;
                   1182:        }
                   1183:     } while( (err == IO_R_SUCCESS) || (err == IO_R_OFFLINE));
                   1184: 
                   1185:     [objectListLock unlock];
                   1186: 
                   1187:     if( err == IO_R_NO_DEVICE)
                   1188:        err = IO_R_SUCCESS;
                   1189: 
                   1190:     return( err);
                   1191: }
                   1192: 
                   1193: + (IOReturn)getIntValues               : (unsigned *)parameterArray
                   1194:                           forParameter : (IOParameterName)parameterName
                   1195:                           objectNumber : (IOObjectNumber)objectNumber
                   1196:                                  count : (unsigned *)count     // in/out
                   1197: {
                   1198:        id instance;
                   1199:        IOReturn rtn = IO_R_SUCCESS;
                   1200:        
                   1201:        [objectListLock lock];
                   1202:        rtn = objectNumToId(objectNumber, &instance);
                   1203:        [objectListLock unlock];
                   1204:        if(rtn == IO_R_SUCCESS)  {
                   1205:                rtn = [instance getIntValues : parameterArray
                   1206:                        forParameter : parameterName
                   1207:                        count : count];
                   1208:        }
                   1209:        return rtn;
                   1210: 
                   1211: }
                   1212: 
                   1213: + (IOReturn)getCharValues              : (unsigned char *)parameterArray
                   1214:                           forParameter : (IOParameterName)parameterName
                   1215:                           objectNumber : (IOObjectNumber)objectNumber
                   1216:                                  count : (unsigned *)count     // in/out
                   1217: {
                   1218:        id instance;
                   1219:        IOReturn rtn = IO_R_SUCCESS;
                   1220:        
                   1221:        [objectListLock lock];
                   1222:        rtn = objectNumToId(objectNumber, &instance);
                   1223:        [objectListLock unlock];
                   1224:        if(rtn == IO_R_SUCCESS)  {
                   1225:                rtn = [instance getCharValues : parameterArray
                   1226:                        forParameter : parameterName
                   1227:                        count : count];
                   1228:        }
                   1229:        return rtn;
                   1230: 
                   1231: }
                   1232: 
                   1233: + (IOReturn)setIntValues               : (unsigned *)parameterArray
                   1234:                           forParameter : (IOParameterName)parameterName
                   1235:                           objectNumber : (IOObjectNumber)objectNumber
                   1236:                                  count : (unsigned)count
                   1237: {
                   1238:        id instance;
                   1239:        IOReturn rtn = IO_R_SUCCESS;
                   1240:        
                   1241:        [objectListLock lock];
                   1242:        rtn = objectNumToId(objectNumber, &instance);
                   1243:        [objectListLock unlock];
                   1244:        if(rtn == IO_R_SUCCESS)  {
                   1245:                rtn = [instance setIntValues : parameterArray
                   1246:                        forParameter : parameterName
                   1247:                        count : count];
                   1248:        }
                   1249:        return rtn;
                   1250: 
                   1251: }
                   1252: 
                   1253: 
                   1254: + (IOReturn)setCharValues              : (unsigned char *)parameterArray
                   1255:                           forParameter : (IOParameterName)parameterName
                   1256:                           objectNumber : (IOObjectNumber)objectNumber
                   1257:                                  count : (unsigned)count
                   1258: {
                   1259:        id instance;
                   1260:        IOReturn rtn = IO_R_SUCCESS;
                   1261:        
                   1262:        [objectListLock lock];
                   1263:        rtn = objectNumToId(objectNumber, &instance);
                   1264:        [objectListLock unlock];
                   1265:        if(rtn == IO_R_SUCCESS)  {
                   1266:                rtn = [instance setCharValues : parameterArray
                   1267:                        forParameter : parameterName
                   1268:                        count : count];
                   1269:        }
                   1270:        return rtn;
                   1271: 
                   1272: }
                   1273: 
                   1274: + (IOReturn) getStringPropertyList             : (IOObjectNumber)objectNumber
                   1275:                           names        : (const char *)names
                   1276:                           results      : (char *)results
                   1277:                           maxLength    : (unsigned int)length
                   1278: {
                   1279:        id instance;
                   1280:        IOReturn rtn = IO_R_SUCCESS;
                   1281:        
                   1282:        [objectListLock lock];
                   1283:        rtn = objectNumToId(objectNumber, &instance);
                   1284:        [objectListLock unlock];
                   1285:        if(rtn == IO_R_SUCCESS)  {
                   1286:                instance = [instance getStringPropertyList : names
                   1287:                        results : results
                   1288:                        maxLength : length];
                   1289:                if( !instance)
                   1290:                    rtn = IO_R_UNSUPPORTED;
                   1291:        }
                   1292:        return rtn;
                   1293: }
                   1294: 
                   1295: + (IOReturn) getByteProperty           : (IOObjectNumber)objectNumber
                   1296:                           name         : (const char *)name
                   1297:                           results      : (char *)results
                   1298:                           maxLength    : (unsigned int *)length
                   1299: {
                   1300:        id instance;
                   1301:        IOReturn rtn = IO_R_SUCCESS;
                   1302:        
                   1303:        [objectListLock lock];
                   1304:        rtn = objectNumToId(objectNumber, &instance);
                   1305:        [objectListLock unlock];
                   1306:        if(rtn == IO_R_SUCCESS)  {
                   1307:                instance = [instance lookUpProperty : name
                   1308:                        value : results
                   1309:                        length : length];
                   1310:                if( !instance)
                   1311:                    rtn = IO_R_UNSUPPORTED;
                   1312:        }
                   1313:        return rtn;
                   1314: }
                   1315: 
                   1316: + (IOReturn)callDeviceMethod           : (IOString)methodName
                   1317:                    inputParams         : (unsigned char *)inputParams
                   1318:                    inputCount          : (unsigned)inputCount
                   1319:                    outputParams        : (unsigned char *)outputParams
                   1320:                    outputCount         : (unsigned *)outputCount       // in/out
                   1321:                    privileged          : (host_priv_t *)privileged
                   1322:                    objectNumber        : (IOObjectNumber)objectNumber
                   1323: 
                   1324: {
                   1325:     id                 instance;
                   1326:     IOReturn   rtn = IO_R_SUCCESS;
                   1327:     SEL                selector;
                   1328:     
                   1329:     [objectListLock lock];
                   1330:     rtn = objectNumToId(objectNumber, &instance);
                   1331:     [objectListLock unlock];
                   1332:     if(rtn == IO_R_SUCCESS)  {
                   1333: 
                   1334:        selector = sel_getUid( methodName );
                   1335:        if( NO == [instance respondsTo:selector])
                   1336:            rtn = IO_R_UNSUPPORTED;
                   1337: 
                   1338:        else if( *outputCount) {
                   1339:            if( inputCount) {
                   1340:                rtn = (IOReturn) objc_msgSend( instance, selector,
                   1341:                        inputParams, inputCount, outputParams, outputCount,
                   1342:                        privileged );
                   1343:            } else {
                   1344:                rtn = (IOReturn) objc_msgSend( instance, selector,
                   1345:                        outputParams, outputCount,
                   1346:                        privileged );
                   1347:            }
                   1348:        } else {
                   1349:            if( inputCount) {
                   1350:                rtn = (IOReturn) objc_msgSend( instance, selector,
                   1351:                        inputParams, inputCount,
                   1352:                        privileged );
                   1353:            } else {
                   1354:                rtn = (IOReturn) objc_msgSend( instance, selector,
                   1355:                        privileged );
                   1356:            }
                   1357:        }
                   1358:     }
                   1359:     return rtn;
                   1360: }
                   1361: 
                   1362: 
                   1363: @end   /* IODevice(GlobalParameter) */
                   1364: 
                   1365: #ifdef KERNEL
                   1366: 
                   1367: /*
                   1368:  * We leave this enabled for user level programs for now; it may be useful...
                   1369:  */
                   1370: @implementation IODevice(kernelPrivate)
                   1371: 
                   1372: /*
                   1373:  * A new class has been loaded into the kernel. Connect the new class
                   1374:  * with all existing classes, probing as appropriate.
                   1375:  * 
                   1376:  * All instance variables in deviceDescription must be valid or 
                   1377:  * null. For newly loaded indirect devices, this method will determine
                   1378:  * appropriate directDevice values. 
                   1379:  *
                   1380:  * Returns IO_R_NO_DEVICE if no devices were instantiated, else IO_R_SUCCESS.
                   1381:  */
                   1382: + (IOReturn)addLoadedClass : newClass
                   1383:               description : deviceDescription
                   1384: {
                   1385:        IOReturn        rtn = 0;
                   1386:        Protocol        **protos;
                   1387:        IOObjectNumber  objectNum = 0;
                   1388:        id              dirDevice;
                   1389:        BOOL            objsCreated = NO;
                   1390:        int             i;
                   1391:        classListEntry *classEntry;
                   1392:        
                   1393:        if (getClassListEntryForId(newClass, &classEntry) == IO_R_SUCCESS)
                   1394:            classEntry->originalDeviceDescription = deviceDescription;
                   1395: 
                   1396:        switch([newClass deviceStyle]) {
                   1397:            case IO_IndirectDevice:
                   1398:                /* 
                   1399:                 * First probe this class once for all other running objects
                   1400:                 * which export the protocol(s) required by this indirect
                   1401:                 * device. 
                   1402:                 * Note all deviceStyles can export a protocol, not just direct 
                   1403:                 * devices.
                   1404:                 */
                   1405:                protos = [newClass requiredProtocols];
                   1406:                if((protos == NULL) || (*protos == nil)) {
                   1407:                        /*
                   1408:                         * This indirect device does not require any
                   1409:                         * protocols. Huh???
                   1410:                         */
                   1411:                        IOLog("Loaded class %s returns nil for "
                   1412:                                "+requiredProtocols\n",
                   1413:                                [newClass name]);
                   1414:                        break;
                   1415:                }
                   1416:                
                   1417:                /*
                   1418:                 * Cycle thru all known devices.
                   1419:                 */
                   1420:                for(objectNum=0; rtn!=IO_R_NO_DEVICE; objectNum++) {
                   1421:                    rtn = objectNumToId(objectNum, &dirDevice);
                   1422:                    switch(rtn) {
                   1423:                        case IO_R_OFFLINE:
                   1424:                            /*
                   1425:                             * No device here, but more to go.
                   1426:                             */
                   1427:                            continue;
                   1428:                            
                   1429:                        case IO_R_NO_DEVICE: 
                   1430:                        default:
                   1431:                            /*
                   1432:                             * No more.
                   1433:                             */
                   1434:                            break;
                   1435:                        
                   1436:                        case IO_R_SUCCESS:
                   1437:                            /*
                   1438:                             * See if this thing supports all the 
                   1439:                             * protocols newClass needs.
                   1440:                             */
                   1441:                            for(i=0; protos[i]; i++) {
                   1442:                                 if(![dirDevice conformsTo:protos[i]]) {
                   1443:                                     goto next_object; /* to next objectNum */
                   1444:                                 }
                   1445:                            }
                   1446:                            
                   1447:                            /*
                   1448:                             * Looks good. Cook up an IODeviceDescription
                   1449:                             * we can pass to newClass.
                   1450:                             */
                   1451:                            [deviceDescription setDirectDevice:dirDevice];
                   1452:                            if([newClass probe:deviceDescription]) {
                   1453:                                objsCreated = YES;
                   1454:                            }
                   1455:                            break;
                   1456:                    }   /* switch rtn */
                   1457: next_object:
                   1458:                    continue;
                   1459:                }       /* for each objectNum */
                   1460:                
                   1461:                break;  /* from case IO_STYLE_INDIRECT */
                   1462:     
                   1463:            case IO_DirectDevice:
                   1464:            case IO_PseudoDevice:
                   1465:                if (![newClass respondsTo:@selector(probe:)]) {
                   1466:                        IOLog("addLoadedClass: Class %s does not "
                   1467:                                "respond to probe:\n",
                   1468:                                [newClass name]);
                   1469:                        break;
                   1470:                }
                   1471:                if([newClass probe:deviceDescription]) {
                   1472:                    objsCreated = YES;
                   1473:                }
                   1474:                break;
                   1475:            
                   1476:        } /* switch deviceStyle */
                   1477:        
                   1478:        if(objsCreated) {
                   1479:                return IO_R_SUCCESS;
                   1480:        }
                   1481:        else {
                   1482:                return IO_R_NO_DEVICE;
                   1483:        }
                   1484: }      
                   1485: 
                   1486: /*
                   1487:  * Probe for any indirect device classes in the system which are 
                   1488:  * interested in connecting to a newly instantiated device of any kind.
                   1489:  * Used only by -registerDevice (so far).
                   1490:  */
                   1491: +(void)connectToIndirectDevices : newObject
                   1492: {
                   1493:        unsigned        classNumber = 0;
                   1494:        Protocol        **protos;
                   1495:        IOReturn        rtn;
                   1496:        classListEntry  *classEntry;
                   1497:        int             i;
                   1498:        id              deviceDescription;
                   1499:        
                   1500:        /*
                   1501:         * We hold classListLock throughout this routine, except for when
                   1502:         * we actually probe an indirect device class.
                   1503:         */
                   1504:        [classListLock lock];
                   1505:        for(classNumber=0; ;classNumber++) {
                   1506:                /*
                   1507:                 * Check out each indirect driver class in classList.
                   1508:                 */
                   1509:                rtn = getClassListEntry(classNumber, &classEntry);
                   1510:                switch(rtn) {
                   1511:                    case IO_R_SUCCESS:
                   1512:                        break;                  // proceed
                   1513:                    case IO_R_NO_DEVICE:        
                   1514:                        goto done;              // normal termination
                   1515:                    case IO_R_OFFLINE:
                   1516:                        goto next_class;        // hole in classList space
                   1517:                }
                   1518:                if([classEntry->classId deviceStyle] != IO_IndirectDevice) {
                   1519:                        goto next_class;
                   1520:                }
                   1521:                
                   1522:                /*
                   1523:                 * We have an indirect device class. See if the protocols
                   1524:                 * it requires are supported by the new object.
                   1525:                 */
                   1526:                protos = [classEntry->classId requiredProtocols];
                   1527:                if((protos == NULL) || (*protos == nil)) {
                   1528:                        /*
                   1529:                         * This indirect device does not require any
                   1530:                         * protocols. Huh???
                   1531:                         */
                   1532:                        IOLog("Loaded class %s returns nil for "
                   1533:                                "+requiredProtocols\n",
                   1534:                                [classEntry->classId name]);
                   1535:                        goto next_class;
                   1536:                }
                   1537:                for(i=0; protos[i]; i++) {
                   1538:                        if(![newObject conformsTo:protos[i]]) {
                   1539:                                goto next_class;
                   1540:                        }
                   1541:                }
                   1542:                
                   1543:                /*
                   1544:                 * Looks good. Cook up an IODeviceDescription we can pass 
                   1545:                 * to the indirect driver class and probe away.
                   1546:                 */
                   1547:                if (classEntry->originalDeviceDescription != nil)
                   1548:                    deviceDescription = classEntry->originalDeviceDescription;
                   1549:                else
                   1550:                    deviceDescription = [[IODeviceDescription alloc] init];
                   1551:                [deviceDescription setDirectDevice:newObject];
                   1552:                [classListLock unlock];
                   1553:                if ([classEntry->classId probe:deviceDescription] == NO)
                   1554:                    [deviceDescription free];
                   1555:                [classListLock lock];
                   1556: 
                   1557: next_class:
                   1558:                continue;
                   1559:        }
                   1560: done:
                   1561:        [classListLock unlock];
                   1562:        return;
                   1563: }
                   1564: 
                   1565: + (List *)objectsForClass:(Class *)driverClass
                   1566: {
                   1567:        id list;
                   1568:        objectListEntry *objectEntry = 
                   1569:                (objectListEntry *)queue_first(&objectList);
                   1570:        
                   1571:        list = [[List alloc] init];
                   1572:        [objectListLock lock];
                   1573:        while(!queue_end(&objectList, (queue_t)objectEntry)) {
                   1574:                if((Class *)[objectEntry->instance class] == driverClass) {
                   1575:                        [list addObject:objectEntry->instance];
                   1576:                }
                   1577:                objectEntry = (objectListEntry *)objectEntry->link.next;
                   1578:        }
                   1579:        [objectListLock unlock];
                   1580:        return list;
                   1581: }
                   1582: 
                   1583: #if 0
                   1584: + (HashTable *)classTableFromConfigTable : configTable
                   1585: {
                   1586:     char *classNameList, *className, *ptr, *str;
                   1587:     int len;
                   1588:     HashTable *hash;
                   1589:     
                   1590:     classNameList = (char *)[configTable valueForStringKey:"Class Names"];
                   1591:     if (classNameList == NULL)
                   1592:        classNameList = (char *)[configTable valueForStringKey:"Driver Name"];
                   1593:     if (classNameList == NULL)
                   1594:        return nil;
                   1595: 
                   1596:     len = strlen(classNameList);
                   1597:     hash = [[HashTable alloc] initKeyDesc:"*"];
                   1598:     className = classNameList;
                   1599:     while (*className) {
                   1600:        ptr = className;
                   1601:        while (*ptr && *ptr != ' ' && *ptr != '\t')
                   1602:            ptr++;
                   1603:        len = ptr - className + 1;
                   1604:        str = IOMalloc(len);
                   1605:        strncpy(str, className, len - 1);
                   1606:        str[len-1] = '\0';
                   1607:        [hash insertKey:str value:objc_getClass(str)];
                   1608:        while (*ptr && (*ptr == ' ' || *ptr == '\t'))
                   1609:            ptr++;
                   1610:        className = ptr;
                   1611:     }
                   1612:     [configTable freeString:classNameList];
                   1613: 
                   1614:     return hash;
                   1615: }
                   1616: #endif
                   1617: 
                   1618: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
                   1619: {
                   1620:     return( nil);
                   1621: }
                   1622: 
                   1623: - property_IODeviceType:(char *)classes length:(unsigned int *)maxLen
                   1624: {
                   1625:     return( nil);
                   1626: }
                   1627: 
                   1628: @end   /* IODevice(kernelPrivate) */
                   1629: 
                   1630: /*
                   1631:  * Lookup by deviceName, kernel internal version. Returns id of specified
                   1632:  * instance in deviceId. 
                   1633:  */
                   1634: IOReturn IOGetObjectForDeviceName(
                   1635:        IOString deviceName,
                   1636:        id *deviceId)                           // returned
                   1637: {
                   1638:        IOReturn rtn;
                   1639:        IOObjectNumber objectNumber;
                   1640:        
                   1641:        [objectListLock lock];
                   1642:        rtn = deviceNameToId(deviceName, deviceId, &objectNumber);
                   1643:        [objectListLock unlock];
                   1644:        return rtn;
                   1645: }
                   1646: 
                   1647: #endif KERNEL
                   1648: 
                   1649: 
                   1650: /*
                   1651:  * Static functions.
                   1652:  */
                   1653:  
                   1654: /*
                   1655:  * Get id of specified global objectNumber. objectListLock must be held on 
                   1656:  * entry.
                   1657:  * Returns IO_R_OFFLINE if a hole is found in IOObjectNumber space at 
                   1658:  * specified objectNumber. Returns IO_R_NO_DEVICE if objectNumber is out
                   1659:  * of range.
                   1660:  */
                   1661: static IOReturn objectNumToId(IOObjectNumber objectNumber, id *instance)
                   1662: {
                   1663:        objectListEntry *objectEntry = 
                   1664:                (objectListEntry *)queue_first(&objectList);
                   1665:        
                   1666:        if(objectNumber >= globalObjectCounter)
                   1667:                return IO_R_NO_DEVICE;
                   1668:        while(!queue_end(&objectList, (queue_t)objectEntry)) {
                   1669:                if(objectEntry->objectNumber == objectNumber) {
                   1670:                        *instance = objectEntry->instance;
                   1671:                        return IO_R_SUCCESS;
                   1672:                }
                   1673:                else
                   1674:                        objectEntry = 
                   1675:                                (objectListEntry *)objectEntry->link.next;
                   1676:        }
                   1677:        
                   1678:        /*
                   1679:         * Not found. This implies a "hole" in the objectNumber space.
                   1680:         */
                   1681:        return IO_R_OFFLINE;
                   1682: } 
                   1683: 
                   1684: /*
                   1685:  * Get id of device with specified name. objectListLock must be held on entry.
                   1686:  */
                   1687: static IOReturn deviceNameToId(IOString name, 
                   1688:        id *instance,
                   1689:        IOObjectNumber *objectNumber)
                   1690: {
                   1691:        objectListEntry *objectEntry = 
                   1692:                (objectListEntry *)queue_first(&objectList);
                   1693:        
                   1694:        while(!queue_end(&objectList, (queue_t)objectEntry)) {
                   1695:                if(strncmp(name, [objectEntry->instance name],
                   1696:                    IO_STRING_LENGTH) == 0) {
                   1697:                        *instance     = objectEntry->instance;
                   1698:                        *objectNumber = objectEntry->objectNumber;
                   1699:                        return IO_R_SUCCESS;
                   1700:                }
                   1701:                else {
                   1702:                        objectEntry = 
                   1703:                                (objectListEntry *)objectEntry->link.next;
                   1704:                }
                   1705:        }
                   1706:        
                   1707:        /*
                   1708:         * Not found. 
                   1709:         */
                   1710:        return IO_R_NO_DEVICE;
                   1711: } 
                   1712: 
                   1713: /*
                   1714:  * Get an instance's objectNum-to-id map entry. objectListLock must be held
                   1715:  * on entry.
                   1716:  */
                   1717: static objectListEntry *getObjectListEntry(id object)
                   1718: {
                   1719:        objectListEntry *objectEntry;
                   1720:        
                   1721:        objectEntry = (objectListEntry *)queue_first(&objectList);
                   1722:        while(!queue_end(&objectList, (queue_t)objectEntry)) {
                   1723:                if(objectEntry->instance == object) {
                   1724:                        goto out;
                   1725:                }
                   1726:                else {
                   1727:                        objectEntry = 
                   1728:                                (objectListEntry *)objectEntry->link.next;
                   1729:                }
                   1730:        }
                   1731:        objectEntry = NULL;
                   1732: out:
                   1733:        return objectEntry;
                   1734: }
                   1735: 
                   1736: /*
                   1737:  * Get a classListEntry for specified class id.
                   1738:  */
                   1739: static IOReturn getClassListEntryForId(
                   1740:     id classId,
                   1741:     classListEntry **entry
                   1742: )
                   1743: {
                   1744:     classListEntry *classEntry;
                   1745:     
                   1746:     [classListLock lock];
                   1747:     classEntry = (classListEntry *)queue_first(&classList);
                   1748:     while(!queue_end(&classList, (queue_t)classEntry)) {
                   1749:        if(classEntry->classId == classId) {
                   1750:            *entry = classEntry;
                   1751:            [classListLock unlock];
                   1752:            return IO_R_SUCCESS;
                   1753:        }
                   1754:        classEntry = (classListEntry *)classEntry->link.next;
                   1755:     }
                   1756:     [classListLock unlock];
                   1757:     return IO_R_OFFLINE;
                   1758: }
                   1759: 
                   1760: /*
                   1761:  * Get a classListEntry for specified classNumber. classListLock must be held
                   1762:  * on entry. 
                   1763:  * Returns IO_R_OFFLINE if a hole is found in classNumber space at 
                   1764:  * specified classNumber. Returns IO_R_NO_DEVICE if classNumber is out
                   1765:  * of range.
                   1766:  */
                   1767: static IOReturn getClassListEntry(unsigned classNumber,
                   1768:        classListEntry  **entry)
                   1769: {
                   1770:        classListEntry *classEntry;
                   1771:        
                   1772:        if(classNumber > classCounter) {
                   1773:                return IO_R_NO_DEVICE;
                   1774:        }
                   1775:        classEntry = (classListEntry *)queue_first(&classList);
                   1776:        while(!queue_end(&classList, (queue_t)classEntry)) {
                   1777:                if(classEntry->classNumber == classNumber) {
                   1778:                        *entry = classEntry;
                   1779:                        return IO_R_SUCCESS;
                   1780:                }
                   1781:                classEntry = (classListEntry *)classEntry->link.next;
                   1782:        }
                   1783:        return IO_R_OFFLINE;
                   1784: }
                   1785: 
                   1786: /* end of IODevice.m */

unix.superglobalmegacorp.com

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