|
|
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: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
25: *
26: * IODevice.m - Implementation of IODevice superclass
27: *
28: * HISTORY
29: * 13-Jan-98 Martin Minow at Apple
30: * Added createMachPort
31: * 20-Jan-93 Doug Mitchell
32: * Implemented the Walrath Changes.
33: * 29-Jan-91 Doug Mitchell at NeXT
34: * Created.
35: */
36:
37: /*
38: * FIXME - should global parameter stuff be KERNEL only?
39: */
40:
41: #import <bsd/sys/types.h>
42: #import <mach/kern_return.h>
43: #import <mach/message.h>
44: #import <driverkit/IODevice.h>
45: #import <driverkit/Device_ddm.h>
46:
47: #ifdef KERNEL
48: #import <kernserv/prototypes.h>
49: #import <mach/mach_interface.h>
50: #else KERNEL
51: #import <mach/mach.h>
52: #import <bsd/string.h>
53: #endif KERNEL
54:
55: #import <machkit/NXLock.h>
56: #import <bsd/sys/errno.h>
57:
58: #import <driverkit/generalFuncs.h>
59: #import <driverkit/IODeviceParams.h>
60: #import <driverkit/IODeviceDescription.h>
61: #import <driverkit/IODeviceDescriptionPrivate.h>
62: #import <driverkit/IODeviceKernPrivate.h>
63: #ifdef KERNEL
64: #import <driverkit/KernStringList.h>
65: #endif
66: #import <kernserv/queue.h>
67: #import <objc/List.h>
68:
69: /*
70: * For stringFromReturn:.
71: */
72: static IONamedValue IOReturn_values[] = {
73: {IO_R_SUCCESS, "Success" },
74: {IO_R_NO_MEMORY, "Memory Allocation error" },
75: {IO_R_RESOURCE, "Resource Shortage" },
76: {IO_R_IPC_FAILURE, "Mach IPC Failure" },
77: {IO_R_NO_DEVICE, "No Such Device" },
78: {IO_R_PRIVILEGE, "Privilege Violation" },
79: {IO_R_INVALID_ARG, "Invalid Argument" },
80: {IO_R_LOCKED_READ, "Device Read Locked" },
81: {IO_R_LOCKED_WRITE, "Device Write Locked" },
82: {IO_R_EXCLUSIVE_ACCESS, "Exclusive Access Device" },
83: {IO_R_BAD_MSG_ID, "Bad IPC Message ID" },
84: {IO_R_UNSUPPORTED, "Unsupported Function" },
85: {IO_R_VM_FAILURE, "Virtual Memory error" },
86: {IO_R_INTERNAL, "Internal Driver error" },
87: {IO_R_IO, "I/O error" },
88: {IO_R_CANT_LOCK, "Can\'t Acquire Desired Lock" },
89: {IO_R_NOT_OPEN, "Device Not Open" },
90: {IO_R_NOT_READABLE, "Device Not Readable" },
91: {IO_R_NOT_WRITABLE, "Device Not Writeable" },
92: {IO_R_ALIGN, "DMA ALignment error" },
93: {IO_R_MEDIA, "Media error" },
94: {IO_R_OPEN, "Device(s) still open" },
95: {IO_R_RLD, "rld failure" },
96: {IO_R_DMA, "DMA failure" },
97: {IO_R_BUSY, "Device Busy" },
98: {IO_R_TIMEOUT, "I/O Timeout" },
99: {IO_R_OFFLINE, "Device Offline" },
100: {IO_R_NOT_READY, "Not Ready" },
101: {IO_R_NOT_ATTACHED, "Device/Channel not attached" },
102: {IO_R_NO_CHANNELS, "No DMA Channels Available" },
103: {IO_R_NO_SPACE, "No Address Space for Mapping" },
104: {IO_R_PORT_EXISTS, "Device Port Already Exists" },
105: {IO_R_CANT_WIRE, "Can\'t Wire Physical Memory" },
106: {IO_R_NO_INTERRUPT, "No Interrupt Port Attached" },
107: {IO_R_NO_FRAMES, "No DMA Frames Enqueued" },
108: {IO_R_INVALID, "INVALID STATUS (Internal Error)" },
109: {0, NULL }
110: };
111:
112: /*
113: * Struct to map "global Object number" to id.
114: */
115: typedef struct {
116: id instance;
117: int objectNumber;
118: queue_chain_t link;
119: } objectListEntry;
120:
121: /*
122: * Struct to maintain IODevice class list.
123: */
124: typedef struct {
125: id classId;
126: int classNumber;
127: int bmajor;
128: int cmajor;
129: id originalDeviceDescription;
130: queue_chain_t link;
131: } classListEntry;
132:
133: /*
134: * ObjectNumber-to-id mapping info.
135: */
136: static int globalObjectCounter;
137: static queue_head_t objectList; // queue of objectListEntry's
138: static NXLock *objectListLock; // protects both of the above
139:
140: /*
141: * IODevice class list.
142: */
143: static int classCounter;
144: static queue_head_t classList;
145: static NXLock *classListLock;
146:
147: /*
148: * Static function prototypes.
149: */
150: static IOReturn objectNumToId(IOObjectNumber objectNum, id *instance);
151: static IOReturn deviceNameToId(IOString name,
152: id *instance,
153: IOObjectNumber *objectNum);
154: static objectListEntry *getObjectListEntry(id object);
155: static IOReturn getClassListEntryForId(
156: id classId,
157: classListEntry **entry);
158: static IOReturn getClassListEntry(unsigned classNumber,
159: classListEntry **entry);
160:
161: @implementation IODevice
162:
163: static BOOL IODeviceInitFlag = NO;
164:
165: /* Shouldn't this be somewhere else? */
166: static inline int _atoi(const char *string)
167: {
168: int sum = 0;
169: while(*string && (*string >= '0' && *string <= '9'))
170: sum = (sum * 10) + (*string++ - '0');
171: return sum;
172: }
173:
174: + initialize
175: {
176: if(self != objc_getClass("IODevice")) {
177: /*
178: * This is someone else's. Register them.
179: */
180: [IODevice registerClass:self];
181: }
182:
183: if(IODeviceInitFlag) {
184: /*
185: * We've already been here. This shouldn't happen unless
186: * someone calls [IODevice initialize] explicitly.
187: */
188: return self;
189: }
190:
191: /*
192: * Init objectNumber-to-id list.
193: */
194:
195: objectListLock = [NXLock new];
196: globalObjectCounter = 0;
197: queue_init(&objectList);
198:
199: /*
200: * Init class list.
201: */
202: queue_init(&classList);
203: classListLock = [NXLock new];
204: IODeviceInitFlag = YES;
205: return self;
206: }
207:
208: /*
209: * Probe method used by direct, indirect, and pseudo devices.
210: * Implemented by most (not all) subclasses.
211: *
212: * Create an instance of subclass to be associated with specified
213: * deviceDescription. Returns a pointer to a nil-terminated array of
214: * id's of instantiated device objects if successful, else returns nil.
215: */
216: + (BOOL)probe : (id)deviceDescription
217: {
218: return NO;
219: }
220:
221: /*
222: * Report basic style of driver (direct, indirect, or pseudo). Must be
223: * implemented by subclass.
224: */
225: + (IODeviceStyle)deviceStyle
226: {
227: return IO_PseudoDevice; // just a place holder
228: }
229:
230: /*
231: * Report protocols needed. Kernel-level indirect devices must implement
232: * this.
233: */
234: + (Protocol **)requiredProtocols
235: {
236: return NULL;
237: }
238:
239: /*
240: * Called from leaf subclass's +initialize method.
241: */
242: + (void)registerClass : classId
243: {
244: classListEntry *listEntry;
245:
246: listEntry = IOMalloc(sizeof(classListEntry));
247: listEntry->classId = classId;
248: listEntry->bmajor = listEntry->cmajor = -1;
249: listEntry->originalDeviceDescription = nil;
250: [classListLock lock];
251: listEntry->classNumber = classCounter++;
252: queue_enter(&classList, listEntry, classListEntry *, link);
253: [classListLock unlock];
254: }
255:
256: /*
257: * Called if/when a class is being removed from an executable's address
258: * space.
259: */
260: + (void)unregisterClass : classId
261: {
262: classListEntry *classEntry;
263:
264: [classListLock lock];
265: classEntry = (classListEntry *)queue_first(&classList);
266: while(!queue_end(&classList, (queue_t)classEntry)) {
267: if(classEntry->classId == classId) {
268: queue_remove(&classList,
269: classEntry,
270: classListEntry *,
271: link);
272: break;
273: }
274: classEntry = (classListEntry *)classEntry->link.next;
275: }
276: [classListLock unlock];
277: }
278:
279: /*
280: * Initialize common instance variables. Typically invoked
281: * via [super init:] in subclass's init: method.
282: */
283: - init
284: {
285: xpr_dev("IODevice init:\n", 1,2,3,4,5);
286: return [super init];
287: }
288:
289: /*
290: * Initialize per specified deviceDescription. Returns nil on error.
291: * This is actually a nop at the IODevice level; subclasses may do with it
292: * as they see fit.
293: */
294: - initFromDeviceDescription : deviceDescription
295: {
296: if( [[self class] deviceStyle] == IO_IndirectDevice)
297: __deviceDescription = [deviceDescription directDevice];
298: else
299: __deviceDescription = deviceDescription;
300: return self;
301: }
302:
303: - deviceDescription
304: {
305: if( [[self class] deviceStyle] == IO_IndirectDevice)
306: return nil;
307: else
308: return __deviceDescription;
309: }
310:
311: - (void)setDeviceDescription : deviceDescription
312: {
313: if( [[self class] deviceStyle] == IO_IndirectDevice)
314: __deviceDescription = [deviceDescription directDevice];
315: else
316: __deviceDescription = deviceDescription;
317: }
318:
319: /*
320: * Returns a string representation of the hardware's location.
321: * Indirect drivers return the direct device's path they were probed on.
322: */
323: - getDevicePath:(char *)path maxLength:(int)maxLen useAlias:(BOOL)doAlias
324: {
325: if( [__deviceDescription respondsTo:@selector(getDevicePath:maxLength:useAlias:)])
326: return( [__deviceDescription getDevicePath:path maxLength:maxLen useAlias:doAlias]);
327:
328: return( nil);
329: }
330:
331: /*
332: * Returns the tail of the matchPath parameter if the head matches the
333: * device's path, else returns nil. Indirect drivers match on the
334: * direct device's path they were probed on.
335: */
336: - (char *) matchDevicePath:(char *)matchPath
337: {
338: if( [__deviceDescription respondsTo:@selector(matchDevicePath:)])
339: return( [__deviceDescription matchDevicePath:matchPath]);
340:
341: return( NULL);
342: }
343:
344: - lookUpProperty:(const char *)propertyName
345: value:(unsigned char *)value
346: length:(unsigned int *)length
347: selector:(SEL)selector
348: isString:(BOOL)isString
349: {
350: id rtn = nil, prtn = nil;
351:
352: if( __deviceDescription)
353: prtn = [__deviceDescription lookUpProperty:propertyName value:value length:length
354: selector:(SEL)selector isString:isString];
355:
356: if( [self respondsTo:selector]) {
357: // guarantee a minimal size so most methods don't have to check
358: if( (isString == NO) || ((strlen( value) + 32) <= *length))
359: rtn = objc_msgSend( self, selector, value, length );
360: }
361:
362: return( prtn ? prtn : rtn);
363: }
364:
365: - lookUpProperty:(const char *)propertyName
366: value:(unsigned char *)value
367: length:(unsigned int *)length
368:
369: {
370: char selName[ 64 ];
371: SEL selector;
372: unsigned int len = 4;
373:
374: *value = 0;
375: sprintf( selName, "property_%s:length:", propertyName);
376: selector = sel_getUid( selName);
377:
378: return( [self lookUpProperty:propertyName value:value length:length
379: selector:selector isString:NO]);
380: }
381:
382: - lookUpStringProperty:(const char *)propertyName
383: value:(char *)value
384: length:(unsigned int)maxLength
385: {
386: char selName[ 64 ];
387: SEL selector;
388:
389: *value = 0;
390: sprintf( selName, "property_%s:length:", propertyName);
391: selector = sel_getUid( selName);
392:
393: return( [self lookUpProperty:propertyName value:value length:&maxLength
394: selector:selector isString:YES]);
395: }
396:
397: - property_IODriverNames:(char *)classes length:(unsigned int *)maxLen
398: {
399: if( *classes)
400: strcat( classes, " ");
401: strcat( classes, [self name]);
402: return( self);
403: }
404:
405: - property_IODevicePath:(char *)path length:(unsigned int *)maxLen
406: {
407: return( [self getDevicePath:path maxLength:*maxLen useAlias:YES]);
408: }
409:
410: #ifdef KERNEL
411: - getStringPropertyList:(const char *)names
412: results:(char *) results
413: maxLength:(unsigned int)length
414: {
415: int index, maxLen, nameLen, nextLen;
416: KernStringList * nameList;
417: char * nextValue;
418: const char * name;
419:
420: nameList = [[KernStringList alloc]
421: initWithWhitespaceDelimitedString:names];
422: if( nameList) {
423: nextValue = results;
424: maxLen = length - (4 + 2);
425:
426: for (index = 0; index < [nameList count]; index++) {
427: name = [nameList stringAt:index];
428: nameLen = strlen( name);
429: nextLen = maxLen - nameLen;
430:
431: if( [self lookUpStringProperty:name value:(nextValue + nameLen + 4) length:nextLen]) {
432:
433: sprintf( nextValue, "\"%s\"=", name);
434: nextValue += nameLen + 3;
435: *nextValue++ = '\"';
436: nextLen = strlen( nextValue) + 2;
437: nextValue += nextLen;
438: strcpy( nextValue - 2, "\";");
439: maxLen -= nextLen + nameLen + 4;
440: }
441: }
442: [nameList free];
443: }
444:
445: *nextValue = 0;
446: return( self);
447: }
448:
449: - matchStringPropertyList:(char *)values
450: {
451: enum { kValueMaxSize = 256 };
452: char * valueBuf;
453: KernStringList * valueList, * lookList;
454: int look, value;
455: id rtn;
456: char * next, * end;
457: BOOL found, lookingName = YES;
458:
459: next = values;
460: valueList = lookList = nil;
461: valueBuf = IOMalloc( kValueMaxSize);
462: if( !valueBuf)
463: return( nil);
464:
465: while(
466: (next = (char *) strchr( next, '\"'))
467: &&
468: (end = (char *) strchr( ++next, '\"')) ) {
469:
470: found = NO;
471: *end = 0; // yikes - modify caller's string
472:
473: if( lookingName) {
474:
475: rtn = [self lookUpStringProperty:next value:valueBuf length:kValueMaxSize];
476: *end = '\"'; // restore caller's string
477: if( !rtn)
478: break;
479: [valueList free];
480: valueList = [[KernStringList alloc]
481: initWithWhitespaceDelimitedString:valueBuf];
482: if( !valueList)
483: break;
484:
485: } else {
486:
487: [lookList free];
488: lookList = [[KernStringList alloc]
489: initWithWhitespaceDelimitedString:next];
490: *end = '\"'; // restore caller's string
491: if( !lookList)
492: break;
493:
494: found = YES;
495: for( look = 0; found && (look < [lookList count]); look++) {
496: found = NO;
497: for( value = 0; !found && (value < [valueList count]); value++)
498: found = (0 == strcmp( [lookList stringAt:look], [valueList stringAt:value] ));
499: }
500: if( !found)
501: break;
502: }
503:
504: next = end + 1;
505: lookingName ^= YES;
506: }
507: [valueList free];
508: [lookList free];
509: IOFree( valueBuf, kValueMaxSize);
510: return( found ? self : nil);
511: }
512:
513: #else /* !KERNEL */
514:
515: - getStringPropertyList:(const char *)names
516: results:(char *) results
517: maxLength:(unsigned int)length
518: {
519: return( nil);
520: }
521: - matchStringPropertyList:(char *)values
522: {
523: return( nil);
524: }
525:
526: #endif /* KERNEL */
527:
528:
529: /*
530: * Free up resources used by this device; invoke Object's free. Instance
531: * will be "gone" upon return.
532: */
533: - free
534: {
535: [self unregisterDevice];
536: return([super free]);
537: }
538:
539: - registerLoudly
540: {
541: return( self);
542: }
543:
544: /*
545: * Register instance with nmserver (or IOServer or ...). _deviceName and
546: * _deviceKind must be valid; _location must be valid or NULL.
547: */
548: - registerDevice
549: {
550: objectListEntry *objectEntry;
551:
552: xpr_dev("IODevice register\n", 1,2,3,4,5);
553:
554: if( [self registerLoudly]) {
555:
556: IOLog("Registering: %s", _deviceName);
557:
558: if(_location[0])
559: IOLog(" at %s", _location);
560:
561: if( (_deviceName[ 0 ] != '/')
562: && [__deviceDescription respondsTo:@selector(nodeName)]
563: && [__deviceDescription nodeName] ) {
564:
565: char slotName[ 32 ];
566:
567: IOLog(" [%s", [__deviceDescription nodeName]);
568:
569: if( [self lookUpStringProperty:IOPropSlotName
570: value:slotName length:sizeof( slotName)])
571: IOLog(", slot %s", slotName);
572: IOLog( "]");
573: }
574: IOLog( "\n");
575: }
576:
577: /*
578: * Create a objectNum-to-id map entry for this instance.
579: */
580: objectEntry = IOMalloc(sizeof(*objectEntry));
581: objectEntry->instance = self;
582: [objectListLock lock];
583: objectEntry->objectNumber = globalObjectCounter++;
584: queue_enter(&objectList,
585: objectEntry,
586: objectListEntry *,
587: link);
588: [objectListLock unlock];
589:
590: /*
591: * See if any indirect devices are interested in this object's
592: * protocol.
593: */
594: [IODevice connectToIndirectDevices:self];
595: return self;
596: }
597:
598: - (void)unregisterDevice
599: {
600: objectListEntry *objectEntry;
601:
602: xpr_dev("IODevice unregister %s\n", _deviceName, 2,3,4,5);
603:
604: /*
605: * Remove this device's objectNum-to-id map entry. This creates a
606: * hole in the global objectNumber space which never gets filled
607: * (in the current implementation).
608: */
609: [objectListLock lock];
610: objectEntry = getObjectListEntry(self);
611: if(objectEntry != NULL) {
612: if( [self registerLoudly])
613: IOLog("Unregistering Device: %s\n", _deviceName);
614: queue_remove(&objectList,
615: objectEntry,
616: objectListEntry *,
617: link);
618: IOFree(objectEntry, sizeof(*objectEntry));
619: }
620: [objectListLock unlock];
621:
622: }
623:
624: /*
625: * Obtain public instance variables.
626: */
627: - (const char *)name
628: {
629: return((const char *)_deviceName);
630: }
631:
632: - (void)setName : (const char *)name
633: {
634: int len;
635:
636: len = strlen((char *)name);
637: if(len >= IO_STRING_LENGTH)
638: len = IO_STRING_LENGTH - 1;
639: strncpy(_deviceName, name, len);
640: _deviceName[len] = '\0';
641: }
642:
643: - (const char *)deviceKind
644: {
645: return((const char *)_deviceKind);
646: }
647:
648: - (void)setDeviceKind : (const char *)type
649: {
650: int len;
651:
652: len = strlen((char *)type);
653: if(len >= IO_STRING_LENGTH)
654: len = IO_STRING_LENGTH - 1;
655: strncpy(_deviceKind, type, len);
656: _deviceKind[len] = '\0';
657: }
658:
659: - (const char *)location
660: {
661: return((const char *)_location);
662: }
663:
664: - (void)setLocation : (const char *)location
665: {
666: int len;
667:
668: if(location == NULL) {
669: _location[0] = '\0';
670: }
671: else {
672: len = strlen((char *)location);
673: if(len >= IO_STRING_LENGTH)
674: len = IO_STRING_LENGTH - 1;
675: strncpy(_location, location, len);
676: _location[len] = '\0';
677: }
678: }
679:
680: - (u_int)unit
681: {
682: return(_unit);
683: }
684:
685: - (void)setUnit : (u_int)unit
686: {
687: _unit = unit;
688: }
689:
690: + (int)blockMajor
691: {
692: classListEntry *classEntry;
693: if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
694: return classEntry->bmajor;
695: else
696: return -1;
697: }
698:
699: + (void)setBlockMajor : (int)bmajor
700: {
701: classListEntry *classEntry;
702: if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
703: classEntry->bmajor = bmajor;
704: }
705:
706: + (int)characterMajor
707: {
708: classListEntry *classEntry;
709: if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
710: return classEntry->cmajor;
711: else
712: return -1;
713: }
714:
715: + (void)setCharacterMajor : (int)cmajor
716: {
717: classListEntry *classEntry;
718: if (getClassListEntryForId(self, &classEntry) == IO_R_SUCCESS)
719: classEntry->cmajor = cmajor;
720: }
721:
722: #if KERNEL
723:
724: + (BOOL)addToCdevswFromDescription: (id) deviceDescription
725: open: (IOSwitchFunc) openFunc
726: close: (IOSwitchFunc) closeFunc
727: read: (IOSwitchFunc) readFunc
728: write: (IOSwitchFunc) writeFunc
729: ioctl: (IOSwitchFunc) ioctlFunc
730: stop: (IOSwitchFunc) stopFunc
731: reset: (IOSwitchFunc) resetFunc
732: select: (IOSwitchFunc) selectFunc
733: mmap: (IOSwitchFunc) mmapFunc
734: getc: (IOSwitchFunc) getcFunc
735: putc: (IOSwitchFunc) putcFunc
736: {
737: const char *majorString;
738: int major, result;
739:
740: majorString = [[deviceDescription configTable]
741: valueForStringKey:"Character Major"];
742: if (majorString) {
743: major = _atoi(majorString);
744: } else {
745: major = -1;
746: }
747: result = IOAddToCdevswAt(
748: major,
749: openFunc,
750: closeFunc,
751: readFunc,
752: writeFunc,
753: ioctlFunc,
754: stopFunc,
755: resetFunc,
756: selectFunc,
757: mmapFunc,
758: getcFunc,
759: putcFunc);
760: if (result < 0) {
761: if (major < 0)
762: IOLog ("%s: could not add to cdevsw table at any major\n",
763: [self name]);
764: else
765: IOLog ("%s: could not add to cdevsw table at major %d\n",
766: [self name], major);
767: return NO;
768: }
769: [self setCharacterMajor: result];
770: return YES;
771: }
772:
773: + (BOOL) addToBdevswFromDescription: (id) deviceDescription
774: open: (IOSwitchFunc) openFunc
775: close: (IOSwitchFunc) closeFunc
776: strategy: (IOSwitchFunc) strategyFunc
777: ioctl: (IOSwitchFunc) ioctlFunc
778: dump: (IOSwitchFunc) dumpFunc
779: psize: (IOSwitchFunc) sizeFunc
780: isTape: (BOOL) isTape
781: {
782: const char *majorString;
783: int major, result;
784:
785: majorString = [[deviceDescription configTable]
786: valueForStringKey:"Block Major"];
787: if (majorString) {
788: major = _atoi(majorString);
789: } else {
790: major = -1;
791: }
792: result = IOAddToBdevswAt(
793: major,
794: openFunc,
795: closeFunc,
796: strategyFunc,
797: ioctlFunc,
798: dumpFunc,
799: sizeFunc,
800: isTape);
801: if (result < 0) {
802: if (major < 0)
803: IOLog ("%s: could not add to bdevsw table at any major\n",
804: [self name]);
805: else
806: IOLog ("%s: could not add to bdevsw table at major %d\n",
807: [self name], major);
808: return NO;
809: }
810: [self setBlockMajor: result];
811: return YES;
812: }
813:
814: + (BOOL) removeFromCdevsw
815: {
816: int major = [self characterMajor];
817: if (major == -1)
818: return NO;
819:
820: IORemoveFromCdevsw(major);
821: [self setCharacterMajor: -1];
822: return YES;
823: }
824:
825: + (BOOL) removeFromBdevsw
826: {
827: int major = [self blockMajor];
828: if (major == -1)
829: return NO;
830:
831: IORemoveFromBdevsw(major);
832: [self setBlockMajor: -1];
833: return YES;
834: }
835:
836: - (IOReturn) serverConnect: (port_t *) machPort // out in IOTask space
837: taskPort: (port_t) taskPort; // in actually ipc_port_t
838: {
839: *machPort = PORT_NULL;
840: return IO_R_UNSUPPORTED;
841: }
842:
843: #else /* !KERNEL */
844:
845: + (BOOL)addToCdevswFromDescription: (id) deviceDescription
846: open: (IOSwitchFunc) openFunc
847: close: (IOSwitchFunc) closeFunc
848: read: (IOSwitchFunc) readFunc
849: write: (IOSwitchFunc) writeFunc
850: ioctl: (IOSwitchFunc) ioctlFunc
851: stop: (IOSwitchFunc) stopFunc
852: reset: (IOSwitchFunc) resetFunc
853: select: (IOSwitchFunc) selectFunc
854: mmap: (IOSwitchFunc) mmapFunc
855: getc: (IOSwitchFunc) getcFunc
856: putc: (IOSwitchFunc) putcFunc
857: {
858: return FALSE;
859: }
860:
861: + (BOOL) addToBdevswFromDescription: (id) deviceDescription
862: open: (IOSwitchFunc) openFunc
863: close: (IOSwitchFunc) closeFunc
864: strategy: (IOSwitchFunc) strategyFunc
865: ioctl: (IOSwitchFunc) ioctlFunc
866: dump: (IOSwitchFunc) dumpFunc
867: psize: (IOSwitchFunc) sizeFunc
868: isTape: (BOOL) isTape
869: {
870: return FALSE;
871: }
872:
873: + (BOOL) removeFromCdevsw
874: {
875: return FALSE;
876: }
877:
878: + (BOOL) removeFromBdevsw
879: {
880: return FALSE;
881: }
882:
883: - (IOReturn) serverConnect: (port_t *) machPort // out in IOTask space
884: taskPort: (port_t) taskPort; // in actually ipc_port_t
885: {
886: return IO_R_UNSUPPORTED;
887: }
888:
889: #endif /* KERNEL */
890:
891: + (int) driverKitVersion
892: {
893: return IO_DRIVERKIT_VERSION;
894: }
895:
896: #define VERSION_CLASS "Version"
897: #define VERSION_METHOD "driverKitVersionFor"
898:
899: + (int) driverKitVersionForDriverNamed:(char *)driverName
900: {
901: char *nameBuf;
902: int size, ret;
903: id versionClass;
904: SEL versionMethod;
905:
906: size = strlen(driverName) + strlen(VERSION_CLASS) + 1;
907: nameBuf = IOMalloc(size);
908: if (nameBuf == NULL)
909: return -1;
910: strcpy(nameBuf, driverName);
911: strcat(nameBuf,VERSION_CLASS);
912: versionClass = objc_getClass(nameBuf);
913: IOFree(nameBuf, size);
914: if (versionClass == nil)
915: return -1;
916: size = strlen(driverName) + strlen(VERSION_METHOD) + 1;
917: nameBuf = IOMalloc(size);
918: if (nameBuf == NULL)
919: return -1;
920: strcpy(nameBuf, VERSION_METHOD);
921: strcat(nameBuf, driverName);
922: versionMethod = sel_getUid(nameBuf);
923: if ([versionClass respondsTo:versionMethod])
924: ret = (int)[versionClass perform:versionMethod];
925: else
926: ret = -1;
927: IOFree(nameBuf, size);
928: return ret;
929: }
930:
931:
932:
933: /*
934: * Get/set parameters.
935: */
936: - (IOReturn)getIntValues : (unsigned *)parameterArray
937: forParameter : (IOParameterName)parameterName
938: count : (unsigned *)count // in/out
939: {
940: if(strcmp(parameterName, IO_UNIT) == 0) {
941: parameterArray[0] = _unit;
942: *count = 1;
943: return IO_R_SUCCESS;
944: } else if(strcmp(parameterName, IO_BLOCK_MAJOR) == 0) {
945: classListEntry *classEntry;
946: if (getClassListEntryForId([self class], &classEntry) ==
947: IO_R_SUCCESS) {
948: parameterArray[0] = classEntry->bmajor;
949: *count = 1;
950: return IO_R_SUCCESS;
951: } else
952: return IO_R_UNSUPPORTED;
953: } else if(strcmp(parameterName, IO_CHARACTER_MAJOR) == 0) {
954: classListEntry *classEntry;
955: if (getClassListEntryForId([self class], &classEntry) ==
956: IO_R_SUCCESS) {
957: parameterArray[0] = classEntry->cmajor;
958: *count = 1;
959: return IO_R_SUCCESS;
960: } else
961: return IO_R_UNSUPPORTED;
962: }
963: return IO_R_UNSUPPORTED;
964: }
965:
966: - (IOReturn)getCharValues : (unsigned char *)parameterArray
967: forParameter : (IOParameterName)parameterName
968: count : (unsigned *)count // in/out
969: {
970: const char *name;
971: unsigned length;
972: int maxCount = *count;
973:
974: if(maxCount == 0) {
975: maxCount = IO_MAX_PARAMETER_ARRAY_LENGTH;
976: }
977: if(strcmp(parameterName, IO_CLASS_NAME) == 0) {
978: name = [[self class] name];
979: goto name_out;
980: }
981: else if(strcmp(parameterName, IO_DEVICE_NAME) == 0) {
982: name = _deviceName;
983: goto name_out;
984: }
985: else if(strcmp(parameterName, IO_DEVICE_KIND) == 0){
986: name = _deviceKind;
987: name_out:
988: length = strlen(name);
989: if(length >= maxCount) {
990: length = maxCount - 1;
991: }
992: *count = length + 1;
993: strncpy(parameterArray, name, length);
994: parameterArray[length] = '\0';
995: return IO_R_SUCCESS;
996: }
997: else {
998: return IO_R_UNSUPPORTED;
999: }
1000: }
1001:
1002: - (IOReturn)setIntValues : (unsigned *)parameterArray
1003: forParameter : (IOParameterName)parameterName
1004: count : (unsigned)count
1005: {
1006: return IO_R_UNSUPPORTED;
1007: }
1008:
1009: - (IOReturn)setCharValues : (unsigned char *)parameterArray
1010: forParameter : (IOParameterName)parameterName
1011: count : (unsigned)count
1012: {
1013: return IO_R_UNSUPPORTED;
1014: }
1015:
1016: /*
1017: * Convert an IOReturn to text. Subclasses which add additional
1018: * IOReturn's should override this method and call
1019: * [super stringFromReturn] if the desired value is not found.
1020: */
1021: - (const char *)stringFromReturn : (IOReturn)rtn
1022: {
1023: return [IODevice stringFromReturn:rtn];
1024: }
1025:
1026: + (const char *)stringFromReturn : (IOReturn)rtn
1027: {
1028: return IOFindNameForValue(rtn, IOReturn_values);
1029: }
1030:
1031: /*
1032: * Convert an IOReturn to an errno.
1033: */
1034: - (int)errnoFromReturn : (IOReturn)rtn
1035: {
1036: switch(rtn) {
1037: case IO_R_SUCCESS:
1038: return(0);
1039: case IO_R_NO_MEMORY:
1040: case IO_R_RESOURCE:
1041: return(ENOMEM);
1042: case IO_R_NO_DEVICE:
1043: return(ENXIO);
1044: case IO_R_PRIVILEGE:
1045: case IO_R_LOCKED_READ:
1046: case IO_R_LOCKED_WRITE:
1047: case IO_R_EXCLUSIVE_ACCESS:
1048: case IO_R_CANT_LOCK:
1049: case IO_R_NOT_READABLE:
1050: case IO_R_NOT_OPEN:
1051: return(EACCES);
1052: case IO_R_INVALID_ARG:
1053: return(EINVAL);
1054: case IO_R_UNSUPPORTED:
1055: return(EOPNOTSUPP);
1056: case IO_R_IO:
1057: case IO_R_MEDIA:
1058: case IO_R_DMA:
1059: return(EIO);
1060: case IO_R_NOT_WRITABLE:
1061: return(EROFS);
1062: case IO_R_OPEN:
1063: case IO_R_BUSY:
1064: return(EBUSY);
1065: default:
1066: return(EIO);
1067: }
1068: }
1069:
1070: @end /* IODevice */
1071:
1072: @implementation IODevice(Internal)
1073:
1074: @end /* IODevice(Internal) */
1075:
1076: /*
1077: * Get/set parameter RPC support. In the kernel, these methods are mainly
1078: * called by the driverServer (although they cal be used by anyone); they
1079: * map an objectNumber to an id and invoke the appropriate methods. Usage in
1080: * user space TBD.
1081: */
1082:
1083: @implementation IODevice(GlobalParameter)
1084:
1085: #if KERNEL
1086: + (IOReturn) serverConnect: (port_t *) machPort // out - IOTask space
1087: objectNumber: (IOObjectNumber) objectNumber
1088: taskPort: (port_t) taskPort; // in - ipc_port_t
1089: {
1090: IODevice *instance;
1091: IOReturn rtn = IO_R_SUCCESS;
1092:
1093: [objectListLock lock];
1094: rtn = objectNumToId(objectNumber, (id) &instance);
1095: [objectListLock unlock];
1096:
1097: if (rtn == IO_R_SUCCESS)
1098: rtn = [instance serverConnect: machPort taskPort: taskPort];
1099:
1100: return rtn;
1101: }
1102: #endif /* KERNEL */
1103:
1104: /*
1105: * Lookup by IOObjectNumber.
1106: */
1107: + (IOReturn)lookupByObjectNumber : (IOObjectNumber)objectNumber
1108: deviceKind : (IOString *)deviceKind
1109: deviceName : (IOString *)deviceName;
1110: {
1111: id instance;
1112: IOReturn rtn = IO_R_SUCCESS;
1113:
1114: [objectListLock lock];
1115: rtn = objectNumToId(objectNumber, &instance);
1116: [objectListLock unlock];
1117: if(rtn == IO_R_SUCCESS) {
1118: strncpy(*deviceKind, [instance deviceKind], IO_STRING_LENGTH);
1119: strncpy(*deviceName, [instance name], IO_STRING_LENGTH);
1120: }
1121: return rtn;
1122: }
1123:
1124: + (IOReturn)lookupByObjectNumber : (IOObjectNumber)objectNumber
1125: instance : (id *)instance
1126: {
1127: IOReturn rtn;
1128:
1129: [objectListLock lock];
1130: rtn = objectNumToId(objectNumber, instance);
1131: [objectListLock unlock];
1132: return rtn;
1133: }
1134:
1135: /*
1136: * Lookup by deviceName.
1137: */
1138: + (IOReturn)lookupByDeviceName : (IOString)deviceName
1139: objectNumber : (IOObjectNumber *)objectNumber
1140: deviceKind : (IOString *)deviceKind;
1141: {
1142: id instance;
1143: IOReturn rtn = IO_R_SUCCESS;
1144:
1145: [objectListLock lock];
1146: rtn = deviceNameToId(deviceName, &instance, objectNumber);
1147: [objectListLock unlock];
1148: if(rtn == IO_R_SUCCESS) {
1149: strncpy(*deviceKind, [instance deviceKind], IO_STRING_LENGTH);
1150: }
1151: return rtn;
1152: }
1153:
1154: + (IOReturn) lookUpByStringPropertyList:(char *)values
1155: results:(char *)results
1156: maxLength:(unsigned int)length
1157: {
1158: IOReturn err;
1159: int objectNum = 0;
1160: id dev;
1161: const char * newName;
1162:
1163: *results = 0;
1164: [objectListLock lock];
1165: do {
1166: err = objectNumToId(objectNum++, &dev);
1167: if( err != IO_R_SUCCESS)
1168: continue;
1169:
1170: if( [dev matchStringPropertyList:values]) {
1171:
1172: newName = [dev name];
1173: if( (1 + 1 + strlen( newName)) < length) { // space & zero chars
1174: if( results[ 0 ]) {
1175: strcat( results, " ");
1176: length--;
1177: }
1178: strcat( results, newName );
1179: length -= strlen( newName);
1180: } else
1181: err = IO_R_RESOURCE;
1182: }
1183: } while( (err == IO_R_SUCCESS) || (err == IO_R_OFFLINE));
1184:
1185: [objectListLock unlock];
1186:
1187: if( err == IO_R_NO_DEVICE)
1188: err = IO_R_SUCCESS;
1189:
1190: return( err);
1191: }
1192:
1193: + (IOReturn)getIntValues : (unsigned *)parameterArray
1194: forParameter : (IOParameterName)parameterName
1195: objectNumber : (IOObjectNumber)objectNumber
1196: count : (unsigned *)count // in/out
1197: {
1198: id instance;
1199: IOReturn rtn = IO_R_SUCCESS;
1200:
1201: [objectListLock lock];
1202: rtn = objectNumToId(objectNumber, &instance);
1203: [objectListLock unlock];
1204: if(rtn == IO_R_SUCCESS) {
1205: rtn = [instance getIntValues : parameterArray
1206: forParameter : parameterName
1207: count : count];
1208: }
1209: return rtn;
1210:
1211: }
1212:
1213: + (IOReturn)getCharValues : (unsigned char *)parameterArray
1214: forParameter : (IOParameterName)parameterName
1215: objectNumber : (IOObjectNumber)objectNumber
1216: count : (unsigned *)count // in/out
1217: {
1218: id instance;
1219: IOReturn rtn = IO_R_SUCCESS;
1220:
1221: [objectListLock lock];
1222: rtn = objectNumToId(objectNumber, &instance);
1223: [objectListLock unlock];
1224: if(rtn == IO_R_SUCCESS) {
1225: rtn = [instance getCharValues : parameterArray
1226: forParameter : parameterName
1227: count : count];
1228: }
1229: return rtn;
1230:
1231: }
1232:
1233: + (IOReturn)setIntValues : (unsigned *)parameterArray
1234: forParameter : (IOParameterName)parameterName
1235: objectNumber : (IOObjectNumber)objectNumber
1236: count : (unsigned)count
1237: {
1238: id instance;
1239: IOReturn rtn = IO_R_SUCCESS;
1240:
1241: [objectListLock lock];
1242: rtn = objectNumToId(objectNumber, &instance);
1243: [objectListLock unlock];
1244: if(rtn == IO_R_SUCCESS) {
1245: rtn = [instance setIntValues : parameterArray
1246: forParameter : parameterName
1247: count : count];
1248: }
1249: return rtn;
1250:
1251: }
1252:
1253:
1254: + (IOReturn)setCharValues : (unsigned char *)parameterArray
1255: forParameter : (IOParameterName)parameterName
1256: objectNumber : (IOObjectNumber)objectNumber
1257: count : (unsigned)count
1258: {
1259: id instance;
1260: IOReturn rtn = IO_R_SUCCESS;
1261:
1262: [objectListLock lock];
1263: rtn = objectNumToId(objectNumber, &instance);
1264: [objectListLock unlock];
1265: if(rtn == IO_R_SUCCESS) {
1266: rtn = [instance setCharValues : parameterArray
1267: forParameter : parameterName
1268: count : count];
1269: }
1270: return rtn;
1271:
1272: }
1273:
1274: + (IOReturn) getStringPropertyList : (IOObjectNumber)objectNumber
1275: names : (const char *)names
1276: results : (char *)results
1277: maxLength : (unsigned int)length
1278: {
1279: id instance;
1280: IOReturn rtn = IO_R_SUCCESS;
1281:
1282: [objectListLock lock];
1283: rtn = objectNumToId(objectNumber, &instance);
1284: [objectListLock unlock];
1285: if(rtn == IO_R_SUCCESS) {
1286: instance = [instance getStringPropertyList : names
1287: results : results
1288: maxLength : length];
1289: if( !instance)
1290: rtn = IO_R_UNSUPPORTED;
1291: }
1292: return rtn;
1293: }
1294:
1295: + (IOReturn) getByteProperty : (IOObjectNumber)objectNumber
1296: name : (const char *)name
1297: results : (char *)results
1298: maxLength : (unsigned int *)length
1299: {
1300: id instance;
1301: IOReturn rtn = IO_R_SUCCESS;
1302:
1303: [objectListLock lock];
1304: rtn = objectNumToId(objectNumber, &instance);
1305: [objectListLock unlock];
1306: if(rtn == IO_R_SUCCESS) {
1307: instance = [instance lookUpProperty : name
1308: value : results
1309: length : length];
1310: if( !instance)
1311: rtn = IO_R_UNSUPPORTED;
1312: }
1313: return rtn;
1314: }
1315:
1316: + (IOReturn)callDeviceMethod : (IOString)methodName
1317: inputParams : (unsigned char *)inputParams
1318: inputCount : (unsigned)inputCount
1319: outputParams : (unsigned char *)outputParams
1320: outputCount : (unsigned *)outputCount // in/out
1321: privileged : (host_priv_t *)privileged
1322: objectNumber : (IOObjectNumber)objectNumber
1323:
1324: {
1325: id instance;
1326: IOReturn rtn = IO_R_SUCCESS;
1327: SEL selector;
1328:
1329: [objectListLock lock];
1330: rtn = objectNumToId(objectNumber, &instance);
1331: [objectListLock unlock];
1332: if(rtn == IO_R_SUCCESS) {
1333:
1334: selector = sel_getUid( methodName );
1335: if( NO == [instance respondsTo:selector])
1336: rtn = IO_R_UNSUPPORTED;
1337:
1338: else if( *outputCount) {
1339: if( inputCount) {
1340: rtn = (IOReturn) objc_msgSend( instance, selector,
1341: inputParams, inputCount, outputParams, outputCount,
1342: privileged );
1343: } else {
1344: rtn = (IOReturn) objc_msgSend( instance, selector,
1345: outputParams, outputCount,
1346: privileged );
1347: }
1348: } else {
1349: if( inputCount) {
1350: rtn = (IOReturn) objc_msgSend( instance, selector,
1351: inputParams, inputCount,
1352: privileged );
1353: } else {
1354: rtn = (IOReturn) objc_msgSend( instance, selector,
1355: privileged );
1356: }
1357: }
1358: }
1359: return rtn;
1360: }
1361:
1362:
1363: @end /* IODevice(GlobalParameter) */
1364:
1365: #ifdef KERNEL
1366:
1367: /*
1368: * We leave this enabled for user level programs for now; it may be useful...
1369: */
1370: @implementation IODevice(kernelPrivate)
1371:
1372: /*
1373: * A new class has been loaded into the kernel. Connect the new class
1374: * with all existing classes, probing as appropriate.
1375: *
1376: * All instance variables in deviceDescription must be valid or
1377: * null. For newly loaded indirect devices, this method will determine
1378: * appropriate directDevice values.
1379: *
1380: * Returns IO_R_NO_DEVICE if no devices were instantiated, else IO_R_SUCCESS.
1381: */
1382: + (IOReturn)addLoadedClass : newClass
1383: description : deviceDescription
1384: {
1385: IOReturn rtn = 0;
1386: Protocol **protos;
1387: IOObjectNumber objectNum = 0;
1388: id dirDevice;
1389: BOOL objsCreated = NO;
1390: int i;
1391: classListEntry *classEntry;
1392:
1393: if (getClassListEntryForId(newClass, &classEntry) == IO_R_SUCCESS)
1394: classEntry->originalDeviceDescription = deviceDescription;
1395:
1396: switch([newClass deviceStyle]) {
1397: case IO_IndirectDevice:
1398: /*
1399: * First probe this class once for all other running objects
1400: * which export the protocol(s) required by this indirect
1401: * device.
1402: * Note all deviceStyles can export a protocol, not just direct
1403: * devices.
1404: */
1405: protos = [newClass requiredProtocols];
1406: if((protos == NULL) || (*protos == nil)) {
1407: /*
1408: * This indirect device does not require any
1409: * protocols. Huh???
1410: */
1411: IOLog("Loaded class %s returns nil for "
1412: "+requiredProtocols\n",
1413: [newClass name]);
1414: break;
1415: }
1416:
1417: /*
1418: * Cycle thru all known devices.
1419: */
1420: for(objectNum=0; rtn!=IO_R_NO_DEVICE; objectNum++) {
1421: rtn = objectNumToId(objectNum, &dirDevice);
1422: switch(rtn) {
1423: case IO_R_OFFLINE:
1424: /*
1425: * No device here, but more to go.
1426: */
1427: continue;
1428:
1429: case IO_R_NO_DEVICE:
1430: default:
1431: /*
1432: * No more.
1433: */
1434: break;
1435:
1436: case IO_R_SUCCESS:
1437: /*
1438: * See if this thing supports all the
1439: * protocols newClass needs.
1440: */
1441: for(i=0; protos[i]; i++) {
1442: if(![dirDevice conformsTo:protos[i]]) {
1443: goto next_object; /* to next objectNum */
1444: }
1445: }
1446:
1447: /*
1448: * Looks good. Cook up an IODeviceDescription
1449: * we can pass to newClass.
1450: */
1451: [deviceDescription setDirectDevice:dirDevice];
1452: if([newClass probe:deviceDescription]) {
1453: objsCreated = YES;
1454: }
1455: break;
1456: } /* switch rtn */
1457: next_object:
1458: continue;
1459: } /* for each objectNum */
1460:
1461: break; /* from case IO_STYLE_INDIRECT */
1462:
1463: case IO_DirectDevice:
1464: case IO_PseudoDevice:
1465: if (![newClass respondsTo:@selector(probe:)]) {
1466: IOLog("addLoadedClass: Class %s does not "
1467: "respond to probe:\n",
1468: [newClass name]);
1469: break;
1470: }
1471: if([newClass probe:deviceDescription]) {
1472: objsCreated = YES;
1473: }
1474: break;
1475:
1476: } /* switch deviceStyle */
1477:
1478: if(objsCreated) {
1479: return IO_R_SUCCESS;
1480: }
1481: else {
1482: return IO_R_NO_DEVICE;
1483: }
1484: }
1485:
1486: /*
1487: * Probe for any indirect device classes in the system which are
1488: * interested in connecting to a newly instantiated device of any kind.
1489: * Used only by -registerDevice (so far).
1490: */
1491: +(void)connectToIndirectDevices : newObject
1492: {
1493: unsigned classNumber = 0;
1494: Protocol **protos;
1495: IOReturn rtn;
1496: classListEntry *classEntry;
1497: int i;
1498: id deviceDescription;
1499:
1500: /*
1501: * We hold classListLock throughout this routine, except for when
1502: * we actually probe an indirect device class.
1503: */
1504: [classListLock lock];
1505: for(classNumber=0; ;classNumber++) {
1506: /*
1507: * Check out each indirect driver class in classList.
1508: */
1509: rtn = getClassListEntry(classNumber, &classEntry);
1510: switch(rtn) {
1511: case IO_R_SUCCESS:
1512: break; // proceed
1513: case IO_R_NO_DEVICE:
1514: goto done; // normal termination
1515: case IO_R_OFFLINE:
1516: goto next_class; // hole in classList space
1517: }
1518: if([classEntry->classId deviceStyle] != IO_IndirectDevice) {
1519: goto next_class;
1520: }
1521:
1522: /*
1523: * We have an indirect device class. See if the protocols
1524: * it requires are supported by the new object.
1525: */
1526: protos = [classEntry->classId requiredProtocols];
1527: if((protos == NULL) || (*protos == nil)) {
1528: /*
1529: * This indirect device does not require any
1530: * protocols. Huh???
1531: */
1532: IOLog("Loaded class %s returns nil for "
1533: "+requiredProtocols\n",
1534: [classEntry->classId name]);
1535: goto next_class;
1536: }
1537: for(i=0; protos[i]; i++) {
1538: if(![newObject conformsTo:protos[i]]) {
1539: goto next_class;
1540: }
1541: }
1542:
1543: /*
1544: * Looks good. Cook up an IODeviceDescription we can pass
1545: * to the indirect driver class and probe away.
1546: */
1547: if (classEntry->originalDeviceDescription != nil)
1548: deviceDescription = classEntry->originalDeviceDescription;
1549: else
1550: deviceDescription = [[IODeviceDescription alloc] init];
1551: [deviceDescription setDirectDevice:newObject];
1552: [classListLock unlock];
1553: if ([classEntry->classId probe:deviceDescription] == NO)
1554: [deviceDescription free];
1555: [classListLock lock];
1556:
1557: next_class:
1558: continue;
1559: }
1560: done:
1561: [classListLock unlock];
1562: return;
1563: }
1564:
1565: + (List *)objectsForClass:(Class *)driverClass
1566: {
1567: id list;
1568: objectListEntry *objectEntry =
1569: (objectListEntry *)queue_first(&objectList);
1570:
1571: list = [[List alloc] init];
1572: [objectListLock lock];
1573: while(!queue_end(&objectList, (queue_t)objectEntry)) {
1574: if((Class *)[objectEntry->instance class] == driverClass) {
1575: [list addObject:objectEntry->instance];
1576: }
1577: objectEntry = (objectListEntry *)objectEntry->link.next;
1578: }
1579: [objectListLock unlock];
1580: return list;
1581: }
1582:
1583: #if 0
1584: + (HashTable *)classTableFromConfigTable : configTable
1585: {
1586: char *classNameList, *className, *ptr, *str;
1587: int len;
1588: HashTable *hash;
1589:
1590: classNameList = (char *)[configTable valueForStringKey:"Class Names"];
1591: if (classNameList == NULL)
1592: classNameList = (char *)[configTable valueForStringKey:"Driver Name"];
1593: if (classNameList == NULL)
1594: return nil;
1595:
1596: len = strlen(classNameList);
1597: hash = [[HashTable alloc] initKeyDesc:"*"];
1598: className = classNameList;
1599: while (*className) {
1600: ptr = className;
1601: while (*ptr && *ptr != ' ' && *ptr != '\t')
1602: ptr++;
1603: len = ptr - className + 1;
1604: str = IOMalloc(len);
1605: strncpy(str, className, len - 1);
1606: str[len-1] = '\0';
1607: [hash insertKey:str value:objc_getClass(str)];
1608: while (*ptr && (*ptr == ' ' || *ptr == '\t'))
1609: ptr++;
1610: className = ptr;
1611: }
1612: [configTable freeString:classNameList];
1613:
1614: return hash;
1615: }
1616: #endif
1617:
1618: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
1619: {
1620: return( nil);
1621: }
1622:
1623: - property_IODeviceType:(char *)classes length:(unsigned int *)maxLen
1624: {
1625: return( nil);
1626: }
1627:
1628: @end /* IODevice(kernelPrivate) */
1629:
1630: /*
1631: * Lookup by deviceName, kernel internal version. Returns id of specified
1632: * instance in deviceId.
1633: */
1634: IOReturn IOGetObjectForDeviceName(
1635: IOString deviceName,
1636: id *deviceId) // returned
1637: {
1638: IOReturn rtn;
1639: IOObjectNumber objectNumber;
1640:
1641: [objectListLock lock];
1642: rtn = deviceNameToId(deviceName, deviceId, &objectNumber);
1643: [objectListLock unlock];
1644: return rtn;
1645: }
1646:
1647: #endif KERNEL
1648:
1649:
1650: /*
1651: * Static functions.
1652: */
1653:
1654: /*
1655: * Get id of specified global objectNumber. objectListLock must be held on
1656: * entry.
1657: * Returns IO_R_OFFLINE if a hole is found in IOObjectNumber space at
1658: * specified objectNumber. Returns IO_R_NO_DEVICE if objectNumber is out
1659: * of range.
1660: */
1661: static IOReturn objectNumToId(IOObjectNumber objectNumber, id *instance)
1662: {
1663: objectListEntry *objectEntry =
1664: (objectListEntry *)queue_first(&objectList);
1665:
1666: if(objectNumber >= globalObjectCounter)
1667: return IO_R_NO_DEVICE;
1668: while(!queue_end(&objectList, (queue_t)objectEntry)) {
1669: if(objectEntry->objectNumber == objectNumber) {
1670: *instance = objectEntry->instance;
1671: return IO_R_SUCCESS;
1672: }
1673: else
1674: objectEntry =
1675: (objectListEntry *)objectEntry->link.next;
1676: }
1677:
1678: /*
1679: * Not found. This implies a "hole" in the objectNumber space.
1680: */
1681: return IO_R_OFFLINE;
1682: }
1683:
1684: /*
1685: * Get id of device with specified name. objectListLock must be held on entry.
1686: */
1687: static IOReturn deviceNameToId(IOString name,
1688: id *instance,
1689: IOObjectNumber *objectNumber)
1690: {
1691: objectListEntry *objectEntry =
1692: (objectListEntry *)queue_first(&objectList);
1693:
1694: while(!queue_end(&objectList, (queue_t)objectEntry)) {
1695: if(strncmp(name, [objectEntry->instance name],
1696: IO_STRING_LENGTH) == 0) {
1697: *instance = objectEntry->instance;
1698: *objectNumber = objectEntry->objectNumber;
1699: return IO_R_SUCCESS;
1700: }
1701: else {
1702: objectEntry =
1703: (objectListEntry *)objectEntry->link.next;
1704: }
1705: }
1706:
1707: /*
1708: * Not found.
1709: */
1710: return IO_R_NO_DEVICE;
1711: }
1712:
1713: /*
1714: * Get an instance's objectNum-to-id map entry. objectListLock must be held
1715: * on entry.
1716: */
1717: static objectListEntry *getObjectListEntry(id object)
1718: {
1719: objectListEntry *objectEntry;
1720:
1721: objectEntry = (objectListEntry *)queue_first(&objectList);
1722: while(!queue_end(&objectList, (queue_t)objectEntry)) {
1723: if(objectEntry->instance == object) {
1724: goto out;
1725: }
1726: else {
1727: objectEntry =
1728: (objectListEntry *)objectEntry->link.next;
1729: }
1730: }
1731: objectEntry = NULL;
1732: out:
1733: return objectEntry;
1734: }
1735:
1736: /*
1737: * Get a classListEntry for specified class id.
1738: */
1739: static IOReturn getClassListEntryForId(
1740: id classId,
1741: classListEntry **entry
1742: )
1743: {
1744: classListEntry *classEntry;
1745:
1746: [classListLock lock];
1747: classEntry = (classListEntry *)queue_first(&classList);
1748: while(!queue_end(&classList, (queue_t)classEntry)) {
1749: if(classEntry->classId == classId) {
1750: *entry = classEntry;
1751: [classListLock unlock];
1752: return IO_R_SUCCESS;
1753: }
1754: classEntry = (classListEntry *)classEntry->link.next;
1755: }
1756: [classListLock unlock];
1757: return IO_R_OFFLINE;
1758: }
1759:
1760: /*
1761: * Get a classListEntry for specified classNumber. classListLock must be held
1762: * on entry.
1763: * Returns IO_R_OFFLINE if a hole is found in classNumber space at
1764: * specified classNumber. Returns IO_R_NO_DEVICE if classNumber is out
1765: * of range.
1766: */
1767: static IOReturn getClassListEntry(unsigned classNumber,
1768: classListEntry **entry)
1769: {
1770: classListEntry *classEntry;
1771:
1772: if(classNumber > classCounter) {
1773: return IO_R_NO_DEVICE;
1774: }
1775: classEntry = (classListEntry *)queue_first(&classList);
1776: while(!queue_end(&classList, (queue_t)classEntry)) {
1777: if(classEntry->classNumber == classNumber) {
1778: *entry = classEntry;
1779: return IO_R_SUCCESS;
1780: }
1781: classEntry = (classListEntry *)classEntry->link.next;
1782: }
1783: return IO_R_OFFLINE;
1784: }
1785:
1786: /* end of IODevice.m */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.