Annotation of driverkit/libDriver/IODevice.m, revision 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.