- 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 <para>This simple example pseudo-device remembers whatever values
you write to it and can then supply them back to you when you 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>/* <programlisting>/*
* Simple `echo' pseudo-device KLD * 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> DEV_MODULE(echo,echo_loader,NULL);</programlisting>
</example>
<para>To install this driver you will first need to make a node on <example>
your filesystem with a command such as:</para> <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> <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> &prompt.root; <userinput>cat /dev/echo</userinput>
Test Data</screen> 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 <para>Additional Resources
<itemizedlist> <itemizedlist>