Some peripheral adapters manage more than one physical device using the same set of control registers. The floppy disk controller is one example of this architecture. This kind of hardware poses a synchronization dilemma. If the driver tries to perform simultaneous operations on more than one of the connected devices without first synchronizing its access to the shared register space, the control registers receive confusing values. To help with this problem, the I/O Manager provides controller objects. The controller object is a kind of mutex that can be owned by only one device at a time. Before accessing any device registers, the driver asks that ownership of the controller object be given to a specific device. If the hardware is free, ownership is granted. If not, the device's request is put on hold until the current owner releases the hardware. By managing the controller object, the I/O Manager guarantees that multiple devices will access the hardware in a serial fashion. The life cycle of a typical controller object is described below.
Obviously, not all drivers need a controller object. If an interface card supports only one physical or virtual device, or if multiple devices on the same card don't share any control registers, then there is no need to create a controller object. Layout of the Controller ObjectFigure 4.4 shows the relationship of a Controller object to other system data structures. The only externally visible field in a Controller object is the PVOID ControllerExtension field, which contains a pointer to the extension block. Figure 4.4. The controller object.Manipulating Controller ObjectsThe I/O Manager exports four functions that operate on controller objects. These functions are listed in Table 4.8. Controller ExtensionsLike device objects, controller objects contain a pointer to an extension structure that can be used to hold any controller-specific data. The extension is also a place to store any information that's global to all the devices attached to a controller. Finally, if the controller (rather than individual devices) is the source of interrupts, it makes sense to store pointers to Interrupt and Adapter objects in the Controller Extension.
Since the controller extension is driver-specific, its structure must be defined in a driver header file. Although the extension's exact contents depend on what a driver does, its general layout looks something like this: typedef struct _CONTROLLER_EXTENSION { // back pointer PCONTROLLER_OBJECT ControllerObject : // other driver-specific declarations : } CONTROLLER_EXTENSION, *PCONTROLLER_EXTENSION;
|