The detach() Entry Point
The kernel calls a driver's detach(9E) entry point to detach an instance of a device or to suspend operation for an instance of a device by power management. This section discusses the operation of detaching device instances. Refer to Chapter 9, Power Management for a discussion of power management issues.
A driver's detach() entry point is called to detach an instance of a device that is bound to the driver. The entry point is called with the instance of the device node to detach and DDI_DETACH specified as the cmd argument to the entry point.
A driver is required to cancel or wait for any time-outs or callbacks to complete, then release any resources that are allocated to the device instance before returning. If for some reason a driver cannot cancel outstanding callbacks for free resources, the driver is required to return the device to its original state and return DDI_FAILURE from the entry point, leaving the device instance in the attached state.
There are two types of callback routines: those that can be canceled and those that cannot. timeout(9F) and bufcall(9F) callbacks can be atomically cancelled by the driver during detach(9E). Other types of callbacks such as scsi_init_pkt(9F) and ddi_dma_buf_bind_handle(9F) cannot be canceled, requiring the driver to either block in detach() until the callback completes or to fail the request to detach.
Example 5-6 detach(9E) Routine
The getinfo() Entry Point
The system calls getinfo(9E) to obtain configuration information that only the driver knows. The mapping of minor numbers to device instances is entirely under the control of the driver. The system sometimes needs to ask the driver which device a particular dev_t represents.
getinfo() can take one of two commands as its infocmd argument: DDI_INFO_DEVT2INSTANCE, which asks for a device's instance number, and DDI_INFO_DEVT2DEVINFO, which asks for pointer to the device's dev_info structure.
In the DDI_INFO_DEVT2INSTANCE case, arg is a dev_t, and getinfo() must translate the minor number in dev_t to an instance number. In the following example, the minor number is the instance number, so getinfo() simply passes back the minor number. In this case, the driver must not assume that a state structure is available, since getinfo() may be called before attach(9E). The mapping that the driver defines between the minor device number and the instance number does not necessarily follow the mapping shown in the example. In all cases, however, the mapping must be static.
In the DDI_INFO_DEVT2DEVINFO case, arg is again a dev_t, so getinfo() first decodes the instance number for the device. It then passes back the dev_info pointer saved in the driver's soft state structure for the appropriate device. This is shown in Example 5-7.
Example 5-7 getinfo(9E) Routine
Note - The getinfo() routine must be kept in sync with minor nodes that the driver creates. Failure to do so may cause failure of hotplug operations and result in system panics.
Using Device IDs
The Solaris DDI interfaces allow drivers to provide a persistent unique identifier for a device, a device ID, which can be used to identify or locate a device and which is independent of the /devices name or device number (dev_t). Applications can use the functions defined in libdevid(3LIB) to read and manipulate the device IDs registered by the drivers.
Before a driver can export a device ID, it needs to verify that the device is capable of either providing a unique ID, such as a WWN (world-wide number), or is capable of storing a host-generated unique ID in an area not accessible through normal operations, such as device NVRAM, reserved sectors, etc.