Annotation of kernel/driverkit/KernDeviceDescription.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: 
        !            25: /*
        !            26:  * Copyright (c) 1994 NeXT Computer, Inc.
        !            27:  *
        !            28:  * Kernel Device Description Object.
        !            29:  *
        !            30:  * HISTORY
        !            31:  *
        !            32:  * 24 Feb 1994 ? at NeXT
        !            33:  *     Major rewrite.
        !            34:  * 17 Jan 1994 ? at NeXT
        !            35:  *     Created.
        !            36:  */
        !            37: 
        !            38: #import <objc/List.h>
        !            39: #import <objc/HashTable.h>
        !            40: #import <driverkit/KernBus.h>
        !            41: #import <driverkit/KernDeviceDescription.h>
        !            42: #import <driverkit/IOConfigTable.h>
        !            43: 
        !            44: #define IRQ_LEVELS_KEY         "IRQ Levels"    // XXX
        !            45: #define BUS_TYPE_KEY           "Bus Type"      // XXX
        !            46: #define BUS_ID_KEY             "Bus ID"        // XXX
        !            47: 
        !            48: static
        !            49: boolean_t
        !            50: parsenum(const char *nptr, char **endptr, unsigned long *result);
        !            51: 
        !            52: @interface KernDeviceDescription (Parsing)
        !            53: - (BOOL)_isShared:(const char *)key;
        !            54: - _parseRangeResourceByKey :(const char *)key value:(const char *)value;
        !            55: - _parseItemResourceByKey :(const char *)key value:(const char *)value;
        !            56: @end
        !            57: 
        !            58: static const char *
        !            59: newString(const char *oldString)
        !            60: {
        !            61:     return strcpy((char *)IOMalloc(strlen(oldString)+1), oldString);
        !            62: }
        !            63: 
        !            64: static void
        !            65: nullFunc(void *null)
        !            66: {
        !            67: }
        !            68: 
        !            69: static void
        !            70: freeString(void *string)
        !            71: {
        !            72:     IOFree(string, strlen(string)+1);
        !            73: }
        !            74: 
        !            75: static void
        !            76: freeResources(void *_resource)
        !            77: {
        !            78:     id resource = (id)_resource;
        !            79:     [resource freeObjects];
        !            80:     [resource free];
        !            81: }
        !            82: 
        !            83: static BOOL isInterrupt(const char *key)
        !            84: {
        !            85:     if (strcmp(key, IRQ_LEVELS_KEY) == 0)      // XXX
        !            86:         return YES;
        !            87:     return NO;
        !            88: }
        !            89: 
        !            90: @implementation KernDeviceDescription
        !            91: 
        !            92: - initFromConfigTable: configTable
        !            93: {
        !            94:     const char *busName;
        !            95:     const char *str;
        !            96:     unsigned long num;
        !            97:     
        !            98:     [super init];
        !            99:     
        !           100:     _configTable = configTable;
        !           101:     _device = nil;
        !           102:     _stringTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"*"];
        !           103:     _resourceTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"@"];
        !           104:     _interruptList = [[List alloc] init];
        !           105:     busName = [_configTable valueForStringKey:BUS_TYPE_KEY];
        !           106:     _busClass = [KernBus lookupBusClassWithName:busName];
        !           107:     str = [_configTable valueForStringKey:BUS_ID_KEY];
        !           108:     if (str && parsenum(str, 0, &num))
        !           109:        _busId = num;
        !           110:     _bus = [KernBus lookupBusInstanceWithName:busName busId:_busId];
        !           111:     if (str) [_configTable freeString:str];
        !           112:     if (busName) [_configTable freeString:busName];
        !           113:     return self;
        !           114: }
        !           115: 
        !           116: - init
        !           117: {
        !           118:     return [self initFromConfigTable:nil];
        !           119: }
        !           120: 
        !           121: - free
        !           122: {
        !           123:     [_stringTable freeKeys:nullFunc values:freeString];
        !           124:     [_stringTable free];
        !           125:     [_resourceTable freeKeys:nullFunc values:freeResources];
        !           126:     [_resourceTable free];
        !           127:     [_interruptList free];
        !           128:     return [super free];
        !           129: }
        !           130: 
        !           131: - configTable
        !           132: {
        !           133:     return _configTable;
        !           134: }
        !           135: 
        !           136: - setDevice:           device
        !           137: {
        !           138:     if (_device == nil || device == nil)
        !           139:        _device = device;
        !           140:        
        !           141:     if (_device != device)
        !           142:        return nil;
        !           143:        
        !           144:     return device;
        !           145: }
        !           146: 
        !           147: - device
        !           148: {
        !           149:     return _device;
        !           150: }
        !           151: 
        !           152: - busClass
        !           153: {
        !           154:     return _busClass;
        !           155: }
        !           156: 
        !           157: - setBus: bus
        !           158: {
        !           159:     _bus = bus;
        !           160:     return bus;
        !           161: }
        !           162: 
        !           163: - bus
        !           164: {
        !           165:     return _bus;
        !           166: }
        !           167: 
        !           168: - (const char *)stringForKey:(const char *)aKey
        !           169: {
        !           170:     const char *value;
        !           171:     
        !           172:     value = [_stringTable valueForKey:aKey];
        !           173:     if (value == NULL) {
        !           174:        value = [_configTable valueForStringKey:aKey];
        !           175:        if (value != NULL)
        !           176:            [_stringTable insertKey:aKey value:(char *)value];
        !           177:     }
        !           178:     return value;
        !           179: }
        !           180: 
        !           181: - resourcesForKey:(const char *)aKey
        !           182: {
        !           183:     return [_resourceTable valueForKey:aKey];
        !           184: }
        !           185: 
        !           186: - setString:(const char *)aString forKey:(const char *)aKey
        !           187: {
        !           188:     char *old, *new;
        !           189:     
        !           190:     new = (char *)newString(aString);
        !           191:     old = (char *)[_stringTable insertKey:aKey value:new];
        !           192: 
        !           193:     if (old)
        !           194:           freeString(old);
        !           195: 
        !           196:     return self;
        !           197: }
        !           198: 
        !           199: - setResources:resources forKey:(const char *)aKey
        !           200: {
        !           201:     id old;
        !           202:     
        !           203:     if (isInterrupt(aKey)) {
        !           204:        [_interruptList empty];
        !           205:        [_interruptList appendList:resources];
        !           206:     }
        !           207:     
        !           208:     old = [_resourceTable insertKey:aKey value:resources];
        !           209:     if (old && old != resources)
        !           210:        freeResources(old);
        !           211:     return self;
        !           212: }
        !           213: 
        !           214: - (BOOL)removeStringForKey:(const char *)aKey
        !           215: {
        !           216:     char *str;
        !           217:     
        !           218:     str = (char *)[_stringTable removeKey:aKey];
        !           219:     if (str) {
        !           220:        freeString(str);
        !           221:        return YES;
        !           222:     }
        !           223:     return NO;
        !           224: }
        !           225: 
        !           226: - (BOOL)removeResourcesForKey:(const char *)aKey
        !           227: {
        !           228:     id old;
        !           229:     
        !           230:     old = [_resourceTable removeKey:aKey];
        !           231:     if (old != nil) {
        !           232:        if (isInterrupt(aKey)) {
        !           233:            int i;
        !           234:            for (i=0; i < [old count]; i++)
        !           235:                [_interruptList removeObject:[old objectAt:i]];
        !           236:        }
        !           237:        freeResources(old);
        !           238:     }
        !           239:     return NO;
        !           240: }
        !           241: 
        !           242: - interrupts
        !           243: {
        !           244:     return _interruptList;
        !           245: }
        !           246: 
        !           247: - (NXHashState)initStringState
        !           248: {
        !           249:     return [_stringTable initState];
        !           250: }
        !           251: 
        !           252: - (BOOL)nextStringState:(NXHashState *)aState key:(const char **)aKey 
        !           253:        value:(char **)aValue
        !           254: {
        !           255:     return [_stringTable nextState:aState key:(void **)aKey
        !           256:                                          value:(void **)aValue];
        !           257: }
        !           258: 
        !           259: - (NXHashState)initResourcesState
        !           260: {
        !           261:     return [_resourceTable initState];
        !           262: }
        !           263: 
        !           264: - (BOOL)nextResourcesState:(NXHashState *)aState key:(const char **)aKey 
        !           265:        value:(id *)aValue
        !           266: {
        !           267:     return [_resourceTable nextState:aState key:(void **)aKey
        !           268:                                            value:(void **)aValue];
        !           269: }
        !           270: 
        !           271: - allocateResourcesForKey: (const char *)key
        !           272: {
        !           273:     const char         *keyValue;
        !           274:     id                 resourceList;
        !           275:     
        !           276:     keyValue = [self stringForKey:key];
        !           277:     /*
        !           278:      * No resources of this type are needed --
        !           279:      * this is not an error.
        !           280:      */
        !           281:     if (keyValue == NULL)
        !           282:        return self;
        !           283:        
        !           284:     if (strchr(keyValue, '-'))
        !           285:        resourceList = [self _parseRangeResourceByKey:key value:keyValue];
        !           286:     else
        !           287:        resourceList = [self _parseItemResourceByKey:key value:keyValue];
        !           288: 
        !           289:     if (resourceList == nil) {
        !           290:        /*
        !           291:         * A resource was requested and was not available.
        !           292:         * This is an error.
        !           293:         */
        !           294:        return nil;
        !           295:     }
        !           296:     
        !           297:     [self setResources:resourceList forKey:key];
        !           298:     return self;
        !           299: }
        !           300: 
        !           301: 
        !           302: static id
        !           303: elementWithItem(
        !           304:     id list,
        !           305:     int item
        !           306: )
        !           307: {
        !           308:     int i;
        !           309:     id object;
        !           310:     
        !           311:     for (i=0; i<[list count]; i++) {
        !           312:        if ([(object = [list objectAt:i]) item] == item)
        !           313:            return object;
        !           314:     }
        !           315:     return nil;
        !           316: }
        !           317: 
        !           318: - allocateItems:(unsigned int *)aList numItems:(unsigned int)length
        !           319:     forKey:(const char *)keyName
        !           320: {
        !           321:     id currentList, newList, reservedList;
        !           322:     int i;
        !           323:     BOOL               share;
        !           324: 
        !           325:     share = [self _isShared:keyName];
        !           326:     currentList = [self resourcesForKey:keyName];
        !           327:     /* the list that will become the new list of resources */
        !           328:     newList = [[List alloc] init];
        !           329:     /* the list of resources that are newly reserved */
        !           330:     reservedList = [[List alloc] init];
        !           331:     
        !           332:     for (i=0; i < length; i++) {
        !           333:        id resource, vendor;
        !           334:        
        !           335:        if ((resource = elementWithItem(currentList, aList[i]))) {
        !           336:            [newList addObject:resource];
        !           337:        } else {
        !           338:            /* Must reserve new item */
        !           339:            vendor = [_bus _lookupResourceWithKey:keyName];
        !           340:            if (vendor == nil)
        !           341:                goto fail;
        !           342:            if ((resource = (share ?
        !           343:                    [vendor shareItem:aList[i]]:
        !           344:                    [vendor reserveItem:aList[i]])) == nil)
        !           345:                goto fail;
        !           346:            [reservedList addObject:resource];
        !           347:            [newList addObject:resource];
        !           348:        }
        !           349:     }
        !           350:     /* Now check for items that should be freed */
        !           351:     for (i=0; i < [currentList count]; i++) {
        !           352:        id object;
        !           353:        
        !           354:        object = [currentList objectAt:i];
        !           355:        if ([newList indexOf:object] == NX_NOT_IN_LIST)
        !           356:            [object free];
        !           357:     }
        !           358: 
        !           359:     /* Now, empty old list, to prevent double freeing
        !           360:      * of its objects.  The list itself will be freed
        !           361:      * when we do a setResources.
        !           362:      */
        !           363:     [currentList empty];
        !           364: 
        !           365:     [self setResources:newList forKey:keyName];
        !           366:     [reservedList free];
        !           367:     return self;
        !           368:     
        !           369: fail:
        !           370:     [[reservedList freeObjects] free];
        !           371:     [newList free];
        !           372:     return nil;
        !           373: }
        !           374: 
        !           375: 
        !           376: static id
        !           377: elementWithRange(
        !           378:     id list,
        !           379:     Range range
        !           380: )
        !           381: {
        !           382:     int i;
        !           383:     id object;
        !           384:     Range _range;
        !           385:     
        !           386:     for (i=0; i<[list count]; i++) {
        !           387:        object = [list objectAt:i];
        !           388:        _range = [object range];
        !           389:        if (_range.base == range.base && _range.length == range.length)
        !           390:            return object;
        !           391:     }
        !           392:     return nil;
        !           393: }
        !           394: 
        !           395: - allocateRanges:(Range *)aList numRanges:(unsigned int)length
        !           396:     forKey:(const char *)keyName
        !           397: {
        !           398:     id currentList, newList, reservedList;
        !           399:     int i;
        !           400:     BOOL               share;
        !           401: 
        !           402:     share = [self _isShared:keyName];
        !           403:     currentList = [self resourcesForKey:keyName];
        !           404:     /* the list that will become the new list of resources */
        !           405:     newList = [[List alloc] init];
        !           406:     /* the list of resources that are newly reserved */
        !           407:     reservedList = [[List alloc] init];
        !           408:     
        !           409:     for (i=0; i < length; i++) {
        !           410:        id resource, vendor;
        !           411:        Range range;
        !           412:        
        !           413:        range = aList[i];
        !           414:        if ((resource = elementWithRange(currentList, range))) {
        !           415:            [newList addObject:resource];
        !           416:        } else {
        !           417:            /* Must reserve new range */
        !           418:            vendor = [_bus _lookupResourceWithKey:keyName];
        !           419:            if (vendor == nil)
        !           420:                goto fail;
        !           421:            if ((resource = (share ?
        !           422:                    [vendor shareRange:range] :
        !           423:                    [vendor reserveRange:range])) == nil)
        !           424:                goto fail;
        !           425:            [reservedList addObject:resource];
        !           426:            [newList addObject:resource];
        !           427:        }
        !           428:     }
        !           429:     /* Now check for items that should be freed */
        !           430:     for (i=0; i < [currentList count]; i++) {
        !           431:        id object;
        !           432:        
        !           433:        object = [currentList objectAt:i];
        !           434:        if ([newList indexOf:object] == NX_NOT_IN_LIST)
        !           435:            [object free];
        !           436:     }
        !           437:     /* Now, empty old list, to prevent double freeing
        !           438:      * of its objects.  The list itself will be freed
        !           439:      * when we do a setResources.
        !           440:      */
        !           441:     [currentList empty];
        !           442: 
        !           443:     [self setResources:newList forKey:keyName];
        !           444:     [reservedList free];
        !           445:     return self;
        !           446:     
        !           447: fail:
        !           448:     [[reservedList freeObjects] free];
        !           449:     [newList free];
        !           450:     return nil;
        !           451: }
        !           452: @end
        !           453: 
        !           454: #include <limits.h>
        !           455: 
        !           456: static inline BOOL
        !           457: isupper(char c)
        !           458: {
        !           459:     return (c >= 'A' && c <= 'Z');
        !           460: }
        !           461: 
        !           462: static inline BOOL
        !           463: isalpha(char c)
        !           464: {
        !           465:     return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
        !           466: }
        !           467: 
        !           468: 
        !           469: static inline BOOL
        !           470: isspace(char c)
        !           471: {
        !           472:     return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
        !           473: }
        !           474: 
        !           475: static inline BOOL
        !           476: isdigit(char c)
        !           477: {
        !           478:     return (c >= '0' && c <= '9');
        !           479: }
        !           480: 
        !           481: /*
        !           482:  * Convert a string to an unsigned long integer.
        !           483:  *
        !           484:  * Ignores `locale' stuff.  Assumes that the upper and lower case
        !           485:  * alphabets and digits are each contiguous.
        !           486:  */
        !           487: static
        !           488: boolean_t
        !           489: parsenum(nptr, endptr, result)
        !           490:        const char *nptr;
        !           491:        char **endptr;
        !           492:        unsigned long *result;
        !           493: {
        !           494:        register const char *s = nptr;
        !           495:        register unsigned long acc;
        !           496:        register int c;
        !           497:        register unsigned long cutoff;
        !           498:        register int neg = 0, any, cutlim;
        !           499:        int base = 0;
        !           500: 
        !           501:        /*
        !           502:         * See strtol for comments as to the logic used.
        !           503:         */
        !           504:        do {
        !           505:                c = *s++;
        !           506:        } while (isspace(c));
        !           507:        if (c == '-') {
        !           508:                neg = 1;
        !           509:                c = *s++;
        !           510:        } else if (c == '+')
        !           511:                c = *s++;
        !           512:        if (c == '0' && (*s == 'x' || *s == 'X')) {
        !           513:                c = s[1];
        !           514:                s += 2;
        !           515:                base = 16;
        !           516:        }
        !           517:        if (base == 0)
        !           518:                base = c == '0' ? 8 : 10;
        !           519:        cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
        !           520:        cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
        !           521:        for (acc = 0, any = 0;; c = *s++) {
        !           522:                if (isdigit(c))
        !           523:                        c -= '0';
        !           524:                else if (isalpha(c))
        !           525:                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
        !           526:                else
        !           527:                        break;
        !           528:                if (c >= base)
        !           529:                        break;
        !           530:                if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
        !           531:                        any = -1;
        !           532:                else {
        !           533:                        any = 1;
        !           534:                        acc *= base;
        !           535:                        acc += c;
        !           536:                }
        !           537:        }
        !           538:        if (any < 0)
        !           539:                acc = ULONG_MAX;
        !           540:        else if (neg)
        !           541:                acc = -acc;
        !           542:        if (endptr != 0)
        !           543:                *endptr = any ? s - 1 : (char *)nptr;
        !           544:        if (result != 0)
        !           545:                *result = acc;
        !           546:        return ((any > 0)? TRUE: FALSE);
        !           547: }
        !           548: 
        !           549: @implementation KernDeviceDescription(Parsing)
        !           550: 
        !           551: 
        !           552: - (BOOL)_isShared:(const char *)key
        !           553: {
        !           554:     char               buf[128];
        !           555:     const char                 *shareKey;
        !           556:     BOOL               result;
        !           557: 
        !           558:     sprintf(buf, "Share %s", key);
        !           559:     if ((shareKey = [_configTable valueForStringKey:buf])) {
        !           560:         result = ((*shareKey == 'y') || (*shareKey == 'Y'));
        !           561:        [_configTable freeString:shareKey];
        !           562:        return( result);
        !           563:     } else
        !           564:        return NO;
        !           565: }
        !           566: 
        !           567: - _parseRangeResourceByKey: (const char *)key value:(const char *)keyValue
        !           568: {
        !           569:     id                 resource, list;
        !           570:     const char         *p;
        !           571:     unsigned long      begin, end;
        !           572:     BOOL               share;
        !           573:     
        !           574:     resource = [_bus _lookupResourceWithKey:key];
        !           575:     if (resource == nil) {
        !           576:        printf("%s: Couldn't locate resource object\n", key);
        !           577:        return nil;
        !           578:     }
        !           579:        
        !           580:     list = [[List alloc] init];
        !           581: 
        !           582:     p = keyValue;
        !           583:     if (keyValue == (void *)nil)
        !           584:        return list;
        !           585: 
        !           586:     share = [self _isShared:key];
        !           587: 
        !           588:     while (parsenum(p, &p, &begin) &&
        !           589:                    parsenum(++p, &p, &end)) {
        !           590:        Range   range = { begin, end - begin + 1 };
        !           591: 
        !           592:        id              rangeResource;
        !           593: 
        !           594:        rangeResource = share ? [resource shareRange:range] :
        !           595:                                [resource reserveRange:range];  
        !           596:        if ([list addObject:rangeResource] == nil) {
        !           597:            printf("%s: Couldn't reserve range %08x-%08x\n", key, begin, end);      
        !           598:            return [[list freeObjects] free];
        !           599:        }
        !           600:     }
        !           601:     
        !           602:     return list;
        !           603: }
        !           604: 
        !           605: - _parseItemResourceByKey: (const char *)key value:(const char *)keyValue
        !           606: {
        !           607:     id                 resource, list;
        !           608:     const char         *p;
        !           609:     unsigned long      item;
        !           610:     BOOL               share;
        !           611:     
        !           612:     resource = [_bus _lookupResourceWithKey:key];
        !           613:     if (resource == nil) {
        !           614:        printf("%s: Couldn't locate resource object\n", key);
        !           615:        return nil;
        !           616:     }
        !           617:        
        !           618:     list = [[List alloc] init];
        !           619: 
        !           620:     p = keyValue;
        !           621:     if (keyValue == (void *)nil)
        !           622:        return list;
        !           623:        
        !           624:     share = [self _isShared:key];
        !           625:     while (parsenum(p, &p, &item)) {   
        !           626:        id              itemResource;
        !           627:        
        !           628:        itemResource = share ? [resource shareItem:item] :
        !           629:                               [resource reserveItem:item];
        !           630:        if ([list addObject:itemResource] == nil) {
        !           631:            printf("%s: Couldn't reserve %d\n", key, item);
        !           632:            return [[list freeObjects] free];
        !           633:        }
        !           634:     }
        !           635:     
        !           636:     return list;
        !           637: }
        !           638: 
        !           639: @end

unix.superglobalmegacorp.com

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