This chapter describes the data structures and routines that the Configuration driver uses to interface with the CAM subsystem. It also describes the /usr/sys/include/io/cam/cam_config.c file, which contains SCSI/CAM peripheral device driver configuration information. SCSI/CAM peripheral device driver writers add to this file external declarations and entries to the SCSI/CAM peripheral driver configuration table for their peripheral device drivers.
The Configuration driver dynamically initializes the XPT and SIM layers of the CAM subsystem at run time. This enables support for a generic kernel that is configured for all processors and all CAM subsystem software, for example, all HBA drivers. After initialization is complete, the Configuration driver scans the SCSI bus and stores INQUIRY information about each SCSI device detected.
Once the CAM subsystem is initialized and the scanning information stored, the SCSI/CAM peripheral device drivers can use the subsystem. They can determine what devices have been detected and allocate memory appropriately. They can also use the XPT_GDEV_TYPE and XPT_SDEV_TYPE get and set device information CCBs to request resources from the XPT layer.
The Configuration driver module logically exists in the SCSI/CAM peripheral device driver layer above the XPT.
The Configuration driver is responsible for supporting the following XPT commands:
The Configuration driver also supports the configuration and bus scanning for loaded SIM modules.
This section describes the following Configuration driver data structures:
The Configuration driver control structure, CCFG_CTRL, contains flags that the Configuration driver uses for the scanning process. It also sets aside an area to contain the data returned from the INQUIRY CCBs during the initial scanning process. The structure is defined as follows:
typedef struct ccfg_ctrl { u_long ccfg_flags; /* controlling flags */ ALL_INQ_DATA inq_buf; /* scratch area for the INQUIRY data */ struct lock_t c_lk_ctrl; /* for locking on the control struct */ } CCFG_CTRL;
The ccfg_flags member contains the flags used by the Configuration driver to control operations. The possible settings are as follows:
The inq_buf member sets aside a working or temporary area to hold the returned data described in the standard INQUIRY structure ALL_INQ_DATA, which is defined in the file /usr/sys/include/io/cam/scsi_all.h.
The Configuration driver works with the XPT to allocate, initialize, and maintain the CAM equipment device table structure (EDT). An EDT structure is allocated for each SCSI bus. The structure is an 8x8-element array that contains device inquiry information, asynchronous callback flags, and a signal flag if a device was found, based on the number of targets and the number of LUNs on the SCSI bus. The structure is defined as follows:
typedef struct edt { CAM_EDT_ENTRY edt[ NDPS ][ NLPT ]; /* A layer for targets/LUNs */ u_long edt_flags; /* Flags for EDT access */ u_long edt_scan_count; /* # of XPT ASYNC CB readers */ struct lock_t c_lk_edt /* For locking per bus */ } EDT;
The edt member is a structure of the type CAM_EDT_ENTRY, which is defined in the /usr/sys/include/io/cam/cam.h file. Each CAM_EDT_ENTRY structure is an entry in the CAM equipment device table that contains the SCSI ID and LUN for each device on the SCSI bus. The array dimensions are the number of devices per SCSI bus (NDPS) and the number of LUNs per target (NLPT). The structure and constants are defined in the /usr/sys/include/io/cam/dec_cam.h file.
The edt_scan_count member contains the number of processes reading the EDT structure.
The edt_flags member sets the flags for controlling access to the CAM equipment device table.
CAM_PERIPHERAL_DRIVER, the SCSI/CAM peripheral driver configuration structure, contains the name of the device and defines the routines that are accessed as part of the system configuration process. The structure is defined as follows:
typedef struct cam_peripheral_driver { char *cpd_name; int (*cpd_slave)(); int (*cpd_attach)(); int (*cpd_unload)(); } CAM_PERIPHERAL_DRIVER;
The cpd_name member is a pointer to the device name contained in the dev_name member of the kernel data structure, device. See Writing Device Drivers: Tutorial and Writing Device Drivers: Reference for more information.
The cpd_slave member is a function pointer to the SCSI/CAM peripheral device driver slave routine, which finds the device attached to the SCSI bus controller.
The cpd_attach member is a function pointer to the SCSI/CAM peripheral device driver attach routine, which attaches the device to the controller and initializes the driver fields for the device.
The cpd_unload member is not implemented.
The Configuration driver file, /usr/sys/io/cam/cam_config.c, contains SCSI/CAM peripheral device driver configuration information. As superuser, SCSI/CAM peripheral device driver writers edit the file to add extern declarations for their hardware devices and to add entries for the device driver to the SCSI/CAM peripheral driver configuration table.
The section of the file where the extern declarations are added looks like the following:
extern int crzslave(), crzattach(); /* Disk Driver */ extern int ctzslave(), ctzattach(); /* Tape Driver */ extern int cczslave(), cczattach(); /* CD-ROM Driver *//* VENDOR: Add the extern declarations for your hardware following this comment line. */
A sample declaration for third-party SCSI/CAM peripheral device driver might be as follows:
extern int toastslave(), toastattach(); /* Non-tape or -disk Driver */
The section of the file where the SCSI/CAM peripheral driver configuration table entries are added looks like the following:
/* * CAM Peripheral Driver Configuration Table. */ struct cam_peripheral_driver cam_peripheral_drivers[] = { { "crz", crzslave, crzattach }, { "ctz", ctzslave, ctzattach }, { "ccz", cczslave, cczattach }/* VENDOR: Add your hardware entries following this comment line. */ };
When you add your entry, be sure to place a comma (,) after the last member in the structure supplied by Digital. A sample entry for third-party hardware might be as follows:
{ "ccz", cczslave, cczattach },/* VENDOR: Add your hardware entries following this comment line. */ { "wheat", toastslave, toastattach} /* Non-tape or -disk Driver */ };
The following Configuration driver routines are entry point routines that are accessible to the XPT and SIM modules as part of the Configuration driver interface. Table 6-1 lists the name of each routine and gives a short description of its function. The sections that follow contain a more detailed description of each routine. Appendix C lists the routines alphabetically and includes descriptions and syntax information in Digital UNIX reference-page format.
Routine | Summary Description |
ccfg_slave | Calls a SCSI/CAM peripheral driver's slave routine after a match on the cpd_name member of the CAM_PERIPHERAL_DRIVER structure is found. |
ccfg_attach | Calls a SCSI/CAM peripheral driver's attach routine after a match on the cpd_name member of the CAM_PERIPHERAL_DRIVER structure is found. |
ccfg_action | Calls the internal routines that handle any CCB that accesses the CAM equipment device table structure. |
ccfg_edtscan | Issues SCSI INQUIRY commands to all possible SCSI targets and LUNs attached to a bus or a particular bus/target/lun. |
The ccfg_slave routine calls a SCSI/CAM peripheral driver's slave routine after a match on the cpd_name member of the CAM_PERIPHERAL_DRIVER structure is found. The routine is called during autoconfiguration. The ccfg_slave routine locates the configured driver in the SCSI/CAM peripheral driver configuration table. If the driver is located successfully, the SCSI/CAM peripheral driver's slave routine is called with a pointer to the unit information structure for the device from the kernel device structure and the virtual address of its control and status register (CSR). The SCSI/CAM peripheral driver's slave routine performs its own slave initialization.
The ccfg_attach routine calls a SCSI/CAM peripheral driver's attach routine after a match on the cpd_name member of the CAM_PERIPHERAL_DRIVER structure is found. The routine is called during autoconfiguration. The ccfg_attach routine locates the configured driver in the SCSI/CAM peripheral driver configuration table. If the driver is located successfully, the SCSI/CAM peripheral driver's attach routine is called with a pointer to the unit information structure for the device from the kernel device structure. The SCSI/CAM peripheral driver's attach routine performs its own attach initialization.
The ccfg_action routine calls the internal routines that handle any CCB that accesses the CAM equipment device table structure. The CAM function codes supported are XPT_GDEV_TYPE, XPT_SASYNC_CB, and XPT_SDEV_TYPE.
The ccfg_edtscan routine issues SCSI INQUIRY commands to all possible SCSI targets and LUNs attached to a bus or a particular bus/target/lun. The routine uses the CAM subsystem in the normal manner by sending SCSI I/O CCBs to the SIMs. The INQUIRY data returned is stored in the EDT structures and the cam_tlun_found flag is set. SCSI/CAM peripheral device drivers can call this routine to reissue a full, partial, or single bus scan command.