From owner-freebsd-hackers Sat Feb 1 17:11:14 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id RAA21891 for hackers-outgoing; Sat, 1 Feb 1997 17:11:14 -0800 (PST) Received: from genesis.atrad.adelaide.edu.au (genesis.atrad.adelaide.edu.au [129.127.96.120]) by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id RAA21886 for ; Sat, 1 Feb 1997 17:11:10 -0800 (PST) Received: (from msmith@localhost) by genesis.atrad.adelaide.edu.au (8.8.2/8.7.3) id LAA15091; Sun, 2 Feb 1997 11:41:00 +1030 (CST) From: Michael Smith Message-Id: <199702020111.LAA15091@genesis.atrad.adelaide.edu.au> Subject: Re: Device driver help needed... In-Reply-To: <199702012336.SAA12533@spoon.beta.com> from "Brian J. McGovern" at "Feb 1, 97 06:36:59 pm" To: mcgovern@spoon.beta.com (Brian J. McGovern) Date: Sun, 2 Feb 1997 11:40:59 +1030 (CST) Cc: hackers@freebsd.org X-Mailer: ELM [version 2.4ME+ PL28 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: owner-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Brian J. McGovern stands accused of saying: > Ok. I'm sure that now I've terribly bastardized the uio structure, but at > least the damn thing compiles :) Let see if I can get some comment > on my interpretation of the uio stucture: "correct" usage of the uio structure means ignoring its contents, with the exception of the uio_resid member, which gives you a count of bytes outstanding. On a read, this is how much of the user buffer is left, on a write this is how much more the user process wants to write. You drag stuff around with uiomove() : u_char mybuf[128]; int hmuch; int result; ... hmuch = min(uio->uio_resid, sizeof(mybuf)); if ((result = uiomove(mybuf, hmuch, uio))) return(result); ... In a read() style routine, this will copy data from mybuf out to the user, in a write() style routine, the data goes the other way. This is handled invisibly by the contents of the uio strcture. > With that in mind, I've bent my device driver to look like this: I'm assuming that this is meant to be a pseudo-device, correct? > static struct cdevsw foo_cdevsw = > { > nxopen, nxclose, fooread, nxwrite, > nxioctl, nxstop, nxreset, nxdevtotty, > nxselect, nxmmap, NULL, "foo", NULL, -1 > }; You probably want nullopen and nullclose there, so that the device can be opened and closed. > fooinit() > { > } If this is a pseudo-device, you're going to want some code here to install you cdevsw and any devfs nodes you plan on advertising. I _strongly_ suggest looking at the logic in vn_drvinit, which does just that (as well as installing a shutdown hook). > static int fooread(dev,myuio, flag) > dev_t dev; > struct uio *myuio; > int flag; > { > unsigned char *buffer_pointer; > int toread; > if ((myuio->uio_iovcnt != 1) || (MINOR(dev) != 0)) > return ENODEV; > while(myuio->uio_resid) > { > buffer_pointer = (message + (myuio->uio_offset % sizeof(message))); > toread = ((long unsigned int)(message + sizeof(message)) - (long unsigned int)buffer_pointer); > uiomove(buffer_pointer, toread, myuio); > myuio->uio_offset + toread; > myuio->uio_resid = myuio->uio_resid - toread; > } > } > #define CDEV_MAJOR 20 Ouch. Leave the innards of the uio structure alone; uiomove takes care of all that for you. If what you want the read function to do is to return as much of the message string as will fit in the requeted read buffer, try : static int fooread(dev_t dev, struct uio *uio, int flag) { int toread; if (MINOR(dev) != 1) return(ENODEV); toread = (min(uio->uio_resid, sizeof(message)); return(uiomove(message, toread, uio)); } > as a pseudo-device driver. The file above is located in > /usr/src/sys/i386/addons/foo.c. Anyone care to give me a set of steps (and > code changes) to get it in the kernel? Thanks. > -Brian Move it to /sys/dev/foo/foo.c, bracket the whole file in #if NFOO > 0 / #endif, add a line to /sys/conf/files that reads '/dev/foo/foo.c optional foo' and stick a line in your kernel config that reads 'pseudo-device foo 1'. Add a SYSINIT macro to your file that looks like : SYSINIT(foodev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,foo_init,NULL); and rework your init function along the lines of the 'vn' one mentioned above. When you're testing your kernels, _don't_ use 'make install' to install them, as it's fairly likely you'll end up with two dead ones in a row 8) -- ]] Mike Smith, Software Engineer msmith@gsoft.com.au [[ ]] Genesis Software genesis@gsoft.com.au [[ ]] High-speed data acquisition and (GSM mobile) 0411-222-496 [[ ]] realtime instrument control. (ph) +61-8-8267-3493 [[ ]] Unix hardware collector. "Where are your PEZ?" The Tick [[