d_open() takes several arguments, the formal list looks something like:
int d_open(dev_t dev, int flag, int mode, struct proc *p)
The dev
argument contains the major and minor number of the
device opened. These are available through the macros major()
and
minor()
The flag
and mode
arguments are as described in the
open(2)
manual page. It is recommended that you check these for access modes
in <sys/fcntl.h> and do what is required. For example if flag
is (O_NONBLOCK | O_EXLOCK) the open should fail if either it would
block, or exclusive access cannot be granted.
The p
argument contains all the information about the current
process.
d_close() takes the same argument list as d_open():
int d_close(dev_t dev , int flag , int mode , struct proc *p)
d_close() is only called on the last close of your device (per minor device). For example in the following code fragment, d_open() is called 3 times, but d_close() is called only once.
... fd1=open("/dev/mydev", O_RDONLY); fd2=open("/dev/mydev", O_RDONLY); fd3=open("/dev/mydev", O_RDONLY); ... <useful stuff with fd1, fd2, fd3 here> ... close(fd1); close(fd2); close(fd3); ...
The arguments are similar to those described above for d_open().
d_read() and d_write take the following argument lists:
int d_read(dev_t dev, struct uio *uio, int flat) int d_write(dev_t dev, struct uio *uio, int flat)
The d_read() and d_write() entry points are called when read(2) and write(2) are called on your device from user-space. The transfer of data can be handled through the kernel support routine uiomove().
It's argument list is as follows:
int d_ioctl(dev_t dev, int cmd, caddr_t arg, int flag, struct proc *p)
d_ioctl() is a catch-all for operations which don't make sense in a read/write paradigm. Probably the most famous of all ioctl's is on tty devices, through stty(1). The ioctl entry point is called from ioctl() in sys/kern/sys_generic.c
There are four different types of ioctl's which can be implemented. <sys/ioccom.h> contains convenience macros for defining these ioctls.
_IO(g,n)
for control type operations.
_IOR(g,n,t)
for operations that read data from a device.
_IOW(g,n,t)
for operations that write data to a device.
_IOWR(g,n,t)
for operations that write to a device, and then
read data back.
Here g
refers to a group. This is an 8-bit value, typically
indicative of the device; for example, 't' is used in tty ioctls.
n
refers to the number of the ioctl within the group. On SCO, this
number alone denotes the ioctl. t
is the data type which will
get passed to the driver; this gets handed to a sizeof() operator in
the kernel. The ioctl() system call will either copyin() or copyout()
or both for your driver, then hand you a pointer to the data structure
in the arg
argument of the d_ioctl call. Currently the data size
is limited to one page (4k on the i386).
d_strategy()'s argument list is as follows:
void d_strategy(struct buf *bp)
d_strategy() is used for devices which use some form of scatter-gather io. It is most common in a block device. This is significantly different than the System V model, where only the block driver performs scatter-gather io. Under BSD, character devices are sometimes requested to perform scatter-gather io via the readv() and writev() system calls.