|
|
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.