Home   Info   DevZone   Wiki  
UsersWeb  |  MainWeb  |  InfoWeb  |  DevZoneWeb  |  SupportWeb
KeithsDriverDesign ] [ not logged in ] [ Web: Imported ] goto:  options
[ get info on or edit ] login or new user ] [ list of topics, hubs & nodes, or recent changes ]

Here is the start of some device driver design information. I would appreciate any comments regarding my ideas. However, please be constructive. (Just saying "it sucks!" doesn't helpÂ…) It may be a good idea for now for nobody but me to modify this page; so please leave notes here: NotesAboutKeithsDeviceDriverDesign

Please note that this isn't even a first draft. It is still wildly incomplete. The rest of the design is floating around in my head, and I haven't had the time to type it out. Some things haven't even been thought through yet; I still don't know how some of the objects relate to each other in terms of subclassing or interfaces. As it is, I'm way past my bedtime.

I also have some ideas regarding interrupt handing and interrupt blocking that is CPU independent and prevents a driver from crashing the system (with the exception of a few core system drivers). I'll get around to noting those later.

Well, here goes.

- KeithMason


RMI

A core concept to this device driver architecture is the use of Sun's Remote Method Invocation (RMI) to communicate between user programs and device drivers. Device drivers are implemented as remote objects such that any communication to a device driver's object actually results in an RMI call to the object. For operations that can be put in the background (methods that do not need to return any data), the RMI call can occur and the current task can go on, scheduling the actual call for when it is appropriate and reducing the number of context switches that occur.

RMI will also allow device drivers to be started and stopped manually or automatically. RMI provides mechanisms to auto-load a Java VM and class set when a message is sent. If an object goes unused for a period of time, the Java VM maintaining it can be shut down and unloaded, freeing up memory space for other uses. Device drivers in this architecture are implemented as basic objects that can take advantage of RMI's features.

RMI also provides naming protocols for access to these device objects from non-device objects. When a device object is instantiated, it can register its name and object reference in a local or network nameserver. Any task interested in accessing this device can simply query the nameserver for the object's instance.

The downside to using RMI currently is permissions. A security system will have to be devised to dictate what permissions a task has to have before it can access device objects. Perhaps prevention of access to the nameserver would be sufficient. However, this is unlikely. A permission system that allows access at the method level is preferable: it will be desirable to give a task permission to access the read method, but not the write method of an arbitrary device object. Furthermore, it will be necessary to have persistent permissions: when a system boots up, permissions for a newly created object must already be correct (having to set permissions on every device object at startup or for transient devices at every initialization is unacceptable).


Internal sockets class

With use of RMI comes the need for sockets. The only sockets that Java defines are IP based. TCP/IP shouldn't be a core mechanism for the OS to operate; it should be an option that can be loaded and unloaded at runtime without affecting access to device drivers from user programs. Therefore, sockets as defined by the default Java API are insufficient.

Java does allow for other socket types to be designed. (And good thing! TCP/IP isn't the only way networks work!) What is needed for device drivers with RMI is a socket type that uses a very simple protocol and is localized to the computer that the OS is running on. These internal sockets must always be available, and must be usable to pass any kind of data stream from any task to any other task at any time without fear of failure. The internal sockets class cannot, then, be a device driver. Instead, it must be in a class that is loaded automatically (and is not unloadable) in every task that is created. This class must be loaded in the initial bootstrap of the OS, and then passed on when additional Java VMs are spawned. (Reloading from disk will not work: disk access requires RMI messaging which requires the internal sockets class already be functional.)

The internal sockets class must not rely on any device driver because it cannot access them. So all resources needed to pass along messages must be internal to the class. This means that it cannot request memory pages from the MemoryPageDevice (a core device driver, described below). Although the class cannot acquire memory pages, it must have them to write data into. So it must either own a pool of memory, there must be some memory that is shared with the Java VM it wants to communicate with, or it must go directly to the processor to get the memory it wants. It also need a mechanism to notify the destination task that there is data to be received.

Internal sockets class also needs the ability to communicate between processors on an SMP system.

No futher design has been done here. I am looking for comments and suggestions. This is probably the second most difficult part of the design (after bootstrapping).


Device driver access using RMI with TCP/IP sockets

Although for proper operation, internal sockets are needed for the OS to work properly, once a TCP/IP stack is in place, there is no reason that RMI can't be extended to use TCP/IP for some device driver communication.

One very nice use of this would be for network multi-processing. Tasks on one computer could be offloaded to other trusted computers on the user's network, effectively giving a user the ability to use every idle computer available to perform local processing tasks. Memory blocks, and even entire address spaces could be transferred to another computer (an address space is actually a very small object, all things considered, and could be transferred quickly) to allow the remote computer to execute one of the local tasks. Any device driver references (as well as permissions to access them) would follow the task to the new computer, allowing the task to continue to access filesystems and devices on the local computer (over TCP/IP), as though the task were still running locally. As code was executed remotely, page faults could be resolved over the network within a few milliseconds (or faster as faster networks are designed). This network page faulting between real memory is faster than swapping from hard drive; even good hard drives would take on average more 10 milliseconds just to seek to the correct track for the swap file! Three 1500 byte packets (one 4K memory page) can be send over 10Mbit Ethernet in under 4 milliseconds. Future optimizations could perform advanced page faulting to transfer the necessary pages before the memory is actually needed, so that no delay is noticed at all.

RMI used in this fashion to provide device driver access to remote computers could also be used as a means of file sharing. If both computers understand the filesystem stored on a given hard drive, either one of them (local or remote) could access the hard drive directly through RMI over TCP/IP without the need for protocols like NFS or FTP. Local hard drive access is identical in operation to remove access. (Designer's note: direct hard drive access may be dangerous. It would probably be better to contact the filesystem driver over the network and let the filesystem driver access the hard drive driver locally. But the basic concept still applies.)


Device

All device classes are subclasses of Device. The device class does not (at this time) define any methods or variables, mainly because most devices do not have any characteristics in common (other than the fact that they are hardware). It is simply there to provide a common parent for every device.

Not all devices need to be hardware. For example, PPP, which is just a serial port protocol, must act as though it were a network adapter. So it is best if the PPP software acted as though it were a piece of hardware. (This needs to be discussed: maybe these so-called "pseudo-devices" should be separated from real hardware, and the NetworkController class [or whatever it ends up being called] could be an interface instead of a class. For that matter, would the TCP/IP stack be considered a pseudo-device? If not, where is the distinction? Perhaps a new class, Protocol , as well as Device should be a subclass of something called Service, and there could be network adapter subclasses descending from both Protocol and Device. Clearly, some more thought needs to go into this.)


MemoryPageDevice & AddressSpaceDevice

These two driver classes share the same Java VM for efficiency; they interact with each other a lot.

The MemoryPageDevice is responsible for doling out pages of RAM (or virtual RAM) and for swapping this RAM out to disk when more is needed. It operates tightly bound with the AddressSpaceDevice which is responsible for mapping system memory pages into virtual address spaces (in which Java VMs reside, execute, and operate their data). Upon initialization*, the MemoryPageDevice class takes ownership of all system memory pages that aren't reserved for the system or devices. (Reserved memory on PCs would include the interrupt page [0-4K] and device space [640K-1M].) Programs allocate additional memory for their address spaces (when objects are instantiated) or for new address spaces (when a new Java VM is spawned) by using RMI with internal sockets to message the MemoryPageDevice driver to request a page. This page can then be sent to the AddressSpaceDevice that the current Java VM is running in, instructing where the page should be placed. (Perhaps this operation would occur in one step for efficiency?) Likewise, tasks can share memory pages with each other by sending each other MemoryPageDevice instances which they can then forward to their own AddressSpaceDevice to add to their address spaces. Pages can be set to shared or copy-on-write arbitrarily (permissions allowing; copy-on-write can be locked-in by the source to prevent the destination from breaking it).

Note that the implementation of these two classes is one of the few architecture dependent parts of the device driver system. They have to communicate with the processor to manage memory pages and address spaces. There will need to be a different implementation of these two classes for different processor types.

Designer's note: death of this task will cause system failure. Is there any way around this? (I.e., restarting the process automatically upon exit.)

* Bootstrapping the OS creates one address space that the Java VM, AddressSpaceDevice, and MemoryPageDevice drivers are loaded into. When the MemoryPageDevice class is initialized, it queries the state of the processor to determine all memory pages in the system, and compares them with the pages in use by the current address space. All pages not marked "hands off" by the bootstrapper and not used by the current address space are added to the available list. When the AddressSpaceDevice class initializes, it creates an instance of itself referring to the address space it is in.


AttachableDevice & AttachedDevice

These are poor names because they are ambiguous. I considered calling "attachable" devices either bus, controller, or parent devices, and "attached" devices "removable". Any ideas?

First a definition to reduce confusion: a device is attachable if it can have devices connected to it; a device is attaching if it gets plugged into an attachable device. AttachableDevice is an interface (not a class, for reasons that become apparent later) that defines a device that can have other devices attached to it. AttachedDevice is an interface (also not a class) that defines a device that is plugged into an AttachableDevice. Almost all devices are attached to an AttachableDevice, so some subclass not too far down from Device should be defined to implement the AttachedDevice interface.

What exactly is an AttachableDevice? The easiest example is a bus device: ISA, PCI, PCMCIA, whatever. These are devices that are designed for the sole purpose of having devices plugged into them. Other obvious AttachableDevices are hard drive controllers: IDE, SCSI, etc., because they also exist to support devices plugged into them. These devices are generally storage devices (disk drives, CDROMs, etc.), but this isn't always the case: you could put a PCMCIA controller onto a SCSI bus, resulting in unlimited types, because a PCMCIA controller is an AttachableDevice itself.

A less obvious example of an AttachableDevice is, for example, a disk drive. You might not ordinarily realize that you can plug a device into a disk drive, but a disk is exactly that: a device that plugs into a disk drive. Disks attach to disk drives in the same way that a disk drive attaches to a SCSI bus or a FLASH card plugs into a PCMCIA bus. Even more importantly, for removable disks, is that they attach in a hot-swappable fashion; removing a disk is the same as ejecting a FLASH card. Disks in hard drives are simply not hot-swappable because they cannot be removed; but they are still separate devices for interface consistency.

* The reason that AttachableDevice and AttachedDevice are interfaces and not classes should be apparent at this point. Many devices are defined as implementing one or both of these, without much regard for class structure. A system bus device is always an AttachableDevice, but so is a serial port driver, and a SCSI bus, and a disk drive. There is no class hierarchy-based rationale that defines whether a device can support sub-devices. Any device in any leg of the device driver system may want to implement this. The same goes for AttachedDevice. A great example of this is the PCMCIA bus. In some systems, it is a top-level bus; that is, it isn't attached to anything. In others, the PCMCIA controller may be chained off of the ISA, PCI, or even the SCSI bus. So some subclasses of PCMCIA will implement AttachedDevice, while others will not. It all depends on the hardware.


HotSwappedDevice

Instances of any HotSwappedDevice (disks included) may remain in the system after the actual disk or other device has been removed from its parent (ed. note: first use of this word!), if their objects are kept around and not garbage collected. When one of these "stale" devices is accessed, the driver object needs to message a request back to some listening object who would then be responsible, for example, for popping up a dialog box asking the user to re-insert the desired device (disk, etc). This request for re-insertion would also apply to other hot-swappable (non-disk) devices such as PCMCIA cards (for example, a modem card, if dialing is attempted).

Instances of hot-swappable objects might be created before they are ever inserted in the system in the first place. They may be created from a marshalled object stream (see Remove Method Invocation documentation for details on marshalling an objects). This could happen, for example, if they are stored on an install disk to refer to continuation disks for the install (disk 2, disk 3, etc.), or saved when a hot-swappable device is inserted for the first time and reloaded from disk upon a subsequent reboot.

By definition, any device that is hot-swappable is also an attached device. Therefore, there should be a HotSwappedDevice interface that inherits from AttachedDevice and defines the additional methods required to support hot-swapping capabilities (including the method callback requesting the user connect the device if the system wants to use it).


Combination Attachable/Attached

Note that many devices fall under both Attachable and Attached (or HotSwapped). (I think that all devices fall under one or the other.) These would be disk drive controllers (because they connect to a system bus such as PCI and disk drives attach to them), disk drives (because they attach to disk drive controllers and disks attach to them), as well as some system busses (such as PCMCIA because they can attach to both other system busses (like an ISA bus) and SCSI busses, and PCMCIA cards attach to them). But less obvious devices also fall under this category. Serial ports are one of them. A serial port (RS-232 being the most common) generally attaches to the ISA bus. Modems, fax modems, printers, etc. can attach to a serial port. The same goes for parallel ports (IEEE-1284).


SystemBusDevice

SystemBusDevices are devices that specify controls for system busses such as ISA, PCI, and PCMCIA. Each type of system bus is a subclass of SystemBusDevice. They implement the Attachable interface, because you can connect devices to them. Reading and writing is not allowed to busses except by devices that are attached to them.

Many busses support plug-and-play operation. It may be desirable to either define a plug-and-play interface, or to have busses such as PCI and PCMCIA be subclasses of a PlugAndPlayBusDevice class.

Designer's note: I am not yet familiar with bus/chipset operations. It may be necessary to break bus class definitions to something substantially different than what is provided here. I would like input from more knowledgeable people.


StorageControllerDevice

StorageControllerDevice is an abstract class that defines communication with devices designed to support mass storage devices. Floppy controllers, IDE, and SCSI are among these. This class contains support for this kind of device in terms of addressability, and access to the connected devices. Very few user-visible operations are supported. Most operation the user will interact with is defined in StorageDriveDevice and StorageDevice. In general, all that the user will access is the methods to retrieve StorageDriveDevice instances.

Support is provided for StorageDriveDevice instances to communicate to their respective hardware through the controller. Obviously, a driver for a SCSI disk knows nothing about the SCSI controller its disk drive is connected to. So the StorageControllerDevice is responsible for this communication.

Note that there is no software distinction between a SystemBusDevice and a StorageControllerDevice at the abstracted level. You can connect a PCMCIA device to a SCSI controller just as easily as you can to an ISA bus. The abstraction is provided for OS end-users to visibly differentiate what is normally a disk controller from what is normally a more generic system bus.


StorageDriveDevice

A StorageDriveDevice provides the abstraction for accessing a storage medium's physical hardware. It provides the consistent shell that a StorageDevice instance will use to retrieve data from the actual disk. To the user, it does nothing more that supply StorageDevice instances for whatever disk is currently in the drive and issue events for insertion and ejection (and, in some cases, offer an option to eject the disk electronically or to lock the eject button).

For the end-user's understanding of his system description, StorageDriveDevice is further abstracted in subclasses for disks (DiskDriveDevice), tape (TapeDriveDevice), etc. which are also further subclassed to specific device types (floppies, hard drives, CDROMs, DVDs, etc.; 2120 tape, 8mm tape, 4mm tape, etc.). This additional abstraction is also useful because some of these devices behave differently than others in trivial ways (tape isn't random access; CDROMs can't generally be written to). However, the StorageDevice and its subclasses normally would handle most of these distinctions.


StorageDevice

A StorageDevice is the actual parent class that handles the real storage medium. Any accesses a filesystem or backup program would make to a disk uses instances of some subclass of StorageDevice. There is a complete device-type hierarchy for disks, tapes, etc., as described in StorageDriveDevice.

This class provides the sector addressing mechanisms needed for each kind of device, ejection requests (which are just forwarded to the device's owner, a StorageDriveDevice instance), disk change handling, etc. (If the user changes a floppy disk while it's being accessed, the StorageDevice instance is guaranteed [to the capability of the hardware] to not read from the correct device; either a device-not-ready error of some kind occurs or a event requesting the user to re-insert the necessary device is generated.)


ExternalBus

Like StorageControllerDevice, this abstraction is provided purely for the user's convenience in identifying his device types. This class may be subclassed further, depending on abstraction need. For example, we may have a SerialBus subclass that further has USB and Firewire as its subclasses. The same operations as the SystemBusDevice and StorageDriveDevice are provided, giving the user access to the child devices connected to the bus.


NetworkDriver

NetworkDriver contains abstraction that exists with most network devices: support for hardware addressing, reading of a packet, writing of a packet, etc. NetworkDriver should be subclassed with additional abstract classes that define specific types of network adapters (for example, EthernetDriver). Subclasses of NetworkDriver should not be instantiated directly; they should always be abstract classes themselves, with their subclasses written as concrete classes for actual network controllers.


CursorDriver

CursorDriver is an abstract class that is subclassed with MouseDriver and TabletDriver. Those classes are subclassed with actual mouse hardware concrete classes (such as LogitechMouseDriver). The distinction between a MouseDriver and a TabletDriver is mostly the option of relative vs. absolute coordinates.

The CursorDriver is an event-based driver. As such, there is no read method. Programs interested in receiving mouse motion information will need to register a listener. Whether this listener uses the MouseEvent and listener mechanism of the AWT is yet to be determined. Even if this mechanism is used, the actual MouseEvent will need to be enhanced to support the idea of relative motion.


Designer's note: Event-based driver operation may be something that we want throughout the device driver system. Why explicitly have to request reading when input from many devices is already unsolicited. Obviously, operations such as disk reading would not apply. However, input events from the keyboard and mouse have aren't the only useful candidates for events. Network adapters received data packets spontaneously; should that be event based? Disk insertion, audio/video streaming, serial port data input, and parallel port out-of-paper notification all qualify. Any AttachableDevice could also benefit from an event based input system: the kinds of unsolicited input received from devices attached to them are unlimited. It would need to use this mechanism to indicate when HotSwappedDevices are connected and disconnected; in fact, it would be unreasonable for any piece of software to try to poll for this activity!


Content of these pages are owned and copyrighted by the poster.
Hosted by: