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