From owner-svn-doc-all@FreeBSD.ORG Tue Nov 27 15:30:40 2012 Return-Path: Delivered-To: svn-doc-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 9E10E3A7; Tue, 27 Nov 2012 15:30:40 +0000 (UTC) (envelope-from eadler@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 71C1D8FC13; Tue, 27 Nov 2012 15:30:40 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qARFUeMq097034; Tue, 27 Nov 2012 15:30:40 GMT (envelope-from eadler@svn.freebsd.org) Received: (from eadler@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qARFUekl097033; Tue, 27 Nov 2012 15:30:40 GMT (envelope-from eadler@svn.freebsd.org) Message-Id: <201211271530.qARFUekl097033@svn.freebsd.org> From: Eitan Adler Date: Tue, 27 Nov 2012 15:30:40 +0000 (UTC) To: doc-committers@freebsd.org, svn-doc-all@freebsd.org, svn-doc-head@freebsd.org Subject: svn commit: r40167 - head/en_US.ISO8859-1/books/arch-handbook/driverbasics X-SVN-Group: doc-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-doc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire doc trees \(except for " user" , " projects" , and " translations" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Nov 2012 15:30:40 -0000 Author: eadler Date: Tue Nov 27 15:30:40 2012 New Revision: 40167 URL: http://svnweb.freebsd.org/changeset/doc/40167 Log: Modernize the example echo module and fix some style(9) issues in the code. Reviewed by: alfred (code) Reviewed by: gonzo (code) Reviewed by: ehaupt (code) Approved by: bcr (mentor) Modified: head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml Modified: head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml ============================================================================== --- head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml Tue Nov 27 09:43:57 2012 (r40166) +++ head/en_US.ISO8859-1/books/arch-handbook/driverbasics/chapter.xml Tue Nov 27 15:30:40 2012 (r40167) @@ -48,13 +48,7 @@ Most devices in a &unix;-like operating system are accessed through device-nodes, sometimes also called special files. These files are usually located under the directory - /dev in the filesystem hierarchy. - In releases of FreeBSD older than 5.0-RELEASE, where - &man.devfs.5; support is not integrated into FreeBSD, - each device node must be - created statically and independent of the existence of the - associated device driver. Most device nodes on the system are - created by running MAKEDEV. + /dev in the filesystem hierarchy. Device drivers can roughly be broken down into two categories; character and network device drivers. @@ -212,20 +206,19 @@ KMOD=skeleton Example of a Sample Echo Pseudo-Device Driver for - &os; 5.X + &os; 10.X /* - * Simple `echo' pseudo-device KLD + * Simple Echo pseudo-device KLD * * Murray Stokely - * - * Converted to 5.X by Søren (Xride) Straarup + * Søren (Xride) Straarup + * Eitan Adler */ #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 */ @@ -234,7 +227,6 @@ KMOD=skeleton #define BUFFERSIZE 256 - /* Function prototypes */ static d_open_t echo_open; static d_close_t echo_close; @@ -251,15 +243,14 @@ static struct cdevsw echo_cdevsw = { .d_name = "echo", }; -typedef struct s_echo { +struct s_echo { char msg[BUFFERSIZE]; int len; -} t_echo; +}; /* vars */ static struct cdev *echo_dev; -static int count; -static t_echo *echomsg; +static struct s_echo *echomsg; MALLOC_DECLARE(M_ECHOBUF); MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module"); @@ -270,20 +261,25 @@ MALLOC_DEFINE(M_ECHOBUF, "echobuffer", " */ static int -echo_loader(struct module *m, int what, void *arg) +echo_loader(struct module *m __unused, int what, void *arg __unused) { - int err = 0; + int error = 0; switch (what) { case MOD_LOAD: /* kldload */ - echo_dev = make_dev(&echo_cdevsw, + error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, + &echo_dev, + &echo_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "echo"); + if (error != 0) + break; + /* kmalloc memory for use by this driver */ - echomsg = malloc(sizeof(t_echo), M_ECHOBUF, M_WAITOK); + echomsg = malloc(sizeof(*echomsg), M_ECHOBUF, M_WAITOK); printf("Echo device loaded.\n"); break; case MOD_UNLOAD: @@ -292,26 +288,27 @@ echo_loader(struct module *m, int what, printf("Echo device unloaded.\n"); break; default: - err = EOPNOTSUPP; + error = EOPNOTSUPP; break; } - return(err); + return (error); } static int -echo_open(struct cdev *dev, int oflags, int devtype, struct thread *p) +echo_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *p __unused) { - int err = 0; + int error = 0; uprintf("Opened device \"echo\" successfully.\n"); - return(err); + return (error); } static int -echo_close(struct cdev *dev, int fflag, int devtype, struct thread *p) +echo_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused, struct thread *p __unused) { + uprintf("Closing device \"echo.\"\n"); - return(0); + return (0); } /* @@ -321,21 +318,21 @@ echo_close(struct cdev *dev, int fflag, */ static int -echo_read(struct cdev *dev, struct uio *uio, int ioflag) +echo_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) { - int err = 0; - int amt; + int error, 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) { + + amt = MIN(uio-<uio_resid, echomsg-<len - uio-<uio_offset); + uio-<uio_offset += amt; + if ((error = uiomove(echomsg-<msg, amt, uio)) != 0) uprintf("uiomove failed!\n"); - } - return(err); + + return (error); } /* @@ -344,23 +341,39 @@ echo_read(struct cdev *dev, struct uio * */ static int -echo_write(struct cdev *dev, struct uio *uio, int ioflag) +echo_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) { - int err = 0; + int error, amt; /* 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 - 1)); + + if (uio-<uio_offset != 0 && (uio-<uio_offset != echomsg-<len)) + return (EINVAL); + + /* + * This is new message, reset length + */ + if (uio-<uio_offset == 0) + echomsg-<len = 0; + + /* NULL charcter should be overriden */ + if (echomsg-<len != 0) + echomsg-<len--; + + /* Copy the string in from user memory to kernel memory */ + amt = MIN(uio-<uio_resid, (BUFFERSIZE - echomsg-<len)); + + error = uiomove(echomsg-<msg + uio-<uio_offset, amt, uio); /* Now we need to null terminate, then record the length */ - *(echomsg->msg + MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1)) = 0; - echomsg->len = MIN(uio->uio_iov->iov_len, BUFFERSIZE); + echomsg-<len += amt + 1; + uio-<uio_offset += amt + 1; + echomsg-<msg[echomsg-<len - 1] = 0; + //echomsg-<msg[BUFFERSIZE - 1] = '\n'; - if (err != 0) { + if (error != 0) uprintf("Write failed: bad address!\n"); - } - count++; - return(err); + return (error); } DEV_MODULE(echo,echo_loader,NULL); @@ -371,7 +384,9 @@ DEV_MODULE(echo,echo_loader,NULL);&prompt.root; echo -n "Test Data" > /dev/echo &prompt.root; cat /dev/echo -Test Data +Opened device "echo" successfully. +Test Data +Closing device "echo." Real hardware devices are described in the next chapter.