docs/55693: Howto make a kernel module for a pseudo-device under 5.X
Søren Straarup
xride at xride.dk
Mon Aug 18 12:40:18 UTC 2003
>Number: 55693
>Category: docs
>Synopsis: Howto make a kernel module for a pseudo-device under 5.X
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: freebsd-doc
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: update
>Submitter-Id: current-users
>Arrival-Date: Mon Aug 18 05:40:15 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator: Xride
>Release: FreeBSD 5.1-CURRENT i386
>Organization:
>Environment:
Changed the pseudo-device kernel module code, from the arch-handbook, so it
will work under 5.X.
--- chapter.diff begins here ---
--- /usr/doc/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.sgml Thu Aug 7 01:48:02 2003
+++ chapter.sgml Mon Aug 18 13:42:46 2003
@@ -335,6 +335,168 @@
DEV_MODULE(echo,echo_loader,NULL);</programlisting>
+ <para>For the 5.X serie this is how the code for the pseudo-device
+ should look:</para>
+
+<programlisting>/*
+ * Simple `echo' pseudo-device KLD
+ *
+ * Murray Stokely
+ */
+
+/*
+ * Conveted to 5.X by S&oring;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;
+static int len;
+
+
+MALLOC_DECLARE(M_ECHOBUF);
+MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
+
+/*
+ * This function acts 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(&echo_cdevsw,
+ 0,
+ UID_ROOT,
+ GID_WHEEL,
+ 0600,
+ "echo");
+ /* kmalloc memory for use by this driver */
+ /* malloc(256,M_ECHOBUF,M_WAITOK); */
+ 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->l
+en - 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_le
+n,BUFFERSIZE));
+
+ /* Now we need to null terminate */
+ *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
+ /* Record the length */
+ 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>
+
+
<para>To install this driver you will first need to make a node on
your filesystem with a command such as:</para>
--- chapter.diff ends here ---
>Description:
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-doc
mailing list