Annotation of kernel/driverkit/KernDeviceDescription.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     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.