|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.