• Aucun résultat trouvé

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.

#include <sys/dev;ce.h>

#include <sys/types.h>

int ddclose (devno, chan)

Dans le document WRITING A DEVICE DRIVER FOR AIX VERSION 3 (Page 101-107)