Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
  Previous   Contents   Next 
   
 
Chapter 10

Drivers for Character Devices

Character devices are devices that do not have physically addressable storage media, such as tape drives or serial ports, where I/O is normally performed in a byte stream. This chapter describes the structure of a character device driver, focusing in particular on character driver entry points. In addition, this chapter describes the use of physio(9F) (in read(9E) and write(9E)) and aphysio(9F) (in aread(9E) and awrite(9E)) in the context of synchronous and asynchronous I/O transfers.

This chapter provides information on the following subjects:

Character Driver Structure Overview

Figure 10-1 shows data structures and routines that define the structure of a character device driver. Device drivers typically include the following:

  • Device-loadable driver section

  • Device configuration section

  • Character driver entry points

The shaded device access section in Figure 10-1 illustrates character driver entry points.

Figure 10-1 Character Driver Roadmap

Associated with each device driver is a dev_ops(9S) structure, which in turn refers to a cb_ops(9S) structure. These structures contain pointers to the driver entry points. Note that some of these entry points can be replaced with nodev(9F) or nulldev(9F) as appropriate.

Character Device Autoconfiguration

The attach(9E) routine should perform the common initialization tasks that all devices require. Typically, these tasks include:

  • Allocating per-instance state structures

  • Registering device interrupts

  • Mapping the device's registers

  • Initializing mutex and condition variables

  • Creating power-manageable components

  • Creating minor nodes

See "The attach() Entry Point" for code examples of these tasks.

Character device drivers create minor nodes of type S_IFCHR. This causes a character special file representing the node to eventually appear in the /devices hierarchy.

Example 10-1 shows a sample attach(9E) routine. It is common to declare any properties associated with the device in an attach() routine; in this example, it is the predefined Size property. Size is the equivalent of the Nblocks property used for getting the size of partition in a block device. If, for example, you are doing character I/O on a disk device, you might use Size to get the size of a partition. Since Size is a 64-bit property--the 32-bit version is size--you must use a 64-bit property interface, in this case ddi_prop_updtate_int64(9E) See "Device Properties" for more on properties.


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

static int
xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
  int instance = ddi_get_instance(dip);
  switch (cmd) {
  case DDI_ATTACH:
allocate a state structure and initialize it.
map the device's registers.
add the device driver's interrupt handler(s).
initialize any mutexes and condition variables.
create power manageable components.
          /*
           * Create the device's minor node. Note that the node_type
           * argument is set to DDI_NT_TAPE.
           */
           if (ddi_create_minor_node(dip, "minor_name", S_IFCHR,
               instance, DDI_NT_TAPE, 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 "Size." Use "Size" 
            * instead of "size" to ensure the property works 
            * for large bytecounts.
            */
            xsp->Size = size of device in bytes;
            maj_number = ddi_driver_major(dip);
            if (ddi_prop_update_int64(makedevice(maj_number, instance), 
                     dip, "Size", xsp->Size) != DDI_PROP_SUCCESS) {
                  cmn_err(CE_CONT, "%s: cannot create Size property\n",
                           ddi_get_name(dip));
                 free resources allocated so far
                 return (DDI_FAILURE);
           }
           ...
           return (DDI_SUCCESS);    
case DDI_RESUME:
        For information, see Chapter 9, Power Management   
default:
        return (DDI_FAILURE);
      }
}

 
 
 
  Previous   Contents   Next