From 12d6dd6d1b1190a14cbbf1bd9d1cf46614d47593 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Mon, 20 Aug 2001 00:49:11 +0000 Subject: [PATCH] Updates from Robert Schwebel. I also deleted a bunch of obsolete stuff and rewrote a few bits that were only moderately wrong. --- Documentation/comedi/Hardware_Driver.HOWTO | 279 ++++++++++----------- 1 file changed, 126 insertions(+), 153 deletions(-) diff --git a/Documentation/comedi/Hardware_Driver.HOWTO b/Documentation/comedi/Hardware_Driver.HOWTO index 544a8dc2..4e7a1966 100644 --- a/Documentation/comedi/Hardware_Driver.HOWTO +++ b/Documentation/comedi/Hardware_Driver.HOWTO @@ -1,181 +1,155 @@ - Hardware driver interface - +========================= [ this is a little outdated -ds ] [ this is a lot outdated -fmh ] +[ this is a little bit less outdated, hopefully -rs ] + + +Table of Contents +================= + +1. Introduction +2. The source tree +3. Adding new drivers +4. Driver basics +5. Instructions + + 1. Introduction -This comedi hardware driver writing HOWTO is written to help you -write a driver for your particular choice of hardware. You should -be familiar with how comedi works from the user's point of view, -i.e., from a process that is utilizing the comedi driver. +This comedi hardware driver writing HOWTO is written to help you write a +driver for your particular choice of hardware. You should be familiar with +how comedi works from the user's point of view, i.e., from a process that is +utilizing the comedi driver. + +This guide does not explain the details of things like reading and writing +I/O ports, Linux kernel internals, or interrupt processing. These issues are +covered in other documents, e.g. + +- The IO-Port Programming Mini HOWTO: + http://www.linuxdoc.org/HOWTO/mini/IO-Port-Programming.html + +- Linux Kernel Module Programming Guide + http://www.linuxdoc.org/LDP/lkmpg/mpg.html + +- Kernel Hacker's Guide + http://www.linuxdoc.org/LDP/khg/HyperNews/get/khg.html + +- The Linux source + -This guide does not explain the details of things like reading -and writing I/O ports, Linux kernel internals, or interrupt -processing. These issues are covered in other documents, -specifically, the IO-Port-Programming mini-HOWTO, the Kernel -Hacker's Guide, and the Linux source. 2. The source tree -As of comedi-0.5.0, hardware drivers need to be part of the -source tree and be compiled with the rest of the comedi driver -into the module comedi.o. Later versions will hopefully support -separate compiling/separate modules, etc. +Currently hardware drivers need to be part of the source tree and be +compiled with the rest of the comedi driver into the module comedi.o. Later +versions will hopefully support separate compiling/separate modules, etc. + +The source for the comedi module is located in the 'comedi/' directory, +including the device independent part. The source files of the hardware +drivers for the different boards are located in 'comedi/drivers/', the +kernel space library (which is used for accessing comedi from realtime +programs) lives in 'comedi/kcomedilib/'. + +In the drivers' directory there is a striped-down example ('skel.c') that +may be a good starting point for new hardware drivers. + + + -The source for the comedi module is located in module/, including -the device independent part and each hardware driver. A hardware -driver, such as the "dt282x" driver, is typically located in the -C source file of the same name. +3. Adding new drivers -The hardware driver "dummy" is a stripped-down example that may be -a good starting point for new hardware drivers. +The best way to write a new driver is to take one of the existing ones (e.g. +the 'skel' driver) and modify it to your own needs. For integrating new +drivers in the comedi source tree the following things have to be done: +- Put your new driver into 'comedi/drivers/mydriver.c'. +- Edit 'comedi/Config.in' and add a new 'dep_tristate' line (look at the + other examples). Invent a senseful name for the driver's variable. +- Add a line to 'comedi/drivers/Makefile', using your freshly defined + variable. -3. comedi_config and *_init() +Now 'make distclean', reconfigure comedi with a new 'make', rebuild and be +happy. If you want to have your driver included in the comedi distribution +(you _definitely_ want to :) ) send it to David Schleef for +review and integration. -The file "module/comeditypes.c" has a list of the initialization -functions for all the drivers. You should add your init function -to this list. The top level Makefile and scripts/configure -take care of all the defines. -The purpose of comeditypes.c is to keep a list of available -hardware drivers by keeping a list of available initialization -functions. Thus, when comedi_config is run, it issues the -COMEDI_CONFIG ioctl() with the name of the driver and -configuration parameters (I/O port address, irq, dma, etc.). -The comedi driver then calls the initialization function of -each hardware driver on the list. -Inside the initialization function, you should perform the -following tasks: - o Check to see if you are the correct hardware driver - for the name specified in the comedi_devconfig structure. - Your hardware driver may consider several names as - "correct", and even behave differently depending on - the name given. The idea here is to support different - cards in a series using different names, but using the - same hardware driver. If you are not the correct - hardware driver, return a 0. +4. Driver basics - o Announce that the hardware driver has begun initialization - by a printk("comedi%d: driver: ",minor); +Implementation details for the following things can be found in the skel +driver. Each driver has to register two functions which are called when you +configure and deconfigure your board: - o Check and request the I/O port region, IRQ, DMA, and other - hardware resources. It is convenient here if you verify the - existence of the hardware and the correctness of the other - information given. Sometimes, unfortunately, this cannot - be done. +- mydriver_attach() +- mydriver_detach() + +In the 'attach' function all properties of a device and its subdevices are +defined. As part of this pointers to the low level instructions being +supported by the subdevice have to be set (see next section) which define +the basic functionality. + + + +5. Instructions + +Instructions (insns) are comedi's low level functins for accessing all kinds +of channels, like analog or digital IOs. + +Drivers for digital IOs should implement the following functions: + +- insn_bits(): + Drivers set this if they have a function that supports reading and writing + multiple bits in a digital I/O subdevice at the same time. Most (if not + all) of the drivers use this interface instead of insn_read and insn_write + for DIO subdevices. + +- insn_config(): + Implements INSN_CONFIG instructions. Currently used for configuring the + direction of digital I/O lines, although will eventually be used for + generic configuration of drivers that is outside the scope of the + currently defined Comedi interface. + +Drivers for analog IOs should implement these function: + +- insn_read(): + Analog inputs have to implement insn_read. + +- insn_write(): + The same with insn_write. + + +[THIS SEEMS TO BE OBSOLETE??? -rs] ------------------------------------------- + +Inside the initialization function, you should perform the following tasks: + + o Announce that the hardware driver has begun initialization by a + printk("comedi%d: driver: ",minor); + + o Check and request the I/O port region, IRQ, DMA, and other hardware + resources. It is convenient here if you verify the existence of the + hardware and the correctness of the other information given. + Sometimes, unfortunately, this cannot be done. o Fill in the comedi_device structure. - o Allocate your private data structure and space for channel - configuration. - - o Configure each channel. Each channel has three function - pointers: one for triggering a single conversion (itrig), - one for triggering general conversions (trig), and one - for setting channel parameters (sp). Each channel also has - a parameter linked list. - Parameters are added to this list via addparam(). All the - parameter routines are in param.c. They are currently not - very efficient, so if you know of a better algorithm... - Look at the header files for parameter types that you may - wish to include. - - o Initialize the read buffer via comedi_initbuf(). The buffering - routines are in buffer.c, and support multiple processes - reading the same device. The buffers are also dynamic, so - you don't have to worry about the hardware driver collecting - 1M of data before the controlling process reads it. I've been - using these routines for a while--they appear to be pretty - stable. Most of the error messages you get from the buffer - routines indicate memory leaks. - - o Set mtrig in the comedi_device structure to the function that - is called for a channel scan trigger. - - o Tell the comedi driver the function to call when your driver - needs to be removed. - - o Return a 1. If there were any errors along the way, you - should return the appropriate error number, but don't forget - to release any resources that you allocated. (It will only - take one time to realize that if you don't release an I/O region, - you have to reboot to get it back. (Or write a hack, as I did.)) - - -4. Set Parameter routines - -When the COMEDI_SETPARAM ioctl() is called, the comedi driver -calls the setparameter routine of the channel involved. Common -settable parameters are input gain (input range) and setting bits -on digital I/O lines as input or output. The setparameter -function should check the validity of the parameter type and -value, and then call changeparam() to update the parameter -linked lists. If necessary, calls to update the hardware -should be made. - - -5. Triggering routines - -Like the setparameter routines, each channel has a trigger -function that is called for a COMEDI_TRIG ioctl(). The trigger -function is called with the comedi_trig structure, which -includes the trigger type, number of samples, and one sample value -(which may be read or written, depending on context). - -As of 0.5.0, there are two triggering routines per channel, one -for TRIGNOW, and one for all the rest. The reason this was done -is because the TRIGNOW functions are exported to the rest of the -kernel (i.e., for RTLinux). - -Trigger types are accompanied by the trigger variable, which -is interpreted based on the trigger type. The types of triggers -(currently) available are: - - o COMEDI_TRIGNOW - causes one sample conversion to be - completed immediately. The trigger variable and number of - samples are ignored. - - o COMEDI_TRIGCLK - causes conversions timed by a clock on - the hardware. The trigger variable determines the clock - speed. - - o COMEDI_TRIGEXT - causes conversions to be triggered by - an external trigger provided by the hardware. The trigger - variable determines the particular choice, if there is - more than one choice. - -Other trigger sources that may be defined in the future are -analog triggers and comedi triggers. Comedi triggers could include -the 100 Hz interrupt, the rtc interrupt, general timing triggers, -signals generated by other boards, etc. - -Except for COMEDI_TRIGNOW, your triggering routine should return -after telling the hardware to perform the requested task. For -COMEDI_TRIGNOW on input, you should wait for the conversion to -finish and return it in the ioctl structure, but do *NOT* report -the sample via report_sample(). - -Typically, you will poll the hardware or the hardware will -generate interrupts to tell you when samples are ready. The -samples should be reported via report_sample(). - - -6. The remove function - -A driver is removed from service via a call to dev->rem(). The driver -is expected to halt all conversions, put the hardware in a sane, -off-line state, delete all channel parameters, free all allocated memory, -and release any irq's and port addresses held. If these things are -not all done, there will be memory leaks, and more importantly, the -driver will not configure properly if reused. + o Allocate your private data structure and subdevices. + + o Set up each subdevice. + + o Return 0, indicating sucess. If there were any errors along + the way, you should return the appropriate error number. If + an error is returned, the _detach function is called. The + _detach function should check any resources that may have been + allocated and release them as necessary. The comedi core frees + dev->subdevices and dev->private, so this does not need to be + done in _detach. A. Goals @@ -204,4 +178,3 @@ A few things to strive for: - -- 2.26.2