diff options
author | Ken Smith <kensmith@FreeBSD.org> | 2003-09-25 12:46:14 +0000 |
---|---|---|
committer | Ken Smith <kensmith@FreeBSD.org> | 2003-09-25 12:46:14 +0000 |
commit | c6674adc3ddd37bf9a9181b6f638e64b76494d1c (patch) | |
tree | 3524ed12c9900a8e4f9554dc016412f3b2579051 | |
parent | 0a49fed78df291b14de73559357c6c9625b5d3aa (diff) | |
download | doc-c6674adc3ddd37bf9a9181b6f638e64b76494d1c.tar.gz doc-c6674adc3ddd37bf9a9181b6f638e64b76494d1c.zip |
- add example FreeBSD 5.X driver submitted by S<F8>ren (Xride) Straarup
(driver tested on i386 and sparc64 platforms)
- minor formatting fixes (add <example></example>)
- minor spelling/grammar fixes
Approved: blackend (mentor)
Notes
Notes:
svn path=/head/; revision=18238
-rw-r--r-- | en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml | 171 |
1 files changed, 167 insertions, 4 deletions
diff --git a/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml b/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml index 61a425b8bd..ece3375310 100644 --- a/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml +++ b/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml @@ -174,7 +174,12 @@ KMOD=skeleton <para>This simple example pseudo-device remembers whatever values you write to it and can then supply them back to you when you - read from it.</para> + read from it. Two versions are shown, one for &os; 4.X and + one for &os; 5.X.</para> + + <example> + <title>Example of a Sample Echo Pseudo-Device Driver for + &os; 4.X</title> <programlisting>/* * Simple `echo' pseudo-device KLD @@ -334,9 +339,167 @@ echo_write(dev_t dev, struct uio *uio, int ioflag) } DEV_MODULE(echo,echo_loader,NULL);</programlisting> + </example> + + <example> + <title>Example of a Sample Echo Pseudo-Device Driver for + &os; 5.X</title> + + <programlisting>/* + * Simple `echo' pseudo-device KLD + * + * Murray Stokely + * + * Converted to 5.X by Søren (Xride) Straarup + */ + +#include <sys/types.h> +#include <sys/module.h> +#include <sys/systm.h> /* uprintf */ +#include <sys/errno.h> +#include <sys/param.h> /* defines used in kernel.h */ +#include <sys/kernel.h> /* types used in module initialization */ +#include <sys/conf.h> /* cdevsw struct */ +#include <sys/uio.h> /* uio struct */ +#include <sys/malloc.h> + +#define BUFFERSIZE 256 +#define CDEV_MAJOR 33 + + +/* Function prototypes */ +static d_open_t echo_open; +static d_close_t echo_close; +static d_read_t echo_read; +static d_write_t echo_write; + +/* Character device entry points */ +static struct cdevsw echo_cdevsw = { + .d_open = echo_open, + .d_close = echo_close, + .d_maj = CDEV_MAJOR, + .d_name = "echo", + .d_read = echo_read, + .d_write = echo_write +}; + +typedef struct s_echo { + char msg[BUFFERSIZE]; + int len; +} t_echo; + +/* vars */ +static dev_t echo_dev; +static int count; +static t_echo *echomsg; + +MALLOC_DECLARE(M_ECHOBUF); +MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module"); + +/* + * This function is called by the kld[un]load(2) system calls to + * determine what actions to take when a module is loaded or unloaded. + */ + +static int +echo_loader(struct module *m, int what, void *arg) +{ + int err = 0; + + switch (what) { + case MOD_LOAD: /* kldload */ + echo_dev = make_dev(<literal>&</literal>echo_cdevsw, + 0, + UID_ROOT, + GID_WHEEL, + 0600, + "echo"); + /* kmalloc memory for use by this driver */ + MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK); + printf("Echo device loaded.\n"); + break; + case MOD_UNLOAD: + destroy_dev(echo_dev); + FREE(echomsg,M_ECHOBUF); + printf("Echo device unloaded.\n"); + break; + default: + err = EINVAL; + break; + } + return(err); +} + +static int +echo_open(dev_t dev, int oflags, int devtype, struct thread *p) +{ + int err = 0; + + uprintf("Opened device \"echo\" successfully.\n"); + return(err); +} + +static int +echo_close(dev_t dev, int fflag, int devtype, struct thread *p) +{ + uprintf("Closing device \"echo.\"\n"); + return(0); +} + +/* + * The read function just takes the buf that was saved via + * echo_write() and returns it to userland for accessing. + * uio(9) + */ + +static int +echo_read(dev_t dev, struct uio *uio, int ioflag) +{ + int err = 0; + int amt; + + /* + * How big is this read operation? Either as big as the user wants, + * or as big as the remaining data + */ + amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? + echomsg->len - uio->uio_offset : 0); + if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) { + uprintf("uiomove failed!\n"); + } + return(err); +} + +/* + * echo_write takes in a character string and saves it + * to buf for later accessing. + */ + +static int +echo_write(dev_t dev, struct uio *uio, int ioflag) +{ + int err = 0; + + /* Copy the string in from user memory to kernel memory */ + err = copyin(uio->uio_iov->iov_base, echomsg->msg, + MIN(uio->uio_iov->iov_len,BUFFERSIZE)); + + /* Now we need to null terminate, then record the length */ + *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0; + echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE); + + if (err != 0) { + uprintf("Write failed: bad address!\n"); + } + count++; + return(err); +} + +DEV_MODULE(echo,echo_loader,NULL);</programlisting> + </example> - <para>To install this driver you will first need to make a node on - your filesystem with a command such as:</para> + <para>To install this driver on &os; 4.X you will first need to + make a node on your filesystem with a command such as:</para> <screen>&prompt.root; <userinput>mknod /dev/echo c 33 0</userinput></screen> @@ -347,7 +510,7 @@ DEV_MODULE(echo,echo_loader,NULL);</programlisting> &prompt.root; <userinput>cat /dev/echo</userinput> Test Data</screen> - <para>Real hardware devices in the next chapter..</para> + <para>Real hardware devices are described in the next chapter.</para> <para>Additional Resources <itemizedlist> |