• Keine Ergebnisse gefunden

The character device driver kernel interface

Im Dokument sea UNIX Writing Drivers (Seite 66-70)

Simple character device drivers

3.2 The character device driver kernel interface

Our first step towards writing a simple character device driver is to gain an understanding of the principal functions that form the basis of the code that needs to be written. This section describes these routines, expanding upon the outline given in Chapter 2. Most of the routines are invoked by the kernel from the cdevsw table.

3.2.1 XXinit

Syntax:

XXinit ()

This routine is called by the operating system at boot time. This is the point at which the peripheral hardware is initialized or reset. No operations that require user processes to be present should be per-formed at this stage. It should display a message on the console confirming that the hardware is present. This can be done by check-ing for a 'signature' value or magic number which some devices guarantee to have set at a given address. Alternatively, known bit patterns can be checked in peripheral registers following a command that is written to the device.

Memory can be requested by the device driver at this point. If contiguous memory is required, this is a suitable time to request it (before it is fragmented by user process activity). No operations that require interrupts can be performed at this stage as interrupts are not enabled when this routine is called.

3.2.2 XXopen

Syntax:

XXopen(dev, flag, id) dev_t dev;

int flag, id;

This routine is called by the operating system every time the device is

open(S) ed. The dey parameter specifies the major and minor device number of the device file used to invoke the driver. It is passed to many of the other driver entry points. flag is used to record the values used with the open (S) call. The values are defined in

( sys/f ile. h). These include values such as FAPPEND which corres-ponds to the O-APPEND parameter used with open (S). The id flag is set by the kernel to indicate how the device is being used by the kernel.

The values are defined in (sys/open.h); for example, OTYP_CHR indi-cates that the XXopen routine is being called as a result of an open(S)

on a character device file.

XXopen is a suitable place to code:

• Error and status checking (for example, is the floppy disk inser-ted?)

• Hardware initialization that requires interrupts in order to com-plete.

• Exclusivity, where only one open (S) of the device is allowed.

• Validation of minor device numbers passed as a parameter.

3.2.3 XXclose

Syntax:

XXclose(dev, flag, id) dev_t dey;

int flag, id;

Whereas the XXopen routine is called whenever a user performs an

open(S) system call on the device, XXclose is called only when the last

close(S) system call is made on the special device file. The only exception to this is when an XXclose routine has been called by another layered XXclose routine (for instance, by a software driver to implement disk mirroring). If this is the case XXclose calls will be paired with XXopen calls and id should be set to OTYP_LYR by the driver invoking the XXclose routine.

The value of flag corresponds to that of the flag passed to the

XXopen routine.

This is a suitable place to code any clean-up operations that are required. These might include flushing buffers, deallocating dynamic resources which have been previously claimed, disabling the device or shutting down a motor drive.

3.2.4 XXread

Syntax:

XXread(dev) dev_t dev;

The character device driver kernel interface 51

This routine is called as a result of a user's read (S) system call.

The routine should:

• Validate the feasibility of the request, bearing in mind the hard-ware constraints.

• Wait for the device to become ready and then send the required bytes to the device's control register in order to request the data from the device.

• Wait for the data to arrive. When the data arrives from the device XXread should transfer it into the user process' address space.

Alternatively, if there has been a hardware error this needs to be passed back to the process which made the read (S) request.

3.2.5 XXwrite

Syntax:

XXwrite(dev) dev_t dev;

This routine is called whenever a user makes a write (S) system call.

The routine should:

• Likewise validate the feasibility of the request, bearing in mind the hardware constraints.

• Copy the data from the user process.

• Wait for the device to become ready and program the device's control registers in order to initiate the transfer.

• Write the data to the device in question. If there is a hardware error this should be passed back to the process which made the wr i te (S)

request.

3.2.6 XXioctl

Syntax:

XXioctl(dev, cmd, arg, mode) dev_t dey;

int cmd, mode;

caddr_t arg;

This routine is used to implement hardware-specific functions.

emd

is

used to specify a device driver-specific command. arg can hold either the address of the argument passed to the system call or a single integer argument. The value of mode corresponds to the value of the flag passed to the open (8) system call.

Given the simple open (8) /close (8) /read (8) /write (8) interface that is available for all files, the I/O control system call ioctl (8) was introduced as a 'catch all' system call to control any idiosyncrasies of the device being controlled. This call is often used by application writers who wish to control the behaviour of a serial line. For exam-ple, the baud rate is modified by the stty (C) command using ioctl (8) requests. However, it can be used to do almost anything.

The device driver writer needs to document the parameters for his or her particular device driver so that users understand the significance of any parameters that are passed to this routine, as these will be device driver specific.

3.2.7 XXhalt

Syntax:

XXhalt()

The halt routine is called by the kernel when the system is shut down.

It allows the device driver to leave the hardware in a state where it can be re-initialized without a power cycle.

3.2.8 XXintr

Syntax:

XXintr(irq) int irq;

This routine is called following an interrupt from the device. irq indicates which interrupt request line generated the interrupt.

The U-area and simple character devices 53 Many devices generate interrupts. They can occur when the device has completed an operation such as a read or a write or when there is a change in the device's status, such as when the carrier signal drops on a communications line.

3.2.9 XXstart

Syntax:

XXstart()

This routine is not a kernel entry point, it is private to the device driver. It is conventionally used to interact directly with the device's hardware, setting up commands in a controller's register in order to start a transfer. XXstart is often called from the XXread, XXwrite and XXintr routines.

3.2.10 XXpoll

Syntax:

XXpoll(ppl) int ppl;

When interrupts from a device are either not available or not reliable this routine can be written and used to service the device. It is called by the kernel following a clock tick. The frequency of the clock is defined by HZ in (sysjparam.h) (HZ is defined as 100 in

sea

UNIX

3.2 v4). The interrupt priority of the system before the clock tick is supplied in ppl.

Im Dokument sea UNIX Writing Drivers (Seite 66-70)