/drivers/staging/comedi/drivers/dmm32at.c
C | 1081 lines | 644 code | 168 blank | 269 comment | 149 complexity | 0b13c4be6207851859d9461c3a825d65 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- comedi/drivers/dmm32at.c
- Diamond Systems mm32at code for a Comedi driver
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /*
- Driver: dmm32at
- Description: Diamond Systems mm32at driver.
- Devices:
- Author: Perry J. Piplani <perry.j.piplani@nasa.gov>
- Updated: Fri Jun 4 09:13:24 CDT 2004
- Status: experimental
- This driver is for the Diamond Systems MM-32-AT board
- http://www.diamondsystems.com/products/diamondmm32at It is being used
- on serveral projects inside NASA, without problems so far. For analog
- input commands, TRIG_EXT is not yet supported at all..
- Configuration Options:
- comedi_config /dev/comedi0 dmm32at baseaddr,irq
- */
- #include <linux/interrupt.h>
- #include "../comedidev.h"
- #include <linux/ioport.h>
- /* Board register addresses */
- #define DMM32AT_MEMSIZE 0x10
- #define DMM32AT_CONV 0x00
- #define DMM32AT_AILSB 0x00
- #define DMM32AT_AUXDOUT 0x01
- #define DMM32AT_AIMSB 0x01
- #define DMM32AT_AILOW 0x02
- #define DMM32AT_AIHIGH 0x03
- #define DMM32AT_DACLSB 0x04
- #define DMM32AT_DACSTAT 0x04
- #define DMM32AT_DACMSB 0x05
- #define DMM32AT_FIFOCNTRL 0x07
- #define DMM32AT_FIFOSTAT 0x07
- #define DMM32AT_CNTRL 0x08
- #define DMM32AT_AISTAT 0x08
- #define DMM32AT_INTCLOCK 0x09
- #define DMM32AT_CNTRDIO 0x0a
- #define DMM32AT_AICONF 0x0b
- #define DMM32AT_AIRBACK 0x0b
- #define DMM32AT_CLK1 0x0d
- #define DMM32AT_CLK2 0x0e
- #define DMM32AT_CLKCT 0x0f
- #define DMM32AT_DIOA 0x0c
- #define DMM32AT_DIOB 0x0d
- #define DMM32AT_DIOC 0x0e
- #define DMM32AT_DIOCONF 0x0f
- #define dmm_inb(cdev, reg) inb((cdev->iobase)+reg)
- #define dmm_outb(cdev, reg, valu) outb(valu, (cdev->iobase)+reg)
- /* Board register values. */
- /* DMM32AT_DACSTAT 0x04 */
- #define DMM32AT_DACBUSY 0x80
- /* DMM32AT_FIFOCNTRL 0x07 */
- #define DMM32AT_FIFORESET 0x02
- #define DMM32AT_SCANENABLE 0x04
- /* DMM32AT_CNTRL 0x08 */
- #define DMM32AT_RESET 0x20
- #define DMM32AT_INTRESET 0x08
- #define DMM32AT_CLKACC 0x00
- #define DMM32AT_DIOACC 0x01
- /* DMM32AT_AISTAT 0x08 */
- #define DMM32AT_STATUS 0x80
- /* DMM32AT_INTCLOCK 0x09 */
- #define DMM32AT_ADINT 0x80
- #define DMM32AT_CLKSEL 0x03
- /* DMM32AT_CNTRDIO 0x0a */
- #define DMM32AT_FREQ12 0x80
- /* DMM32AT_AICONF 0x0b */
- #define DMM32AT_RANGE_U10 0x0c
- #define DMM32AT_RANGE_U5 0x0d
- #define DMM32AT_RANGE_B10 0x08
- #define DMM32AT_RANGE_B5 0x00
- #define DMM32AT_SCINT_20 0x00
- #define DMM32AT_SCINT_15 0x10
- #define DMM32AT_SCINT_10 0x20
- #define DMM32AT_SCINT_5 0x30
- /* DMM32AT_CLKCT 0x0f */
- #define DMM32AT_CLKCT1 0x56 /* mode3 counter 1 - write low byte only */
- #define DMM32AT_CLKCT2 0xb6 /* mode3 counter 2 - write high and low byte */
- /* DMM32AT_DIOCONF 0x0f */
- #define DMM32AT_DIENABLE 0x80
- #define DMM32AT_DIRA 0x10
- #define DMM32AT_DIRB 0x02
- #define DMM32AT_DIRCL 0x01
- #define DMM32AT_DIRCH 0x08
- /* board AI ranges in comedi structure */
- static const struct comedi_lrange dmm32at_airanges = {
- 4,
- {
- UNI_RANGE(10),
- UNI_RANGE(5),
- BIP_RANGE(10),
- BIP_RANGE(5),
- }
- };
- /* register values for above ranges */
- static const unsigned char dmm32at_rangebits[] = {
- DMM32AT_RANGE_U10,
- DMM32AT_RANGE_U5,
- DMM32AT_RANGE_B10,
- DMM32AT_RANGE_B5,
- };
- /* only one of these ranges is valid, as set by a jumper on the
- * board. The application should only use the range set by the jumper
- */
- static const struct comedi_lrange dmm32at_aoranges = {
- 4,
- {
- UNI_RANGE(10),
- UNI_RANGE(5),
- BIP_RANGE(10),
- BIP_RANGE(5),
- }
- };
- /*
- * Board descriptions for two imaginary boards. Describing the
- * boards in this way is optional, and completely driver-dependent.
- * Some drivers use arrays such as this, other do not.
- */
- struct dmm32at_board {
- const char *name;
- int ai_chans;
- int ai_bits;
- const struct comedi_lrange *ai_ranges;
- int ao_chans;
- int ao_bits;
- const struct comedi_lrange *ao_ranges;
- int have_dio;
- int dio_chans;
- };
- static const struct dmm32at_board dmm32at_boards[] = {
- {
- .name = "dmm32at",
- .ai_chans = 32,
- .ai_bits = 16,
- .ai_ranges = &dmm32at_airanges,
- .ao_chans = 4,
- .ao_bits = 12,
- .ao_ranges = &dmm32at_aoranges,
- .have_dio = 1,
- .dio_chans = 24,
- },
- };
- /*
- * Useful for shorthand access to the particular board structure
- */
- #define thisboard ((const struct dmm32at_board *)dev->board_ptr)
- /* this structure is for data unique to this hardware driver. If
- * several hardware drivers keep similar information in this structure,
- * feel free to suggest moving the variable to the struct comedi_device struct.
- */
- struct dmm32at_private {
- int data;
- int ai_inuse;
- unsigned int ai_scans_left;
- /* Used for AO readback */
- unsigned int ao_readback[4];
- unsigned char dio_config;
- };
- /*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
- #define devpriv ((struct dmm32at_private *)dev->private)
- /*
- * The struct comedi_driver structure tells the Comedi core module
- * which functions to call to configure/deconfigure (attach/detach)
- * the board, and also about the kernel module that contains
- * the device code.
- */
- static int dmm32at_attach(struct comedi_device *dev,
- struct comedi_devconfig *it);
- static int dmm32at_detach(struct comedi_device *dev);
- static struct comedi_driver driver_dmm32at = {
- .driver_name = "dmm32at",
- .module = THIS_MODULE,
- .attach = dmm32at_attach,
- .detach = dmm32at_detach,
- /* It is not necessary to implement the following members if you are
- * writing a driver for a ISA PnP or PCI card */
- /* Most drivers will support multiple types of boards by
- * having an array of board structures. These were defined
- * in dmm32at_boards[] above. Note that the element 'name'
- * was first in the structure -- Comedi uses this fact to
- * extract the name of the board without knowing any details
- * about the structure except for its length.
- * When a device is attached (by comedi_config), the name
- * of the device is given to Comedi, and Comedi tries to
- * match it by going through the list of board names. If
- * there is a match, the address of the pointer is put
- * into dev->board_ptr and driver->attach() is called.
- *
- * Note that these are not necessary if you can determine