Specifications
Writing a User-Level Device Drive
r
17-9
you use the userdma(2) system call to prepare a buffer for
DMA transfers.
The dmavec structure has been defined to describe a physical buffer fragment. This
structure is defined in the file <sys/mman.h> as follows:
struct dmavec {
unsigned int dma_paddr;
unsigned int dma_plen;
};
The fields in the structure are described as follows:
dma_paddr the physical address of the buffer fragment
dma_plen the length in bytes of the buffer fragment
Overview of User-Level Device Driver Routines 17
The types of library routines that compose a user-level device driver depend upon the
nature of the device being controlled by the driver. They can include an open and a
close routine, an aread routine, an awrite routine, one or more control routines, an
interrupt-handling routine, and other routines that are specific to the device. A controller
that performs serial line communications, for example, requires an open,aclose,an
aread,anawrite, and, perhaps, some control routines. An (H)VME reflective memory
board, on the other hand, requires only an open,aclose, and some control routines. In
either case, if the controller generates interrupts, a user-level interrupt-handling routine
can be required.
A user-level driver’s routines can be classified according to whether they provide
noncritical or critical services. Noncritical services include allocation of resources and
initialization of the device to be used. Critical services include those that provide access to
the device. A driver’s initialization routines provide noncritical services. They perform
such functions as attaching shared memory regions, initializing a user’s data buffers for
DMA operations, and performing device initialization and reset services. Because
initialization routines use system calls to perform their functions, they are slow, and they
incur the overhead of kernel entry. A driver’s I/O and control routines provide critical
services. They perform such functions as initiating a device I/O request, handling inter-
rupts, and providing support for polling or waiting for I/O completion. I/O and control
routines are fast, deterministic routines that do not use system calls to perform their
functions.
A distinction is made between noncritical and critical services in an effort to help the user
determine the appropriate time in an application to invoke a user-level device driver’s
routines. To perform some I/O operations, certain kernel services must be used--those for
locking pages in memory, translating virtual addresses to physical addresses, and so on.
These services cannot be performed at user level. Because one of the objectives of a user-
level driver is to provide a means for avoiding entry into the kernel, such services as these
should be performed once as a part of initialization procedures--at a time when the
application is not bound by timing constraints. The noncritical routines that can be called
at this time are the user-level driver’s open and close routines. The critical routines that
can be called when the application is running under strict timing constraints are the user-
level driver’s aread, awrite, acheck, await, control, and interrupt routines.