|
|
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) 1993, 1994 NeXT Computer, Inc. ! 27: * ! 28: * Kernel Bus Resource Object(s). ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 1 Jul 1994 ? at NeXT ! 33: * Modifications to support shared interrupts. ! 34: * 16 Mar 1994 ? at NeXT ! 35: * Added range mapping. ! 36: * 24 Feb 1994 ? at NeXT ! 37: * Major rewrite. ! 38: * 31 Oct 1993 ? at NeXT ! 39: * Created. ! 40: */ ! 41: ! 42: #import <mach/mach_types.h> ! 43: ! 44: #import <objc/HashTable.h> ! 45: ! 46: #import <driverkit/KernBus.h> ! 47: #import <driverkit/KernBusPrivate.h> ! 48: #import <driverkit/KernDeviceDescription.h> ! 49: ! 50: @implementation KernBusItemResource ! 51: ! 52: - initWithItemCount: (unsigned int)count ! 53: itemBase: (unsigned int)base ! 54: itemKind: kind ! 55: owner: owner ! 56: { ! 57: [super init]; ! 58: ! 59: /* ! 60: * Check for base wrap ! 61: * and invalid count. ! 62: */ ! 63: if (count > 1024 || (base + count) <= base) ! 64: return [self free]; ! 65: ! 66: _owner = owner; ! 67: _kind = (kind == nil)? [KernBusItem class]: kind; ! 68: _items = (void *)IOMalloc(count * sizeof (KernBusItem *)); ! 69: _itemCount = 0; ! 70: bzero(_items, count * sizeof (KernBusItem *)); ! 71: _count = count; _base = base; ! 72: ! 73: return self; ! 74: } ! 75: ! 76: - initWithItemCount: (unsigned int)count ! 77: itemKind: kind ! 78: owner: owner ! 79: { ! 80: return [self initWithItemCount:count itemBase:0 itemKind:kind owner:owner]; ! 81: } ! 82: ! 83: - init ! 84: { ! 85: return [self free]; ! 86: } ! 87: ! 88: - free ! 89: { ! 90: if (_itemCount > 0) ! 91: return self; ! 92: ! 93: if (_count > 0 && _items) ! 94: IOFree(_items, sizeof (_count * sizeof (KernBusItem *))); ! 95: ! 96: return [super free]; ! 97: } ! 98: ! 99: - reserveItem: (unsigned int)item ! 100: { ! 101: KernBusItem **items = _items; ! 102: id *object; ! 103: ! 104: /* ! 105: * Check for invalid ! 106: * item. ! 107: */ ! 108: if (item < _base || item >= (_base + _count)) ! 109: return nil; ! 110: ! 111: object = &items[item - _base]; ! 112: ! 113: if (*object == nil) { ! 114: if ((*object = [[_kind alloc] ! 115: initForResource:self ! 116: item:item ! 117: shareable:NO]) != nil) { ! 118: if (_itemCount++ == 0) ! 119: [_owner _resourceActive]; ! 120: } ! 121: } ! 122: else ! 123: return nil; ! 124: ! 125: return *object; ! 126: } ! 127: ! 128: - shareItem: (unsigned int)item ! 129: { ! 130: KernBusItem **items = _items; ! 131: id *object; ! 132: ! 133: /* ! 134: * Check for invalid ! 135: * item. ! 136: */ ! 137: if (item < _base || item >= (_base + _count)) ! 138: return nil; ! 139: ! 140: object = &items[item - _base]; ! 141: ! 142: if (*object == nil) { ! 143: if ((*object = [[_kind alloc] ! 144: initForResource:self ! 145: item:item ! 146: shareable:YES]) != nil) { ! 147: if (_itemCount++ == 0) ! 148: [_owner _resourceActive]; ! 149: } ! 150: } ! 151: else ! 152: return [*object share]; ! 153: ! 154: return *object; ! 155: } ! 156: ! 157: #ifdef notdef ! 158: - reserveAnyItem ! 159: { ! 160: id *object = _items; ! 161: int i; ! 162: ! 163: if (_itemCount >= _count) ! 164: return nil; ! 165: ! 166: for (i = 0; i < _count; i++, object++) { ! 167: if (*object == nil) { ! 168: if ((*object = [[_kind alloc] ! 169: initForResource:self ! 170: item:i ! 171: shareable:NO]) != nil) { ! 172: if (_itemCount++ == 0) ! 173: [_owner _resourceActive]; ! 174: ! 175: return *object; ! 176: } ! 177: } ! 178: } ! 179: ! 180: return nil; ! 181: } ! 182: ! 183: - shareAnyItem ! 184: { ! 185: id *object = _items; ! 186: int i; ! 187: ! 188: for (i = 0; i < _count; i++, object++) { ! 189: if (*object == nil) { ! 190: if ((*object = [[_kind alloc] ! 191: initForResource:self ! 192: item:i ! 193: shareable:YES]) != nil) { ! 194: if (_itemCount++ == 0) ! 195: [_owner _resourceActive]; ! 196: ! 197: return *object; ! 198: } ! 199: } ! 200: else if ([*object share]) ! 201: return *object; ! 202: } ! 203: ! 204: return nil; ! 205: } ! 206: #endif ! 207: ! 208: - (unsigned int) findFreeItem ! 209: { ! 210: KernBusItem **items = _items; ! 211: unsigned int i; ! 212: ! 213: for (i = 0; i < _count; i++) ! 214: if (items[i] == nil) ! 215: break; ! 216: ! 217: /* ! 218: * If there are no free items, we return an invalid item. ! 219: */ ! 220: return i + _base; ! 221: } ! 222: ! 223: @end ! 224: ! 225: @implementation KernBusItemResource(Private) ! 226: ! 227: - _destroyItem: object ! 228: { ! 229: KernBusItem **item, **items = _items; ! 230: KernBusItem_ *iv = (KernBusItem_ *)object; ! 231: ! 232: if (![object isKindOf:_kind]) ! 233: return nil; ! 234: ! 235: item = &items[iv->_item - _base]; ! 236: if (*item == nil) ! 237: return nil; ! 238: ! 239: *item = nil; ! 240: if (--_itemCount == 0) ! 241: [_owner _resourceInactive]; ! 242: ! 243: return [object dealloc]; ! 244: } ! 245: ! 246: @end ! 247: ! 248: @implementation KernBusItem ! 249: ! 250: - initForResource: resource ! 251: item: (unsigned int)item ! 252: shareable: (BOOL)shareable ! 253: { ! 254: if (resource == nil) ! 255: return [super free]; ! 256: ! 257: [super init]; ! 258: ! 259: _resource = resource; ! 260: _item = item; ! 261: _useCount = 1; ! 262: _shareable = shareable; ! 263: ! 264: return self; ! 265: } ! 266: ! 267: - init ! 268: { ! 269: return [super free]; ! 270: } ! 271: ! 272: - free ! 273: { ! 274: if (--_useCount > 0) ! 275: return nil; ! 276: ! 277: return [_resource _destroyItem:self]; ! 278: } ! 279: ! 280: - dealloc ! 281: { ! 282: if (_useCount > 0) ! 283: return self; ! 284: ! 285: return [super free]; ! 286: } ! 287: ! 288: - share ! 289: { ! 290: if (!_shareable) ! 291: return nil; ! 292: ! 293: _useCount++; ! 294: ! 295: return self; ! 296: } ! 297: ! 298: - (unsigned int)item ! 299: { ! 300: return _item; ! 301: } ! 302: ! 303: @end ! 304: ! 305: @implementation KernBusRangeResource ! 306: ! 307: - initWithExtent: (Range)extent ! 308: kind: kind ! 309: owner: owner ! 310: { ! 311: unsigned int end = extent.base + extent.length; ! 312: ! 313: [super init]; ! 314: ! 315: /* ! 316: * Check for wraparound. ! 317: */ ! 318: if (!rangeIsValid(extent)) ! 319: return [self free]; ! 320: ! 321: _owner = owner; ! 322: _kind = (kind == nil)? [KernBusRange class]: kind; ! 323: _rangeCount = 0; ! 324: _ranges = 0; ! 325: _end = end; _base = extent.base; ! 326: ! 327: return self; ! 328: } ! 329: ! 330: - free ! 331: { ! 332: if (_rangeCount > 0) ! 333: return self; ! 334: ! 335: return [super free]; ! 336: } ! 337: ! 338: - reserveRange: (Range)range ! 339: { ! 340: unsigned int base = range.base; ! 341: unsigned int end = base + range.length; ! 342: void **prevnext = &_ranges; ! 343: KernBusRange_ *new, *next; ! 344: id object = nil; ! 345: ! 346: /* ! 347: * Check region for wrap. ! 348: */ ! 349: if (!rangeIsValid(range)) ! 350: return nil; ! 351: ! 352: /* ! 353: * Check region against ! 354: * address space. ! 355: */ ! 356: if (base < _base || (_end > 0 && end > _end)) ! 357: return nil; ! 358: ! 359: /* ! 360: * Add range if no overlap ! 361: * with existing regions. ! 362: */ ! 363: while (TRUE) { ! 364: if ((next = *prevnext) == 0 || end <= next->_base) { ! 365: if ((object = [[_kind alloc] ! 366: initForResource:self ! 367: range:range ! 368: shareable:NO]) != nil) { ! 369: new = (KernBusRange_ *)object; ! 370: new->_next = next; ! 371: *prevnext = new; ! 372: if (_rangeCount++ == 0) ! 373: [_owner _resourceActive]; ! 374: } ! 375: break; ! 376: } ! 377: else if (next->_end > base) ! 378: break; ! 379: ! 380: prevnext = &next->_next; ! 381: } ! 382: ! 383: return object; ! 384: } ! 385: ! 386: - shareRange: (Range)range ! 387: { ! 388: unsigned int base = range.base; ! 389: unsigned int end = base + range.length; ! 390: void **prevnext = &_ranges; ! 391: KernBusRange_ *new, *next; ! 392: id object = nil; ! 393: ! 394: /* ! 395: * Check region for wrap. ! 396: */ ! 397: if (!rangeIsValid(range)) ! 398: return nil; ! 399: ! 400: /* ! 401: * Check region against ! 402: * address space. ! 403: */ ! 404: if (base < _base || (_end > 0 && end > _end)) ! 405: return nil; ! 406: ! 407: /* ! 408: * Add range if no overlap ! 409: * with existing regions. ! 410: */ ! 411: while (TRUE) { ! 412: if ((next = *prevnext) == 0 || end <= next->_base) { ! 413: if ((object = [[_kind alloc] ! 414: initForResource:self ! 415: range:range ! 416: shareable:YES]) != nil) { ! 417: new = (KernBusRange_ *)object; ! 418: new->_next = next; ! 419: *prevnext = new; ! 420: if (_rangeCount++ == 0) ! 421: [_owner _resourceActive]; ! 422: } ! 423: break; ! 424: } ! 425: #if !ppc ! 426: else if (base >= next->_base && end <= next->_end) { ! 427: object = (KernBusRange *)next; object = [object share]; ! 428: break; ! 429: } ! 430: else if (next->_end > base) ! 431: break; ! 432: #endif ! 433: prevnext = &next->_next; ! 434: } ! 435: ! 436: return object; ! 437: } ! 438: ! 439: - (Range)findFreeRangeWithSize:(unsigned int)size ! 440: alignment:(unsigned int)align ! 441: { ! 442: Range result; ! 443: unsigned int base; ! 444: unsigned int end; ! 445: void **prevnext = &_ranges; ! 446: KernBusRange_ *new, *next; ! 447: id object = nil; ! 448: ! 449: base = _base; ! 450: end = base + size; ! 451: result.base = result.length = 0; ! 452: ! 453: /* ! 454: * Add range if no overlap ! 455: * with existing regions. ! 456: */ ! 457: for (base = _base, end = base + size; ! 458: base < _end; ! 459: base += align, end += align) { ! 460: while (TRUE) { ! 461: if ((next = *prevnext) == 0 || end <= next->_base) { ! 462: result.base = base; ! 463: result.length = end - base; ! 464: break; ! 465: } ! 466: else if (next->_end > base) ! 467: break; ! 468: ! 469: prevnext = &next->_next; ! 470: } ! 471: ! 472: if (result.length) ! 473: break; ! 474: } ! 475: ! 476: return result; ! 477: } ! 478: ! 479: @end ! 480: ! 481: @implementation KernBusRangeResource(Private) ! 482: ! 483: - _destroyRange: object ! 484: { ! 485: void **prevnext = &_ranges; ! 486: KernBusRange_ *next; ! 487: ! 488: // Should check class of object ! 489: ! 490: if (![object isKindOf:_kind]) ! 491: return nil; ! 492: ! 493: while ((next = *prevnext) != 0) { ! 494: if (next == (KernBusRange_ *)object) { ! 495: *prevnext = next->_next; ! 496: if (--_rangeCount == 0) ! 497: [_owner _resourceInactive]; ! 498: ! 499: return [object dealloc]; ! 500: } ! 501: ! 502: prevnext = &next->_next; ! 503: } ! 504: ! 505: return nil; ! 506: } ! 507: ! 508: @end ! 509: ! 510: @implementation KernBusRange ! 511: ! 512: - initForResource: resource ! 513: range: (Range)range ! 514: shareable: (BOOL)shareable ! 515: { ! 516: if (resource == nil) ! 517: return [super free]; ! 518: ! 519: [super init]; ! 520: ! 521: _resource = resource; ! 522: _base = range.base; ! 523: _end = _base + range.length; ! 524: _useCount = 1; ! 525: _shareable = shareable; ! 526: _mappingCount = 0; ! 527: ! 528: return self; ! 529: } ! 530: ! 531: - init ! 532: { ! 533: return [super free]; ! 534: } ! 535: ! 536: - free ! 537: { ! 538: if (_mappingCount > 0) ! 539: return self; ! 540: ! 541: if (--_useCount > 0) ! 542: return nil; ! 543: ! 544: return [_resource _destroyRange:self]; ! 545: } ! 546: ! 547: - dealloc ! 548: { ! 549: if (_useCount > 0) ! 550: return self; ! 551: ! 552: return [super free]; ! 553: } ! 554: ! 555: - share ! 556: { ! 557: if (!_shareable) ! 558: return nil; ! 559: ! 560: _useCount++; ! 561: ! 562: return self; ! 563: } ! 564: ! 565: - (Range)range ! 566: { ! 567: Range range; ! 568: ! 569: range.base = _base; ! 570: range.length = _end - _base; ! 571: ! 572: return range; ! 573: } ! 574: ! 575: @end ! 576: ! 577: @implementation KernBusRange(Private) ! 578: ! 579: - _addMapping ! 580: { ! 581: _mappingCount++; ! 582: ! 583: return self; ! 584: } ! 585: ! 586: - _destroyMapping: object ! 587: { ! 588: _mappingCount--; ! 589: ! 590: return [object free]; ! 591: } ! 592: ! 593: @end ! 594: ! 595: @implementation KernBusRangeMapping ! 596: ! 597: - initWithRange: range ! 598: subRange: (Range)subRange ! 599: { ! 600: Range resourceRange; ! 601: unsigned int resourceBase, resourceEnd; ! 602: unsigned int mappedBase, mappedEnd; ! 603: ! 604: if (range == nil) ! 605: return [self free]; ! 606: ! 607: [super init]; ! 608: ! 609: if (!rangeIsValid(subRange)) ! 610: return [self free]; ! 611: ! 612: /* ! 613: * Convert range into ! 614: * endpoints. ! 615: */ ! 616: resourceRange = [range range]; ! 617: resourceBase = resourceRange.base; ! 618: resourceEnd = resourceBase + resourceRange.length; ! 619: ! 620: /* ! 621: * Convert subrange into ! 622: * absolute endpoints. ! 623: */ ! 624: mappedBase = resourceBase + subRange.base; ! 625: mappedEnd = resourceBase + subRange.base + subRange.length; ! 626: ! 627: /* ! 628: * Check subrange against ! 629: * range. ! 630: */ ! 631: if (mappedBase < resourceBase || ! 632: (resourceEnd > 0 && mappedEnd > resourceEnd)) ! 633: return [self free]; ! 634: ! 635: _range = range; ! 636: _mappedRange.base = mappedBase; ! 637: _mappedRange.length = subRange.length; ! 638: ! 639: [range _addMapping]; ! 640: ! 641: return self; ! 642: } ! 643: ! 644: - free ! 645: { ! 646: id range = _range; ! 647: ! 648: if (range == nil) ! 649: return [super free]; ! 650: ! 651: _range = nil; ! 652: ! 653: return [range _destroyMapping:self]; ! 654: } ! 655: ! 656: - (Range)mappedRange ! 657: { ! 658: return _mappedRange; ! 659: } ! 660: ! 661: @end ! 662: ! 663: @implementation KernBus ! 664: ! 665: static HashTable *_busClasses, *_busInstances; ! 666: ! 667: + initialize ! 668: { ! 669: if (_busClasses == nil) { ! 670: _busClasses = [[HashTable alloc] initKeyDesc:"*"]; ! 671: } ! 672: if (_busInstances == nil) { ! 673: _busInstances = [[HashTable alloc] initKeyDesc:"*"]; ! 674: } ! 675: ! 676: return self; ! 677: } ! 678: ! 679: + registerBusClass:busClass name:(char *)className ! 680: { ! 681: [_busClasses insertKey:className value:busClass]; ! 682: ! 683: return busClass; ! 684: } ! 685: ! 686: + registerBusInstance:busInstance name:(char *)busName busId:(int)index ! 687: { ! 688: HashTable *t; ! 689: ! 690: t = [_busInstances valueForKey:busName]; ! 691: if (t == NULL) { ! 692: t = [[HashTable alloc] initKeyDesc:"i"]; ! 693: [_busInstances insertKey:busName value:t]; ! 694: } ! 695: [t insertKey:(void *)index value:busInstance]; ! 696: return busInstance; ! 697: } ! 698: ! 699: + lookupBusClassWithName:(char *)busName ! 700: { ! 701: return [_busClasses valueForKey:busName]; ! 702: } ! 703: ! 704: + lookupBusInstanceWithName:(char *)busName busId:(int)index ! 705: { ! 706: HashTable *t; ! 707: id obj = nil; ! 708: ! 709: t = [_busInstances valueForKey:busName]; ! 710: if (t) { ! 711: obj = [t valueForKey:(void *)index]; ! 712: } ! 713: return obj; ! 714: } ! 715: ! 716: - init ! 717: { ! 718: [super init]; ! 719: ! 720: if (_resources == nil) ! 721: _resources = [[HashTable alloc] initKeyDesc:"*"]; ! 722: ! 723: return self; ! 724: } ! 725: ! 726: - free ! 727: { ! 728: if (_activeResourceCount > 0) ! 729: return self; ! 730: ! 731: return [super free]; ! 732: } ! 733: ! 734: - (BOOL)areResourcesActive ! 735: { ! 736: return _activeResourceCount > 0; ! 737: } ! 738: ! 739: + deviceDescriptionFromConfigTable:table ! 740: { ! 741: return [[KernDeviceDescription alloc] initFromConfigTable:table]; ! 742: } ! 743: ! 744: /* ! 745: * Allocate resources for bus. ! 746: * Return nil if there is an error allocating a resource. ! 747: */ ! 748: - allocateResourcesForDeviceDescription:descr ! 749: { ! 750: const char **names; ! 751: ! 752: for (names = [self resourceNames]; names && *names; names++) { ! 753: if ([descr allocateResourcesForKey:*names] == nil) ! 754: return nil; ! 755: } ! 756: return descr; ! 757: } ! 758: ! 759: - _insertResource: object ! 760: withKey: (const char *)key ! 761: { ! 762: HashTable *resources = (HashTable *)_resources; ! 763: ! 764: if ([resources isKey:key]) ! 765: return nil; ! 766: ! 767: [resources insertKey:key value:object]; ! 768: ! 769: return object; ! 770: } ! 771: ! 772: - _deleteResourceWithKey: (const char *)key ! 773: { ! 774: HashTable *resources = (HashTable *)_resources; ! 775: id object; ! 776: ! 777: if ((object = [resources valueForKey:key]) == nil) ! 778: return nil; ! 779: ! 780: [resources removeKey:key]; ! 781: ! 782: return object; ! 783: } ! 784: ! 785: - _lookupResourceWithKey: (const char *)key ! 786: { ! 787: HashTable *resources = (HashTable *)_resources; ! 788: ! 789: return [resources valueForKey:key]; ! 790: } ! 791: ! 792: - (const char **)resourceNames ! 793: { ! 794: static const char *names[1]; ! 795: ! 796: return names; ! 797: } ! 798: ! 799: + (BOOL)configureDriverWithTable:configTable ! 800: { ! 801: return NO; ! 802: } ! 803: ! 804: - (int)busId ! 805: { ! 806: return _busId; ! 807: } ! 808: ! 809: - (void)setBusId:(int)busId ! 810: { ! 811: _busId = busId; ! 812: } ! 813: ! 814: + (BOOL)probeBus:configTable ! 815: { ! 816: [[self alloc] init]; ! 817: return YES; ! 818: } ! 819: ! 820: @end ! 821: ! 822: @implementation KernBus(Private) ! 823: ! 824: - (void)_resourceActive ! 825: { ! 826: _activeResourceCount++; ! 827: } ! 828: ! 829: - (void)_resourceInactive ! 830: { ! 831: _activeResourceCount--; ! 832: } ! 833: ! 834: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.