Writing Device Drivers

open(9E)

The open(9E) entry point is used to gain access to a given device. The open(9E) routine of a block driver is called when a user thread issues an open(2) or mount(2) system call on a block special file associated with the minor device, or when a layered driver calls open(9E). See "File I/O" for more information.

The open(9E) entry point should check for the following:

Example 11-2 demonstrates a block driver open(9E) entry point.


Example 11-2 Block Driver open(9E) Routine

static int
xxopen(dev_t *devp, int flags, int otyp, cred_t *credp)
{
       minor_t             instance;
       struct xxstate            *xsp;

     instance = getminor(*devp);
     xsp = ddi_get_soft_state(statep, instance);
     if (xsp == NULL)
               return (ENXIO);
     mutex_enter(&xsp->mu);
     /*
        * only honor FEXCL. If a regular open or a layered open
        * is still outstanding on the device, the exclusive open
        * must fail.
        */
     if ((flags & FEXCL) && (xsp->open || xsp->nlayered)) {
           mutex_exit(&xsp->mu);
           return (EAGAIN);
     }
     switch (otyp) {
       case OTYP_LYR:
             xsp->nlayered++;
             break;
      case OTYP_BLK:
             xsp->open = 1;
             break;
     default:
             mutex_exit(&xsp->mu);
             return (EINVAL);
     }
   mutex_exit(&xsp->mu);
      return (0);
}

The otyp argument is used to specify the type of open on the device. OTYP_BLK is the typical open type for a block device. A device can be opened several times with otyp set to OTYP_BLK, although close(9E) will be called only once when the final close of type OTYP_BLK has occurred for the device. otyp is set to OTYP_LYR if the device is being used as a layered device. For every open of type OTYP_LYR, the layering driver issues a corresponding close of type OTYP_LYR. The example keeps track of each type of open so the driver can determine when the device is not being used in close(9E).