Writing Device Drivers

Autoconfiguration

attach(9E) should perform the common initialization tasks for each instance of a device. Typically, these tasks include:

Block device drivers create minor nodes of type S_IFBLK. This causes a block special file representing the node to eventually appear in the /devices hierarchy.

Logical device names for block devices appear in the /dev/dsk directory, and consist of a controller number, bus-address number, disk number, and slice number. These names are created by the disks(1M) program if the node type is set to DDI_NT_BLOCK or DDI_NT_BLOCK_CHAN. DDI_NT_BLOCK_CHAN should be specified if the device communicates on a channel (a bus with an additional level of addressability), such as SCSI disks, and causes a bus-address field (tN) to appear in the logical name. DDI_NT_BLOCK should be used for most other devices.

For each minor device (which corresponds to each partition on the disk), the driver must also create an nblocks property. This is an integer property giving the number of blocks supported by the minor device expressed in units of DEV_BSIZE (512 bytes). The file system uses the nblocks property to determine device limits. See "Properties" for details.

Example 10-1 shows a typical attach(9E) entry point with emphasis on creating the device's minor node and the nblocks property.


Example 10-1 Block Driver attach(9E) Routine

static int
xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
 	switch (cmd) {
	   case DDI_ATTACH:
		      allocate a state structure and initialize it
		      map the devices registers
		      add the device driver's interrupt handler(s)
		      initialize any mutexs and condition variables
		      read label information if the device is a disk
		      create power manageable components
		   /*
		    * Create the device minor node. Note that the node_type
		    * argument is set to DDI_NT_BLOCK.
		    */
		   if (ddi_create_minor_node(dip, "minor_name", S_IFBLK,
		           minor_number,  DDI_NT_BLOCK, 0) == DDI_FAILURE) {
			          free resources allocated so far
			      /* Remove any previously allocated minor nodes */
			      ddi_remove_minor_node(dip, NULL);
			      return (DDI_FAILURE);
		    }
		   /*
		    * Create driver properties like "nblocks". If the device
		    * is a disk, the nblocks property is usually calculated from
		    * information in the disk label.
		    */
		    xsp->nblocks = size of device in 512 byte blocks;
		   if (ddi_prop_update_int(makedevice(DDI_MAJOR_T_UNKNOWN,
			      instance), dip, "nblocks", xsp->nblocks)
			      != DDI_PROP_SUCCESS) {
			      cmn_err(CE_CONT, "%s: cannot create nblocks property\n",
				           ddi_get_name(dip));
			     free resources allocated so far
			     return (DDI_FAILURE);
		   }
		   xsp->open = 0;
		   xsp->nlayered = 0;
		   ...
		   return (DDI_SUCCESS);

  	case DDI_PM_RESUME:
		    For information, see Chapter 8, Power Management	case DDI_RESUME:
		    For information, see Chapter 8, Power Management	   default:
		      return (DDI_FAILURE);
 	}
}

Properties are associated with device numbers. In Example 10-1, attach(9E) builds a device number using makedevice(9F). At this point, however, only the minor number component of the device number is known, so it must use the special major number DDI_MAJOR_T_UNKNOWN to build the device number.