The attach() Entry Point
The kernel calls a driver's attach(9E) entry point to attach an instance of a device or to resume operation for an instance of a device that has been suspended or shut down by the power management framework. This section discusses only the operation of attaching device instances; the power management discussion is left to Chapter 9, Power Management.
A driver's attach(9E) entry point is called to attach each instance of a device that is bound to the driver. The entry point is called with the instance of the device node to attach, with DDI_ATTACH specified as the cmd argument to attach(9E). The attach entry point will typically include the following types of processing:
Allocating a soft state structure for the device instance
Registering the device's interrupts
Creating minor device nodes for the device instance
Reporting that the device instance has attached
Driver Soft State Management
To assist device driver writers in allocating state structures, the Solaris 9 DDI/DKI provides a set of memory management routines called software state management routines (also known as the soft state routines). These routines dynamically allocate, retrieve, and destroy memory items of a specified size, and hide the details of list management. An instance number identifies the desired memory item. This number can be (and usually is) the instance number assigned by the system.
Drivers will typically allocate a soft state structure for each device instance that attaches to the driver by calling ddi_soft_state_zalloc(9F), passing the instance number of the device. Because there cannot be two device nodes with the same instance number, ddi_soft_state_zalloc(9F) will fail if an allocation already exists for a given instance number.
A driver's character or block entry point (cb_ops(9S)) will reference a particular soft state structure by first decoding the device's instance number from the dev_t argument that is passed to the entry point function. The driver then calls ddi_get_soft_state(9F), passing the per-driver soft state list and the instance number that was derived. If ddi_get_soft_state(9F) returns a NULL value, the driver should treat this as if the device does not exist and return the appropriate code.
See "Creating Minor Device Nodes" for additional information on how instance numbers and device numbers, or dev_t's, are related.
Lock and Conditional Variable Initialization
Drivers should initialize any per-instance locks and condition variables during attach. The initialization of any locks which are acquired by the driver's interrupt handler must be initialized prior to adding any interrupt handlers. See Chapter 3, Multithreading for a description of lock initialization and usage. See Chapter 7, Interrupt Handlers for a discussion of the issues surrounding interrupt handler and locks.
Creating Minor Device Nodes
An important part of the attach process is the creation of minor nodes for the device instance. A minor node contains the information exported by the device and the DDI framework which the system uses to create a special file for the minor node under /devices.
Minor nodes are created when the driver calls ddi_create_minor_node(9F). The driver supplies a minor number, a minor name, a minor node type, and whether the minor node represents a block or character device.
Drivers can choose to create any number of minor nodes for a device. The Solaris DDI/DDK expects certain classes of devices to have minor nodes created in a particular format. For example, disk drivers are expected to create 16 minor nodes for each physical disk instance attached; 8 minor nodes are created, representing the a - h block device interfaces, with an additional 8 minor nodes for the a,raw - h,raw character device interfaces.
The minor number passed to ddi_create_minor_node(9F) is defined wholly by the driver itself. The minor number is usually an encoding of the device's instance number with a minor node identifier. Taking the above example, the driver creates minor numbers for each of the minor nodes by taking the devices instance number, shifting it left 3 bits, and OR'ing in the minor node index whose values range from 0 to 7. Note that minor nodes a and a,raw share the same minor number. They are distinguished by the spec_type argument passed to ddi_create_minor_node().
The minor node type passed to ddi_create_minor_node(9F) classifies the type of device, such as disks, tapes, network interfaces, frame buffers, and so forth. Table 5-1 lists the types of possible nodes that may be created.
Table 5-1 Possible Node Types
Constant | Description |
---|---|
DDI_NT_SERIAL | Serial port |
DDI_NT_SERIAL_DO | Dialout ports |
DDI_NT_BLOCK | Hard disks |
DDI_NT_BLOCK_CHAN | Hard disks with channel or target numbers |
DDI_NT_CD | ROM drives (CD-ROM) |
DDI_NT_CD_CHAN | ROM drives with channel or target numbers |
DDI_NT_FD | Floppy disks |
DDI_NT_TAPE | Tape drives |
DDI_NT_NET | Network devices |
DDI_NT_DISPLAY | Display devices |
DDI_NT_MOUSE | Mouse |
DDI_NT_KEYBOARD | Keyboard |
DDI_NT_AUDIO | Audio Device |
DDI_PSEUDO | General pseudo devices |
The node types DDI_NT_BLOCK, DDI_NT_BLOCK_CHAN, DDI_NT_CD, and DDI_NT_CD_CHAN cause devfsadm(1M) to identify the device instance as a disk and to create names in the /dev/dsk or /dev/rdsk directory.
The node type DDI_NT_TAPE causes devfsadm(1M) to identify the device instance as a tape and to create names in the /dev/rmt directory.
The node types DDI_NT_SERIAL and DDI_NT_SERIAL_DO causesdevfsadm(1M) to identify the device instance as a serial port and to create names in the /dev/term and /dev/cua directories and to add entries in /etc/inittab.
Vendor-supplied strings should include an identifying value to make them unique, such as their name or stock symbol (if appropriate). The string can be used in conjunction with devfsadm(1M) and devlink.tab(4) to create logical names in /dev.
Deferred Attach
open(9E) might be called on a minor device before attach(9E) has succeeded on the corresponding instance. open() must then return ENXIO, which will cause the system to attempt to attach the device. If the attach succeeds, the open is retried automatically.
Example 5-5 Example attach(9E) Entry Point
Note - The attach(9E) routine must not make any assumptions about the order of invocations on different device instances. The system may invoke attach(9E) concurrently on different device instances. The system may also invoke attach(9E) and detach(9E) concurrently on different device instances.