From owner-freebsd-hackers Sun Feb 23 18:19:42 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id SAA18567 for hackers-outgoing; Sun, 23 Feb 1997 18:19:42 -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 SAA18548 for ; Sun, 23 Feb 1997 18:19:29 -0800 (PST) Received: (from msmith@localhost) by genesis.atrad.adelaide.edu.au (8.8.5/8.7.3) id MAA04053; Mon, 24 Feb 1997 12:49:06 +1030 (CST) From: Michael Smith Message-Id: <199702240219.MAA04053@genesis.atrad.adelaide.edu.au> Subject: Re: Device driver cookbook. In-Reply-To: from patrick collins at "Feb 24, 97 10:58:14 am" To: pc012@seqeb.gov.au (patrick collins) Date: Mon, 24 Feb 1997 12:49:04 +1030 (CST) Cc: mcgovern@spoon.beta.com, 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 patrick collins stands accused of saying: > > I am particularly interested in writing a device driver for a > digital I/O card I have. This card consists of a couple of 8255 PIO's. I > would like my device driver to be able to configure one 8255 for input > and the other for output. I would like the device driver to be able to > read the inputs every n milliseconds in order to be able to count a 2 Hz > pulse train on these inputs. > > I have a fairly general idea on how to go about this but would appreciate > any pointers you might have, especially in the area of how to get the device > driver to continually read the input ports without the intervention of the > application software. You want a polling routine that looks something like this : void zog_poller(void *what) { zog_softc *sc = (zog_softc *)what; static int initted = 0; u_char curr; int bit; /* get port value */ curr = inb(sc->base + PORTA); /* have valid state? */ if (initted) { /* check bits */ for (bit = 0; bit < 8; bit++) { /* bit is set, and was clear? */ if ((curr & (1<state & (1<count[bit]++; } } } sc->state = curr; /* update state */ initted = 1; /* definitely initted now */ timeout(zog_poller, what, hz/ZOG_TIMEOUT); } Then you can start the poller when you want with timeout(zog_poller, sc, hz/ZOG_TIMEOUT); where 'sc' is the softc structure for the device in question. The last argument to timeout() is the number of timer ticks between invocations of the routine; 'hz' is the number of ticks per second. In the above example if your pulse train is coming in every two seconds, you'd want to sample at least four times per second (ZOG_TIMEOUT = 4), but you might want to sample faster to compensate for possible periods where interrupt activity makes you lag. You might want to do this in your open routine. You can kill the timeout routine with untimeout(zog_poller, sc)l for eg. in your close() routine. Then you could write a read() handler that uses printf() into a buffer to return the current counter values, or you could just copy them out to the caller as-is. > Patrick Collins - Load Survey Technician email : pc012@seqeb.gov.au -- ]] 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 [[