From owner-freebsd-hackers@FreeBSD.ORG Wed Nov 21 11:44:18 2007 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E1DDA16A419 for ; Wed, 21 Nov 2007 11:44:18 +0000 (UTC) (envelope-from Danovitsch@vitsch.net) Received: from VM01.Vitsch.net (vm01.vitsch.net [85.17.51.140]) by mx1.freebsd.org (Postfix) with ESMTP id 7794613C447 for ; Wed, 21 Nov 2007 11:44:18 +0000 (UTC) (envelope-from Danovitsch@vitsch.net) Received: from Tuinhuisje.Vitsch.net ([217.166.176.2]) by VM01.Vitsch.net (8.13.8/8.13.8) with ESMTP id lALBimA2061332; Wed, 21 Nov 2007 12:44:48 +0100 (CET) (envelope-from Danovitsch@vitsch.net) Received: from [192.168.72.10] (81-171-30-78.dsl.fiberworld.nl [81.171.30.78] (may be forged)) (authenticated bits=0) by Tuinhuisje.Vitsch.net (8.13.1/8.13.1) with ESMTP id lALBhwJH037492; Wed, 21 Nov 2007 12:43:59 +0100 (CET) (envelope-from Danovitsch@vitsch.net) From: "Daan Vreeken [PA4DAN]" Organization: Vitsch Electronics To: Michiel Overtoom Date: Wed, 21 Nov 2007 12:43:49 +0100 User-Agent: KMail/1.9.7 References: <200711200051.45420.michiel@motoom.org> In-Reply-To: <200711200051.45420.michiel@motoom.org> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200711211243.49878.Danovitsch@vitsch.net> Cc: freebsd-hackers@freebsd.org Subject: Re: Hooking a kernelmodule-function into a timer interrupt X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Nov 2007 11:44:19 -0000 Hi Michiel, On Tuesday 20 November 2007 00:51:45 Michiel Overtoom wrote: > I'm interfacing an analog-digital converter to the parallel port and I'm > able to make it work from userland using the ppio driver. But now I want > to move the conversion software into a loadable kernel module, and have the > conversion routine called many times per second, for example 1000 times per > second. If would be nice if it gets called at the kern.clockrate. I have > no clear idea how to proceed, I suspect I have to install a pointer to my > conversion function into some list of functions which get called each clock > tick, but I don't know where, or how. Any tips would be very welcome. > > Some more background info: the chip is a ADC08031, hooked up directly to > some input and output pins on the parallel port. The ADC has a serial > output, and I use one pin on the parport to clock it. I want to have the > clocking code executed in some low level timer interrupt handler. I > inserted some test code into 'hardclock()' in 'kern_clock.c' to toggle a > bit on the parport, which worked nicely: it got called 1000 times per > second, which I could actually verify with a frequency meter hooked up to > the parport; but stuffing the conversion software directly into > kern_clock.c would not be an elegant solution. Next you're going to tell us you desperately need the FPU in your control loop ;-) I have done exactly the same as you propose some time ago, but I'm using a (Humusoft) PCI board with ADCs/DACs. To be able to load control loops from a kernel module I've done the following : In kern/kern_clock.c I've added : typedef void (*control_loop_t)(void *arg); static void *control_arg; static control_loop_t control_loop = NULL; And later on inside hardclock() I've added : if (control_loop != NULL) { control_loop(control_arg); } This gives you a variable "control_loop" and "control_arg" that you can fill in from your kernel module. "control_arg" is an optional argument that gets passed to the function. I use it to transfer a pointer to my driver's softc structure to the control loop. In the kernel module you define : typedef void (*control_loop_t)(void *arg); extern void *control_arg; extern control_loop_t control_loop; Then in your attach or module load function your attach your control function : control_arg = sc; control_loop = &loop_func; Make sure you fill in the argument first as your function could be called the very instruction after you fill in the function pointer. On detach or module unload you simply disable your control loop with : control_loop = NULL; My control function looks like this : void loop_func(void *arg) { struct softc *card = (struct softc *)arg; // do something usefull } ps: Suc6 met software schrijven ;-) -- Daan