|
|
1.1 ! root 1: {\rtf0\ansi{\fonttbl\f0\fmodern Ohlfs;\f2\fmodern Courier;} ! 2: \paperw13040 ! 3: \paperh9940 ! 4: \margl120 ! 5: \margr120 ! 6: {\colortbl;\red0\green0\blue0;} ! 7: \pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\f0\b0\i0\ulnone\fs24\fc0\cf0 Here's a proposal for the mechanism by which drivers which have just been loaded into the kernel will be connected with the appropriate direct and/or indirect devices which already exist in the kernel. This proposal does NOT cover the means by which drivers are actually loaded into the kernel. That may very well be an MD solution. The mechanism proposed here is indeed machine independent and I will write it if people think it will be useful.\ ! 8: \ ! 9: Problem: You load in a new indirect device driver - for example, a new SCSI indirect device like a scanner. Once it's loaded into the kernel, you want to give the class a chance to connect with each instance of SCSIController which currently is running in the system. Or: you load in a new direct device - say, a new SCSIController object. Once it's loaded and initialized, you want to give all of the SCSI indirect devices in the system a chance to connect to this new controller. The kernel's standard SCSIDisk object will want to see if there are any disk drivers connected to the controller attached to this new driver. \ ! 10: \ ! 11: Solution: \ ! 12: \ ! 13: * All IODevices must implement this factory method:\ ! 14: \ ! 15: ! 16: \f2\fc1\cf1 + (IODeviceStyle) ! 17: \b deviceStyle ! 18: \b0 ;\ ! 19: ! 20: \f0\fc0\cf0 \ ! 21: ...which returns one of these: \ ! 22: \ ! 23: ! 24: \f2\fc1\cf1 typedef enum \{\ ! 25: IO_STYLE_DIRECT,\ ! 26: IO_STYLE_INDIRECT,\ ! 27: IO_STYLE_PSEUDO\ ! 28: \} ! 29: \b IODeviceStyle ! 30: \b0 ;\ ! 31: ! 32: \f0\fc0\cf0 \ ! 33: I am certainly open for suggestion for the name of this property. Seems like they're all used up (type, name, class, etc.). Anyway, it's pretty self-explanatory - it answers the question "Is this device a direct device, an indirect device, or a pseudo device?"\ ! 34: \ ! 35: * All devices to which an indirect device can be connected must declare their exported interface as an ObjC protocol. (For example, SCSIControllerPublic or FloppyControllerPublic.)\ ! 36: \ ! 37: * Indirect devices have a factory method, which returns a (Protocol **), and which is a list of protocols the class requires.\ ! 38: \ ! 39: * Remember that a list of running IODevice objects in the kernel is maintained by IODevice. A driver instance adds itself to this list at -registerDevice time. Let's call this list deviceList for now.\ ! 40: \ ! 41: * A list of IODevice leaf subclasses (i.e., not abstract superclasses) in the system will be maintained by IODevice. Each IODevice leaf subclass must call this method on self or super at class +initialize time:\ ! 42: \ ! 43: + ! 44: \f2\b\fc1\cf1 registerClass ! 45: \f0\b0\fc0\cf0 ;\ ! 46: \ ! 47: Let's call the resulting list, which will be maintained by IODevice, the classList for now.\ ! 48: \ ! 49: * There is a new kernel function - which may be private, let's see if we need to export it:\ ! 50: \ ! 51: ! 52: \f2\fc1\cf1 IOReturn ! 53: \b IOAddLoadedDevice ! 54: \b0 (\ ! 55: id newClass,\ ! 56: id deviceDescription);\ ! 57: ! 58: \f0\fc0\cf0 \ ! 59: This function is responsible for probing the newly added class, and possibly other classes in the system, as appropriate. \ ! 60: \ ! 61: The deviceDescription argument passed to this function is an IODeviceDescription or a subclass of same. It contains a valid _deviceMaster and _devicePort if the driver being loaded is a direct device. (Where these data come from is beyond the scope of this proposal.) It also contains whatever machine-dependent or device-dependent configuration info is appropriate to the loaded device. The newClass argument is simply the id of the new class which has been loaded.\ ! 62: \ ! 63: Here's some pseudocode which illustrates what this function does:\ ! 64: \ ! 65: ! 66: \f2\fc1\cf1 IOReturn IOAddLoadedDevice(\ ! 67: id newClass,\ ! 68: id deviceDescription)\ ! 69: \{\ ! 70: switch([newClass deviceStyle]) \{\ ! 71: case IO_STYLE_INDIRECT:\ ! 72: /* \ ! 73: * First probe this class once for all other running objects\ ! 74: * which export the protocol(s) required by this indirect device. \ ! 75: * Note all deviceStyles can export a protocol, not just direct \ ! 76: * devices.\ ! 77: */\ ! 78: get protocols needed for newClass;\ ! 79: for each object in deviceList \{\ ! 80: for each protocol needed by newClass \{\ ! 81: if found object doesn't support it \{\ ! 82: continue to next object in device list;\ ! 83: \}\ ! 84: \}\ ! 85: cons up an IODeviceDescription with \ ! 86: _directDevice = the object we just found;\ ! 87: newObject = [newClass probe:IODeviceDescription];\ ! 88: if(newObject) \{\ ! 89: /*\ ! 90: * See if any other indirect devices in the system want \ ! 91: * to connect to this new object.\ ! 92: */\ ! 93: connectToIndirectDevices(newObject);\ ! 94: \}\ ! 95: \}\ ! 96: break;\ ! 97: \ ! 98: case IO_STYLE_DIRECT:\ ! 99: case IO_STYLE_PSEUDO:\ ! 100: newObject = [newClass probe:deviceDescription];\ ! 101: if(newObject) \{\ ! 102: /*\ ! 103: * See if any other indirect devices in the system want \ ! 104: * to connect to this new object.\ ! 105: */\ ! 106: connectToIndirectDevices(newObject);\ ! 107: \}\ ! 108: break;\ ! 109: \}\ ! 110: return error if we did not create any new devices;\ ! 111: \ ! 112: \ ! 113: /*\ ! 114: * Probe for any indirect device classes in the system which are \ ! 115: * interested in connecting to a newly instantiated device of any kind.\ ! 116: * (private, only used by IOAddLoadedDevice().)\ ! 117: */\ ! 118: void connectToIndirectDevices(id newObject)\ ! 119: \{\ ! 120: for each indirect device class in classList \{\ ! 121: for each protocol needed by newObject \{\ ! 122: if newObject doesn't support this protocol \{\ ! 123: continue to next indirect device;\ ! 124: \}\ ! 125: \} \ ! 126: cons up an IODeviceDescription with \ ! 127: _directDevice = newObject;\ ! 128: probe indirect device with this IODeviceDescription;\ ! 129: \} \ ! 130: return;\ ! 131: \}\ ! 132: ! 133: \f0\fc0\cf0 \ ! 134: [\ ! 135: \ ! 136: ! 137: \fc1\cf1 addenda 14 Jan 93\ ! 138: \ ! 139: I think connectToIndirectDevices() should be called from registerDevice.\ ! 140: Initial autoconfig would work like this:\ ! 141: \ ! 142: for each indirect device in statis indirect device list \{\ ! 143: registerClass:indirectDevice\ ! 144: \}\ ! 145: \ ! 146: for each device in pseudoDevice list \{\ ! 147: probe it (may result in instantiations, registerDevice, and \ ! 148: indirect probes via connectToIndirectDevices)\ ! 149: \}\ ! 150: \ ! 151: start up direct devices;\ ! 152: \ ! 153: ...simplifies things immensely, probe: doesn't return anything (except maybe\ ! 154: "yes, I started up something"\ ! 155: \ ! 156: Also, addLoadedDevice doesn't need to call connectToIndirectDevices!\ ! 157: \ ! 158: end addenda \ ! 159: ]\ ! 160: \ ! 161: ! 162: \fc0\cf0 One thing I'm not sure a ! 163: \fc1\cf1 bout is connectToIndirectDevices() - we may actually want to export some form of this in case some driver's probe: method creates multiple instances of the device and if these newly created instances also export a protocol for use by indirect devices. This seems pretty far-fetched, but you never know...\ ! 164: \ ! 165: ! 166: \fc0\cf0 I think that about does it. Should be pretty straightforward. Comments?\ ! 167: \ ! 168: --dpm\ ! 169: \ ! 170: ......\ ! 171: file - driverkit/notes/loadingDrivers.rtf\ ! 172: ! 173: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.