• Keine Ergebnisse gefunden

DEVICE DRIVERS 3-23

Im Dokument INTER ACTIVE (Seite 62-66)

Function Specifications (Driver Entry Points)

DEVICE DRIVERS 3-23

#include "syslbuf .hn dskstrategy(bp) struct buf *bp;

{

/* body of strategy routine * / }

The strategy routine uses the following fields in the buffer, but it should not set them:

1. dev _t b_dev;

b_dev contains the major and minor number of the device where the 1j0 is to occur. The minor number is contained in the 8 low order bits, and the major number is contained in the next S low order bits. The 3 high order bits should not be used.

2. daddr_t b_blkno;

b_blkno is the block number of the device where the 1j0 is to occur.

3. unsigned int b_bcount;

b_bcount is the number of bytes to be transferred by the I/O operation.

4. caddr_t b_un.b_addr

b_un.b~ddr is the address of the data in the buffer. The data array is SBUFSIZE bytes long.

S. int b-flags

b_flags gives the buffer status. If the B_READ bit is set, then the I/O operation is to read from the device; if the B_WRITE bit is set, then the I/O operation is to write the device.

3-24 ISDG

If the strategy routine finds an error in setting up the I/O or if the device reports an error via an interrupt, the driver should set the following fields:

1. bJlags should have the B_ERROR bit or'ed in. The driver should not assign a value to b_flags because that may erase other bit patterns that the kernel relies on.

2. char b_error

b_error should be set to an appropriate error value. Typical values are EIO for some physical I/O error, ENXIO for attempting I/O on a bad device or bad device address, or EACCES for attempting to access a device illegally. The kernel later sets u.t1-error with the value of b_error so that any appropriate value for u.u_error could be set.

3. unsigned int b-I"esid;

loctl

b-I"esid should be set to the number of bytes that have not been transmitted.

The driver ioctl routine controls hardware parameters and the interpreta-tion of data as it passes through the driver via read and write:

nnetioctl(dev, cmd, arg, mode) int cmd, arg, mode;

dev_t dev;

The routine takes four parameters, all integers:

1. dev - The minor device (unit) number.

2. cmd - A command argument that the driver ioctl function interprets as the type of operation the driver should perform. The command types vary across the range of devices, but the user manual specifies the command types that must work for terminals (see the User'sjSystem Administrator's Reference Manual Section 7, termio(7». Drivers that use an ioctl function typically have a command to "read" the current ioctl settings and at least one other that sets new settings. The kernel does not interpret the command type, so a driver is free to define its own commands.

DEVICE DRIVERS 3-25

By convention, ioctl commands are set to complex numbers to help guard against accidental misuse by users. A common technique is to pick the first letter of the device name and left shift the ASCII code by 8, then "or" in a command code into the lower 8 bits. The values for ioctl commands are usually defined in the driver header file so that both the driver and user programs can access the commands via #defines. See trace.h in Appendix C for an example of ioctl assignments.

3. arg - An arbitrary argument that can pass parameters between a user program and the driver. The argument can be the address of a struc-ture in the user program that contains settings for the driver or hardware. The driver reads the settings from the user program via the copyinO function and does the appropriate operations. Similarly, the driver collects current settings and uses the copyoutO function to write the data into the user program structure. Alternatively, the argument may be an arbitrary integer that has some meaning to the driver.

Except for terminal drivers where the User's/System Administrator's Reference Manual specifies the argument values (see Section 7, ter-mio(7», the interpretation of the argument is driver-dependent and usually depends on the command type; the kernel does not interpret the argument.

4. mode - An argument (need not be used) that contains values set when the device was opened. The driver can use the mode to determine if the device unit was opened for reading or writing, if necessary, by checking the FREAD or FWRITE setting.

Code for Bringing a Device into Service

There may be requirements for writing initialization code to bring a device into service. Often this can be done in the open routine by creating a flag to determine if this is the first open (generally after a reboot of the system) of the device. If such code is necessary, the driver should contain an initialization function that follows the naming convention described earlier. For our exam-ple, nnet, the initialization function would be called nnetinitO.

If the initialization routine must be called at system initialization time, the Master file entry for the driver should contain an "I" in field 3 in addition to the other driver functions that are supported.

3·26 ISDG

Poll

The routine nnetpoll, if present, is called by the system clock at spl60 dur-ing every clock tick. It is useful for repriming devices that constantly lose interrupts.

nnetpoll(ps) int ps;

The parameter ps is an integer that indicates the previous process's priority when it was interrupted by the system clock.

Halt

The routine nnethalt, if present, is called when the system is shut down.

nnethaltO

Kenter

The routine nnetkenter, if present, is called whenever the kernel is entered from user mode. It should be used with extreme care. Significant overhead in a kenter routine could adversely affect system performance.

nnetkenterO

The kenter routine is called with interrupts disabled. It must not enable inter-rupts, use spl routines, use printf statements, or sleep.

Kexit

The routine nnetkexit, if present, is called whenever the kernel is about to return to user mode. It should be used with extreme care. Significant overhead in a kexit routine could adversely affect system performance.

nnetkexitO

The kexit routine is called with interrupts disabled. It must not enable inter-rupts, use spl routines, use printf statements, or sleep.

Interrupt Handler

As described earlier, hardware interrupts cause the processor to stop its current execution stream and to start executing an instruction stream that ser-vices the interrupt. The system identifies the device causing the interrupt and accesses a table of interrupt vectors to transfer control to the interrupt handler for the device.

Im Dokument INTER ACTIVE (Seite 62-66)