cb_pcidda.c revision 2696fb57e6af653dd8b4df41b16754579f42fc78
1086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
2086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    comedi/drivers/cb_pcidda.c
3086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    This intends to be a driver for the ComputerBoards / MeasurementComputing
4086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    PCI-DDA series.
5086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
7086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
8086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
9086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    COMEDI - Linux Control and Measurement Device Interface
10086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
11086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
12086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    This program is free software; you can redistribute it and/or modify
13086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    it under the terms of the GNU General Public License as published by
14086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    the Free Software Foundation; either version 2 of the License, or
15086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    (at your option) any later version.
16086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
17086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    This program is distributed in the hope that it will be useful,
18086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    but WITHOUT ANY WARRANTY; without even the implied warranty of
19086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    GNU General Public License for more details.
21086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
22086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    You should have received a copy of the GNU General Public License
23086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    along with this program; if not, write to the Free Software
24086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
26086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez*/
27086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
28086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezDriver: cb_pcidda
29086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezDescription: MeasurementComputing PCI-DDA series
30086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezAuthor: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
31086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezStatus: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
32086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezDevices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
33086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez  PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
34086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
35086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezConfiguration options:
36086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez  [0] - PCI bus of device (optional)
37086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez  [1] - PCI slot of device (optional)
38086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez  If bus/slot is not specified, the first available PCI
39086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez  device will be used.
40086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
41086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezOnly simple analog output writing is supported.
42086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
43086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezSo far it has only been tested with:
44086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez  - PCI-DDA08/12
45086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezPlease report success/failure with other different cards to
46086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez<comedi@comedi.org>.
47086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez*/
48086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
49086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#include "../comedidev.h"
50086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
51086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#include "comedi_pci.h"
52086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#include "8255.h"
53086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
542696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PCI_VENDOR_ID_CB	0x1307	/*  PCI vendor number of ComputerBoards */
552696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define N_BOARDS	10	/*  Number of boards in cb_pcidda_boards */
562696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define EEPROM_SIZE	128	/*  number of entries in eeprom */
572696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define MAX_AO_CHANNELS 8	/*  maximum number of ao channels for supported boards */
58086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
59086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* PCI-DDA base addresses */
60086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define DIGITALIO_BADRINDEX	2
612696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  DIGITAL I/O is pci_dev->resource[2] */
62086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define DIGITALIO_SIZE 8
632696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  DIGITAL I/O uses 8 I/O port addresses */
64086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define DAC_BADRINDEX	3
652696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  DAC is pci_dev->resource[3] */
66086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
67086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* Digital I/O registers */
682696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT1A 0		/*  PORT 1A DATA */
69086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
702696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT1B 1		/*  PORT 1B DATA */
71086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
722696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT1C 2		/*  PORT 1C DATA */
73086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
742696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define CONTROL1 3		/*  CONTROL REGISTER 1 */
75086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
762696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT2A 4		/*  PORT 2A DATA */
77086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
782696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT2B 5		/*  PORT 2B DATA */
79086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
802696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT2C 6		/*  PORT 2C DATA */
81086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
822696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define CONTROL2 7		/*  CONTROL REGISTER 2 */
83086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
84086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* DAC registers */
852696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DACONTROL	0	/*  D/A CONTROL REGISTER */
862696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SU	0000001		/*  Simultaneous update enabled */
872696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define NOSU	0000000		/*  Simultaneous update disabled */
882696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	ENABLEDAC	0000002	/*  Enable specified DAC */
892696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DISABLEDAC	0000000	/*  Disable specified DAC */
902696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define RANGE2V5	0000000	/*  2.5V */
912696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define RANGE5V	0000200		/*  5V */
922696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define RANGE10V	0000300	/*  10V */
932696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define UNIP	0000400		/*  Unipolar outputs */
942696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define BIP	0000000		/*  Bipolar outputs */
952696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
962696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DACALIBRATION1	4	/*  D/A CALIBRATION REGISTER 1 */
972696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* write bits */
982696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SERIAL_IN_BIT	0x1	/*  serial data input for eeprom, caldacs, reference dac */
99086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define	CAL_CHANNEL_MASK	(0x7 << 1)
100086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define	CAL_CHANNEL_BITS(channel)	(((channel) << 1) & CAL_CHANNEL_MASK)
1012696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* read bits */
102086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define	CAL_COUNTER_MASK	0x1f
1032696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	CAL_COUNTER_OVERFLOW_BIT	0x20	/*  calibration counter overflow status bit */
1042696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	AO_BELOW_REF_BIT	0x40	/*  analog output is less than reference dac voltage */
1052696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SERIAL_OUT_BIT	0x80	/*  serial data out, for reading from eeprom */
106086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
1072696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DACALIBRATION2	6	/*  D/A CALIBRATION REGISTER 2 */
1082696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SELECT_EEPROM_BIT	0x1	/*  send serial data in to eeprom */
1092696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DESELECT_REF_DAC_BIT	0x2	/*  don't send serial data to MAX542 reference dac */
1102696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DESELECT_CALDAC_BIT(n)	(0x4 << (n))	/*  don't send serial data to caldac n */
1112696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DUMMY_BIT	0x40	/*  manual says to set this bit with no explanation */
112086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
1132696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DADATA	8		/*  FIRST D/A DATA REGISTER (0) */
114086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
1159ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidda_ranges = {
116086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	6,
117086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
118086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			BIP_RANGE(10),
119086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			BIP_RANGE(5),
120086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			BIP_RANGE(2.5),
121086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			UNI_RANGE(10),
122086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			UNI_RANGE(5),
123086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			UNI_RANGE(2.5),
124086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
125086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
126086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
127086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
128086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Board descriptions for two imaginary boards.  Describing the
129086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * boards in this way is optional, and completely driver-dependent.
130086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Some drivers use arrays such as this, other do not.
131086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
1321657e325042ffc723182377a47d38ccc7319078fBill Pembertonstruct cb_pcidda_board {
133086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	const char *name;
1342696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	char status;		/*  Driver status: */
1352696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
1362696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*
1372696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 * 0 - tested
1382696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 * 1 - manual read, not tested
1392696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 * 2 - manual not read
1402696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 */
1412696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
142086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned short device_id;
143086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int ao_chans;
144086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int ao_bits;
1459ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *ranges;
1461657e325042ffc723182377a47d38ccc7319078fBill Pemberton};
1472696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
1481657e325042ffc723182377a47d38ccc7319078fBill Pembertonstatic const struct cb_pcidda_board cb_pcidda_boards[] = {
149086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
150086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      name:	"pci-dda02/12",
151086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      status:	1,
152086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      device_id:0x20,
153086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_chans:2,
154086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_bits:	12,
155086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ranges:	&cb_pcidda_ranges,
156086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		},
157086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
158086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      name:	"pci-dda04/12",
159086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      status:	1,
160086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      device_id:0x21,
161086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_chans:4,
162086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_bits:	12,
163086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ranges:	&cb_pcidda_ranges,
164086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		},
165086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
166086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      name:	"pci-dda08/12",
167086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      status:	0,
168086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      device_id:0x22,
169086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_chans:8,
170086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_bits:	12,
171086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ranges:	&cb_pcidda_ranges,
172086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		},
173086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
174086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      name:	"pci-dda02/16",
175086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      status:	2,
176086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      device_id:0x23,
177086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_chans:2,
178086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_bits:	16,
179086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ranges:	&cb_pcidda_ranges,
180086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		},
181086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
182086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      name:	"pci-dda04/16",
183086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      status:	2,
184086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      device_id:0x24,
185086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_chans:4,
186086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_bits:	16,
187086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ranges:	&cb_pcidda_ranges,
188086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		},
189086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
190086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      name:	"pci-dda08/16",
191086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      status:	0,
192086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      device_id:0x25,
193086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_chans:8,
194086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ao_bits:	16,
195086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	      ranges:	&cb_pcidda_ranges,
196086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		},
197086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
198086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
199086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
200086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{PCI_VENDOR_ID_CB, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
201086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{PCI_VENDOR_ID_CB, 0x0021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
202086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{PCI_VENDOR_ID_CB, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
203086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{PCI_VENDOR_ID_CB, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
204086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{PCI_VENDOR_ID_CB, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
205086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{PCI_VENDOR_ID_CB, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
206086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{0}
207086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
208086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
209086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezMODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
210086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
211086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
212086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Useful for shorthand access to the particular board structure
213086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
2141657e325042ffc723182377a47d38ccc7319078fBill Pemberton#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
215086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
216086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* this structure is for data unique to this hardware driver.  If
217086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez   several hardware drivers keep similar information in this structure,
21871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton   feel free to suggest moving the variable to the struct comedi_device struct.  */
219cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pembertonstruct cb_pcidda_private {
220086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int data;
221086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
222086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* would be useful for a PCI device */
223086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	struct pci_dev *pci_dev;
224086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
225086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned long digitalio;
226086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned long dac;
2272696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
2282696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* unsigned long control_status; */
2292696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* unsigned long adc_fifo; */
2302696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
2312696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	unsigned int dac_cal1_bits;	/*  bits last written to da calibration register 1 */
2322696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	unsigned int ao_range[MAX_AO_CHANNELS];	/*  current range settings for output channels */
2332696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	u16 eeprom_data[EEPROM_SIZE];	/*  software copy of board's eeprom */
234cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pemberton};
235086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
236086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
237086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * most drivers define the following macro to make it easy to
238086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * access the private structure.
239086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
240cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pemberton#define devpriv ((struct cb_pcidda_private *)dev->private)
241086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
2420707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it);
24371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidda_detach(struct comedi_device * dev);
2442696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
24534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
24690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
2472696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
2482696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
2492696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
2502696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
2512696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
25271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic unsigned int cb_pcidda_serial_in(struct comedi_device * dev);
25371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
254086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int num_bits);
25571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
256086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int address);
25771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel,
258086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int range);
259086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
260086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
261139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module
262086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * which functions to call to configure/deconfigure (attach/detach)
263086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the board, and also about the kernel module that contains
264086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the device code.
265086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
266139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_cb_pcidda = {
267086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez      driver_name:"cb_pcidda",
268086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez      module:THIS_MODULE,
269086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez      attach:cb_pcidda_attach,
270086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez      detach:cb_pcidda_detach,
271086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
272086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
273086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
274086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Attach is called by the Comedi core to configure the driver
275086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * for a particular board.
276086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
2770707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int cb_pcidda_attach(struct comedi_device * dev, struct comedi_devconfig * it)
278086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
27934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
280086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	struct pci_dev *pcidev;
281086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int index;
282086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
283086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("comedi%d: cb_pcidda: ", dev->minor);
284086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
285086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
286086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Allocate the private structure area.
287086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
288cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pemberton	if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
289086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -ENOMEM;
290086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
291086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
292086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Probe the device to determine what device in the series it is.
293086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
294086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("\n");
295086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
296086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
297086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		pcidev != NULL;
298086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
299086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (pcidev->vendor == PCI_VENDOR_ID_CB) {
300086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			if (it->options[0] || it->options[1]) {
301086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				if (pcidev->bus->number != it->options[0] ||
302086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez					PCI_SLOT(pcidev->devfn) !=
303086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez					it->options[1]) {
304086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez					continue;
305086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				}
306086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			}
307086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			for (index = 0; index < N_BOARDS; index++) {
308086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				if (cb_pcidda_boards[index].device_id ==
309086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez					pcidev->device) {
310086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez					goto found;
311086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				}
312086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			}
313086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
314086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
315086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!pcidev) {
316086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		printk("Not a ComputerBoards/MeasurementComputing card on requested position\n");
317086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -EIO;
318086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
319086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez      found:
320086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->pci_dev = pcidev;
321086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	dev->board_ptr = cb_pcidda_boards + index;
3222696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  "thisboard" macro can be used from here. */
323086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("Found %s at requested position\n", thisboard->name);
324086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
325086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/*
326086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * Enable PCI device and request regions.
327086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 */
328086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (comedi_pci_enable(pcidev, thisboard->name)) {
329086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		printk("cb_pcidda: failed to enable PCI device and request regions\n");
330086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -EIO;
331086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
332086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
333086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
334086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Allocate the I/O ports.
335086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
336086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->digitalio =
337086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		pci_resource_start(devpriv->pci_dev, DIGITALIO_BADRINDEX);
338086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->dac = pci_resource_start(devpriv->pci_dev, DAC_BADRINDEX);
339086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
340086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
341086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Warn about the status of the driver.
342086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
343086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (thisboard->status == 2)
344086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		printk("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. " "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. " "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
345086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
346086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
347086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Initialize dev->board_name.
348086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
349086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	dev->board_name = thisboard->name;
350086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
351086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
352086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Allocate the subdevice structures.
353086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
354086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (alloc_subdevices(dev, 3) < 0)
355086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -ENOMEM;
356086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
357086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s = dev->subdevices + 0;
358086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* analog output subdevice */
359086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->type = COMEDI_SUBD_AO;
360086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->subdev_flags = SDF_WRITABLE;
361086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->n_chan = thisboard->ao_chans;
362086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->maxdata = (1 << thisboard->ao_bits) - 1;
363086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->range_table = thisboard->ranges;
364086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->insn_write = cb_pcidda_ao_winsn;
365086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
3662696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* s->subdev_flags |= SDF_CMD_READ; */
3672696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* s->do_cmd = cb_pcidda_ai_cmd; */
3682696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
3692696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
3702696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  two 8255 digital io subdevices */
371086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s = dev->subdevices + 1;
372086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	subdev_8255_init(dev, s, NULL, devpriv->digitalio);
373086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s = dev->subdevices + 2;
374086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
375086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
376086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk(" eeprom:");
377086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (index = 0; index < EEPROM_SIZE; index++) {
378086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
379086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		printk(" %i:0x%x ", index, devpriv->eeprom_data[index]);
380086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
381086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("\n");
382086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
3832696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  set calibrations dacs */
384086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (index = 0; index < thisboard->ao_chans; index++)
385086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
386086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
387086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 1;
388086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
389086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
390086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
391086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * _detach is called to deconfigure a device.  It should deallocate
392086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * resources.
393086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * This function is also called when _attach() fails, so it should be
394086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * careful not to release resources that were not necessarily
395086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * allocated by _attach().  dev->private and dev->subdevices are
396086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * deallocated automatically by the core.
397086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
39871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidda_detach(struct comedi_device * dev)
399086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
400086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
401086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Deallocate the I/O ports.
402086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
403086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (devpriv) {
404086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (devpriv->pci_dev) {
405086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			if (devpriv->dac) {
406086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				comedi_pci_disable(devpriv->pci_dev);
407086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			}
408086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			pci_dev_put(devpriv->pci_dev);
409086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
410086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
4112696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  cleanup 8255 */
412086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (dev->subdevices) {
413086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 1);
414086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 2);
415086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
416086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
417086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("comedi%d: cb_pcidda: remove\n", dev->minor);
418086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
419086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0;
420086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
421086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
422086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
423086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * I will program this later... ;-)
424086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
425086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#if 0
42634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidda_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
427086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
428086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("cb_pcidda_ai_cmd\n");
429086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("subdev: %d\n", cmd->subdev);
430086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("flags: %d\n", cmd->flags);
431086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("start_src: %d\n", cmd->start_src);
432086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("start_arg: %d\n", cmd->start_arg);
433086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("scan_begin_src: %d\n", cmd->scan_begin_src);
434086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("convert_src: %d\n", cmd->convert_src);
435086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("convert_arg: %d\n", cmd->convert_arg);
436086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("scan_end_src: %d\n", cmd->scan_end_src);
437086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("scan_end_arg: %d\n", cmd->scan_end_arg);
438086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("stop_src: %d\n", cmd->stop_src);
439086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("stop_arg: %d\n", cmd->stop_arg);
440086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("chanlist_len: %d\n", cmd->chanlist_len);
441086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
442086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#endif
443086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
444086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#if 0
44534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidda_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
446ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd)
447086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
448086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int err = 0;
449086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int tmp;
450086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
451086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* cmdtest tests a particular command to see if it is valid.
452086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
453086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * and then have it executes by the cmd ioctl.
454086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 *
455086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
456086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * the command passes. */
457086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
458086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 1: make sure trigger sources are trivially valid */
459086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
460086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->start_src;
461086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->start_src &= TRIG_NOW;
462086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
463086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
464086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
465086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->scan_begin_src;
466086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
467086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
468086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
469086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
470086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->convert_src;
471086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
472086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
473086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
474086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
475086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->scan_end_src;
476086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->scan_end_src &= TRIG_COUNT;
477086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
478086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
479086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
480086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->stop_src;
481086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
482086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
483086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
484086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
485086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
486086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 1;
487086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
488086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
489086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
490086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* note that mutual compatiblity is not an issue here */
491086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_begin_src != TRIG_TIMER
492086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		&& cmd->scan_begin_src != TRIG_EXT)
493086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
494086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
495086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
496086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
497086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
498086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
499086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
500086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 2;
501086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
502086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 3: make sure arguments are trivially compatible */
503086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
504086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->start_arg != 0) {
505086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cmd->start_arg = 0;
506086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
507086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
508086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define MAX_SPEED	10000	/* in nanoseconds */
509086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define MIN_SPEED	1000000000	/* in nanoseconds */
510086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
511086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
512086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_arg < MAX_SPEED) {
513086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg = MAX_SPEED;
514086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
515086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
516086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_arg > MIN_SPEED) {
517086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg = MIN_SPEED;
518086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
519086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
520086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	} else {
521086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* external trigger */
522086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* should be level/edge, hi/lo specification here */
523086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* should specify multiple external triggers */
524086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_arg > 9) {
525086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg = 9;
526086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
527086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
528086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
529086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->convert_src == TRIG_TIMER) {
530086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->convert_arg < MAX_SPEED) {
531086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->convert_arg = MAX_SPEED;
532086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
533086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
534086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->convert_arg > MIN_SPEED) {
535086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->convert_arg = MIN_SPEED;
536086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
537086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
538086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	} else {
539086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* external trigger */
540086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* see above */
541086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->convert_arg > 9) {
542086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->convert_arg = 9;
543086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
544086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
545086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
546086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
547086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
548086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
549086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
550086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
551086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->stop_src == TRIG_COUNT) {
552086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->stop_arg > 0x00ffffff) {
553086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->stop_arg = 0x00ffffff;
554086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
555086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
556086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	} else {
557086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* TRIG_NONE */
558086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->stop_arg != 0) {
559086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->stop_arg = 0;
560086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
561086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
562086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
563086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
564086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
565086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 3;
566086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
567086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 4: fix up any arguments */
568086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
569086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
570086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		tmp = cmd->scan_begin_arg;
571086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cb_pcidda_ns_to_timer(&cmd->scan_begin_arg,
572086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->flags & TRIG_ROUND_MASK);
573086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (tmp != cmd->scan_begin_arg)
574086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
575086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
576086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->convert_src == TRIG_TIMER) {
577086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		tmp = cmd->convert_arg;
578086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cb_pcidda_ns_to_timer(&cmd->convert_arg,
579086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->flags & TRIG_ROUND_MASK);
580086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (tmp != cmd->convert_arg)
581086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
582086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_src == TRIG_TIMER &&
583086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg <
584086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->convert_arg * cmd->scan_end_arg) {
585086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg =
586086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				cmd->convert_arg * cmd->scan_end_arg;
587086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
588086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
589086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
590086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
591086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
592086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 4;
593086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
594086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0;
595086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
596086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#endif
597086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
598086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* This function doesn't require a particular form, this is just
599086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * what happens to be used in some of the drivers.  It should
600086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * convert ns nanoseconds to a counter value suitable for programming
601086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the device.  Also, it should adjust ns so that it cooresponds to
602086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the actual time that the device will use. */
603086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#if 0
604086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
605086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
606086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* trivial timer */
607086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return *ns;
608086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
609086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#endif
610086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
61134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidda_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
61290035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
613086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
614086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int command;
615086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int channel, range;
616086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
617086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	channel = CR_CHAN(insn->chanspec);
618086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	range = CR_RANGE(insn->chanspec);
619086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6202696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  adjust calibration dacs if range has changed */
621086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (range != devpriv->ao_range[channel])
622086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cb_pcidda_calibrate(dev, channel, range);
623086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
624086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* output channel configuration */
625086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	command = NOSU | ENABLEDAC;
626086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
627086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* output channel range */
628086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	switch (range) {
629086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	case 0:
630086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		command |= BIP | RANGE10V;
631086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		break;
632086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	case 1:
633086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		command |= BIP | RANGE5V;
634086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		break;
635086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	case 2:
636086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		command |= BIP | RANGE2V5;
637086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		break;
638086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	case 3:
639086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		command |= UNIP | RANGE10V;
640086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		break;
641086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	case 4:
642086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		command |= UNIP | RANGE5V;
643086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		break;
644086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	case 5:
645086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		command |= UNIP | RANGE2V5;
646086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		break;
647086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	};
648086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
649086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* output channel specification */
650086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	command |= channel << 2;
651086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw(command, devpriv->dac + DACONTROL);
652086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
653086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* write data */
654086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw(data[0], devpriv->dac + DADATA + channel * 2);
655086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
656086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* return the number of samples read/written */
657086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 1;
658086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
659086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6602696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* lowlevel read from eeprom */
66171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic unsigned int cb_pcidda_serial_in(struct comedi_device * dev)
662086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
663086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int value = 0;
664086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int i;
6652696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int value_width = 16;	/*  number of bits wide values are */
666086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
667086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (i = 1; i <= value_width; i++) {
6682696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton		/*  read bits most significant bit first */
669086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) {
670086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			value |= 1 << (value_width - i);
671086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
672086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
673086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
674086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return value;
675086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
676086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6772696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* lowlevel write to eeprom/dac */
67871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidda_serial_out(struct comedi_device * dev, unsigned int value,
679086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int num_bits)
680086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
681086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int i;
682086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
683086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (i = 1; i <= num_bits; i++) {
6842696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton		/*  send bits most significant bit first */
685086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (value & (1 << (num_bits - i)))
686086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
687086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		else
688086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
689086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
690086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
691086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
692086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6932696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* reads a 16 bit value from board's eeprom */
69471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic unsigned int cb_pcidda_read_eeprom(struct comedi_device * dev,
695086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int address)
696086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
697086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int i;
698086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int cal2_bits;
699086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int value;
7002696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int max_num_caldacs = 4;	/*  one caldac for every two dac channels */
7012696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int read_instruction = 0x6;	/*  bits to send to tell eeprom we want to read */
702086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	const int instruction_length = 3;
703086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	const int address_length = 8;
704086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7052696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  send serial output stream to eeprom */
706086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
7072696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate caldacs (one caldac for every two channels) */
708086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (i = 0; i < max_num_caldacs; i++) {
709086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cal2_bits |= DESELECT_CALDAC_BIT(i);
710086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
711086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
712086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7132696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  tell eeprom we want to read */
714086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, read_instruction, instruction_length);
7152696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  send address we want to read from */
716086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, address, address_length);
717086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
718086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	value = cb_pcidda_serial_in(dev);
719086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7202696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate eeprom */
721086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits &= ~SELECT_EEPROM_BIT;
722086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
723086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
724086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return value;
725086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
726086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7272696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* writes to 8 bit calibration dacs */
72871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidda_write_caldac(struct comedi_device * dev, unsigned int caldac,
729086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int channel, unsigned int value)
730086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
731086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int cal2_bits;
732086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int i;
7332696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int num_channel_bits = 3;	/*  caldacs use 3 bit channel specification */
7342696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int num_caldac_bits = 8;	/*  8 bit calibration dacs */
7352696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int max_num_caldacs = 4;	/*  one caldac for every two dac channels */
736086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
737086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* write 3 bit channel */
738086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, channel, num_channel_bits);
7392696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  write 8 bit caldac value */
740086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, value, num_caldac_bits);
741086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7422696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/*
7432696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton* latch stream into appropriate caldac deselect reference dac
7442696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton*/
745086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
7462696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate caldacs (one caldac for every two channels) */
747086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (i = 0; i < max_num_caldacs; i++) {
748086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cal2_bits |= DESELECT_CALDAC_BIT(i);
749086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
7502696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  activate the caldac we want */
751086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
752086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
7532696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate caldac */
754086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits |= DESELECT_CALDAC_BIT(caldac);
755086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
756086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
757086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7582696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac that calibrates given analog out channel */
759086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int caldac_number(unsigned int channel)
760086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
761086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return channel / 2;
762086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
763086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7642696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides fine gain for given ao channel */
765086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int fine_gain_channel(unsigned int ao_channel)
766086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
767086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 4 * (ao_channel % 2);
768086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
769086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7702696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides coarse gain for given ao channel */
771086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int coarse_gain_channel(unsigned int ao_channel)
772086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
773086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 1 + 4 * (ao_channel % 2);
774086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
775086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7762696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides coarse offset for given ao channel */
777086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int coarse_offset_channel(unsigned int ao_channel)
778086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
779086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 2 + 4 * (ao_channel % 2);
780086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
781086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7822696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides fine offset for given ao channel */
783086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int fine_offset_channel(unsigned int ao_channel)
784086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
785086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 3 + 4 * (ao_channel % 2);
786086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
787086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7882696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns eeprom address that provides offset for given ao channel and range */
789086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int offset_eeprom_address(unsigned int ao_channel,
790086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int range)
791086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
792086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0x7 + 2 * range + 12 * ao_channel;
793086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
794086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7952696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns eeprom address that provides gain calibration for given ao channel and range */
796086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int gain_eeprom_address(unsigned int ao_channel,
797086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int range)
798086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
799086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0x8 + 2 * range + 12 * ao_channel;
800086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
801086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8022696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns upper byte of eeprom entry, which gives the coarse adjustment values */
803086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int eeprom_coarse_byte(unsigned int word)
804086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
805086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return (word >> 8) & 0xff;
806086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
807086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8082696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns lower byte of eeprom entry, which gives the fine adjustment values */
809086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int eeprom_fine_byte(unsigned int word)
810086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
811086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return word & 0xff;
812086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
813086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8142696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* set caldacs to eeprom values for given channel and range */
81571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidda_calibrate(struct comedi_device * dev, unsigned int channel,
816086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int range)
817086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
818086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
819086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8202696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  remember range so we can tell when we need to readjust calibration */
821086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->ao_range[channel] = range;
822086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8232696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  get values from eeprom data */
824086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	coarse_offset =
825086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_coarse_byte(devpriv->
826086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_data[offset_eeprom_address(channel, range)]);
827086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	fine_offset =
828086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_fine_byte(devpriv->
829086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_data[offset_eeprom_address(channel, range)]);
830086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	coarse_gain =
831086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_coarse_byte(devpriv->
832086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_data[gain_eeprom_address(channel, range)]);
833086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	fine_gain =
834086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_fine_byte(devpriv->
835086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		eeprom_data[gain_eeprom_address(channel, range)]);
836086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8372696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  set caldacs */
838086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
839086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		coarse_offset_channel(channel), coarse_offset);
840086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
841086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		fine_offset_channel(channel), fine_offset);
842086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
843086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		coarse_gain_channel(channel), coarse_gain);
844086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
845086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		fine_gain_channel(channel), fine_gain);
846086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
847086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
848086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
849086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * A convenient macro that defines init_module() and cleanup_module(),
850086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * as necessary.
851086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
852086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezCOMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table);
853