- 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)
This commit is contained in:
Ken Smith 2003-09-25 12:46:14 +00:00
parent 0a49fed78d
commit c6674adc3d
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=18238

View file

@ -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;&nbsp; 4.X and
one for &os;&nbsp; 5.X.</para>
<example>
<title>Example of a Sample Echo Pseudo-Device Driver for
&os;&nbsp;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>
<para>To install this driver you will first need to make a node on
your filesystem with a command such as:</para>
<example>
<title>Example of a Sample Echo Pseudo-Device Driver for
&os;&nbsp;5.X</title>
<programlisting>/*
* Simple `echo' pseudo-device KLD
*
* Murray Stokely
*
* Converted to 5.X by Søren (Xride) Straarup
*/
#include &lt;sys/types.h&gt;
#include &lt;sys/module.h&gt;
#include &lt;sys/systm.h&gt; /* uprintf */
#include &lt;sys/errno.h&gt;
#include &lt;sys/param.h&gt; /* defines used in kernel.h */
#include &lt;sys/kernel.h&gt; /* types used in module initialization */
#include &lt;sys/conf.h&gt; /* cdevsw struct */
#include &lt;sys/uio.h&gt; /* uio struct */
#include &lt;sys/malloc.h&gt;
#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-&gt;uio_resid, (echomsg-&gt;len - uio-&gt;uio_offset &gt; 0) ?
echomsg-&gt;len - uio-&gt;uio_offset : 0);
if ((err = uiomove(echomsg-&gt;msg + uio-&gt;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-&gt;uio_iov-&gt;iov_base, echomsg-&gt;msg,
MIN(uio-&gt;uio_iov-&gt;iov_len,BUFFERSIZE));
/* Now we need to null terminate, then record the length */
*(echomsg-&gt;msg + MIN(uio-&gt;uio_iov-&gt;iov_len,BUFFERSIZE)) = 0;
echomsg-&gt;len = MIN(uio-&gt;uio_iov-&gt;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 on &os;&nbsp;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>