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