aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Smith <kensmith@FreeBSD.org>2003-09-25 12:46:14 +0000
committerKen Smith <kensmith@FreeBSD.org>2003-09-25 12:46:14 +0000
commitc6674adc3ddd37bf9a9181b6f638e64b76494d1c (patch)
tree3524ed12c9900a8e4f9554dc016412f3b2579051
parent0a49fed78df291b14de73559357c6c9625b5d3aa (diff)
downloaddoc-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.sgml171
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;&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>
+
+ <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 you will first need to make a node on
- your filesystem with a command such as:</para>
+ <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>