Device Driver Tutorial

Defining the Device Attach Entry Point

The attach(9E) routine returns type int. The attach(9E) routine must return either DDI_SUCCESS or DDI_FAILURE. These two constants are defined in sunddi.h. All of the autoconfiguration entry point routines except for prop_op(9E) return either DDI_SUCCESS or DDI_FAILURE.

The attach(9E) routine takes two arguments. The first argument is a pointer to the dev_info structure for this driver. All of the autoconfiguration entry point routines take a dev_info argument. The second argument is a constant that specifies the attach type. The value that is passed through this second argument is either DDI_ATTACH or DDI_RESUME. Every attach(9E) routine must define behavior for at least DDI_ATTACH.

The DDI_ATTACH code must initialize a device instance. In a realistic driver, you define and manage multiple instances of the driver by using a state structure and the ddi_soft_state(9F) functions. Each instance of the driver has its own copy of the state structure that holds data specific to that instance. One of the pieces of data that is specific to each instance is the device instance pointer. Each instance of the device driver is represented by a separate device file in /devices. Each device instance file is pointed to by a separate device instance pointer. See Managing Device State for information about state structures and ddi_soft_state(9F) functions. See Devices as Files for information about device files and instances.

This dummy driver allows only one instance. Because this driver allows only one instance, this driver does not use a state structure. This driver still must declare a device instance pointer and initialize the pointer value in the attach(9E) routine. Enter the following code near the beginning of dummy.c to declare a device instance pointer for this driver:

dev_info_t *dummy_dip;  /* keep track of one instance */

The following code is the dummy_attach() routine that you should enter into your dummy.c file. You can copy the name portion of this function definition directly from the declaration you entered in Declaring the Autoconfiguration Entry Points.

static int
dummy_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
    cmn_err(CE_NOTE, "Inside dummy_attach");
    switch(cmd) {
    case DDI_ATTACH:
        dummy_dip = dip;
        if (ddi_create_minor_node(dip, "0", S_IFCHR,
            ddi_get_instance(dip), DDI_PSEUDO,0)
            != DDI_SUCCESS) {
            cmn_err(CE_NOTE,
                "%s%d: attach: could not add character node.",
                "dummy", 0);
            return(DDI_FAILURE);
        } else
            return DDI_SUCCESS;
    default:
        return DDI_FAILURE;
    }
}

First, use cmn_err(9F) to write a message to the system log, as you did in your _init(9E) entry point. Then provide DDI_ATTACH behavior. Within the DDI_ATTACH code, first assign the device instance pointer from the dummy_attach() argument to the dummy_dip variable that you declared above. You need to save this pointer value in the global variable so that you can use this pointer to get information about this instance from dummy_getinfo() and detach this instance in dummy_detach(). In this dummy_attach() routine, the device instance pointer is used by the ddi_get_instance(9F) function to return the instance number. The device instance pointer and the instance number both are used by ddi_create_minor_node(9F) to create a new device node.

A realistic driver probably would use the ddi_soft_state(9F) functions to create and manage a device node. This dummy driver uses the ddi_create_minor_node(9F) function to create a device node. The ddi_create_minor_node(9F) function takes six arguments. The first argument to the ddi_create_minor_node(9F) function is the device instance pointer that points to the dev_info structure of this device. The second argument is the name of this minor node. The third argument is S_IFCHR if this device is a character minor device or is S_IFBLK if this device is a block minor device. This dummy driver is a character driver.

The fourth argument to the ddi_create_minor_node(9F) function is the minor number of this minor device. This number is also called the instance number. The ddi_get_instance(9F) function returns this instance number. The fifth argument to the ddi_create_minor_node(9F) function is the node type. The ddi_create_minor_node(9F) man page lists the possible node types. The DDI_PSEUDO node type is for pseudo devices. The sixth argument to the ddi_create_minor_node(9F) function specifies whether this is a clone device. This is not a clone device, so set this argument value to 0.

If the ddi_create_minor_node(9F) call is not successful, write a message to the system log and return DDI_FAILURE. If the ddi_create_minor_node(9F) call is successful, return DDI_SUCCESS. If this dummy_attach() routine receives any cmd other than DDI_ATTACH, return DDI_FAILURE.