[go: nahoru, domu]

196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit/*
296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    comedi/drivers/icp_multi.c
396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    COMEDI - Linux Control and Measurement Device Interface
596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org>
696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    This program is free software; you can redistribute it and/or modify
896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    it under the terms of the GNU General Public License as published by
996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    the Free Software Foundation; either version 2 of the License, or
1096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    (at your option) any later version.
1196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
1296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    This program is distributed in the hope that it will be useful,
1396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    but WITHOUT ANY WARRANTY; without even the implied warranty of
1496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit    GNU General Public License for more details.
1696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit*/
1796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
1896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit/*
1996341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitDriver: icp_multi
2096341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitDescription: Inova ICP_MULTI
2196341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitAuthor: Anne Smorthit <anne.smorthit@sfwte.ch>
2296341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitDevices: [Inova] ICP_MULTI (icp_multi)
2396341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitStatus: works
2496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
2596341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitThe driver works for analog input and output and digital input and output.
2696341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitIt does not work with interrupts or with the counters.  Currently no support
2796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitfor DMA.
2896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
2996341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitIt has 16 single-ended or 8 differential Analogue Input channels with 12-bit
3096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitresolution.  Ranges : 5V, 10V, +/-5V, +/-10V, 0..20mA and 4..20mA.  Input
3196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitranges can be individually programmed for each channel.  Voltage or current
3296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitmeasurement is selected by jumper.
3396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
3496341f71538c48dcec873873cabc11477cf26ae9Anne SmorthitThere are 4 x 12-bit Analogue Outputs.  Ranges : 5V, 10V, +/-5V, +/-10V
3596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
3696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit16 x Digital Inputs, 24V
3796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
3896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit8 x Digital Outputs, 24V, 1A
3996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
4096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit4 x 16-bit counters
4196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
42194b9e3cf49319231e8b47125dc5d043350f4406H Hartley SweetenConfiguration options: not applicable, uses PCI auto config
4396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit*/
4496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
45ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/module.h>
4633782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include <linux/pci.h>
4733782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include <linux/delay.h>
4825436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
4996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
5033782dd5edf8db3cdb7c81a3523bf743dd0209b7H Hartley Sweeten#include "../comedidev.h"
5196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
5296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_ADC_CSR	0	/* R/W: ADC command/status register */
5396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_AI		2	/* R:   Analogue input data */
5496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_DAC_CSR	4	/* R/W: DAC command/status register */
5596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_AO		6	/* R/W: Analogue output data */
5696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_DI		8	/* R/W: Digital inouts */
5796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_DO		0x0A	/* R/W: Digital outputs */
5896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_INT_EN	0x0C	/* R/W: Interrupt enable register */
5996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_INT_STAT	0x0E	/* R/W: Interrupt status register */
6096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR0		0x10	/* R/W: Counter 0 */
6196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR1		0x12	/* R/W: counter 1 */
6296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR2		0x14	/* R/W: Counter 2 */
6396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ICP_MULTI_CNTR3		0x16	/* R/W: Counter 3 */
6496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
65b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/*  Define bits from ADC command/status register */
6696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	ADC_ST		0x0001	/* Start ADC */
6796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	ADC_BSY		0x0001	/* ADC busy */
6896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_BI		0x0010	/* Bipolar input range 1 = bipolar */
6996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define ADC_RA		0x0020	/* Input range 0 = 5V, 1 = 10V */
7096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	ADC_DI		0x0040	/* Differential input mode 1 = differential */
7196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
72b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/*  Define bits from DAC command/status register */
7396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	DAC_ST		0x0001	/* Start DAC */
7496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define DAC_BSY		0x0001	/* DAC busy */
7596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	DAC_BI		0x0010	/* Bipolar input range 1 = bipolar */
7696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	DAC_RA		0x0020	/* Input range 0 = 5V, 1 = 10V */
7796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
78b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/*  Define bits from interrupt enable/status registers */
7996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	ADC_READY	0x0001	/* A/d conversion ready interrupt */
8096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	DAC_READY	0x0002	/* D/a conversion ready interrupt */
8196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	DOUT_ERROR	0x0004	/* Digital output error interrupt */
8296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	DIN_STATUS	0x0008	/* Digital input status change interrupt */
8396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	CIE0		0x0010	/* Counter 0 overrun interrupt */
8496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	CIE1		0x0020	/* Counter 1 overrun interrupt */
8596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	CIE2		0x0040	/* Counter 2 overrun interrupt */
8696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#define	CIE3		0x0080	/* Counter 3 overrun interrupt */
8796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
88b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/*  Useful definitions */
89b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton#define	Status_IRQ	0x00ff	/*  All interrupts */
9096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
91b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton/*  Define analogue range */
923e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweetenstatic const struct comedi_lrange range_analog = {
933e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten	4, {
943e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten		UNI_RANGE(5),
953e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten		UNI_RANGE(10),
963e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten		BIP_RANGE(5),
973e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten		BIP_RANGE(10)
983e54cdb1fd094d4483b03128a4dce53cfb6c9855H Hartley Sweeten	}
9996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit};
10096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
10196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthitstatic const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
10296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
10396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit/*
10496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit==============================================================================
10596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	Data & Structure declarations
10696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit==============================================================================
10796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit*/
10896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
10952bfe6c8e8746591e276de2594b8c98a51222d49Bill Pembertonstruct icp_multi_private {
110b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned int AdcCmdStatus;	/*  ADC Command/Status register */
111b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned int DacCmdStatus;	/*  DAC Command/Status register */
112b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned int IntEnable;	/*  Interrupt Enable register */
113b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned int IntStatus;	/*  Interrupt Status register */
11420ce161d2f53af092fe8dabfef6fb0d7af846c43Masanari Iida	unsigned int act_chanlist[32];	/*  list of scanned channel */
115b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned char act_chanlist_len;	/*  len of scanlist */
116b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned char act_chanlist_pos;	/*  actual position in MUX list */
117b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned int *ai_chanlist;	/*  actaul chanlist */
118b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	unsigned int do_data;	/*  Remember digital output data */
11952bfe6c8e8746591e276de2594b8c98a51222d49Bill Pemberton};
12096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void setup_channel_list(struct comedi_device *dev,
1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s,
123d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			       unsigned int *chanlist, unsigned int n_chan)
124d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten{
12565e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten	struct icp_multi_private *devpriv = dev->private;
126d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	unsigned int i, range, chanprog;
127d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	unsigned int diff;
12896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
129d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	devpriv->act_chanlist_len = n_chan;
130d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	devpriv->act_chanlist_pos = 0;
131d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten
132d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	for (i = 0; i < n_chan; i++) {
133d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		/*  Get channel */
134d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		chanprog = CR_CHAN(chanlist[i]);
135d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten
136d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		/*  Determine if it is a differential channel (Bit 15  = 1) */
137d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		if (CR_AREF(chanlist[i]) == AREF_DIFF) {
138d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			diff = 1;
139d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			chanprog &= 0x0007;
140d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		} else {
141d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			diff = 0;
142d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			chanprog &= 0x000f;
143d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		}
144d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten
145d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		/*  Clear channel, range and input mode bits
146d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		 *  in A/D command/status register */
147d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		devpriv->AdcCmdStatus &= 0xf00f;
148d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten
149d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		/*  Set channel number and differential mode status bit */
150d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		if (diff) {
151d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			/*  Set channel number, bits 9-11 & mode, bit 6 */
152d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			devpriv->AdcCmdStatus |= (chanprog << 9);
153d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			devpriv->AdcCmdStatus |= ADC_DI;
154d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		} else
155d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			/*  Set channel number, bits 8-11 */
156d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten			devpriv->AdcCmdStatus |= (chanprog << 8);
157d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten
158d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		/*  Get range for current channel */
159d68a8635c5b706e3c037d89fd130e62ddce5c823H Hartley Sweeten		range = range_codes_analog[CR_RANGE(chanlist[i])];
160d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		/*  Set range. bits 4-5 */
161d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		devpriv->AdcCmdStatus |= range;
162d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten
163d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten		/* Output channel, range, mode to ICP Multi */
164a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten		writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR);
165d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	}
166d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten}
16796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
168e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweetenstatic int icp_multi_ai_eoc(struct comedi_device *dev,
169e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			    struct comedi_subdevice *s,
170e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			    struct comedi_insn *insn,
171e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			    unsigned long context)
172e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten{
173e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	unsigned int status;
174e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten
175a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	status = readw(dev->mmio + ICP_MULTI_ADC_CSR);
176e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	if ((status & ADC_BSY) == 0)
177e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten		return 0;
178e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	return -EBUSY;
179e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten}
180e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten
1810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_read_ai(struct comedi_device *dev,
1820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  struct comedi_subdevice *s,
183a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten				  struct comedi_insn *insn,
184a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten				  unsigned int *data)
18596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
18665e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten	struct icp_multi_private *devpriv = dev->private;
187e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	int ret = 0;
188e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	int n;
18996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
190b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Disable A/D conversion ready interrupt */
19196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->IntEnable &= ~ADC_READY;
192a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN);
19396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
194b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Clear interrupt status */
19596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->IntStatus |= ADC_READY;
196a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT);
19796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
198a622afcb7e4c7d24bb29b07e82fd8b7fcd81c0c0Dirk Hohndel	/*  Set up appropriate channel, mode and range data, for specified ch */
19996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	setup_channel_list(dev, s, &insn->chanspec, 1);
20096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
20196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	for (n = 0; n < insn->n; n++) {
202b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton		/*  Set start ADC bit */
20396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		devpriv->AdcCmdStatus |= ADC_ST;
204a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten		writew(devpriv->AdcCmdStatus, dev->mmio + ICP_MULTI_ADC_CSR);
20596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		devpriv->AdcCmdStatus &= ~ADC_ST;
20696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
2075f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
20896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
209b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton		/*  Wait for conversion to complete, or get fed up waiting */
210e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten		ret = comedi_timeout(dev, s, insn, icp_multi_ai_eoc, 0);
211dbd446fc7aab519c213e63eefa15c82586a50989H Hartley Sweeten		if (ret)
212e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			break;
21396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
214a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten		data[n] = (readw(dev->mmio + ICP_MULTI_AI) >> 4) & 0x0fff;
21596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	}
21696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
217b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Disable interrupt */
21896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->IntEnable &= ~ADC_READY;
219a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN);
22096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
221b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Clear interrupt status */
22296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->IntStatus |= ADC_READY;
223a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT);
22496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
225e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	return ret ? ret : n;
226e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten}
227e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten
228e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweetenstatic int icp_multi_ao_eoc(struct comedi_device *dev,
229e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			    struct comedi_subdevice *s,
230e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			    struct comedi_insn *insn,
231e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			    unsigned long context)
232e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten{
233e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	unsigned int status;
234e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten
235a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	status = readw(dev->mmio + ICP_MULTI_DAC_CSR);
236e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	if ((status & DAC_BSY) == 0)
237e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten		return 0;
238e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten	return -EBUSY;
23996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
24096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
241bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweetenstatic int icp_multi_ao_insn_write(struct comedi_device *dev,
2420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
243a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten				   struct comedi_insn *insn,
244a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten				   unsigned int *data)
24596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
24665e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten	struct icp_multi_private *devpriv = dev->private;
247bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	unsigned int chan = CR_CHAN(insn->chanspec);
248bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	unsigned int range = CR_RANGE(insn->chanspec);
249bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	int i;
25096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
251b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Disable D/A conversion ready interrupt */
25296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->IntEnable &= ~DAC_READY;
253a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(devpriv->IntEnable, dev->mmio + ICP_MULTI_INT_EN);
25496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
255b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Clear interrupt status */
25696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->IntStatus |= DAC_READY;
257a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(devpriv->IntStatus, dev->mmio + ICP_MULTI_INT_STAT);
25896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
259b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Set up range and channel data */
260b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Bit 4 = 1 : Bipolar */
261b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Bit 5 = 0 : 5V */
262b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Bit 5 = 1 : 10V */
263b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Bits 8-9 : Channel number */
26496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->DacCmdStatus &= 0xfccf;
265d68a8635c5b706e3c037d89fd130e62ddce5c823H Hartley Sweeten	devpriv->DacCmdStatus |= range_codes_analog[range];
26696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	devpriv->DacCmdStatus |= (chan << 8);
26796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
268a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR);
26996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
270bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	for (i = 0; i < insn->n; i++) {
271bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten		unsigned int val = data[i];
272bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten		int ret;
273bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten
274a622afcb7e4c7d24bb29b07e82fd8b7fcd81c0c0Dirk Hohndel		/*  Wait for analogue output data register to be
275a622afcb7e4c7d24bb29b07e82fd8b7fcd81c0c0Dirk Hohndel		 *  ready for new data, or get fed up waiting */
276e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten		ret = comedi_timeout(dev, s, insn, icp_multi_ao_eoc, 0);
277e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten		if (ret) {
278e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			/*  Disable interrupt */
279e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			devpriv->IntEnable &= ~DAC_READY;
280e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			writew(devpriv->IntEnable,
281a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten			       dev->mmio + ICP_MULTI_INT_EN);
28296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
283e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			/*  Clear interrupt status */
284e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			devpriv->IntStatus |= DAC_READY;
285e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			writew(devpriv->IntStatus,
286a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten			       dev->mmio + ICP_MULTI_INT_STAT);
28796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
288e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten			return ret;
289e2fde58204af85f20d08e2dc97b9586d2f34497eH Hartley Sweeten		}
29096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
291bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten		writew(val, dev->mmio + ICP_MULTI_AO);
29296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
293b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton		/*  Set DAC_ST bit to write the data to selected channel */
29496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		devpriv->DacCmdStatus |= DAC_ST;
295a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten		writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR);
29696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		devpriv->DacCmdStatus &= ~DAC_ST;
29796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
298bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten		s->readback[chan] = val;
29996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	}
30096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
301bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	return insn->n;
30296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
30396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
3040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_bits_di(struct comedi_device *dev,
3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  struct comedi_subdevice *s,
306a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten				  struct comedi_insn *insn,
307a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten				  unsigned int *data)
30896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
309a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	data[1] = readw(dev->mmio + ICP_MULTI_DI);
31096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
311a2714e3e42e746d6c8525c35fdcc58fb60c2830dH Hartley Sweeten	return insn->n;
31296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
31396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
3140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_bits_do(struct comedi_device *dev,
3150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  struct comedi_subdevice *s,
31697f4289ad08cffe55de06d4ac4f89ac540450aeeH Hartley Sweeten				  struct comedi_insn *insn,
31797f4289ad08cffe55de06d4ac4f89ac540450aeeH Hartley Sweeten				  unsigned int *data)
31896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
31997f4289ad08cffe55de06d4ac4f89ac540450aeeH Hartley Sweeten	if (comedi_dio_update_state(s, data))
320a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten		writew(s->state, dev->mmio + ICP_MULTI_DO);
32196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
322a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	data[1] = readw(dev->mmio + ICP_MULTI_DI);
32396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
324a2714e3e42e746d6c8525c35fdcc58fb60c2830dH Hartley Sweeten	return insn->n;
32596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
32696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_read_ctr(struct comedi_device *dev,
3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
33096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
33196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	return 0;
33296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
33396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int icp_multi_insn_write_ctr(struct comedi_device *dev,
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    struct comedi_subdevice *s,
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    struct comedi_insn *insn,
3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    unsigned int *data)
33896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
33996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	return 0;
34096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
34196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
34270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t interrupt_service_icp_multi(int irq, void *d)
34396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
34471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
34596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	int int_no;
34696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
347b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Is this interrupt from our board? */
348a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	int_no = readw(dev->mmio + ICP_MULTI_INT_STAT) & Status_IRQ;
34996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	if (!int_no)
350b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton		/*  No, exit */
35196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		return IRQ_NONE;
35296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
353b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Determine which interrupt is active & handle it */
35496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	switch (int_no) {
35596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case ADC_READY:
35696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
35796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case DAC_READY:
35896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
35996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case DOUT_ERROR:
36096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
36196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case DIN_STATUS:
36296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
36396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case CIE0:
36496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
36596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case CIE1:
36696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
36796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case CIE2:
36896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
36996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	case CIE3:
37096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
37196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	default:
37296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		break;
37396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
37496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	}
37596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
37696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	return IRQ_HANDLED;
37796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
37896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
37996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#if 0
3800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int check_channel_list(struct comedi_device *dev,
3810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
3820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      unsigned int *chanlist, unsigned int n_chan)
38396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
38496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	unsigned int i;
38596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
386b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Check that we at least have one channel to check */
38796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	if (n_chan < 1) {
3883df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten		dev_err(dev->class_dev, "range/channel list is empty!\n");
38996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		return 0;
39096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	}
391b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Check all channels */
39296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	for (i = 0; i < n_chan; i++) {
393b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton		/*  Check that channel number is < maximum */
39496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		if (CR_AREF(chanlist[i]) == AREF_DIFF) {
39508567ce9b6b6235897d0895630b88d4cb84f9784H Hartley Sweeten			if (CR_CHAN(chanlist[i]) > (s->nchan / 2)) {
3963df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten				dev_err(dev->class_dev,
3973df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten					"Incorrect differential ai ch-nr\n");
39896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit				return 0;
39996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit			}
40096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		} else {
401281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten			if (CR_CHAN(chanlist[i]) > s->n_chan) {
4023df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten				dev_err(dev->class_dev,
4033df73e07d552051dfaf98c07f9bb818bbff08268H Hartley Sweeten					"Incorrect ai channel number\n");
40496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit				return 0;
40596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit			}
40696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		}
40796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	}
40896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	return 1;
40996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
41096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit#endif
41196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
41271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int icp_multi_reset(struct comedi_device *dev)
41396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
41465e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten	struct icp_multi_private *devpriv = dev->private;
41596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	unsigned int i;
41696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
417b6c777571b8d387d3add91170826f32a379e4313Bill Pemberton	/*  Clear INT enables and requests */
418a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(0, dev->mmio + ICP_MULTI_INT_EN);
419a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(0x00ff, dev->mmio + ICP_MULTI_INT_STAT);
42096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
421fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	/* Set DACs to 0..5V range and 0V output */
422fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	for (i = 0; i < 4; i++) {
423fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		devpriv->DacCmdStatus &= 0xfcce;
42496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
425fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		/*  Set channel number */
426fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		devpriv->DacCmdStatus |= (i << 8);
42796341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
428fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		/*  Output 0V */
429a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten		writew(0, dev->mmio + ICP_MULTI_AO);
43096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
431fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		/*  Set start conversion bit */
432fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		devpriv->DacCmdStatus |= DAC_ST;
43396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
434fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		/*  Output to command / status register */
435a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten		writew(devpriv->DacCmdStatus, dev->mmio + ICP_MULTI_DAC_CSR);
43696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
437fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		/*  Delay to allow DAC time to recover */
438fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten		udelay(1);
439fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	}
440fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten
441fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	/* Digital outputs to 0 */
442a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	writew(0, dev->mmio + ICP_MULTI_DO);
44396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
44496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	return 0;
44596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
44696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
447a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int icp_multi_auto_attach(struct comedi_device *dev,
448750af5e568d060ec6994cdcb4e86cdddfcd473c0Ian Abbott					   unsigned long context_unused)
44996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
450750af5e568d060ec6994cdcb4e86cdddfcd473c0Ian Abbott	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
45165e9e2dc2cca5590affcc299454a783578c9457bH Hartley Sweeten	struct icp_multi_private *devpriv;
45234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
45312b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten	int ret;
454194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten
4550bdab509bf9c6d838dc0a3b1d68bbf841fc20b5aH Hartley Sweeten	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
456c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten	if (!devpriv)
457c34fa261b0ac3a862ccd3f71ee55a16b920dfc83H Hartley Sweeten		return -ENOMEM;
45896341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
459818f569fe930c5b8a05d1a44ece3c63c99c13c88H Hartley Sweeten	ret = comedi_pci_enable(dev);
460194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten	if (ret)
461194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten		return ret;
46296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
463a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	dev->mmio = pci_ioremap_bar(pcidev, 2);
464a3e63288103ccdda45f741a4dad22cb7f12ea105H Hartley Sweeten	if (!dev->mmio)
46596341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		return -ENOMEM;
46696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
46712b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten	ret = comedi_alloc_subdevices(dev, 5);
4688b6c56949ffa83dbc2a6e8fa3f98b10a19372207H Hartley Sweeten	if (ret)
46996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit		return ret;
47096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
47196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	icp_multi_reset(dev);
47296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
473194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten	if (pcidev->irq) {
474194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten		ret = request_irq(pcidev->irq, interrupt_service_icp_multi,
475194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten				  IRQF_SHARED, dev->board_name, dev);
476194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten		if (ret == 0)
477194b9e3cf49319231e8b47125dc5d043350f4406H Hartley Sweeten			dev->irq = pcidev->irq;
478798cdd05e00f2ffb2aa763f5bc2605cd9c08a265H Hartley Sweeten	}
47996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
48012b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten	s = &dev->subdevices[0];
481281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten	dev->read_subdev = s;
482281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten	s->type = COMEDI_SUBD_AI;
48308567ce9b6b6235897d0895630b88d4cb84f9784H Hartley Sweeten	s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
484281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten	s->n_chan = 16;
485efac035ca6eaaf6ca353e730055022cdf03ae7bbH Hartley Sweeten	s->maxdata = 0x0fff;
486281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten	s->len_chanlist = 16;
487abdeac3fd65534dd9b8f46a0fa3ce5c9d545a8f7H Hartley Sweeten	s->range_table = &range_analog;
488281ecb066de68938ce551a7a22d139bc103251a4H Hartley Sweeten	s->insn_read = icp_multi_insn_read_ai;
48996341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
49012b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten	s = &dev->subdevices[1];
491fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	s->type = COMEDI_SUBD_AO;
492fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
493fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	s->n_chan = 4;
49468b82e0954c3a80b230722f5315f7d41eca3d0a2H Hartley Sweeten	s->maxdata = 0x0fff;
495fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	s->len_chanlist = 4;
496fafe91a8b2ea372b76e0cbad995cea8afd77b5daH Hartley Sweeten	s->range_table = &range_analog;
497bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	s->insn_write = icp_multi_ao_insn_write;
498bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	s->insn_read = comedi_readback_insn_read;
499bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten
500bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	ret = comedi_alloc_subdev_readback(s);
501bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten	if (ret)
502bba804d9a336e2eccaf4ad16fccba0f1ee283185H Hartley Sweeten		return ret;
50396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
50412b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten	s = &dev->subdevices[2];
50548f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten	s->type = COMEDI_SUBD_DI;
50648f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten	s->subdev_flags = SDF_READABLE;
50748f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten	s->n_chan = 16;
50848f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten	s->maxdata = 1;
50948f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten	s->len_chanlist = 16;
51048f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten	s->range_table = &range_digital;
51148f31251264c3cabcec274da184ad669c195a627H Hartley Sweeten	s->insn_bits = icp_multi_insn_bits_di;
51296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
51312b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten	s = &dev->subdevices[3];
5142aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten	s->type = COMEDI_SUBD_DO;
5152aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
5162aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten	s->n_chan = 8;
5172aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten	s->maxdata = 1;
5182aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten	s->len_chanlist = 8;
5192aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten	s->range_table = &range_digital;
5202aa707058ffa3c31abf8b7480c7773400cc87d01H Hartley Sweeten	s->insn_bits = icp_multi_insn_bits_do;
52196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
52212b4a097b6fd6d7c7e18dbb40d2ed62cdc26cd3bH Hartley Sweeten	s = &dev->subdevices[4];
5235b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->type = COMEDI_SUBD_COUNTER;
5245b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
5255b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->n_chan = 4;
5265b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->maxdata = 0xffff;
5275b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->len_chanlist = 4;
5285b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->state = 0;
5295b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->insn_read = icp_multi_insn_read_ctr;
5305b93da54bf0a55fd53b96cfb1ac0ce0f8905d1e0H Hartley Sweeten	s->insn_write = icp_multi_insn_write_ctr;
53196341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
53296341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit	return 0;
53396341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
53496341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit
535484ecc95d9cdfa8b2f7029e2f3409cf078aed4abH Hartley Sweetenstatic void icp_multi_detach(struct comedi_device *dev)
53696341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit{
537caf6d12d036ea78e8f54c40fa99320416b040c71H Hartley Sweeten	if (dev->mmio)
538caf6d12d036ea78e8f54c40fa99320416b040c71H Hartley Sweeten		icp_multi_reset(dev);
539aac307f9dd5ce1fe651140a036ab4b0a0571b54aH Hartley Sweeten	comedi_pci_detach(dev);
54096341f71538c48dcec873873cabc11477cf26ae9Anne Smorthit}
54190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
542d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweetenstatic struct comedi_driver icp_multi_driver = {
543d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	.driver_name	= "icp_multi",
544d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	.module		= THIS_MODULE,
545750af5e568d060ec6994cdcb4e86cdddfcd473c0Ian Abbott	.auto_attach	= icp_multi_auto_attach,
546d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten	.detach		= icp_multi_detach,
547d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten};
548554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten
549a690b7e535f2f97a3a05ee570715abeb60a8910fBill Pembertonstatic int icp_multi_pci_probe(struct pci_dev *dev,
550b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten			       const struct pci_device_id *id)
551554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten{
552b8f4ac237e382accd4b30c75043939f7ed9e79a6H Hartley Sweeten	return comedi_pci_auto_config(dev, &icp_multi_driver, id->driver_data);
553554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten}
554554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten
55541e043fcfa2236bb2c4a8335eb09f4c8cee224b3Jingoo Hanstatic const struct pci_device_id icp_multi_pci_table[] = {
556472cd3db7b47a0720678e4c7cc1a472d2c06c218H Hartley Sweeten	{ PCI_DEVICE(PCI_VENDOR_ID_ICP, 0x8000) },
557554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten	{ 0 }
558554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten};
559554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley SweetenMODULE_DEVICE_TABLE(pci, icp_multi_pci_table);
560554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten
561554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweetenstatic struct pci_driver icp_multi_pci_driver = {
562554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten	.name		= "icp_multi",
563554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten	.id_table	= icp_multi_pci_table,
564554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten	.probe		= icp_multi_pci_probe,
5659901a4d75d007686e8f6473189cafc4b216b7449Peter Huewe	.remove		= comedi_pci_auto_unconfig,
566554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweeten};
567554e02c92468dc4958a528a953e590fd3ccd8f84H Hartley Sweetenmodule_comedi_pci_driver(icp_multi_driver, icp_multi_pci_driver);
568d79fc8e161c56626b67226198871c16aa0fcad15H Hartley Sweeten
56990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
57090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
57190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
572