dmm32at.c revision 34c43922e62708d45e9660eee4b4f1fb7b4bf2c7
13c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
23c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    comedi/drivers/dmm32at.c
33c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    Diamond Systems mm32at code for a Comedi driver
43c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
53c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    COMEDI - Linux Control and Measurement Device Interface
63c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
73c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
83c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    This program is free software; you can redistribute it and/or modify
93c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    it under the terms of the GNU General Public License as published by
103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    the Free Software Foundation; either version 2 of the License, or
113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    (at your option) any later version.
123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    This program is distributed in the hope that it will be useful,
143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    but WITHOUT ANY WARRANTY; without even the implied warranty of
153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    GNU General Public License for more details.
173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    You should have received a copy of the GNU General Public License
193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    along with this program; if not, write to the Free Software
203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani*/
233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniDriver: dmm32at
253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniDescription: Diamond Systems mm32at driver.
263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniDevices:
273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniAuthor: Perry J. Piplani <perry.j.piplani@nasa.gov>
283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniUpdated: Fri Jun  4 09:13:24 CDT 2004
293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniStatus: experimental
303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniThis driver is for the Diamond Systems MM-32-AT board
323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanihttp://www.diamondsystems.com/products/diamondmm32at It is being used
333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanion serveral projects inside NASA, without problems so far. For analog
343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplaniinput commands, TRIG_EXT is not yet supported at all..
353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniConfiguration Options:
373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani  comedi_config /dev/comedi0 dmm32at baseaddr,irq
383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani*/
393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * The previous block comment is used to automatically generate
423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * documentation in Comedi and Comedilib.  The fields:
433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *
443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Driver: the name of the driver
453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Description: a short phrase describing the driver.  Don't list boards.
463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Devices: a full list of the boards that attempt to be supported by
473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   the driver.  Format is "(manufacturer) board name [comedi name]",
483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   where comedi_name is the name that is used to configure the board.
493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   See the comment near board_name: in the comedi_driver structure
503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   below.  If (manufacturer) or [comedi name] is missing, the previous
513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   value is used.
523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Author: you
533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Updated: date when the _documentation_ was last updated.  Use 'date -R'
543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   to get a value for this.
553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Status: a one-word description of the status.  Valid values are:
563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   works - driver works correctly on most boards supported, and
573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *     passes comedi_test.
583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   unknown - unknown.  Usually put there by ds.
593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   experimental - may not work in any particular release.  Author
603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *     probably wants assistance testing it.
613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   bitrotten - driver has not been update in a long time, probably
623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *     doesn't work, and probably is missing support for significant
633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *     Comedi interface features.
643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *   untested - author probably wrote it "blind", and is believed to
653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *     work, but no confirmation.
663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *
673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * These headers should be followed by a blank line, and any comments
683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * you wish to say about the driver.  The comment area is the place
693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * to put any known bugs, limitations, unsupported features, supported
703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * command triggers, whether or not commands are supported on particular
713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * subdevices, etc.
723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *
733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Somewhere in the comment should be information about configuration
743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * options that are used with comedi_config.
753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#include "../comedidev.h"
783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#include <linux/ioport.h>
793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* Board register addresses */
813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_MEMSIZE 0x10
833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CONV 0x00
853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AILSB 0x00
863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AUXDOUT 0x01
873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AIMSB 0x01
883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AILOW 0x02
893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AIHIGH 0x03
903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DACLSB 0x04
923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DACSTAT 0x04
933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DACMSB 0x05
943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FIFOCNTRL 0x07
963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FIFOSTAT 0x07
973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CNTRL 0x08
993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AISTAT 0x08
1003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_INTCLOCK 0x09
1023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CNTRDIO 0x0a
1043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AICONF 0x0b
1063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AIRBACK 0x0b
1073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLK1 0x0d
1093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLK2 0x0e
1103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKCT 0x0f
1113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOA 0x0c
1133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOB 0x0d
1143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOC 0x0e
1153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOCONF 0x0f
1163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define dmm_inb(cdev,reg) inb((cdev->iobase)+reg)
1183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define dmm_outb(cdev,reg,valu) outb(valu,(cdev->iobase)+reg)
1193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* Board register values. */
1213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_DACSTAT 0x04 */
1233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DACBUSY 0x80
1243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_FIFOCNTRL 0x07 */
1263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FIFORESET 0x02
1273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCANENABLE 0x04
1283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_CNTRL 0x08 */
1303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RESET 0x20
1313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_INTRESET 0x08
1323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKACC 0x00
1333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOACC 0x01
1343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_AISTAT 0x08 */
1363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_STATUS 0x80
1373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_INTCLOCK 0x09 */
1393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_ADINT 0x80
1403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKSEL 0x03
1413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_CNTRDIO 0x0a */
1433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FREQ12 0x80
1443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_AICONF 0x0b */
1463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_U10 0x0c
1473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_U5 0x0d
1483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_B10 0x08
1493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_B5 0x00
1503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_20 0x00
1513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_15 0x10
1523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_10 0x20
1533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_5 0x30
1543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_CLKCT 0x0f */
1563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKCT1 0x56	/* mode3 counter 1 - write low byte only */
1573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKCT2 0xb6	/*  mode3 counter 2 - write high and low byte */
1583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_DIOCONF 0x0f */
1603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIENABLE 0x80
1613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRA 0x10
1623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRB 0x02
1633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRCL 0x01
1643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRCH 0x08
1653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* board AI ranges in comedi structure */
1673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic const comedi_lrange dmm32at_airanges = {
1683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	4,
1693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	{
1703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			UNI_RANGE(10),
1713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			UNI_RANGE(5),
1723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			BIP_RANGE(10),
1733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			BIP_RANGE(5),
1743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
1753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
1763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* register values for above ranges */
1783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic const unsigned char dmm32at_rangebits[] = {
1793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_U10,
1803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_U5,
1813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_B10,
1823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_B5,
1833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
1843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* only one of these ranges is valid, as set by a jumper on the
1863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * board. The application should only use the range set by the jumper
1873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
1883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic const comedi_lrange dmm32at_aoranges = {
1893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	4,
1903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	{
1913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			UNI_RANGE(10),
1923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			UNI_RANGE(5),
1933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			BIP_RANGE(10),
1943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			BIP_RANGE(5),
1953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
1963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
1973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
1993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Board descriptions for two imaginary boards.  Describing the
2003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * boards in this way is optional, and completely driver-dependent.
2013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Some drivers use arrays such as this, other do not.
2023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
2033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanitypedef struct dmm32at_board_struct {
2043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	const char *name;
2053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int ai_chans;
2063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int ai_bits;
2073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	const comedi_lrange *ai_ranges;
2083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int ao_chans;
2093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int ao_bits;
2103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	const comedi_lrange *ao_ranges;
2113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int have_dio;
2123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int dio_chans;
2133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani} dmm32at_board;
2143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic const dmm32at_board dmm32at_boards[] = {
2153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	{
2163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      name:	"dmm32at",
2173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      ai_chans:32,
2183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      ai_bits:	16,
2193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      ai_ranges:&dmm32at_airanges,
2203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      ao_chans:4,
2213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      ao_bits:	12,
2223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      ao_ranges:&dmm32at_aoranges,
2233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      have_dio:1,
2243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	      dio_chans:24,
2253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		},
2263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
2273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
2293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Useful for shorthand access to the particular board structure
2303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
2313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define thisboard ((const dmm32at_board *)dev->board_ptr)
2323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* this structure is for data unique to this hardware driver.  If
2343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * several hardware drivers keep similar information in this structure,
23571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton * feel free to suggest moving the variable to the struct comedi_device struct.
2363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
2373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanitypedef struct {
2383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int data;
2403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int ai_inuse;
2413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned int ai_scans_left;
2423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* Used for AO readback */
244790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int ao_readback[4];
2453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char dio_config;
2463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani} dmm32at_private;
2483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
2503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * most drivers define the following macro to make it easy to
2513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * access the private structure.
2523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
2533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define devpriv ((dmm32at_private *)dev->private)
2543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
2563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * The comedi_driver structure tells the Comedi core module
2573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * which functions to call to configure/deconfigure (attach/detach)
2583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * the board, and also about the kernel module that contains
2593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * the device code.
2603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
26171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it);
26271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dmm32at_detach(struct comedi_device * dev);
2633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic comedi_driver driver_dmm32at = {
2643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani      driver_name:"dmm32at",
2653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani      module:THIS_MODULE,
2663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani      attach:dmm32at_attach,
2673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani      detach:dmm32at_detach,
2683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* It is not necessary to implement the following members if you are
2693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * writing a driver for a ISA PnP or PCI card */
2703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* Most drivers will support multiple types of boards by
2713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * having an array of board structures.  These were defined
2723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * in dmm32at_boards[] above.  Note that the element 'name'
2733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * was first in the structure -- Comedi uses this fact to
2743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * extract the name of the board without knowing any details
2753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * about the structure except for its length.
2763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * When a device is attached (by comedi_config), the name
2773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * of the device is given to Comedi, and Comedi tries to
2783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * match it by going through the list of board names.  If
2793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * there is a match, the address of the pointer is put
2803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * into dev->board_ptr and driver->attach() is called.
2813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani *
2823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Note that these are not necessary if you can determine
2833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * the type of board in software.  ISA PnP, PCI, and PCMCIA
2843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * devices are such boards.
2853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
2863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani      board_name:&dmm32at_boards[0].name,
2873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani      offset:sizeof(dmm32at_board),
2883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani      num_names:sizeof(dmm32at_boards) / sizeof(dmm32at_board),
2893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
2903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* prototypes for driver functions below */
29234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
293790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
29434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
295790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
29634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
297790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
29834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
299790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
30034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
301790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data);
30234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
3033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	comedi_cmd * cmd);
30434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
30534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
3063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic int dmm32at_ns_to_timer(unsigned int *ns, int round);
3073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG);
30871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonvoid dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec);
3093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
3113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Attach is called by the Comedi core to configure the driver
3123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * for a particular board.  If you specified a board_name array
3133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * in the driver structure, dev->board_ptr contains that
3143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * address.
3153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
31671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dmm32at_attach(struct comedi_device * dev, comedi_devconfig * it)
3173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
3183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int ret;
31934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
3203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char aihi, ailo, fifostat, aistat, intstat, airback;
3213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned long iobase;
3223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned int irq;
3233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	iobase = it->options[0];
3253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	irq = it->options[1];
3263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	printk("comedi%d: dmm32at: attaching\n", dev->minor);
3283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	printk("dmm32at: probing at address 0x%04lx, irq %u\n", iobase, irq);
3293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* register address space */
3313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!request_region(iobase, DMM32AT_MEMSIZE, thisboard->name)) {
3323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		printk("I/O port conflict\n");
3333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EIO;
3343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
3353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dev->iobase = iobase;
3363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* the following just makes sure the board is there and gets
3383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	   it to a known state */
3393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* reset the board */
3413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_RESET);
3423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* allow a millisecond to reset */
3443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	udelay(1000);
3453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* zero scan and fifo control */
3473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_FIFOCNTRL, 0x0);
3483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* zero interrupt and clock control */
3503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_INTCLOCK, 0x0);
3513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* write a test channel range, the high 3 bits should drop */
3533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AILOW, 0x80);
3543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AIHIGH, 0xff);
3553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the range at 10v unipolar */
3573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AICONF, DMM32AT_RANGE_U10);
3583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* should take 10 us to settle, here's a hundred */
3603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	udelay(100);
3613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* read back the values */
3633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	ailo = dmm_inb(dev, DMM32AT_AILOW);
3643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	aihi = dmm_inb(dev, DMM32AT_AIHIGH);
3653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	fifostat = dmm_inb(dev, DMM32AT_FIFOSTAT);
3663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	aistat = dmm_inb(dev, DMM32AT_AISTAT);
3673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	intstat = dmm_inb(dev, DMM32AT_INTCLOCK);
3683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	airback = dmm_inb(dev, DMM32AT_AIRBACK);
3693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	printk("dmm32at: lo=0x%02x hi=0x%02x fifostat=0x%02x\n",
3713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		ailo, aihi, fifostat);
3723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	printk("dmm32at: aistat=0x%02x intstat=0x%02x airback=0x%02x\n",
3733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		aistat, intstat, airback);
3743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) ||
3763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		(aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) {
3773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		printk("dmmat32: board detection failed\n");
3783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EIO;
3793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
3803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* board is there, register interrupt */
3823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (irq) {
3833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		ret = comedi_request_irq(irq, dmm32at_isr, 0, thisboard->name,
3843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			dev);
3853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (ret < 0) {
3863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			printk("irq conflict\n");
3873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			return ret;
3883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
3893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dev->irq = irq;
3903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
3913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
3933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * If you can probe the device to determine what device in a series
3943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * it is, this is the place to do it.  Otherwise, dev->board_ptr
3953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * should already be initialized.
3963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
3973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	//dev->board_ptr = dmm32at_probe(dev);
3983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
4003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Initialize dev->board_name.  Note that we can use the "thisboard"
4013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * macro now, since we just initialized it in the last line.
4023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
4033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dev->board_name = thisboard->name;
4043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
4063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Allocate the private structure area.  alloc_private() is a
4073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * convenient macro defined in comedidev.h.
4083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
4093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (alloc_private(dev, sizeof(dmm32at_private)) < 0)
4103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -ENOMEM;
4113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
4133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Allocate the subdevice structures.  alloc_subdevice() is a
4143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * convenient macro defined in comedidev.h.
4153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
4163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (alloc_subdevices(dev, 3) < 0)
4173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -ENOMEM;
4183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s = dev->subdevices + 0;
4203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dev->read_subdev = s;
4213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* analog input subdevice */
4223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->type = COMEDI_SUBD_AI;
4233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* we support single-ended (ground) and differential */
4243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
4253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->n_chan = thisboard->ai_chans;
4263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->maxdata = (1 << thisboard->ai_bits) - 1;
4273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->range_table = thisboard->ai_ranges;
4283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->len_chanlist = 32;	/* This is the maximum chanlist length that
4293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				   the board can handle */
4303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->insn_read = dmm32at_ai_rinsn;
4313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->do_cmd = dmm32at_ai_cmd;
4323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->do_cmdtest = dmm32at_ai_cmdtest;
4333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->cancel = dmm32at_ai_cancel;
4343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s = dev->subdevices + 1;
4363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* analog output subdevice */
4373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->type = COMEDI_SUBD_AO;
4383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->subdev_flags = SDF_WRITABLE;
4393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->n_chan = thisboard->ao_chans;
4403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->maxdata = (1 << thisboard->ao_bits) - 1;
4413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->range_table = thisboard->ao_ranges;
4423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->insn_write = dmm32at_ao_winsn;
4433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->insn_read = dmm32at_ao_rinsn;
4443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s = dev->subdevices + 2;
4463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* digital i/o subdevice */
4473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (thisboard->have_dio) {
4483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* get access to the DIO regs */
4503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC);
4513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* set the DIO's to the defualt input setting */
4523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB |
4533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE;
4543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config);
4553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* set up the subdevice */
4573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->type = COMEDI_SUBD_DIO;
4583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
4593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->n_chan = thisboard->dio_chans;
4603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->maxdata = 1;
4613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->state = 0;
4623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->range_table = &range_digital;
4633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->insn_bits = dmm32at_dio_insn_bits;
4643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->insn_config = dmm32at_dio_insn_config;
4653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
4663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->type = COMEDI_SUBD_UNUSED;
4673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
4683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* success */
4703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	printk("comedi%d: dmm32at: attached\n", dev->minor);
4713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 1;
4733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
4753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
4773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * _detach is called to deconfigure a device.  It should deallocate
4783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * resources.
4793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * This function is also called when _attach() fails, so it should be
4803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * careful not to release resources that were not necessarily
4813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * allocated by _attach().  dev->private and dev->subdevices are
4823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * deallocated automatically by the core.
4833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
48471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dmm32at_detach(struct comedi_device * dev)
4853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
4863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	printk("comedi%d: dmm32at: remove\n", dev->minor);
4873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (dev->irq)
4883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		comedi_free_irq(dev->irq, dev);
4893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (dev->iobase)
4903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		release_region(dev->iobase, DMM32AT_MEMSIZE);
4913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 0;
4933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
4943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
4963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * "instructions" read/write data in "one-shot" or "software-triggered"
4973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * mode.
4983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
4993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
50034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
501790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data)
5023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
5033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int n, i;
5043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned int d;
5053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char status;
5063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned short msb, lsb;
5073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char chan;
5083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int range;
5093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get the channel and range number */
5113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	chan = CR_CHAN(insn->chanspec) & (s->n_chan - 1);
5133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	range = CR_RANGE(insn->chanspec);
5143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	//printk("channel=0x%02x, range=%d\n",chan,range);
5163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* zero scan and fifo control and reset fifo */
5183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_FIFORESET);
5193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* write the ai channel range regs */
5213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AILOW, chan);
5223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AIHIGH, chan);
5233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the range bits */
5243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AICONF, dmm32at_rangebits[range]);
5253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* wait for circuit to settle */
5273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	for (i = 0; i < 40000; i++) {
5283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		status = dmm_inb(dev, DMM32AT_AIRBACK);
5293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if ((status & DMM32AT_STATUS) == 0)
5303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			break;
5313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
5323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (i == 40000) {
5333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		printk("timeout\n");
5343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -ETIMEDOUT;
5353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
5363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* convert n samples */
5383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	for (n = 0; n < insn->n; n++) {
5393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* trigger conversion */
5403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_CONV, 0xff);
5413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* wait for conversion to end */
5423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		for (i = 0; i < 40000; i++) {
5433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			status = dmm_inb(dev, DMM32AT_AISTAT);
5443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			if ((status & DMM32AT_STATUS) == 0)
5453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				break;
5463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
5473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (i == 40000) {
5483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			printk("timeout\n");
5493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			return -ETIMEDOUT;
5503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
5513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* read data */
5533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		lsb = dmm_inb(dev, DMM32AT_AILSB);
5543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		msb = dmm_inb(dev, DMM32AT_AIMSB);
5553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* invert sign bit to make range unsigned, this is an
5573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   idiosyncracy of the diamond board, it return
5583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   conversions as a signed value, i.e. -32768 to
5593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   32767, flipping the bit and interpreting it as
5603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   signed gives you a range of 0 to 65535 which is
5613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   used by comedi */
5623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		d = ((msb ^ 0x0080) << 8) + lsb;
5633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		data[n] = d;
5653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
5663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* return the number of samples read/written */
5683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return n;
5693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
5703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
57134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
5723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	comedi_cmd * cmd)
5733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
5743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int err = 0;
5753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int tmp;
5763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int start_chan, gain, i;
5773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	//printk("dmmat32 in command test\n");
5793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* cmdtest tests a particular command to see if it is valid.
5813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * Using the cmdtest ioctl, a user can create a valid cmd
5823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * and then have it executes by the cmd ioctl.
5833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 *
5843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
5853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * the command passes. */
5863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* step 1: make sure trigger sources are trivially valid */
5883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	tmp = cmd->start_src;
5903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	cmd->start_src &= TRIG_NOW;
5913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!cmd->start_src || tmp != cmd->start_src)
5923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
5933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	tmp = cmd->scan_begin_src;
5953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	cmd->scan_begin_src &= TRIG_TIMER /*| TRIG_EXT */ ;
5963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
5973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
5983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	tmp = cmd->convert_src;
6003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	cmd->convert_src &= TRIG_TIMER /*| TRIG_EXT */ ;
6013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!cmd->convert_src || tmp != cmd->convert_src)
6023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	tmp = cmd->scan_end_src;
6053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	cmd->scan_end_src &= TRIG_COUNT;
6063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
6073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	tmp = cmd->stop_src;
6103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
6113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!cmd->stop_src || tmp != cmd->stop_src)
6123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
6153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 1;
6163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* step 2: make sure trigger sources are unique and mutually compatible */
6183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* note that mutual compatiblity is not an issue here */
6203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->scan_begin_src != TRIG_TIMER &&
6213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		cmd->scan_begin_src != TRIG_EXT)
6223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
6243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
6263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
6293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 2;
6303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* step 3: make sure arguments are trivially compatible */
6323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->start_arg != 0) {
6343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		cmd->start_arg = 0;
6353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
6373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define MAX_SCAN_SPEED	1000000	/* in nanoseconds */
6383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define MIN_SCAN_SPEED	1000000000	/* in nanoseconds */
6393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->scan_begin_src == TRIG_TIMER) {
6413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->scan_begin_arg < MAX_SCAN_SPEED) {
6423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->scan_begin_arg = MAX_SCAN_SPEED;
6433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
6443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
6453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->scan_begin_arg > MIN_SCAN_SPEED) {
6463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->scan_begin_arg = MIN_SCAN_SPEED;
6473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
6483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
6493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
6503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* external trigger */
6513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* should be level/edge, hi/lo specification here */
6523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* should specify multiple external triggers */
6533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->scan_begin_arg > 9) {
6543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->scan_begin_arg = 9;
6553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
6563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
6573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
6583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->convert_src == TRIG_TIMER) {
6593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->convert_arg >= 17500)
6603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 20000;
6613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		else if (cmd->convert_arg >= 12500)
6623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 15000;
6633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		else if (cmd->convert_arg >= 7500)
6643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 10000;
6653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		else
6663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 5000;
6673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
6693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* external trigger */
6703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* see above */
6713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->convert_arg > 9) {
6723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 9;
6733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
6743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
6753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
6763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->scan_end_arg != cmd->chanlist_len) {
6783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		cmd->scan_end_arg = cmd->chanlist_len;
6793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		err++;
6803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
6813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->stop_src == TRIG_COUNT) {
6823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->stop_arg > 0xfffffff0) {
6833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->stop_arg = 0xfffffff0;
6843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
6853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
6863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->stop_arg == 0) {
6873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->stop_arg = 1;
6883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
6893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
6903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
6913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* TRIG_NONE */
6923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->stop_arg != 0) {
6933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->stop_arg = 0;
6943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
6953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
6963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
6973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
6993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 3;
7003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* step 4: fix up any arguments */
7023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->scan_begin_src == TRIG_TIMER) {
7043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		tmp = cmd->scan_begin_arg;
7053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm32at_ns_to_timer(&cmd->scan_begin_arg,
7063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->flags & TRIG_ROUND_MASK);
7073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (tmp != cmd->scan_begin_arg)
7083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
7093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
7103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->convert_src == TRIG_TIMER) {
7113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		tmp = cmd->convert_arg;
7123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm32at_ns_to_timer(&cmd->convert_arg,
7133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->flags & TRIG_ROUND_MASK);
7143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (tmp != cmd->convert_arg)
7153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
7163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->scan_begin_src == TRIG_TIMER &&
7173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->scan_begin_arg <
7183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg * cmd->scan_end_arg) {
7193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->scan_begin_arg =
7203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				cmd->convert_arg * cmd->scan_end_arg;
7213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			err++;
7223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
7233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
7243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
7263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 4;
7273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* step 5 check the channel list, the channel list for this
7293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	   board must be consecutive and gains must be the same */
7303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->chanlist) {
7323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		gain = CR_RANGE(cmd->chanlist[0]);
7333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		start_chan = CR_CHAN(cmd->chanlist[0]);
7343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		for (i = 1; i < cmd->chanlist_len; i++) {
7353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			if (CR_CHAN(cmd->chanlist[i]) !=
7363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				(start_chan + i) % s->n_chan) {
7373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				comedi_error(dev,
7383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani					"entries in chanlist must be consecutive channels, counting upwards\n");
7393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				err++;
7403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			}
7413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			if (CR_RANGE(cmd->chanlist[i]) != gain) {
7423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				comedi_error(dev,
7433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani					"entries in chanlist must all have the same gain\n");
7443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				err++;
7453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			}
7463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
7473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
7483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
7503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 5;
7513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 0;
7533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
7543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
75534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
7563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
7573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	comedi_cmd *cmd = &s->async->cmd;
7583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int i, range;
7593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char chanlo, chanhi, status;
7603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!cmd->chanlist)
7623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EINVAL;
7633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get the channel list and range */
7653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	chanlo = CR_CHAN(cmd->chanlist[0]) & (s->n_chan - 1);
7663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	chanhi = chanlo + cmd->chanlist_len - 1;
7673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (chanhi >= s->n_chan)
7683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EINVAL;
7693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	range = CR_RANGE(cmd->chanlist[0]);
7703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* reset fifo */
7723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_FIFORESET);
7733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set scan enable */
7753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_FIFOCNTRL, DMM32AT_SCANENABLE);
7763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* write the ai channel range regs */
7783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AILOW, chanlo);
7793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AIHIGH, chanhi);
7803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the range bits */
7823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_AICONF, dmm32at_rangebits[range]);
7833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* reset the interrupt just in case */
7853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_INTRESET);
7863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->stop_src == TRIG_COUNT)
7883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->ai_scans_left = cmd->stop_arg;
7893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	else {			/* TRIG_NONE */
7903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->ai_scans_left = 0xffffffff;	/* indicates TRIG_NONE to isr */
7913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
7923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
7933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* wait for circuit to settle */
7943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	for (i = 0; i < 40000; i++) {
7953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		status = dmm_inb(dev, DMM32AT_AIRBACK);
7963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if ((status & DMM32AT_STATUS) == 0)
7973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			break;
7983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
7993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (i == 40000) {
8003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		printk("timeout\n");
8013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -ETIMEDOUT;
8023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
8033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (devpriv->ai_scans_left > 1) {
8053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* start the clock and enable the interrupts */
8063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm32at_setaitimer(dev, cmd->scan_begin_arg);
8073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
8083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* start the interrups and initiate a single scan */
8093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT);
8103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_CONV, 0xff);
8113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
8123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* 	printk("dmmat32 in command\n"); */
8143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* 	for(i=0;i<cmd->chanlist_len;i++) */
8163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* 		comedi_buf_put(s->async,i*100); */
8173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* 	s->async->events |= COMEDI_CB_EOA; */
8193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* 	comedi_event(dev, s); */
8203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 0;
8223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
8243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
82534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
8263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
8273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	devpriv->ai_scans_left = 1;
8283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 0;
8293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
8303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic irqreturn_t dmm32at_isr(int irq, void *d PT_REGS_ARG)
8323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
8333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char intstat;
8343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned int samp;
8353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned short msb, lsb;
8363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int i;
83771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
8383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!dev->attached) {
8403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		comedi_error(dev, "spurious interrupt");
8413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return IRQ_HANDLED;
8423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
8433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	intstat = dmm_inb(dev, DMM32AT_INTCLOCK);
8453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (intstat & DMM32AT_ADINT) {
84734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton		struct comedi_subdevice *s = dev->read_subdev;
8483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		comedi_cmd *cmd = &s->async->cmd;
8493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		for (i = 0; i < cmd->chanlist_len; i++) {
8513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			/* read data */
8523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			lsb = dmm_inb(dev, DMM32AT_AILSB);
8533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			msb = dmm_inb(dev, DMM32AT_AIMSB);
8543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			/* invert sign bit to make range unsigned */
8563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			samp = ((msb ^ 0x0080) << 8) + lsb;
8573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			comedi_buf_put(s->async, samp);
8583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
8593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (devpriv->ai_scans_left != 0xffffffff) {	/* TRIG_COUNT */
8613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			devpriv->ai_scans_left--;
8623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			if (devpriv->ai_scans_left == 0) {
8633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				/* disable further interrupts and clocks */
8643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				dmm_outb(dev, DMM32AT_INTCLOCK, 0x0);
8653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				/* set the buffer to be flushed with an EOF */
8663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				s->async->events |= COMEDI_CB_EOA;
8673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			}
8683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
8703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* flush the buffer */
8713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		comedi_event(dev, s);
8723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
8733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* reset the interrupt */
8753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_INTRESET);
8763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return IRQ_HANDLED;
8773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
8783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* This function doesn't require a particular form, this is just
8803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * what happens to be used in some of the drivers.  It should
8813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * convert ns nanoseconds to a counter value suitable for programming
8823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * the device.  Also, it should adjust ns so that it cooresponds to
8833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * the actual time that the device will use. */
8843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic int dmm32at_ns_to_timer(unsigned int *ns, int round)
8853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
8863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* trivial timer */
8873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* if your timing is done through two cascaded timers, the
8883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * i8253_cascade_ns_to_timer() function in 8253.h can be
8893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * very helpful.  There are also i8254_load() and i8254_mm_load()
8903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * which can be used to load values into the ubiquitous 8254 counters
8913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 */
8923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
8933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return *ns;
8943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
8953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
89634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
897790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data)
8983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
8993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int i;
9003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int chan = CR_CHAN(insn->chanspec);
9013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char hi, lo, status;
9023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* Writing a list of values to an AO channel is probably not
9043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * very useful, but that's how the interface is defined. */
9053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	for (i = 0; i < insn->n; i++) {
9063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->ao_readback[chan] = data[i];
9083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* get the low byte */
9103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		lo = data[i] & 0x00ff;
9113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* high byte also contains channel number */
9123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		hi = (data[i] >> 8) + chan * (1 << 6);
9133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		//printk("writing 0x%02x  0x%02x\n",hi,lo);
9143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* write the low and high values to the board */
9153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_DACLSB, lo);
9163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_DACMSB, hi);
9173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* wait for circuit to settle */
9193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		for (i = 0; i < 40000; i++) {
9203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			status = dmm_inb(dev, DMM32AT_DACSTAT);
9213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			if ((status & DMM32AT_DACBUSY) == 0)
9223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				break;
9233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
9243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (i == 40000) {
9253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			printk("timeout\n");
9263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			return -ETIMEDOUT;
9273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
9283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* dummy read to update trigger the output */
9293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		status = dmm_inb(dev, DMM32AT_DACMSB);
9303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
9323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* return the number of samples read/written */
9343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return i;
9353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
9363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* AO subdevices should have a read insn as well as a write insn.
9383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * Usually this means copying a value stored in devpriv. */
93934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
940790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data)
9413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
9423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int i;
9433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int chan = CR_CHAN(insn->chanspec);
9443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	for (i = 0; i < insn->n; i++)
9463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		data[i] = devpriv->ao_readback[chan];
9473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return i;
9493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
9503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DIO devices are slightly special.  Although it is possible to
9523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * implement the insn_read/insn_write interface, it is much more
9533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * useful to applications if you implement the insn_bits interface.
9543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * This allows packed reading/writing of the DIO channels.  The
9553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * comedi core can convert between insn_bits and insn_read/write */
95634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
957790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data)
9583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
9593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char diobits;
9603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (insn->n != 2)
9623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EINVAL;
9633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* The insn data is a mask in data[0] and the new data
9653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * in data[1], each channel cooresponding to a bit. */
9663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (data[0]) {
9673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->state &= ~data[0];
9683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		s->state |= data[0] & data[1];
9693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* Write out the new digital output lines */
9703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		//outw(s->state,dev->iobase + DMM32AT_DIO);
9713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
9723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get access to the DIO regs */
9743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC);
9753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* if either part of dio is set for output */
9773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
9783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
9793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		diobits = (s->state & 0x00ff0000) >> 16;
9803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_DIOC, diobits);
9813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
9823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
9833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		diobits = (s->state & 0x0000ff00) >> 8;
9843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_DIOB, diobits);
9853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
9863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
9873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		diobits = (s->state & 0x000000ff);
9883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm_outb(dev, DMM32AT_DIOA, diobits);
9893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
9903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* now read the state back in */
9923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->state = dmm_inb(dev, DMM32AT_DIOC);
9933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->state <<= 8;
9943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->state |= dmm_inb(dev, DMM32AT_DIOB);
9953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->state <<= 8;
9963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	s->state |= dmm_inb(dev, DMM32AT_DIOA);
9973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	data[1] = s->state;
9983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
9993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* on return, data[1] contains the value of the digital
10003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * input and output lines. */
10013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	//data[1]=inw(dev->iobase + DMM32AT_DIO);
10023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* or we could just return the software copy of the output values if
10033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * it was a purely digital output subdevice */
10043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	//data[1]=s->state;
10053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 2;
10073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
10083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
100934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dmm32at_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s,
1010790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	comedi_insn * insn, unsigned int * data)
10113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
10123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char chanbit;
10133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int chan = CR_CHAN(insn->chanspec);
10143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (insn->n != 1)
10163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EINVAL;
10173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (chan < 8)
10193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRA;
10203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	else if (chan < 16)
10213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRB;
10223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	else if (chan < 20)
10233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRCL;
10243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	else
10253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRCH;
10263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* The input or output configuration of each digital line is
10283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * configured by a special insn_config instruction.  chanspec
10293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * contains the channel to be changed, and data[0] contains the
10303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
10313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* if output clear the bit, otherwise set it */
10333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (data[0] == COMEDI_OUTPUT) {
10343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->dio_config &= ~chanbit;
10353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
10363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->dio_config |= chanbit;
10373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
10383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get access to the DIO regs */
10393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC);
10403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the DIO's to the new configuration setting */
10413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_DIOCONF, devpriv->dio_config);
10423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 1;
10443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
10453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
104671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonvoid dmm32at_setaitimer(struct comedi_device * dev, unsigned int nansec)
10473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
10483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char lo1, lo2, hi2;
10493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned short both2;
10503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* based on 10mhz clock */
10523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	lo1 = 200;
10533c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	both2 = nansec / 20000;
10543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	hi2 = (both2 & 0xff00) >> 8;
10553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	lo2 = both2 & 0x00ff;
10563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the counter frequency to 10mhz */
10583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CNTRDIO, 0);
10593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get access to the clock regs */
10613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_CLKACC);
10623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* write the counter 1 control word and low byte to counter */
10643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT1);
10653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CLK1, lo1);
10663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* write the counter 2 control word and low byte then to counter */
10683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CLKCT, DMM32AT_CLKCT2);
10693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CLK2, lo2);
10703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_CLK2, hi2);
10713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* enable the ai conversion interrupt and the clock to start scans */
10733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	dmm_outb(dev, DMM32AT_INTCLOCK, DMM32AT_ADINT | DMM32AT_CLKSEL);
10743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
10763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
10773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/*
10783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * A convenient macro that defines init_module() and cleanup_module(),
10793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * as necessary.
10803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
10813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniCOMEDI_INITCLEANUP(driver_dmm32at);
1082