Chapter 11Configuring STREAMS Drivers and Modules
This chapter contains information about configuring STREAMS
drivers and modules into the Solaris operating environment. It describes how
to configure a driver and a module for the STREAMS framework only. For more
in-depth information on the general configuration mechanism, see Writing Device Drivers.
This chapter has the following organization:
Kernel Data Structures
The following sections contain descriptions of the pointer relationships
maintained by the kernel and the various data structures used in STREAMS drivers.
When the kernel accesses a driver, it uses a sequence of pointers in various
data structures. It looks first at the data structure relationship, and then
the entry point interface for loading the driver into the kernel and accessing
the driver from the application level.
The order of data structures the kernel uses to get to a driver is as
follows:
| modlinkage(9S) | Contains the revision number and a list of drivers
to dynamically load. It is used by mod_install in the _init routine to load the module into the kernel. Points to a modldrv(9S)
or modlstrmod(9S).
| | modldrv(9S) | Contains information about the driver being loaded and points to the devops structure.
| | modlstrmod(9S) | Points to an fmodsw(9S) structure (which points to a streamtab(9S)).
Only used by STREAMS modules.
| | dev_ops(9S) | Contains list of entry points for a driver, such as identify, attach, and info. Also points to a cb_ops(9S) structure.
| | cb_ops(9S) | Points to list of threadable
entry points to driver, like open, close, read, write, ioctl. Also points
to the streamtab.
| | streamtab(9S) | Points to the read and write queue init
structures.
| | qinit(9S) | Points to the entry points
of the STREAMS portion of the driver, such as put, srv, open, close, as well
as the mod_info structure. These entry points only process
messages.
|
Each STREAMS driver or module contains the linkage connections
for the various data structures which is a list of pointers to dev_ops(9S) structures.
In each dev_ops(9S)
structure is a pointer to the cb_ops(9S) structure. In the cb_ops(9S) structure contains a pointer
to the streamtab struct. If the driver
is not a STREAMS driver, streamtab is NULL. If the driver
is a STREAMS driver, streamtab contains initialization
routines for the driver.
modlinkage
The definition of modlinkage(9S) is:
struct modlinkage {
int ml_rev; /* rev of loadable modules system */
void *ml_linkage[4]; /* NULL terminated list of linkage
* structures */
};
|
modldrv
The definition
of modldrv(9S)
is:
struct modldrv {
struct mod_ops *drv_modops;
char *drv_linkinfo;
struct dev_ops *drv_dev_ops;
};
|
modlstrmod
The definition of modlstrmod(9S) is below. It does not point to dev_ops(9S)
structures because modules can only be pushed onto an existing stream.
struct modlstrmod {
struct mod_ops *strmod_modops;
char *strmod_linkinfo;
struct fmodsw *strmod_fmodsw;
};
|
dev_ops
The dev_ops(9S) structure represents
a specific class or type of device. Each dev_ops(9S) structure represents a unique device
to the operating system. Each device has its own dev_ops(9S) structure,
which in turn contains a cb_ops(9S) structure.
struct dev_ops {
int devo_rev; /* Driver build version */
int devo_refcnt; /* device reference count */
int (*devo_getinfo)(dev_info_t *dip, ddi_info_cmd_t infocmd,
void *arg, void **result);
int (*devo_identify)(dev_info_t *dip);
int (*devo_probe)(dev_info_t *dip);
int (*devo_attach)(dev_info_t *dip, ddi_attach_cmd_t cmd);
int (*devo_detach)(dev_info_t *dip, ddi_detach_cmd_t cmd);
int (*devo_reset)(dev_info_t *dip, ddi_reset_cmd_t cmd);
struct cb_ops *devo_cb_ops; /* cb_ops ptr for leaf driver*/
struct bus_ops *devo_bus_ops; /* ptr for nexus drivers */
};
|
cb_ops
The cb_ops(9S) structure is the SunOS 5 version
of the cdevsw and bdevsw tables of previous
versions of UNIX System V. It contains character and block device information
and the driver entry points for non-STREAMS drivers.
struct cb_ops {
int *cb_open)(dev_t *devp, int flag, int otyp,
cred_t *credp);
int (*cb_close)(dev_t dev, int flag, int otyp,
cred_t *credp);
int (*cb_strategy)(struct buf *bp);
int (*cb_print)(dev_t dev, char *str);
int (*cb_dump)(dev_t dev, caddr_t addr,daddr_t blkno,
int nblk);
int (*cb_read)(dev_t dev, struct uio *uiop, cred_t *credp);
int (*cb_write)(dev_t dev, struct uio *uiop, cred_t *credp);
int (*cb_ioctl)(dev_t dev, int cmd, int arg, int mode,
cred_t *credp, int *rvalp);
int (*cb_devmap)(dev_t dev, dev_info_t *dip,
ddi_devmap_data_t *dvdp, ddi_devmap_cmd_t cmd,
off_t offset, unsigned int len, unsigned int prot,
cred_t *credp);
int (*cb_mmap)(dev_t dev, off_t off, int prot);
int (*cb_segmap)(dev_t dev, off_t off, struct as *asp,
caddr_t *addrp, off_t len, unsigned int prot,
unsigned int maxprot, unsigned int flags,
cred_t *credp);
int (*cb_chpoll)(dev_t dev, short events, int anyyet,
short *reventsp, struct pollhead **phpp);
int (*cb_prop_op)(dev_t dev, dev_info_t *dip,
ddi_prop_op_t prop_op, int mod_flags, char *name,
caddr_t valuep, int *length);
struct streamtab *cb_str; /* streams information */
/*
* The cb_flag fields are here to tell the system a bit about
* the device. The bit definitions are in <sys/conf.h>.
*/
int cb_flag; /* driver compatibility flag */
};
|
|