DDI: 8 sample driver

_load entry point routine

The _load(D2) entry point routine is called when the driver is first loaded into the kernel, which could be the first time it is called or, if it is statically configured (marked by $static in the Master file), in the final stages of system configuration. For DDI 8 drivers, the _load( ) entry point must not be prefixed, and must initialize the driver and resources that are required by the driver as a whole, but not resources that are allocated for specific devices.

Allocate global resources

For the samp driver, the _load( ) entry point routine populates and initializes a bcb(D4) (breakup control) structure that will be used for actual I/O operations by the biostart(D2) entry point routine. Notice that the structure is named samp_bcb, using the driver prefix to avoid collision with a bcb structure for another driver in the kernel. The code calls the bcb_alloc(D3) function to allocate the bcb (the KM_SLEEP flag indicates that it will block if necessary to wait for resources required for the allocation). It then populates the bcb_addrtypes member with BA_UIO to indicate that the I/O operations will use the uio(D4) structure. The bcb_granularity member is set to 1, to indicate the minimum acceptable offset or size of a transfer. The bcb_physreqp member points to a physreq(D4) structure that defines the physical requirements for the memory being allocated. This is allocated with the physreq_alloc(D3) function, and set up to block if necessary to wait for resources to be available.

Once the bcb is allocated and populated, the driver calls the bcb_prep(D3) to prepare the bcb and the associated physreq structure for use. Note that the physreq is not explicitly populated; physreq_alloc( ) allocates a physreq structure with default values set for the required members. The ddi8_sample driver has minimal hardware requirements so the default values are adequate. Most true hardware drivers will need to explicitly populate members of the physreq structure.

The code tests that this can happen and, if it does not, calls the samp_free_globals( ) subordinate routine to free up any resources that might have been allocated and exits gracefully by returning the ENOSYS error code discussed on the errnos(D5) manual page. This illustrates a primary principle of driver writing: always check for error conditions and handle them, even if it is unimaginable that the error could actually occur.

Register the driver

No other resources are required for the driver itself, so it calls the drv_attach(D3) function to register the driver in the kernel, based on information populated in the driver's drvinfo(D4) structure in the "Header files and declarations" part of the driver. Again, notice that the driver is coded to handle the condition where the driver cannot be registered so it fails gracefully and frees up any resources that may have been allocated.

This also illustrates one of the uses of a subordinate driver routine. If the bcb structure cannot be prepped or if the drv_attach( ) function fails, the same clean up is required. So coding that clean up functionality in a subordinate routine that is called in both places makes for cleaner code that is easier to maintain.

© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 6 and UnixWare (SVR5) HDK - June 2005