|
|||
Part I Designing Device Drivers for the Solaris Platform 1. Overview of Solaris Device Drivers 2. Solaris Kernel and Device Tree 5. Managing Events and Queueing Tasks 7. Device Access: Programmed I/O 10. Mapping Device and Kernel Memory 14. Layered Driver Interface (LDI) Part II Designing Specific Kinds of Device Drivers 15. Drivers for Character Devices 18. SCSI Host Bus Adapter Drivers 19. Drivers for Network Devices Part III Building a Device Driver 21. Compiling, Loading, Packaging, and Testing Drivers 22. Debugging, Testing, and Tuning Device Drivers 23. Recommended Coding Practices B. Summary of Solaris DDI/DKI Services C. Making a Device Driver 64-Bit Ready |
Data Structures Required for DriversTo support autoconfiguration, drivers are required to statically initialize the following data structures: The data structures in Figure 5-1 are relied on by the driver. These structures must be provided and be initialized correctly. Without these data structures, the driver might not load properly. As a result, the necessary routines might not be loaded. If an operation is not supported by the driver, the address of the nodev(9F) routine can be used as a placeholder. In some instances, the driver supports the entry point and only needs to return success or failure. In such cases, the address of the routine nulldev(9F) can be used. Note - These structures should be initialized at compile-time. The driver should not access or change the structures at any other time. modlinkage Structurestatic struct modlinkage xxmodlinkage = { MODREV_1, /* ml_rev */ &xxmodldrv, /* ml_linkage[] */ NULL /* NULL termination */ }; The first field is the version number of the module that loads the subsystem. This field should be MODREV_1. The second field points to driver's modldrv structure defined next. The last element of the structure should always be NULL. modldrv Structurestatic struct modldrv xxmodldrv = { &mod_driverops, /* drv_modops */ "generic driver v1.1", /* drv_linkinfo */ &xx_dev_ops /* drv_dev_ops */ }; This structure describes the module in more detail. The first field provides information regarding installation of the module. This field should be set to &mod_driverops for driver modules. The second field is a string to be displayed by modinfo(1M). The second field should contain sufficient information for identifying the version of source code that generated the driver binary. The last field points to the driver's dev_ops structure defined in the following section. dev_ops Structurestatic struct dev_ops xx_dev_ops = { DEVO_REV, /* devo_rev, */ 0, /* devo_refcnt */ xxgetinfo, /* getinfo(9E) */ nulldev, /* identify(9E) */ xxprobe, /* probe(9E) */ xxattach, /* attach(9E) */ xxdetach, /* detach(9E) */ nodev, /* devo_reset */ &xx_cb_ops, /* devo_cb_ops */ NULL, /* devo_bus_ops */ &xxpower /* power(9E) */ }; The dev_ops(9S) structure enables the kernel to find the autoconfiguration entry points of the device driver. The devo_rev field identifies the revision number of the structure. This field must be set to DEVO_REV. The devo_refcnt field must be initialized to zero. The function address fields should be filled in with the address of the appropriate driver entry point, except in the following cases:
The devo_cb_ops member should include the address of the cb_ops(9S) structure. The devo_bus_ops field must be set to NULL. cb_ops Structurestatic struct cb_ops xx_cb_ops = { xxopen, /* open(9E) */ xxclose, /* close(9E) */ xxstrategy, /* strategy(9E) */ xxprint, /* print(9E) */ xxdump, /* dump(9E) */ xxread, /* read(9E) */ xxwrite, /* write(9E) */ xxioctl, /* ioctl(9E) */ xxdevmap, /* devmap(9E) */ nodev, /* mmap(9E) */ xxsegmap, /* segmap(9E) */ xxchpoll, /* chpoll(9E) */ xxprop_op, /* prop_op(9E) */ NULL, /* streamtab(9S) */ D_MP | D_64BIT, /* cb_flag */ CB_REV, /* cb_rev */ xxaread, /* aread(9E) */ xxawrite /* awrite(9E) */ }; The cb_ops(9S) structure contains the entry points for the character operations and block operations of the device driver. Any entry points that the driver does not support should be initialized to nodev(9F). For example, character device drivers should set all the block-only fields, such as cb_stategy, to nodev(9F). Note that the mmap(9E) entry point is maintained for compatibility with previous releases. Drivers should use the devmap(9E) entry point for device memory mapping. If devmap(9E) is supported, set mmap(9E) to nodev(9F). The streamtab field indicates whether the driver is STREAMS-based. Only the network device drivers that are discussed in Chapter 19, Drivers for Network Devices are STREAMS-based. All non-STREAMS-based drivers must set the streamtab field to NULL. The cb_flag member contains the following flags:
cb_rev is the cb_ops structure revision number. This field must be set to CB_REV. |
||
|