The Design and Implementation of the FreeBSD SCSI Subsystem
PrevThe Design and Implementation of the FreeBSD SCSI Subsystem 

The Peripheral Driver

Situated above the Transport Layer and serving as the interface between CAM and standard Operating System services are the peripheral drivers. The tasks of a peripheral driver fall into two general area: attaching to the XPT, and sending and receiving CCBs in response to Operating System requests. Although the types of peripheral drivers and the commands they use are as varied as SCSI devices, the methods and often state machines used to implement these drivers are common. This section outlines the proceedure for registering a peripheral driver with the system, the generic CCB types a peripher driver may encounter and examples of how to use them, and concludes by describing peripheral driver actions that are particular to drivers serving in either an initiator or target role.

Attaching to the Transport Layer

Once the XPT has completed initialization after system startup, it iterrates through all known peripheral drivers and calls the driver's initialization function. The current mecahnism for registering a driver with the XPT is through a linker set. Linker sets are a special construct placed in the peripheral driver's source code that instructs the linker to combine similar data found in other object files into a single array in the final binary. Although this mechanism is easy to use and works, it poses some problems for using Loadable Kernel Modules. For this reason, the registration mechanism may change at a later date.

Figure 6. Adding a Peripheral Driver to Peripheral Driver Linker Set

static  periph_init_t   dainit;
    
static struct periph_driver dadriver =
{      
	dainit,                                /* Our initialization routine */
	"da",                                  /* Our exported base name     */
        TAILQ_HEAD_INITIALIZER(dadriver.units) /* Instance/Unit list 	     */
};

DATA_SET(periphdriver_set, dadriver); /* Add us to the peripheral linker set */

/* Master driver initialization routine */
static void
dainit(void)
{
       ...
}
	

PrevHome 
The Transport Layer