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 EEPROM_SIZE	128	/*  number of entries in eeprom */
562696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define MAX_AO_CHANNELS 8	/*  maximum number of ao channels for supported boards */
57086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
58086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* PCI-DDA base addresses */
59086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define DIGITALIO_BADRINDEX	2
602696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  DIGITAL I/O is pci_dev->resource[2] */
61086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define DIGITALIO_SIZE 8
622696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  DIGITAL I/O uses 8 I/O port addresses */
63086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define DAC_BADRINDEX	3
642696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  DAC is pci_dev->resource[3] */
65086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
66086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* Digital I/O registers */
672696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT1A 0		/*  PORT 1A DATA */
68086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
692696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT1B 1		/*  PORT 1B DATA */
70086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
712696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT1C 2		/*  PORT 1C DATA */
72086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
732696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define CONTROL1 3		/*  CONTROL REGISTER 1 */
74086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
752696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT2A 4		/*  PORT 2A DATA */
76086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
772696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT2B 5		/*  PORT 2B DATA */
78086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
792696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define PORT2C 6		/*  PORT 2C DATA */
80086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
812696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define CONTROL2 7		/*  CONTROL REGISTER 2 */
82086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
83086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* DAC registers */
842696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DACONTROL	0	/*  D/A CONTROL REGISTER */
852696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SU	0000001		/*  Simultaneous update enabled */
862696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define NOSU	0000000		/*  Simultaneous update disabled */
872696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	ENABLEDAC	0000002	/*  Enable specified DAC */
882696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DISABLEDAC	0000000	/*  Disable specified DAC */
892696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define RANGE2V5	0000000	/*  2.5V */
902696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define RANGE5V	0000200		/*  5V */
912696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define RANGE10V	0000300	/*  10V */
922696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define UNIP	0000400		/*  Unipolar outputs */
932696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define BIP	0000000		/*  Bipolar outputs */
942696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
952696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DACALIBRATION1	4	/*  D/A CALIBRATION REGISTER 1 */
962696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* write bits */
972696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SERIAL_IN_BIT	0x1	/*  serial data input for eeprom, caldacs, reference dac */
98086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define	CAL_CHANNEL_MASK	(0x7 << 1)
99086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define	CAL_CHANNEL_BITS(channel)	(((channel) << 1) & CAL_CHANNEL_MASK)
1002696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* read bits */
101086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define	CAL_COUNTER_MASK	0x1f
1022696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	CAL_COUNTER_OVERFLOW_BIT	0x20	/*  calibration counter overflow status bit */
1032696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	AO_BELOW_REF_BIT	0x40	/*  analog output is less than reference dac voltage */
1042696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SERIAL_OUT_BIT	0x80	/*  serial data out, for reading from eeprom */
105086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
1062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DACALIBRATION2	6	/*  D/A CALIBRATION REGISTER 2 */
1072696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	SELECT_EEPROM_BIT	0x1	/*  send serial data in to eeprom */
1082696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DESELECT_REF_DAC_BIT	0x2	/*  don't send serial data to MAX542 reference dac */
1092696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DESELECT_CALDAC_BIT(n)	(0x4 << (n))	/*  don't send serial data to caldac n */
1102696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define	DUMMY_BIT	0x40	/*  manual says to set this bit with no explanation */
111086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
1122696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton#define DADATA	8		/*  FIRST D/A DATA REGISTER (0) */
113086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
1149ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidda_ranges = {
115086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	6,
116086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
1170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
1180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(2.5),
1200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(10),
1210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(5),
1220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(2.5),
1230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
124086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
125086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
126086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
127086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Board descriptions for two imaginary boards.  Describing the
128086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * boards in this way is optional, and completely driver-dependent.
129086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Some drivers use arrays such as this, other do not.
130086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
1311657e325042ffc723182377a47d38ccc7319078fBill Pembertonstruct cb_pcidda_board {
132086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	const char *name;
1332696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	char status;		/*  Driver status: */
1342696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
1352696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*
1362696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 * 0 - tested
1372696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 * 1 - manual read, not tested
1382696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 * 2 - manual not read
1392696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	 */
1402696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
141086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned short device_id;
142086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int ao_chans;
143086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int ao_bits;
1449ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *ranges;
1451657e325042ffc723182377a47d38ccc7319078fBill Pemberton};
1462696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
1471657e325042ffc723182377a47d38ccc7319078fBill Pembertonstatic const struct cb_pcidda_board cb_pcidda_boards[] = {
148086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
1490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dda02/12",
1500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .status = 1,
1510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x20,
1520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_chans = 2,
1530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_bits = 12,
1540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidda_ranges,
1550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
156086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
1570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dda04/12",
1580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .status = 1,
1590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x21,
1600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_chans = 4,
1610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_bits = 12,
1620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidda_ranges,
1630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
164086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
1650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dda08/12",
1660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .status = 0,
1670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x22,
1680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_chans = 8,
1690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_bits = 12,
1700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidda_ranges,
1710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
172086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
1730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dda02/16",
1740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .status = 2,
1750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x23,
1760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_chans = 2,
1770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_bits = 16,
1780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidda_ranges,
1790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
180086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
1810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dda04/16",
1820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .status = 2,
1830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x24,
1840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_chans = 4,
1850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_bits = 16,
1860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidda_ranges,
1870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
188086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	{
1890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-dda08/16",
1900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .status = 0,
1910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x25,
1920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_chans = 8,
1930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_bits = 16,
1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidda_ranges,
1950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
196086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
197086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
198086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
19907c2412a5e65f3f7087473d86742b418cd4c96fbJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0020) },
20007c2412a5e65f3f7087473d86742b418cd4c96fbJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0021) },
20107c2412a5e65f3f7087473d86742b418cd4c96fbJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0022) },
20207c2412a5e65f3f7087473d86742b418cd4c96fbJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0023) },
20307c2412a5e65f3f7087473d86742b418cd4c96fbJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0024) },
20407c2412a5e65f3f7087473d86742b418cd4c96fbJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0025) },
20507c2412a5e65f3f7087473d86742b418cd4c96fbJavier Martinez Canillas	{ 0 }
206086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
207086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
208086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan MartinezMODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
209086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
210086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
211086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Useful for shorthand access to the particular board structure
212086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
2131657e325042ffc723182377a47d38ccc7319078fBill Pemberton#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
214086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
215086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* this structure is for data unique to this hardware driver.  If
216086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez   several hardware drivers keep similar information in this structure,
21771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton   feel free to suggest moving the variable to the struct comedi_device struct.  */
218cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pembertonstruct cb_pcidda_private {
219086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int data;
220086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
221086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* would be useful for a PCI device */
222086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	struct pci_dev *pci_dev;
223086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
224086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned long digitalio;
225086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned long dac;
2262696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
2272696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* unsigned long control_status; */
2282696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* unsigned long adc_fifo; */
2292696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
2302696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	unsigned int dac_cal1_bits;	/*  bits last written to da calibration register 1 */
2312696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	unsigned int ao_range[MAX_AO_CHANNELS];	/*  current range settings for output channels */
2322696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	u16 eeprom_data[EEPROM_SIZE];	/*  software copy of board's eeprom */
233cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pemberton};
234086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
235086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
236086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * most drivers define the following macro to make it easy to
237086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * access the private structure.
238086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
239cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pemberton#define devpriv ((struct cb_pcidda_private *)dev->private)
240086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
2410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidda_attach(struct comedi_device *dev,
2420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_devconfig *it);
243da91b2692e0939b307f9047192d2b9fe07793e7aBill 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); */
2450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidda_ao_winsn(struct comedi_device *dev,
2460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
2470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data);
2482696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
2492696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
2502696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
2512696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
2522696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
253da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
254da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
2550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 unsigned int num_bits);
256da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
2570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  unsigned int address);
258da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
2590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				unsigned int range);
260086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
261086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
262139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module
263086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * which functions to call to configure/deconfigure (attach/detach)
264086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the board, and also about the kernel module that contains
265086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the device code.
266086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
267139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_cb_pcidda = {
26868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "cb_pcidda",
26968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
27068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = cb_pcidda_attach,
27168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = cb_pcidda_detach,
272086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez};
273086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
274086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
275086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Attach is called by the Comedi core to configure the driver
276086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * for a particular board.
277086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
2780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidda_attach(struct comedi_device *dev,
2790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_devconfig *it)
280086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
28134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
28220fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	struct pci_dev *pcidev = NULL;
283086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int index;
284086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
285086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
286086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
287086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Allocate the private structure area.
288086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
289cc7bb61e00a2e9e4e0d742b9917cb37406080922Bill Pemberton	if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
290086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -ENOMEM;
291086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
292086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
293086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Probe the device to determine what device in the series it is.
294086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
295086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
29620fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	for_each_pci_dev(pcidev) {
297086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (pcidev->vendor == PCI_VENDOR_ID_CB) {
298086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			if (it->options[0] || it->options[1]) {
299086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				if (pcidev->bus->number != it->options[0] ||
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    PCI_SLOT(pcidev->devfn) != it->options[1]) {
301086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez					continue;
302086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				}
303086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			}
304821e67a135d8773c8e9c0b97088b2e64c3d0d631Dan Carpenter			for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) {
305086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				if (cb_pcidda_boards[index].device_id ==
3060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    pcidev->device) {
307086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez					goto found;
308086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				}
309086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			}
310086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
311086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
312086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!pcidev) {
313143c128cc1c024189da84911df3819cc5036caeaRavishankar karkala Mallikarjunayya		dev_err(dev->hw_dev, "Not a ComputerBoards/MeasurementComputing card on requested position\n");
314086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -EIO;
315086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
3160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
317086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->pci_dev = pcidev;
318086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	dev->board_ptr = cb_pcidda_boards + index;
3192696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  "thisboard" macro can be used from here. */
320143c128cc1c024189da84911df3819cc5036caeaRavishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "Found %s at requested position\n",
321143c128cc1c024189da84911df3819cc5036caeaRavishankar karkala Mallikarjunayya		thisboard->name);
322086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
323086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/*
324086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * Enable PCI device and request regions.
325086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 */
326086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (comedi_pci_enable(pcidev, thisboard->name)) {
327143c128cc1c024189da84911df3819cc5036caeaRavishankar karkala Mallikarjunayya		dev_err(dev->hw_dev, "cb_pcidda: failed to enable PCI device and request regions\n");
328086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -EIO;
329086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
330086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
331086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
332086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Allocate the I/O ports.
333086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
334086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->digitalio =
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, DIGITALIO_BADRINDEX);
336086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->dac = pci_resource_start(devpriv->pci_dev, DAC_BADRINDEX);
337086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
338086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
339086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Warn about the status of the driver.
340086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
341086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (thisboard->status == 2)
3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
346086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
347086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
348086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Initialize dev->board_name.
349086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
350086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	dev->board_name = thisboard->name;
351086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
352086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
353086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * Allocate the subdevice structures.
354086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
355086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (alloc_subdevices(dev, 3) < 0)
356086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return -ENOMEM;
357086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
358086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s = dev->subdevices + 0;
359086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* analog output subdevice */
360086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->type = COMEDI_SUBD_AO;
361086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->subdev_flags = SDF_WRITABLE;
362086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->n_chan = thisboard->ao_chans;
363086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->maxdata = (1 << thisboard->ao_bits) - 1;
364086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->range_table = thisboard->ranges;
365086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s->insn_write = cb_pcidda_ao_winsn;
366086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
3672696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* s->subdev_flags |= SDF_CMD_READ; */
3682696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* s->do_cmd = cb_pcidda_ai_cmd; */
3692696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
3702696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton
3712696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  two 8255 digital io subdevices */
372086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s = dev->subdevices + 1;
373086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	subdev_8255_init(dev, s, NULL, devpriv->digitalio);
374086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	s = dev->subdevices + 2;
375086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
376086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
377143c128cc1c024189da84911df3819cc5036caeaRavishankar karkala Mallikarjunayya	dev_dbg(dev->hw_dev, "eeprom:\n");
378086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (index = 0; index < EEPROM_SIZE; index++) {
379086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
380143c128cc1c024189da84911df3819cc5036caeaRavishankar karkala Mallikarjunayya		dev_dbg(dev->hw_dev, "%i:0x%x\n", index, devpriv->eeprom_data[index]);
381086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
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 */
398da91b2692e0939b307f9047192d2b9fe07793e7aBill 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) {
40520db7d7de7027ddee5df1b51b3d013568273b9dfAndrea Gelmini			if (devpriv->dac)
406086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez				comedi_pci_disable(devpriv->pci_dev);
407086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			pci_dev_put(devpriv->pci_dev);
408086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
409086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
4102696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  cleanup 8255 */
411086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (dev->subdevices) {
412086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 1);
413086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 2);
414086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
415086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
416086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0;
417086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
418086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
419086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
420086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * I will program this later... ;-)
421086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
422086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#if 0
4230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidda_ai_cmd(struct comedi_device *dev,
4240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
425086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
426086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("cb_pcidda_ai_cmd\n");
427086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("subdev: %d\n", cmd->subdev);
428086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("flags: %d\n", cmd->flags);
429086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("start_src: %d\n", cmd->start_src);
430086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("start_arg: %d\n", cmd->start_arg);
431086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("scan_begin_src: %d\n", cmd->scan_begin_src);
432086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("convert_src: %d\n", cmd->convert_src);
433086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("convert_arg: %d\n", cmd->convert_arg);
434086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("scan_end_src: %d\n", cmd->scan_end_src);
435086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("scan_end_arg: %d\n", cmd->scan_end_arg);
436086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("stop_src: %d\n", cmd->stop_src);
437086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("stop_arg: %d\n", cmd->stop_arg);
438086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	printk("chanlist_len: %d\n", cmd->chanlist_len);
439086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
440086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#endif
441086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
442086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#if 0
4430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
4440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
4450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd)
446086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
447086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int err = 0;
448086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int tmp;
449086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
450086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* cmdtest tests a particular command to see if it is valid.
451086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
452086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * and then have it executes by the cmd ioctl.
453086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 *
454086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
455086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	 * the command passes. */
456086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
457086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 1: make sure trigger sources are trivially valid */
458086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
459086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->start_src;
460086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->start_src &= TRIG_NOW;
461086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
462086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
463086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
464086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->scan_begin_src;
465086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
466086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
467086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
468086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
469086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->convert_src;
470086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
471086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
472086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
473086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
474086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->scan_end_src;
475086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->scan_end_src &= TRIG_COUNT;
476086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
477086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
478086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
479086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	tmp = cmd->stop_src;
480086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
481086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
482086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
483086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
484086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
485086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 1;
486086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
487086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
488086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
489828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel	/* note that mutual compatibility is not an issue here */
490086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_begin_src != TRIG_TIMER
4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    && cmd->scan_begin_src != TRIG_EXT)
492086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
493086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
494086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
495086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
496086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
497086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
498086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
499086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 2;
500086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
501086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 3: make sure arguments are trivially compatible */
502086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
503086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->start_arg != 0) {
504086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cmd->start_arg = 0;
505086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
506086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
507086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define MAX_SPEED	10000	/* in nanoseconds */
508086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#define MIN_SPEED	1000000000	/* in nanoseconds */
509086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
510086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
511086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_arg < MAX_SPEED) {
512086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg = MAX_SPEED;
513086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
514086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
515086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_arg > MIN_SPEED) {
516086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg = MIN_SPEED;
517086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
518086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
519086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	} else {
520086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* external trigger */
521086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* should be level/edge, hi/lo specification here */
522086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* should specify multiple external triggers */
523086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_arg > 9) {
524086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg = 9;
525086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
526086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
527086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
528086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->convert_src == TRIG_TIMER) {
529086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->convert_arg < MAX_SPEED) {
530086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->convert_arg = MAX_SPEED;
531086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
532086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
533086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->convert_arg > MIN_SPEED) {
534086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->convert_arg = MIN_SPEED;
535086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
536086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
537086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	} else {
538086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* external trigger */
539086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* see above */
540086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->convert_arg > 9) {
541086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->convert_arg = 9;
542086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
543086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
544086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
545086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
546086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
547086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
548086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		err++;
549086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
550086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->stop_src == TRIG_COUNT) {
551086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->stop_arg > 0x00ffffff) {
552086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->stop_arg = 0x00ffffff;
553086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
554086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
555086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	} else {
556086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		/* TRIG_NONE */
557086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->stop_arg != 0) {
558086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->stop_arg = 0;
559086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
560086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
561086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
562086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
563086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
564086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 3;
565086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
566086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* step 4: fix up any arguments */
567086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
568086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
569086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		tmp = cmd->scan_begin_arg;
570086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cb_pcidda_ns_to_timer(&cmd->scan_begin_arg,
5710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      cmd->flags & TRIG_ROUND_MASK);
572086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (tmp != cmd->scan_begin_arg)
573086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
574086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
575086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (cmd->convert_src == TRIG_TIMER) {
576086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		tmp = cmd->convert_arg;
577086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cb_pcidda_ns_to_timer(&cmd->convert_arg,
5780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      cmd->flags & TRIG_ROUND_MASK);
579086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (tmp != cmd->convert_arg)
580086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
581086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (cmd->scan_begin_src == TRIG_TIMER &&
5820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->scan_begin_arg <
5830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cmd->convert_arg * cmd->scan_end_arg) {
584086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			cmd->scan_begin_arg =
5850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    cmd->convert_arg * cmd->scan_end_arg;
586086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			err++;
587086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		}
588086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
589086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
590086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	if (err)
591086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		return 4;
592086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
593086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0;
594086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
595086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#endif
596086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
597086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/* This function doesn't require a particular form, this is just
598086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * what happens to be used in some of the drivers.  It should
599086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * convert ns nanoseconds to a counter value suitable for programming
600086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the device.  Also, it should adjust ns so that it cooresponds to
601086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * the actual time that the device will use. */
602086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#if 0
603086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
604086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
605086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* trivial timer */
606086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return *ns;
607086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
608086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez#endif
609086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidda_ao_winsn(struct comedi_device *dev,
6110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
6120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      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;
64795cd17c9f3734091a5811fabbd778e3f7b1f0789Joe Perches	}
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 */
661da91b2692e0939b307f9047192d2b9fe07793e7aBill 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 */
66920db7d7de7027ddee5df1b51b3d013568273b9dfAndrea Gelmini		if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT)
670086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			value |= 1 << (value_width - i);
671086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
672086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
673086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return value;
674086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
675086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6762696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* lowlevel write to eeprom/dac */
677da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
6780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 unsigned int num_bits)
679086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
680086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	int i;
681086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
682086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	for (i = 1; i <= num_bits; i++) {
6832696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton		/*  send bits most significant bit first */
684086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		if (value & (1 << (num_bits - i)))
685086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
686086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		else
687086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez			devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
688086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
689086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	}
690086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
691086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
6922696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* reads a 16 bit value from board's eeprom */
693da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
6940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  unsigned int address)
695086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
696086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int i;
697086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int cal2_bits;
698086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int value;
6992696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int max_num_caldacs = 4;	/*  one caldac for every two dac channels */
7002696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int read_instruction = 0x6;	/*  bits to send to tell eeprom we want to read */
701086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	const int instruction_length = 3;
702086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	const int address_length = 8;
703086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7042696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  send serial output stream to eeprom */
705086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
7062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate caldacs (one caldac for every two channels) */
70720db7d7de7027ddee5df1b51b3d013568273b9dfAndrea Gelmini	for (i = 0; i < max_num_caldacs; i++)
708086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cal2_bits |= DESELECT_CALDAC_BIT(i);
709086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
710086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7112696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  tell eeprom we want to read */
712086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, read_instruction, instruction_length);
7132696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  send address we want to read from */
714086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, address, address_length);
715086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
716086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	value = cb_pcidda_serial_in(dev);
717086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7182696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate eeprom */
719086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits &= ~SELECT_EEPROM_BIT;
720086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
721086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
722086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return value;
723086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
724086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7252696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* writes to 8 bit calibration dacs */
7260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void cb_pcidda_write_caldac(struct comedi_device *dev,
7270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int caldac, unsigned int channel,
7280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int value)
729086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
730086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int cal2_bits;
731086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int i;
7322696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int num_channel_bits = 3;	/*  caldacs use 3 bit channel specification */
7332696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int num_caldac_bits = 8;	/*  8 bit calibration dacs */
7342696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	const int max_num_caldacs = 4;	/*  one caldac for every two dac channels */
735086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
736086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	/* write 3 bit channel */
737086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, channel, num_channel_bits);
7382696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  write 8 bit caldac value */
739086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_serial_out(dev, value, num_caldac_bits);
740086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7412696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/*
7422696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton* latch stream into appropriate caldac deselect reference dac
7432696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton*/
744086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
7452696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate caldacs (one caldac for every two channels) */
74620db7d7de7027ddee5df1b51b3d013568273b9dfAndrea Gelmini	for (i = 0; i < max_num_caldacs; i++)
747086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez		cal2_bits |= DESELECT_CALDAC_BIT(i);
7482696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  activate the caldac we want */
749086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
750086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
7512696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  deactivate caldac */
752086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cal2_bits |= DESELECT_CALDAC_BIT(caldac);
753086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
754086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
755086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7562696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac that calibrates given analog out channel */
757086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int caldac_number(unsigned int channel)
758086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
759086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return channel / 2;
760086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
761086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7622696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides fine gain for given ao channel */
763086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int fine_gain_channel(unsigned int ao_channel)
764086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
765086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 4 * (ao_channel % 2);
766086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
767086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7682696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides coarse gain for given ao channel */
769086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int coarse_gain_channel(unsigned int ao_channel)
770086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
771086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 1 + 4 * (ao_channel % 2);
772086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
773086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7742696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides coarse offset for given ao channel */
775086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int coarse_offset_channel(unsigned int ao_channel)
776086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
777086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 2 + 4 * (ao_channel % 2);
778086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
779086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7802696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns caldac channel that provides fine offset for given ao channel */
781086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int fine_offset_channel(unsigned int ao_channel)
782086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
783086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 3 + 4 * (ao_channel % 2);
784086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
785086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7862696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns eeprom address that provides offset for given ao channel and range */
787086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int offset_eeprom_address(unsigned int ao_channel,
7880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  unsigned int range)
789086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
790086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0x7 + 2 * range + 12 * ao_channel;
791086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
792086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
7932696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns eeprom address that provides gain calibration for given ao channel and range */
794086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int gain_eeprom_address(unsigned int ao_channel,
7950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int range)
796086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
797086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return 0x8 + 2 * range + 12 * ao_channel;
798086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
799086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8002696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns upper byte of eeprom entry, which gives the coarse adjustment values */
801086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int eeprom_coarse_byte(unsigned int word)
802086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
803086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return (word >> 8) & 0xff;
804086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
805086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8062696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* returns lower byte of eeprom entry, which gives the fine adjustment values */
807086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinezstatic unsigned int eeprom_fine_byte(unsigned int word)
808086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
809086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	return word & 0xff;
810086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
811086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8122696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* set caldacs to eeprom values for given channel and range */
813da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
8140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				unsigned int range)
815086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez{
816086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
817086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8182696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  remember range so we can tell when we need to readjust calibration */
819086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	devpriv->ao_range[channel] = range;
820086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8212696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  get values from eeprom data */
822086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	coarse_offset =
8230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    eeprom_coarse_byte(devpriv->eeprom_data
8240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       [offset_eeprom_address(channel, range)]);
825086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	fine_offset =
8260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    eeprom_fine_byte(devpriv->eeprom_data
8270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     [offset_eeprom_address(channel, range)]);
828086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	coarse_gain =
8290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    eeprom_coarse_byte(devpriv->eeprom_data
8300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       [gain_eeprom_address(channel, range)]);
831086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	fine_gain =
8320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    eeprom_fine_byte(devpriv->eeprom_data
8330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     [gain_eeprom_address(channel, range)]);
834086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
8352696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  set caldacs */
836086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
8370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       coarse_offset_channel(channel), coarse_offset);
838086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
8390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       fine_offset_channel(channel), fine_offset);
840086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
8410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       coarse_gain_channel(channel), coarse_gain);
842086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez	cb_pcidda_write_caldac(dev, caldac_number(channel),
8430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       fine_gain_channel(channel), fine_gain);
844086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez}
845086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez
846086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez/*
847086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * A convenient macro that defines init_module() and cleanup_module(),
848086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez * as necessary.
849086df5b5fea9c6bd1374acb6dea2c558247d4637Ivan Martinez */
850727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_cb_pcidda_pci_probe(struct pci_dev *dev,
851727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas						const struct pci_device_id *ent)
852727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
853727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, driver_cb_pcidda.driver_name);
854727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
855727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
856727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_cb_pcidda_pci_remove(struct pci_dev *dev)
857727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
858727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
859727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
860727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
861727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_cb_pcidda_pci_driver = {
862727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = cb_pcidda_pci_table,
863727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &driver_cb_pcidda_pci_probe,
864727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&driver_cb_pcidda_pci_remove)
865727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
866727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
867727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_cb_pcidda_init_module(void)
868727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
869727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
870727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
871727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&driver_cb_pcidda);
872727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
873727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
874727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
875727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	driver_cb_pcidda_pci_driver.name = (char *)driver_cb_pcidda.driver_name;
876727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&driver_cb_pcidda_pci_driver);
877727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
878727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
879727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_cb_pcidda_cleanup_module(void)
880727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
881727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&driver_cb_pcidda_pci_driver);
882727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&driver_cb_pcidda);
883727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
884727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
885727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_cb_pcidda_init_module);
886727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_cb_pcidda_cleanup_module);
88790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
88890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
88990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
89090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
891