The kernel calls the ddopen routine of a device driver when a program issues an open or creat subroutine call. It can also be called when a system call, kernel process, or other device driver uses the fp_opendev or fp_open kernel service to use the device.
The ddopen routine must first ensure exclusive access to the device, if necessary. Many character devices, such as printers and plotters, should be opened by only one process at a time. The ddopen routine can enforce this by maintaining a static flag variable, which is set to 1 if the device is open and 0 if not. Each time the ddopen routine is called, it checks the value of the flag. If the value is other than zero, the ddopen routine returns with a return code of EBUSY to indicate that the device is already open. Otherwise, the routine sets the flag and returns normally. The ddclose entry point later clears the flag when the device is closed. Since most block devices can be used by several processes at once, a block driver should not try to enforce opening by a single user.
The ddopen routine must initialize the device if this is the first open that has occurred. Initialization involves the following steps:
• The ddopen routine should allocate the required system resources to the device, such as DMA channels, interrupt levels, and priorities. It should, if necessary, register its device interrupt handler for the interrupt level required to support the target device. The ijnit and dJnit kernel services are available for initializing these resources.
• If this device driver is providing the head role for a device and another device driver is providing the handler role, the ddopen routine should open the device handler by using the fp_opendev kernel service.
Note: The fp_opendev kernel service requires a devno parameter to identify which device handler to open. This devno value, taken from the appropriate DDS, should have been stored in a special save area when the device driver's ddconfig routine was called.
The flag word devflag has the following flags, as defined in the <sys/devlce.h>
header file:
DKERNEL Entry point called by kernel routine using the fp_opendev or fp_open kernel service.
DREAD Open for reading.
DWRITE Open for writing.
DAPPEND Open for appending.
DNDELAY Device open in non-blocking mode.
The ddopen entry point can indicate an error condition to the user mode application program by returning a nonzero return code. Returning a nonzero return code causes the open or creat subroutines to return a value of·1 and makes the return code available to the usermode application in the errno external variable. The return code used should be one of the values defined in the <sys/errno.h> header file.
If a nonzero return code is returned by the ddopen routine, the open request is considered to have failed. No access to the device instance is available to the caller as a result. In addition, for non-multiplexed drivers, if the failed open was the first open of the device instance, the kernel calls the driver's ddclose entry point to allow resources and device driver state to be cleaned up. If the driver was multiplexed, the kernel does not call the ddclose entry point on an open failure. When applicable, the return values defined in the POS/X 1003.1 standard for the open subroutine should be used.
1
ricopen(devno, devflag, mpxchan, ext_ptr) dev t devno;
t_sel_que *sqelml_ptr;/* select queue element pointer */
t_sel_que *sqelm2_ptr;/* select queue element pointer */
t chan info *tmp_chnptr;/* temp channel info pointer */
58
65 if(acb_ptr->n_open_ports == 8)
66 {
67
68 /* first initialise the offlevel intr structures */
69 acb_ptr->arq_sched
=
FALSE;78 aCb_ptr->offl.p_acb_intr
=
(struct t_acb *)acb_ptr;71 intr_ptr
=
&(acb_ptr->offl.offl_intr);72 INIT_OFFL3(intr_ptr, ricoffl, IO_SEG_REG);
73
74 acb_ptr->slih_intr.next = NULL;
75 acb_ptr->slih_intr.handler = ricintr;
76 acb_ptr->slih_intr.bus_type
=
BUS_MICRO_CHANNEL;77 acb_ptr->slih_intr.flags
=
0;78 aCb_ptr->slih_intr.level = acb_ptr->int_lvl;
79 acb_ptr->slih_;ntr.priority
=
INTCLASS1;80 acb_ptr->slih_intr.bid
=
IO_SEG_REG;81
82 acb_ptr->cmd_queue_lock
=
LOCK_AVAIL;83
92 bus_sr
=
BUSIO_ATT(acb_ptr->io_segreg_val, 0);93
185 if(dds_ptr->dds_wrk.p_chan_info[mpxchan] == NULL)
196 {
197 /* allocate memory for channel related structures */
198 dds_ptr->dds_wrk.p_chan_info[mpxchan]
=
tmp_chnptr =199 (t_chan_info *)xmalloc«uint)sizeof(t_chan_info),(uint)2,
118 bzero«vo;d *)tmp_chnptr, (uint)sizeof(t_chan_info»;
Figure 4-10 (Part 2 of 3). Code Sample of the ricopen Routine
119
1213 /* set major/minor device number */
121 tmp_chnptr->devno
=
devno;122 tmp_chnptr->rcv_event_lst
=
EVENT_NULL;123 tmp_chnptr->xmt_event_lst = EVENT_NULL;
124 acb_ptr->txfl_event_lst
=
EVENT_NULL;125
126 }
127
128 /* now fetch the temporary channel info pointer */
129 tmp_chnptr
=
dds_ptr->dds_wrk.p_chan_info[mpxchan];1313
131 /* set common values for user and kernel llc calls */
132 tmp_chnptr->devflag
=
devflag; /* device flags opened with */133
134 /* set port state variable to open */
135 dds_ptr->dds_dvc.port_state
=
OPEN;136
137 /* increment number of open ports */
138 acb_ptr->n_open_ports++;
139
1413 returnee);
141 } /* end ricopen */
142
Figure 4-10 (Part 3 of 3). Code Sample of the ricopen Routine
4.1.4 ddclose Device Driver Entry Point
Figure 4-11 on page 4-25 shows the device driver ddclose entry point.
close("/dev/ric" ••.• )
UscrSpace Kernel Space
ddmpx called on last close for multiplexed device drivers DO half: paglilble
config open read write iocd select
(close the device handler) DO Bottom
off-level interrupt handler. etc.
Hardware
Figure 4-11. Device Driver ddclose Entry Point
The ddclose device driver entry routine closes a previously open device instance. (A device instance is a specific port on a communications adapter or a hard disk on a SCSI adapter, etc.) The ddclose routine is executed only in the process environment. It should provide the required serialization of its data structures by using the locking kernel services in conjunction with a private lock word defined in the driver. Refer to Figure 4-13 on page 4-28 for the ricclose sample code.
The ddclose routine expects two parameters. These are devno and chan, where:
devno
chan
Specifies the major and minor device numbers of the device instance to close.
Specifies the channel number (for multiplexed devices only).
The following example shows the syntax of a ddclose entry point.