6.3. Board-specific functionality
Prev | 6. Writing a Comedi driver | Next

### 6.3. Board-specific functionality

The `comedi/drivers` subdirectory contains the board-specific device driver code. Each new card must get an entry in this directory. Or extend the functionality of an already existing driver file if the new card is quite similar to that implemented in an already existing driver. For example, many of the National Instruments DAQ cards use the same driver files.

To help device driver writers, Comedi provides the “skeleton” of a new device driver, in the `comedi/drivers/skel.c` file. Before starting to write a new driver, make sure you understand this file, and compare it to what you find in the other already available board-specific files in the same directory.

The first thing you notice in `skel.c` is the documentation section: the Comedi documentation is partially generated automatically, from the information that is given in this section. So, please comply with the structure and the keywords provided as Comedi standards.

The second part of the device driver contains board-specific static data structure and defines: addresses of hardware registers; defines and function prototypes for functionality that is only used inside of the device driver for this board; the encoding of the types and number of available channels; PCI information; etc.

Each driver has to register two functions which are called when you load and unload your board's device driver (typically via a kernel module):

      mydriver_attach();
      mydriver_detach();

In the “attach” function, memory is allocated for the necessary data structures, all properties of a device and its subdevices are defined, and filled in in the generic Comedi data structures. As part of this, pointers to the low level instructions being supported by the subdevice have to be set, which define the basic functionality. In somewhat more detail, the `mydriver_attach` function must:

- 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.

- allocate memory for the private data structures.

- initialize the board registers and possible subdevices (timer, DMA, PCI, hardware FIFO, etc.).

- return `1`, indicating success. If there were any errors along the way, you should return the appropriate (negative) error number. If an error is returned, the `mydriver_detach` function is called. The `mydriver_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 `mydriver_detach`.

- If the driver has the possibility to offer asynchronous data acquisition, you have to code an interrupt service routine, event handling routines, and/or callback routines.

Typically, you will be able to implement most of the above-mentioned functionality by cut-and-paste from already existing drivers. The `mydriver_attach` function needs most of your attention, because it must correctly define and allocate the (private and generic) data structures that are needed for this device. That is, each sub-device and each channel must get appropriate data fields, and an appropriate initialization. The good news, of course, is that Comedi provides the data structures and the defines that fit very well with almost all DAQ functionalities found on interface cards. These can be found in the header files of the `include/linux/` directory.

Drivers with digital I/O subdevices should implement the following functions, setting the function pointers in the comedi_subdevice:

- `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.

Finally, the device driver writer must implement the `insn_read` and `insn_write` functions for the analog channels on the card:

- `insn_read`: acquire the inputs on the board and transfer them to the software buffer of the driver.

- `insn_write`: transfer data from the software buffer to the card, and execute the appropriate output conversions.

In some drivers, you want to catch interrupts, and/or want to use the `INSN_INTTRIG` instruction. In this case, you must provide and register these callback functions.

Implementation of all of the above-mentioned functions requires perfect knowledge about the hardware registers and addresses of the interface card. In general, you can find some inspiration in the already available device drivers, but don't trust that blind cut-and-paste will bring you far…

Prev | Up | Next
6.2. Generic functionality | Home | 6.4. Callbacks, events and interrupts