DEV(10.2) DEV(10.2)
NAME
Dev - device driver interface
SYNOPSIS
struct Dev
{
int dc;
char* name;
void (*reset)(void); /* native only */
void (*init)(void);
void (*shutdown)(void); /* native */
Chan* (*attach)(char *spec);
Walkqid* (*walk)(Chan *c, Chan *nc, char **name, int nname);
int (*stat)(Chan *c, uchar *db, int dbsize);
Chan* (*open)(Chan *c, int mode);
void (*create)(Chan *c, char *name, int mode, ulong perm);
void (*close)(Chan *c);
long (*read)(Chan *c, void *buf, long nbytes, vlong offset);
Block* (*bread)(Chan *c, long nbytes, ulong offset);
long (*write)(Chan *c, void*, long, vlong offset);
long (*bwrite)(Chan *c, Block *b, ulong offset);
void (*remove)(Chan *c);
int (*wstat)(Chan *c, uchar *db, int dbsize);
void (*power)(int on); /* native only */
int (*config)(int on, char *spec, DevConf *cf); /* native */
};
DESCRIPTION
Every device driver serves a unique name space that represents to the
corresponding device(s). Applications act on the space using the oper‐
ations of sys-bind(2), sys-open(2), sys-read(2), sys-stat(2), and other
system calls. Within the kernel, the Dev structure defines the inter‐
face between the kernel and a device driver for all operations on that
driver's name space.
Dev identifies the driver, and lists a set of C functions that are the
driver's operations. Most are operations on the Chan type that is the
kernel representation of a file or directory active in a name space.
The kernel converts system calls acting on file descriptors into calls
to a device's Dev operations acting on channel values. All channel
values presented through the Dev interface are associated with the cor‐
responding device driver: for channel c, c->type specifies that driver.
Within the driver, the c->qid.path of a channel c identifies a file in
the driver's name space, or even a client-specific instance of a file
(eg, for multiplexors such as ip(3)). The interpretation of the path
is completely determined by the driver.
A device driver in the source file devx.c exports an initialised
instance of Dev xdevtab. For instance, devcons.c contains the global
initialiser:
Dev consdevtab = {
'c',
"cons",
devreset,
consinit,
devshutdown,
consattach,
conswalk,
consstat,
consopen,
devcreate,
consclose,
consread,
devbread,
conswrite,
devbwrite,
devremove,
devwstat,
};
The kernel accesses the driver only through its Dev structure, and con‐
sequently entry points such as consinit, consread, etc. can (and
should) be declared static, and thus local to the file.
The following elements of Dev identify the driver:
dc The device's type, represented by a Unicode character (`rune')
that must be unique amongst those in a given kernel (and ideally
for a given platform). Its value is the value of Dir.dtype in
the result of a sys-stat(2) applied to any file in the device.
name The name that identifies the driver in a kernel configuration
file and in /dev/drivers (see cons(3)).
All the other entries are functions. In many cases, the values given
in a device's Dev will be the default operations provided by devat‐
tach(10.2).
reset()
Called once during system initialisation by the native kernel's
main after initialising all supporting subsystems, including
memory allocation, traps, screen, MMU (if used), but with inter‐
rupts disabled, and before any kernel process environment has
been established. Typically used on some platforms to force
some devices into a sane state before interrupts are enabled.
init() Called once during system initialisation in the context of the
first kernel process, with interrupts enabled, before the vir‐
tual machine has been started.
shutdown()
Called once in native kernels during system shut down. Used on
only a few platforms to force a device into a state that will
allow it to function correctly during and after a soft reboot
(eg, without doing a full system hardware reset).
attach(spec)
Called on each new attach to the device (eg, a reference to #c
by sys-bind(2)). Spec is the string following the device char‐
acter and before a subsequent `/' in the bind request. It is
the empty string for most devies. If the attach is successful,
attach should return a Chan the refers to the root of the tree
served by the device driver. Normally, it will suffice to
return the value of devattach(10.2).
walk(c, nc, name, nname)
Walks existing channel c from its current position in the device
tree to that specified by the path represented by name[0], ...
name[nname-1]. The driver must interpret `..' as a walk from
the current position one level up towards the root of the device
tree. The result is represented by a dynamically-allocated
Walkqid value, with contents as described in devattach(10.2).
Most drivers simply pass parameters on to devwalk in devat‐
tach(10.2) and return its result.
stat(c, db, nbytes)
Fill db with stat(5) data describing the file referenced by c.
Nbytes gives the size of db; if the data will not fit, return
the value specified for convD2M in styx(10.2). Most drivers
simply pass parameters on to devstat in devattach(10.2); a few
fill a local copy of a Dir structure, and call convD2M to store
the machine-independent representation in db.
open(c, mode)
Open the file represented by Chan c, in the given mode (see sys-
open(2)), and if successful, return a Chan value representing
the result (usually c). Many drivers simply apply devopen of
devattach(10.2). Exclusive use drivers might check and incre‐
ment a reference count.
create(c, name, mode, perm)
C should be a directory. Create a new file name in that direc‐
tory, with permissions perm, opened with the given mode. If
successful, make c refer to the newly created file. Most driv‐
ers return an error on all creation attempts, by specifying
devcreate of devattach(10.2) in the Dev table.
close(c)
Close channel c. This must be implemented by all drivers; there
is no default, although the function often is a no-op. Exclu‐
sive use drivers might decrement a reference count.
read(c, buf, nbytes, offset)
Implement a sys-read(2) of nbytes of data from the given offset
in file c, and if successful, place the data in buf, and return
the number of bytes read, which must be no greater than nbytes.
Devices sometimes ignore the offset. All device drivers must
implement read; there is no default. Note that if c is a direc‐
tory, the data has an array of stat(5) data listing the direc‐
tory contents, in the format prescribed by read(5). Most driv‐
ers have devdirread of devattach(10.2) do the work when c is the
root directory of the device's tree.
bread(c, nbytes, offset)
Implement a sys-read(2) of nbytes of data from the given offset
in file c, and if successful return the data in a Block (see
allocb(10.2) and qio(10.2)). Most drivers use the default
devbread provided by devattach(10.2), and nearly all ignore the
offset in any case. Drivers that manipulate Blocks internally,
such as ip(3), ssl(3) and similar protocol devices, and drivers
that are likely to provide data to those devices, will provide a
devbread implementation so as to reduce the number of times the
data is copied.
write(c, buf, nbytes, offset)
Implement a write of nbytes of data from buf to file c, which
must not be a directory, starting at the given byte offset.
Return the number of bytes actually written. There is no
default, but drivers that do not implement writes to any of
their files can simply call error(Eperm) to signal an error.
bwrite(c, b, offset)
Similar to the write entry point, but the data is contained in a
Block b (see allocb(10.2)). B should be freed before return,
whether the driver signals an error or not. Most drivers use
the default devbwrite from devattach(10.2), which calls the
driver's write entry point using the data in b. Drivers that
manipulate Blocks internally, such as ip(3), ssl(3) and similar
protocol devices, will provide a devbwrite implementation so as
to avoid copying the data needlessly.
remove(c)
Remove the file referenced by c. Most drivers raise an error by
using the default devremove from devattach(10.2).
wstat(c, db, dbsize)
Change the attributes of file c, using the stat(5) data in buf‐
fer db, which is dbsize bytes long. Usually a driver will use
convM2D of styx(10.2) to convert the data to a Dir structure,
then apply the rules of stat(5) to decide which attributes are
to be changed (and whether the change is allowed). Most drivers
simply return an error on all wstat requests by using the
default devwstat from devattach(10.2).
power(on)
Reserved for use in native kernels, to allow the kernel to power
the device on and off for power-saving; on is non-zero if the
device is being powered up, and zero if it is being powered
down. The device driver should save the device state if neces‐
sary. Leave the Dev entry null for now.
config(on, spec, cf)
Reserved for use in native kernels to allow a device to be con‐
figured on and off dynamically. Leave the Dev entry null for
now.
The elements reset, shutdown, power, and config are currently present
only in the native kernels.
SEE ALSOintro(2), intro(5), allocb(10.2), devattach(10.2), newchan(10.2),
qio(10.2)
DEV(10.2)