FreeBSD Device Driver Writer's Guide : Types of drivers. : Character : Entry Points
Previous: Data Structures
Next: Header Files

2.1.2. Entry Points

2.1.2.1. d_open()

d_open() takes several arguments, the formal list looks something like:


int
d_open(dev_t dev, int flag, int mode, struct proc *p)

d_open() is called on every open of the device.

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.

2.1.2.2. d_close()

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().

2.1.2.3. d_read() and d_write()

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().

2.1.2.4. d_ioctl()

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).

2.1.2.5. d_stop()

2.1.2.6. d_reset()

2.1.2.7. d_devtotty()

2.1.2.8. d_select()

2.1.2.9. d_mmap()

2.1.2.10. d_strategy()

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.


FreeBSD Device Driver Writer's Guide : Types of drivers. : Character : Entry Points
Previous: Data Structures
Next: Header Files
www@freebsd.org