[go: nahoru, domu]

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/*
193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniDriver: dmm32at
203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniDescription: Diamond Systems mm32at driver.
213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniDevices:
223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniAuthor: Perry J. Piplani <perry.j.piplani@nasa.gov>
233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniUpdated: Fri Jun  4 09:13:24 CDT 2004
243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniStatus: experimental
253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniThis driver is for the Diamond Systems MM-32-AT board
273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanihttp://www.diamondsystems.com/products/diamondmm32at It is being used
283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanion serveral projects inside NASA, without problems so far. For analog
293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplaniinput commands, TRIG_EXT is not yet supported at all..
303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. PiplaniConfiguration Options:
323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani  comedi_config /dev/comedi0 dmm32at baseaddr,irq
333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani*/
343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
35ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/module.h>
36ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/delay.h>
3725436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#include "../comedidev.h"
393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4027020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten#include "comedi_fc.h"
4127020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten
423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* Board register addresses */
433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CONV 0x00
443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AILSB 0x00
453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AUXDOUT 0x01
463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AIMSB 0x01
473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AILOW 0x02
483c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AIHIGH 0x03
493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DACSTAT 0x04
51bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten#define DMM32AT_DACLSB_REG	0x04
52bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten#define DMM32AT_DACMSB_REG	0x05
53bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten#define DMM32AT_DACMSB_CHAN(x)	((x) << 6)
543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FIFOCNTRL 0x07
563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FIFOSTAT 0x07
573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CNTRL 0x08
593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AISTAT 0x08
603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_INTCLOCK 0x09
623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CNTRDIO 0x0a
643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AICONF 0x0b
663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_AIRBACK 0x0b
673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLK1 0x0d
693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLK2 0x0e
703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKCT 0x0f
713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOA 0x0c
733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOB 0x0d
743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOC 0x0e
753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOCONF 0x0f
763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
773c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* Board register values. */
783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_DACSTAT 0x04 */
803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DACBUSY 0x80
813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_FIFOCNTRL 0x07 */
833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FIFORESET 0x02
843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCANENABLE 0x04
853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_CNTRL 0x08 */
873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RESET 0x20
883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_INTRESET 0x08
893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKACC 0x00
903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIOACC 0x01
913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_AISTAT 0x08 */
933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_STATUS 0x80
943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_INTCLOCK 0x09 */
963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_ADINT 0x80
973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKSEL 0x03
983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_CNTRDIO 0x0a */
1003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_FREQ12 0x80
1013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_AICONF 0x0b */
1033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_U10 0x0c
1043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_U5 0x0d
1053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_B10 0x08
1063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_RANGE_B5 0x00
1073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_20 0x00
1083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_15 0x10
1093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_10 0x20
1103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_SCINT_5 0x30
1113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_CLKCT 0x0f */
1133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKCT1 0x56	/* mode3 counter 1 - write low byte only */
1143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_CLKCT2 0xb6	/*  mode3 counter 2 - write high and low byte */
1153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* DMM32AT_DIOCONF 0x0f */
1173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIENABLE 0x80
1183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRA 0x10
1193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRB 0x02
1203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRCL 0x01
1213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define DMM32AT_DIRCH 0x08
1223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* board AI ranges in comedi structure */
1249ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange dmm32at_airanges = {
12545ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten	4, {
12645ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		UNI_RANGE(10),
12745ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		UNI_RANGE(5),
12845ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		BIP_RANGE(10),
12945ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		BIP_RANGE(5)
13045ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten	}
1313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
1323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* register values for above ranges */
1343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplanistatic const unsigned char dmm32at_rangebits[] = {
1353c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_U10,
1363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_U5,
1373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_B10,
1383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	DMM32AT_RANGE_B5,
1393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
1403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani/* only one of these ranges is valid, as set by a jumper on the
1423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani * board. The application should only use the range set by the jumper
1433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani */
1449ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange dmm32at_aoranges = {
14545ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten	4, {
14645ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		UNI_RANGE(10),
14745ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		UNI_RANGE(5),
14845ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		BIP_RANGE(10),
14945ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten		BIP_RANGE(5)
15045ddfc5a51f0ea179bcb82a4170c33ceed46c4b2H Hartley Sweeten	}
1513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani};
1523c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
15339d31e09a0cc299e01b8acb66b60fbcc453b9c8bBill Pembertonstruct dmm32at_private {
1543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int data;
1553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int ai_inuse;
1563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned int ai_scans_left;
1573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char dio_config;
15839d31e09a0cc299e01b8acb66b60fbcc453b9c8bBill Pemberton};
1593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
160f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweetenstatic int dmm32at_ai_status(struct comedi_device *dev,
161f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			     struct comedi_subdevice *s,
162f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			     struct comedi_insn *insn,
163f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			     unsigned long context)
164f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten{
165f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	unsigned char status;
166f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten
167f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	status = inb(dev->iobase + context);
168f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	if ((status & DMM32AT_STATUS) == 0)
169f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		return 0;
170f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	return -EBUSY;
171f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten}
172f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten
1730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dmm32at_ai_rinsn(struct comedi_device *dev,
1740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
1750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
1763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
177f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	int n;
1783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned int d;
1793c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned short msb, lsb;
1803c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char chan;
1813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int range;
182f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	int ret;
1833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get the channel and range number */
1853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	chan = CR_CHAN(insn->chanspec) & (s->n_chan - 1);
1873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	range = CR_RANGE(insn->chanspec);
1883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* zero scan and fifo control and reset fifo */
19029f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL);
1913c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* write the ai channel range regs */
19329f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(chan, dev->iobase + DMM32AT_AILOW);
19429f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(chan, dev->iobase + DMM32AT_AIHIGH);
1953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the range bits */
19629f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AICONF);
1973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
1983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* wait for circuit to settle */
199f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	ret = comedi_timeout(dev, s, insn, dmm32at_ai_status, DMM32AT_AIRBACK);
200f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	if (ret)
201f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		return ret;
2023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* convert n samples */
2043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	for (n = 0; n < insn->n; n++) {
2053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* trigger conversion */
20629f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten		outb(0xff, dev->iobase + DMM32AT_CONV);
207f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten
2083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* wait for conversion to end */
209f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		ret = comedi_timeout(dev, s, insn, dmm32at_ai_status,
210f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten				     DMM32AT_AISTAT);
211f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		if (ret)
212f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			return ret;
2133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* read data */
21599953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten		lsb = inb(dev->iobase + DMM32AT_AILSB);
21699953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten		msb = inb(dev->iobase + DMM32AT_AIMSB);
2173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* invert sign bit to make range unsigned, this is an
21925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		   idiosyncrasy of the diamond board, it return
2203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   conversions as a signed value, i.e. -32768 to
2213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   32767, flipping the bit and interpreting it as
2223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   signed gives you a range of 0 to 65535 which is
2233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		   used by comedi */
2243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		d = ((msb ^ 0x0080) << 8) + lsb;
2253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		data[n] = d;
2273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
2283c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* return the number of samples read/written */
2303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return n;
2313c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
2323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
233a207c12f62e8b53e1e1600ca384b13a39a9feed2H Hartley Sweetenstatic int dmm32at_ns_to_timer(unsigned int *ns, unsigned int flags)
23447ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten{
23547ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	/* trivial timer */
23647ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	return *ns;
23747ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten}
23847ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
239869149961951afccb103d43217282756b17f2f96H Hartley Sweetenstatic int dmm32at_ai_check_chanlist(struct comedi_device *dev,
240869149961951afccb103d43217282756b17f2f96H Hartley Sweeten				     struct comedi_subdevice *s,
241869149961951afccb103d43217282756b17f2f96H Hartley Sweeten				     struct comedi_cmd *cmd)
242869149961951afccb103d43217282756b17f2f96H Hartley Sweeten{
243869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
244869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
245869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	int i;
246869149961951afccb103d43217282756b17f2f96H Hartley Sweeten
247869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	for (i = 1; i < cmd->chanlist_len; i++) {
248869149961951afccb103d43217282756b17f2f96H Hartley Sweeten		unsigned int chan = CR_CHAN(cmd->chanlist[i]);
249869149961951afccb103d43217282756b17f2f96H Hartley Sweeten		unsigned int range = CR_RANGE(cmd->chanlist[i]);
250869149961951afccb103d43217282756b17f2f96H Hartley Sweeten
251869149961951afccb103d43217282756b17f2f96H Hartley Sweeten		if (chan != (chan0 + i) % s->n_chan) {
252869149961951afccb103d43217282756b17f2f96H Hartley Sweeten			dev_dbg(dev->class_dev,
253869149961951afccb103d43217282756b17f2f96H Hartley Sweeten				"entries in chanlist must be consecutive channels, counting upwards\n");
254869149961951afccb103d43217282756b17f2f96H Hartley Sweeten			return -EINVAL;
255869149961951afccb103d43217282756b17f2f96H Hartley Sweeten		}
256869149961951afccb103d43217282756b17f2f96H Hartley Sweeten		if (range != range0) {
257869149961951afccb103d43217282756b17f2f96H Hartley Sweeten			dev_dbg(dev->class_dev,
258869149961951afccb103d43217282756b17f2f96H Hartley Sweeten				"entries in chanlist must all have the same gain\n");
259869149961951afccb103d43217282756b17f2f96H Hartley Sweeten			return -EINVAL;
260869149961951afccb103d43217282756b17f2f96H Hartley Sweeten		}
261869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	}
262869149961951afccb103d43217282756b17f2f96H Hartley Sweeten
263869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	return 0;
264869149961951afccb103d43217282756b17f2f96H Hartley Sweeten}
265869149961951afccb103d43217282756b17f2f96H Hartley Sweeten
2660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dmm32at_ai_cmdtest(struct comedi_device *dev,
2670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
2680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_cmd *cmd)
2693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
2703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int err = 0;
271d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten	unsigned int arg;
2723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
27327020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	/* Step 1 : check if triggers are trivially valid */
2743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
27527020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
27627020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
27727020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten					TRIG_TIMER /*| TRIG_EXT */);
27827020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->convert_src,
27927020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten					TRIG_TIMER /*| TRIG_EXT */);
28027020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
28127020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
2823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
2843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 1;
2853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
28627020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	/* Step 2a : make sure trigger sources are unique */
2873c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
28827020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
28927020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_is_unique(cmd->convert_src);
29027020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	err |= cfc_check_trigger_is_unique(cmd->stop_src);
29127020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten
29227020ffed9166d65ce1e5b523051d13bfa2329b0H Hartley Sweeten	/* Step 2b : and mutually compatible */
2933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
2943c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
2953c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 2;
2963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
297e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten	/* Step 3: check if arguments are trivially valid */
298e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten
299e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
3003c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define MAX_SCAN_SPEED	1000000	/* in nanoseconds */
3023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani#define MIN_SCAN_SPEED	1000000000	/* in nanoseconds */
3033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->scan_begin_src == TRIG_TIMER) {
305e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
306e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten						 MAX_SCAN_SPEED);
307e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
308e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten						 MIN_SCAN_SPEED);
3093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
3103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* external trigger */
3113c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* should be level/edge, hi/lo specification here */
3123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* should specify multiple external triggers */
313e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9);
3143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
315e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten
3163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->convert_src == TRIG_TIMER) {
3173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (cmd->convert_arg >= 17500)
3183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 20000;
3193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		else if (cmd->convert_arg >= 12500)
3203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 15000;
3213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		else if (cmd->convert_arg >= 7500)
3223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 10000;
3233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		else
3243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			cmd->convert_arg = 5000;
3253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
3263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* external trigger */
3273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* see above */
328e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 9);
3293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
3303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
331e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
332e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten
3333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->stop_src == TRIG_COUNT) {
334e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten		err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0xfffffff0);
335e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
3363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
3373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* TRIG_NONE */
338e43ed5fa1435e3ae8a2a5727ea30581640f9e18dH Hartley Sweeten		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
3393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
3403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
3423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 3;
3433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3443c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* step 4: fix up any arguments */
3453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->scan_begin_src == TRIG_TIMER) {
347d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten		arg = cmd->scan_begin_arg;
348a207c12f62e8b53e1e1600ca384b13a39a9feed2H Hartley Sweeten		dmm32at_ns_to_timer(&arg, cmd->flags);
349d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
3503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
3513c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->convert_src == TRIG_TIMER) {
352d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten		arg = cmd->convert_arg;
353a207c12f62e8b53e1e1600ca384b13a39a9feed2H Hartley Sweeten		dmm32at_ns_to_timer(&arg, cmd->flags);
354d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten		err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
355d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten
356d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten		if (cmd->scan_begin_src == TRIG_TIMER) {
357d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten			arg = cmd->convert_arg * cmd->scan_end_arg;
358d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
359d579392a3fab9acd63123f4167abd822600777a4H Hartley Sweeten							 arg);
3603c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
3613c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
3623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
3643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 4;
3653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
366869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	/* Step 5: check channel list if it exists */
367869149961951afccb103d43217282756b17f2f96H Hartley Sweeten	if (cmd->chanlist && cmd->chanlist_len > 0)
368869149961951afccb103d43217282756b17f2f96H Hartley Sweeten		err |= dmm32at_ai_check_chanlist(dev, s, cmd);
3693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (err)
3713c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return 5;
3723c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
3733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 0;
3743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
3753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
37647ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweetenstatic void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec)
37747ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten{
37847ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	unsigned char lo1, lo2, hi2;
37947ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	unsigned short both2;
38047ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
38147ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	/* based on 10mhz clock */
38247ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	lo1 = 200;
38347ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	both2 = nansec / 20000;
38447ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	hi2 = (both2 & 0xff00) >> 8;
38547ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	lo2 = both2 & 0x00ff;
38647ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
38747ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	/* set the counter frequency to 10mhz */
38829f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(0, dev->iobase + DMM32AT_CNTRDIO);
38947ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
39047ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	/* get access to the clock regs */
39129f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_CLKACC, dev->iobase + DMM32AT_CNTRL);
39247ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
39347ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	/* write the counter 1 control word and low byte to counter */
39429f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_CLKCT1, dev->iobase + DMM32AT_CLKCT);
39529f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(lo1, dev->iobase + DMM32AT_CLK1);
39647ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
39747ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	/* write the counter 2 control word and low byte then to counter */
39829f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_CLKCT2, dev->iobase + DMM32AT_CLKCT);
39929f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(lo2, dev->iobase + DMM32AT_CLK2);
40029f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(hi2, dev->iobase + DMM32AT_CLK2);
40147ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
40247ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten	/* enable the ai conversion interrupt and the clock to start scans */
40329f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_ADINT | DMM32AT_CLKSEL, dev->iobase + DMM32AT_INTCLOCK);
40447ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten}
40547ae6a72597c29745fc18d693fe00bc8a537cfdfH Hartley Sweeten
406da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
4073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
4083eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten	struct dmm32at_private *devpriv = dev->private;
409ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
410f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	int range;
411f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	unsigned char chanlo, chanhi;
412f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	int ret;
4133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!cmd->chanlist)
4153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EINVAL;
4163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get the channel list and range */
4183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	chanlo = CR_CHAN(cmd->chanlist[0]) & (s->n_chan - 1);
4193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	chanhi = chanlo + cmd->chanlist_len - 1;
4203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (chanhi >= s->n_chan)
4213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return -EINVAL;
4223c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	range = CR_RANGE(cmd->chanlist[0]);
4233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* reset fifo */
42529f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_FIFORESET, dev->iobase + DMM32AT_FIFOCNTRL);
4263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4273c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set scan enable */
42829f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_SCANENABLE, dev->iobase + DMM32AT_FIFOCNTRL);
4293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4303c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* write the ai channel range regs */
43129f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(chanlo, dev->iobase + DMM32AT_AILOW);
43229f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(chanhi, dev->iobase + DMM32AT_AIHIGH);
4333c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the range bits */
43529f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(dmm32at_rangebits[range], dev->iobase + DMM32AT_AICONF);
4363c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4373c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* reset the interrupt just in case */
43829f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_INTRESET, dev->iobase + DMM32AT_CNTRL);
4393c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (cmd->stop_src == TRIG_COUNT)
4413c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->ai_scans_left = cmd->stop_arg;
4423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	else {			/* TRIG_NONE */
44327bf0bc906e80fdb531524dab22a7851a4c21698Mark		devpriv->ai_scans_left = 0xffffffff; /* indicates TRIG_NONE to
44427bf0bc906e80fdb531524dab22a7851a4c21698Mark						      * isr */
4453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
4463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
447f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	/*
448f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	 * wait for circuit to settle
449f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	 * we don't have the 'insn' here but it's not needed
450f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	 */
451f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	ret = comedi_timeout(dev, s, NULL, dmm32at_ai_status, DMM32AT_AIRBACK);
452f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	if (ret)
453f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		return ret;
4543c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (devpriv->ai_scans_left > 1) {
4563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* start the clock and enable the interrupts */
4573c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		dmm32at_setaitimer(dev, cmd->scan_begin_arg);
4583c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	} else {
4593c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* start the interrups and initiate a single scan */
46029f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten		outb(DMM32AT_ADINT, dev->iobase + DMM32AT_INTCLOCK);
46129f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten		outb(0xff, dev->iobase + DMM32AT_CONV);
4623c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
4633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4643c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 0;
4653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
4673c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dmm32at_ai_cancel(struct comedi_device *dev,
4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
4703c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
4713eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten	struct dmm32at_private *devpriv = dev->private;
4723eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten
4733c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	devpriv->ai_scans_left = 1;
4743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return 0;
4753c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
4763c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
47770265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t dmm32at_isr(int irq, void *d)
4783c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
4793eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten	struct comedi_device *dev = d;
4803eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten	struct dmm32at_private *devpriv = dev->private;
4813c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char intstat;
4823c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned int samp;
4833c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned short msb, lsb;
4843c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	int i;
4853c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4863c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (!dev->attached) {
4872d60dd4a75bf1ddd60629c4d3fc5279205e701e2H Hartley Sweeten		dev_err(dev->class_dev, "spurious interrupt\n");
4883c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		return IRQ_HANDLED;
4893c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
4903c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
49199953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten	intstat = inb(dev->iobase + DMM32AT_INTCLOCK);
4923c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4933c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	if (intstat & DMM32AT_ADINT) {
49434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton		struct comedi_subdevice *s = dev->read_subdev;
495ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton		struct comedi_cmd *cmd = &s->async->cmd;
4963c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
4973c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		for (i = 0; i < cmd->chanlist_len; i++) {
4983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			/* read data */
49999953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten			lsb = inb(dev->iobase + DMM32AT_AILSB);
50099953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten			msb = inb(dev->iobase + DMM32AT_AIMSB);
5013c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5023c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			/* invert sign bit to make range unsigned */
5033c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			samp = ((msb ^ 0x0080) << 8) + lsb;
5043672effdeae5395d661a2103f69082146ef949fcIan Abbott			comedi_buf_put(s, samp);
5053c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
5063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5073c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		if (devpriv->ai_scans_left != 0xffffffff) {	/* TRIG_COUNT */
5083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			devpriv->ai_scans_left--;
5093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			if (devpriv->ai_scans_left == 0) {
5103c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				/* disable further interrupts and clocks */
51129f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten				outb(0x0, dev->iobase + DMM32AT_INTCLOCK);
5123c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				/* set the buffer to be flushed with an EOF */
5133c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani				s->async->events |= COMEDI_CB_EOA;
5143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani			}
5153c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5163c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		}
5173c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* flush the buffer */
5183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		comedi_event(dev, s);
5193c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
5203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5213c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* reset the interrupt */
52229f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_INTRESET, dev->iobase + DMM32AT_CNTRL);
5233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	return IRQ_HANDLED;
5243c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
5253c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
526f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweetenstatic int dmm32at_ao_eoc(struct comedi_device *dev,
527f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			  struct comedi_subdevice *s,
528f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			  struct comedi_insn *insn,
529f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			  unsigned long context)
530f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten{
531f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	unsigned char status;
532f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten
533f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	status = inb(dev->iobase + DMM32AT_DACSTAT);
534f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	if ((status & DMM32AT_DACBUSY) == 0)
535f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		return 0;
536f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten	return -EBUSY;
537f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten}
538f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten
539bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweetenstatic int dmm32at_ao_insn_write(struct comedi_device *dev,
540bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten				 struct comedi_subdevice *s,
541bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten				 struct comedi_insn *insn,
542bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten				 unsigned int *data)
5433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
544bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
545bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten	int i;
5463c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	for (i = 0; i < insn->n; i++) {
548b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten		unsigned int val = data[i];
549b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten		int ret;
5503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
551bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten		/* write LSB then MSB + chan to load DAC */
552bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten		outb(val & 0xff, dev->iobase + DMM32AT_DACLSB_REG);
553bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten		outb((val >> 8) | DMM32AT_DACMSB_CHAN(chan),
554bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten		     dev->iobase + DMM32AT_DACMSB_REG);
5553c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5563c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		/* wait for circuit to settle */
557f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		ret = comedi_timeout(dev, s, insn, dmm32at_ao_eoc, 0);
558f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten		if (ret)
559f7b3d79a622c97483c8d0e6e4bbd5207929259d9H Hartley Sweeten			return ret;
56065e2618fd3bbe9c3776048212dc15ddc7fe61451H Hartley Sweeten
561bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten		/* dummy read to update DAC */
562bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten		inb(dev->iobase + DMM32AT_DACMSB_REG);
5633c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
564b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten		s->readback[chan] = val;
5653c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
5663c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
567bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten	return insn->n;
5683c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
5693c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
5700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dmm32at_dio_insn_bits(struct comedi_device *dev,
5710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
572b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten				 struct comedi_insn *insn,
573b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten				 unsigned int *data)
5743c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
5753eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten	struct dmm32at_private *devpriv = dev->private;
576b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	unsigned int mask;
577b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	unsigned int val;
578b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten
579b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	mask = comedi_dio_update_state(s, data);
580b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	if (mask) {
581b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		/* get access to the DIO regs */
582b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
583b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten
584b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		/* if either part of dio is set for output */
585b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
586b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		    ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
587b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten			val = (s->state & 0x00ff0000) >> 16;
588b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten			outb(val, dev->iobase + DMM32AT_DIOC);
589b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		}
590b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
591b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten			val = (s->state & 0x0000ff00) >> 8;
592b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten			outb(val, dev->iobase + DMM32AT_DIOB);
593b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		}
594b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
595b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten			val = (s->state & 0x000000ff);
596b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten			outb(val, dev->iobase + DMM32AT_DIOA);
597b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten		}
5983c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	}
5993c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
600b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	val = inb(dev->iobase + DMM32AT_DIOA);
601b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
602b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
603b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	s->state = val;
6043c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
605b3ff824a81e8978deb56f6d163479c1a0a606037H Hartley Sweeten	data[1] = val;
6063c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
607a2714e3e42e746d6c8525c35fdcc58fb60c2830dH Hartley Sweeten	return insn->n;
6083c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
6093c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dmm32at_dio_insn_config(struct comedi_device *dev,
6110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
61249b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten				   struct comedi_insn *insn,
61349b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten				   unsigned int *data)
6143c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani{
6153eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten	struct dmm32at_private *devpriv = dev->private;
61649b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
61749b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	unsigned int mask;
6183c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	unsigned char chanbit;
61949b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	int ret;
6203c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
62149b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	if (chan < 8) {
62249b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten		mask = 0x0000ff;
6233c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRA;
62449b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	} else if (chan < 16) {
62549b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten		mask = 0x00ff00;
6263c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRB;
62749b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	} else if (chan < 20) {
62849b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten		mask = 0x0f0000;
6293c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRCL;
63049b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	} else {
63149b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten		mask = 0xf00000;
6323c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		chanbit = DMM32AT_DIRCH;
63349b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	}
6343c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
63549b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	ret = comedi_dio_insn_config(dev, s, insn, data, mask);
63649b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	if (ret)
63749b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten		return ret;
6383c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
63949b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	if (data[0] == INSN_CONFIG_DIO_OUTPUT)
6403c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->dio_config &= ~chanbit;
64120962c10c19862c58c03eec2434279a5d104c40eAndrea Gelmini	else
6423c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani		devpriv->dio_config |= chanbit;
6433c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* get access to the DIO regs */
64429f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
6453c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani	/* set the DIO's to the new configuration setting */
64629f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF);
6473c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
64849b71ebab2b40ffec19007e8b4dba6b8f8622f46H Hartley Sweeten	return insn->n;
6493c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani}
6503c501880ac4436ad2db5feed6e7d7548e13d539fPerry J. Piplani
6514f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweetenstatic int dmm32at_attach(struct comedi_device *dev,
6524f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten			  struct comedi_devconfig *it)
6534f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten{
6543eff01744009de100f03a1dc2e3d5f98da2235e5H Hartley Sweeten	struct dmm32at_private *devpriv;
6554f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	int ret;
6564f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	struct comedi_subdevice *s;
6574f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	unsigned char aihi, ailo, fifostat, aistat, intstat, airback;
6584f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
65988634cd820850241aafb9c1ecc822c5a4c361c0cH Hartley Sweeten	ret = comedi_request_region(dev, it->options[0], 0x10);
6602dd11a812aa908b3a8f2f88cce9f0c24c34c3cabH Hartley Sweeten	if (ret)
6612dd11a812aa908b3a8f2f88cce9f0c24c34c3cabH Hartley Sweeten		return ret;
6624f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6634f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* the following just makes sure the board is there and gets
6644f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	   it to a known state */
6654f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6664f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* reset the board */
66729f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_RESET, dev->iobase + DMM32AT_CNTRL);
6684f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6694f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* allow a millisecond to reset */
6704f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	udelay(1000);
6714f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6724f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* zero scan and fifo control */
67329f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(0x0, dev->iobase + DMM32AT_FIFOCNTRL);
6744f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6754f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* zero interrupt and clock control */
67629f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(0x0, dev->iobase + DMM32AT_INTCLOCK);
6774f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6784f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* write a test channel range, the high 3 bits should drop */
67929f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(0x80, dev->iobase + DMM32AT_AILOW);
68029f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(0xff, dev->iobase + DMM32AT_AIHIGH);
6814f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6824f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* set the range at 10v unipolar */
68329f747c21e4318cc41efa82dac217da9ee8d5533H Hartley Sweeten	outb(DMM32AT_RANGE_U10, dev->iobase + DMM32AT_AICONF);
6844f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6854f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* should take 10 us to settle, here's a hundred */
6864f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	udelay(100);
6874f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6884f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* read back the values */
68999953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten	ailo = inb(dev->iobase + DMM32AT_AILOW);
69099953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten	aihi = inb(dev->iobase + DMM32AT_AIHIGH);
69199953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten	fifostat = inb(dev->iobase + DMM32AT_FIFOSTAT);
69299953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten	aistat = inb(dev->iobase + DMM32AT_AISTAT);
69399953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten	intstat = inb(dev->iobase + DMM32AT_INTCLOCK);
69499953ea1ec780c22bacf065fc7c9750f0182c0f4H Hartley Sweeten	airback = inb(dev->iobase + DMM32AT_AIRBACK);
6954f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
6964f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	if ((ailo != 0x00) || (aihi != 0x1f) || (fifostat != 0x80) ||
6974f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	    (aistat != 0x60 || (intstat != 0x00) || airback != 0x0c)) {
69845d351031e1326a4d0a988c776f23673f7e1ffd2H Hartley Sweeten		dev_err(dev->class_dev, "board detection failed\n");
6994f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten		return -EIO;
7004f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	}
7014f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
7020c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten	if (it->options[1]) {
7030c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		ret = request_irq(it->options[1], dmm32at_isr, 0,
7040c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten				  dev->board_name, dev);
7050c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		if (ret == 0)
7060c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten			dev->irq = it->options[1];
7074f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	}
7084f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
7090bdab509bf9c6d838dc0a3b1d68bbf841fc20b5aH Hartley Sweeten	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
710c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten	if (!devpriv)
711c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten		return -ENOMEM;
7124f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
7134f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	ret = comedi_alloc_subdevices(dev, 3);
7144f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	if (ret)
7154f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten		return ret;
7164f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
7172930d0ba656d035d01a2cac37b6fe1250df16c28H Hartley Sweeten	s = &dev->subdevices[0];
7184f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* analog input subdevice */
7194f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	s->type = COMEDI_SUBD_AI;
7204f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* we support single-ended (ground) and differential */
7210c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
7222792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->n_chan = 32;
7232792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->maxdata = 0xffff;
7242792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->range_table = &dmm32at_airanges;
7254f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	s->insn_read = dmm32at_ai_rinsn;
7260c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten	if (dev->irq) {
7270c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		dev->read_subdev = s;
7280c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		s->subdev_flags |= SDF_CMD_READ;
7290c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		s->len_chanlist = 32;
7300c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		s->do_cmd = dmm32at_ai_cmd;
7310c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		s->do_cmdtest = dmm32at_ai_cmdtest;
7320c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten		s->cancel = dmm32at_ai_cancel;
7330c2e55324199d89aaea816ce7a76571c3f88d158H Hartley Sweeten	}
7344f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
7352930d0ba656d035d01a2cac37b6fe1250df16c28H Hartley Sweeten	s = &dev->subdevices[1];
7364f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* analog output subdevice */
7374f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	s->type = COMEDI_SUBD_AO;
7384f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	s->subdev_flags = SDF_WRITABLE;
7392792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->n_chan = 4;
7402792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->maxdata = 0x0fff;
7412792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->range_table = &dmm32at_aoranges;
742bf8e3e3ad467f9e63069d19e56baf40644b7ec03H Hartley Sweeten	s->insn_write = dmm32at_ao_insn_write;
743b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten	s->insn_read = comedi_readback_insn_read;
744b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten
745b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten	ret = comedi_alloc_subdev_readback(s);
746b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten	if (ret)
747b328ad30759bf3134175242cf7ea9a81b1ef02a5H Hartley Sweeten		return ret;
7484f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
7492930d0ba656d035d01a2cac37b6fe1250df16c28H Hartley Sweeten	s = &dev->subdevices[2];
7504f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten	/* digital i/o subdevice */
7512792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten
7522792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	/* get access to the DIO regs */
7532792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
7542792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	/* set the DIO's to the defualt input setting */
7552792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	devpriv->dio_config = DMM32AT_DIRA | DMM32AT_DIRB |
7562792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten		DMM32AT_DIRCL | DMM32AT_DIRCH | DMM32AT_DIENABLE;
7572792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	outb(devpriv->dio_config, dev->iobase + DMM32AT_DIOCONF);
7582792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten
7592792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	/* set up the subdevice */
7602792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->type = COMEDI_SUBD_DIO;
7612792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
7622792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->n_chan = 24;
7632792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->maxdata = 1;
7642792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->state = 0;
7652792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->range_table = &range_digital;
7662792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->insn_bits = dmm32at_dio_insn_bits;
7672792182816be376391c2cfc142bfd32f3ab8c5cdH Hartley Sweeten	s->insn_config = dmm32at_dio_insn_config;
7684f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
7699b35db028f7f5c375ab9cef095ea48250d4c15ffH Hartley Sweeten	return 0;
7704f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten}
7714f793db33dc3bab1b77a540386a662fbfd595e08H Hartley Sweeten
77217f49dd46c5db2912d2dd985f400f6237fd30255H Hartley Sweetenstatic struct comedi_driver dmm32at_driver = {
77317f49dd46c5db2912d2dd985f400f6237fd30255H Hartley Sweeten	.driver_name	= "dmm32at",
77417f49dd46c5db2912d2dd985f400f6237fd30255H Hartley Sweeten	.module		= THIS_MODULE,
77517f49dd46c5db2912d2dd985f400f6237fd30255H Hartley Sweeten	.attach		= dmm32at_attach,
7763d1fe3f785c80e17f62acf8f92570ae9210bd588H Hartley Sweeten	.detach		= comedi_legacy_detach,
77717f49dd46c5db2912d2dd985f400f6237fd30255H Hartley Sweeten};
77817f49dd46c5db2912d2dd985f400f6237fd30255H Hartley Sweetenmodule_comedi_driver(dmm32at_driver);
77990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
78090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
78190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
78290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
783