]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/comedi/drivers/cb_pcidas.c
staging: comedi: cb_pcidas: cleanup the boardinfo 4
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / comedi / drivers / cb_pcidas.c
CommitLineData
59c7dd3d
IM
1/*
2 comedi/drivers/cb_pcidas.c
3
4 Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
5 David Schleef and the rest of the Comedi developers comunity.
6
7 Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
8 Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
9
10 COMEDI - Linux Control and Measurement Device Interface
11 Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
27************************************************************************
28*/
29/*
30Driver: cb_pcidas
31Description: MeasurementComputing PCI-DAS series with the AMCC S5933 PCI controller
32Author: Ivan Martinez <imr@oersted.dtu.dk>,
33 Frank Mori Hess <fmhess@users.sourceforge.net>
34Updated: 2003-3-11
35Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
36 PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
37 PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
38
39Status:
40 There are many reports of the driver being used with most of the
41 supported cards. Despite no detailed log is maintained, it can
42 be said that the driver is quite tested and stable.
43
44 The boards may be autocalibrated using the comedi_calibrate
45 utility.
46
47Configuration options:
48 [0] - PCI bus of device (optional)
49 [1] - PCI slot of device (optional)
50 If bus/slot is not specified, the first supported
51 PCI device found will be used.
52
53For commands, the scanned channels must be consecutive
54(i.e. 4-5-6-7, 2-3-4,...), and must all have the same
55range and aref.
f1bc4343
BD
56
57AI Triggering:
58 For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
59 For 1602 series, the start_arg is interpreted as follows:
bc04bec0
MI
60 start_arg == 0 => gated trigger (level high)
61 start_arg == CR_INVERT => gated trigger (level low)
f1bc4343
BD
62 start_arg == CR_EDGE => Rising edge
63 start_arg == CR_EDGE | CR_INVERT => Falling edge
64 For the other boards the trigger will be done on rising edge
59c7dd3d
IM
65*/
66/*
67
68TODO:
69
70analog triggering on 1602 series
71*/
72
73#include "../comedidev.h"
74#include <linux/delay.h>
70265d24 75#include <linux/interrupt.h>
59c7dd3d
IM
76
77#include "8253.h"
78#include "8255.h"
79#include "amcc_s5933.h"
59c7dd3d
IM
80#include "comedi_fc.h"
81
cf530aa4 82/* PCI vendor number of ComputerBoards/MeasurementComputing */
59c7dd3d 83#define PCI_VENDOR_ID_CB 0x1307
cf530aa4
BP
84#define TIMER_BASE 100 /* 10MHz master clock */
85#define AI_BUFFER_SIZE 1024 /* maximum fifo size of any supported board */
86#define AO_BUFFER_SIZE 1024 /* maximum fifo size of any supported board */
59c7dd3d
IM
87#define NUM_CHANNELS_8800 8
88#define NUM_CHANNELS_7376 1
89#define NUM_CHANNELS_8402 2
90#define NUM_CHANNELS_DAC08 1
91
59c7dd3d 92/* Control/Status registers */
cf530aa4
BP
93#define INT_ADCFIFO 0 /* INTERRUPT / ADC FIFO register */
94#define INT_EOS 0x1 /* interrupt end of scan */
95#define INT_FHF 0x2 /* interrupt fifo half full */
96#define INT_FNE 0x3 /* interrupt fifo not empty */
97#define INT_MASK 0x3 /* mask of interrupt select bits */
98#define INTE 0x4 /* interrupt enable */
99#define DAHFIE 0x8 /* dac half full interrupt enable */
25985edc 100#define EOAIE 0x10 /* end of acquisition interrupt enable */
cf530aa4
BP
101#define DAHFI 0x20 /* dac half full read status / write interrupt clear */
102#define EOAI 0x40 /* read end of acq. interrupt status / write clear */
103#define INT 0x80 /* read interrupt status / write clear */
104#define EOBI 0x200 /* read end of burst interrupt status */
105#define ADHFI 0x400 /* read half-full interrupt status */
106#define ADNEI 0x800 /* read fifo not empty interrupt latch status */
107#define ADNE 0x1000 /* read, fifo not empty (realtime, not latched) status */
108#define DAEMIE 0x1000 /* write, dac empty interrupt enable */
109#define LADFUL 0x2000 /* read fifo overflow / write clear */
110#define DAEMI 0x4000 /* dac fifo empty interrupt status / write clear */
111
112#define ADCMUX_CONT 2 /* ADC CHANNEL MUX AND CONTROL register */
59c7dd3d
IM
113#define BEGIN_SCAN(x) ((x) & 0xf)
114#define END_SCAN(x) (((x) & 0xf) << 4)
115#define GAIN_BITS(x) (((x) & 0x3) << 8)
cf530aa4
BP
116#define UNIP 0x800 /* Analog front-end unipolar for range */
117#define SE 0x400 /* Inputs in single-ended mode */
118#define PACER_MASK 0x3000 /* pacer source bits */
119#define PACER_INT 0x1000 /* internal pacer */
120#define PACER_EXT_FALL 0x2000 /* external falling edge */
121#define PACER_EXT_RISE 0x3000 /* external rising edge */
122#define EOC 0x4000 /* adc not busy */
123
124#define TRIG_CONTSTAT 4 /* TRIGGER CONTROL/STATUS register */
125#define SW_TRIGGER 0x1 /* software start trigger */
126#define EXT_TRIGGER 0x2 /* external start trigger */
127#define ANALOG_TRIGGER 0x3 /* external analog trigger */
128#define TRIGGER_MASK 0x3 /* mask of bits that determine start trigger */
f1bc4343
BD
129#define TGPOL 0x04 /* invert the edge/level of the external trigger (1602 only) */
130#define TGSEL 0x08 /* if set edge triggered, otherwise level trigerred (1602 only) */
cf530aa4
BP
131#define TGEN 0x10 /* enable external start trigger */
132#define BURSTE 0x20 /* burst mode enable */
133#define XTRCL 0x80 /* clear external trigger */
134
135#define CALIBRATION_REG 6 /* CALIBRATION register */
136#define SELECT_8800_BIT 0x100 /* select 8800 caldac */
137#define SELECT_TRIMPOT_BIT 0x200 /* select ad7376 trim pot */
138#define SELECT_DAC08_BIT 0x400 /* select dac08 caldac */
59c7dd3d 139#define CAL_SRC_BITS(x) (((x) & 0x7) << 11)
cf530aa4
BP
140#define CAL_EN_BIT 0x4000 /* read calibration source instead of analog input channel 0 */
141#define SERIAL_DATA_IN_BIT 0x8000 /* serial data stream going to 8800 and 7376 */
59c7dd3d 142
cf530aa4 143#define DAC_CSR 0x8 /* dac control and status register */
59c7dd3d 144enum dac_csr_bits {
cf530aa4
BP
145 DACEN = 0x2, /* dac enable */
146 DAC_MODE_UPDATE_BOTH = 0x80, /* update both dacs when dac0 is written */
59c7dd3d
IM
147};
148static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
149{
150 return (range & 0x3) << (8 + 2 * (channel & 0x1));
151}
0a85b6f0 152
59c7dd3d
IM
153static inline unsigned int DAC_RANGE_MASK(unsigned int channel)
154{
155 return 0x3 << (8 + 2 * (channel & 0x1));
156};
157
cf530aa4 158/* bits for 1602 series only */
59c7dd3d 159enum dac_csr_bits_1602 {
cf530aa4
BP
160 DAC_EMPTY = 0x1, /* dac fifo empty, read, write clear */
161 DAC_START = 0x4, /* start/arm dac fifo operations */
162 DAC_PACER_MASK = 0x18, /* bits that set dac pacer source */
163 DAC_PACER_INT = 0x8, /* dac internal pacing */
164 DAC_PACER_EXT_FALL = 0x10, /* dac external pacing, falling edge */
165 DAC_PACER_EXT_RISE = 0x18, /* dac external pacing, rising edge */
59c7dd3d
IM
166};
167static inline unsigned int DAC_CHAN_EN(unsigned int channel)
168{
cf530aa4 169 return 1 << (5 + (channel & 0x1)); /* enable channel 0 or 1 */
59c7dd3d
IM
170};
171
172/* analog input fifo */
cf530aa4
BP
173#define ADCDATA 0 /* ADC DATA register */
174#define ADCFIFOCLR 2 /* ADC FIFO CLEAR */
59c7dd3d 175
cf530aa4 176/* pacer, counter, dio registers */
59c7dd3d
IM
177#define ADC8254 0
178#define DIO_8255 4
179#define DAC8254 8
180
cf530aa4 181/* analog output registers for 100x, 1200 series */
59c7dd3d
IM
182static inline unsigned int DAC_DATA_REG(unsigned int channel)
183{
184 return 2 * (channel & 0x1);
185}
186
187/* analog output registers for 1602 series*/
cf530aa4
BP
188#define DACDATA 0 /* DAC DATA register */
189#define DACFIFOCLR 2 /* DAC FIFO CLEAR */
59c7dd3d 190
cf530aa4 191/* bit in hexadecimal representation of range index that indicates unipolar input range */
59c7dd3d 192#define IS_UNIPOLAR 0x4
cf530aa4 193/* analog input ranges for most boards */
9ced1de6 194static const struct comedi_lrange cb_pcidas_ranges = {
59c7dd3d
IM
195 8,
196 {
0a85b6f0
MT
197 BIP_RANGE(10),
198 BIP_RANGE(5),
199 BIP_RANGE(2.5),
200 BIP_RANGE(1.25),
201 UNI_RANGE(10),
202 UNI_RANGE(5),
203 UNI_RANGE(2.5),
204 UNI_RANGE(1.25)
205 }
59c7dd3d
IM
206};
207
cf530aa4 208/* pci-das1001 input ranges */
9ced1de6 209static const struct comedi_lrange cb_pcidas_alt_ranges = {
59c7dd3d
IM
210 8,
211 {
0a85b6f0
MT
212 BIP_RANGE(10),
213 BIP_RANGE(1),
214 BIP_RANGE(0.1),
215 BIP_RANGE(0.01),
216 UNI_RANGE(10),
217 UNI_RANGE(1),
218 UNI_RANGE(0.1),
219 UNI_RANGE(0.01)
220 }
59c7dd3d
IM
221};
222
cf530aa4 223/* analog output ranges */
9ced1de6 224static const struct comedi_lrange cb_pcidas_ao_ranges = {
59c7dd3d
IM
225 4,
226 {
0a85b6f0
MT
227 BIP_RANGE(5),
228 BIP_RANGE(10),
229 UNI_RANGE(5),
230 UNI_RANGE(10),
231 }
59c7dd3d
IM
232};
233
234enum trimpot_model {
235 AD7376,
236 AD8402,
237};
238
5c2670cb 239struct cb_pcidas_board {
59c7dd3d
IM
240 const char *name;
241 unsigned short device_id;
8f608fc8 242 int ai_nchan; /* Inputs in single-ended mode */
cf530aa4
BP
243 int ai_bits; /* analog input resolution */
244 int ai_speed; /* fastest conversion period in ns */
245 int ao_nchan; /* number of analog out channels */
246 int has_ao_fifo; /* analog output has fifo */
247 int ao_scan_speed; /* analog output speed for 1602 series (for a scan, not conversion) */
248 int fifo_size; /* number of samples fifo can hold */
9ced1de6 249 const struct comedi_lrange *ranges;
59c7dd3d
IM
250 enum trimpot_model trimpot;
251 unsigned has_dac08:1;
23e3cce3 252 unsigned is_1602:1;
5c2670cb 253};
59c7dd3d 254
5c2670cb 255static const struct cb_pcidas_board cb_pcidas_boards[] = {
59c7dd3d 256 {
17883d63
HS
257 .name = "pci-das1602/16",
258 .device_id = 0x1,
8f608fc8 259 .ai_nchan = 16,
17883d63
HS
260 .ai_bits = 16,
261 .ai_speed = 5000,
262 .ao_nchan = 2,
263 .has_ao_fifo = 1,
264 .ao_scan_speed = 10000,
265 .fifo_size = 512,
266 .ranges = &cb_pcidas_ranges,
267 .trimpot = AD8402,
268 .has_dac08 = 1,
269 .is_1602 = 1,
270 }, {
271 .name = "pci-das1200",
272 .device_id = 0xF,
8f608fc8 273 .ai_nchan = 16,
17883d63
HS
274 .ai_bits = 12,
275 .ai_speed = 3200,
276 .ao_nchan = 2,
17883d63
HS
277 .fifo_size = 1024,
278 .ranges = &cb_pcidas_ranges,
279 .trimpot = AD7376,
17883d63
HS
280 }, {
281 .name = "pci-das1602/12",
282 .device_id = 0x10,
8f608fc8 283 .ai_nchan = 16,
17883d63
HS
284 .ai_bits = 12,
285 .ai_speed = 3200,
286 .ao_nchan = 2,
287 .has_ao_fifo = 1,
288 .ao_scan_speed = 4000,
289 .fifo_size = 1024,
290 .ranges = &cb_pcidas_ranges,
291 .trimpot = AD7376,
17883d63
HS
292 .is_1602 = 1,
293 }, {
294 .name = "pci-das1200/jr",
295 .device_id = 0x19,
8f608fc8 296 .ai_nchan = 16,
17883d63
HS
297 .ai_bits = 12,
298 .ai_speed = 3200,
17883d63
HS
299 .fifo_size = 1024,
300 .ranges = &cb_pcidas_ranges,
301 .trimpot = AD7376,
17883d63
HS
302 }, {
303 .name = "pci-das1602/16/jr",
304 .device_id = 0x1C,
8f608fc8 305 .ai_nchan = 16,
17883d63
HS
306 .ai_bits = 16,
307 .ai_speed = 5000,
17883d63
HS
308 .fifo_size = 512,
309 .ranges = &cb_pcidas_ranges,
310 .trimpot = AD8402,
311 .has_dac08 = 1,
312 .is_1602 = 1,
313 }, {
314 .name = "pci-das1000",
315 .device_id = 0x4C,
8f608fc8 316 .ai_nchan = 16,
17883d63
HS
317 .ai_bits = 12,
318 .ai_speed = 4000,
17883d63
HS
319 .fifo_size = 1024,
320 .ranges = &cb_pcidas_ranges,
321 .trimpot = AD7376,
17883d63
HS
322 }, {
323 .name = "pci-das1001",
324 .device_id = 0x1a,
8f608fc8 325 .ai_nchan = 16,
17883d63
HS
326 .ai_bits = 12,
327 .ai_speed = 6800,
328 .ao_nchan = 2,
17883d63
HS
329 .fifo_size = 1024,
330 .ranges = &cb_pcidas_alt_ranges,
331 .trimpot = AD7376,
17883d63
HS
332 }, {
333 .name = "pci-das1002",
334 .device_id = 0x1b,
8f608fc8 335 .ai_nchan = 16,
17883d63
HS
336 .ai_bits = 12,
337 .ai_speed = 6800,
338 .ao_nchan = 2,
17883d63
HS
339 .fifo_size = 1024,
340 .ranges = &cb_pcidas_ranges,
341 .trimpot = AD7376,
17883d63 342 },
59c7dd3d
IM
343};
344
59c7dd3d
IM
345/* this structure is for data unique to this hardware driver. If
346 several hardware drivers keep similar information in this structure,
71b5f4f1 347 feel free to suggest moving the variable to the struct comedi_device struct. */
c77e2589 348struct cb_pcidas_private {
59c7dd3d
IM
349 /* would be useful for a PCI device */
350 struct pci_dev *pci_dev;
cf530aa4 351 /* base addresses */
59c7dd3d
IM
352 unsigned long s5933_config;
353 unsigned long control_status;
354 unsigned long adc_fifo;
355 unsigned long pacer_counter_dio;
356 unsigned long ao_registers;
cf530aa4 357 /* divisors of master clock for analog input pacing */
59c7dd3d
IM
358 unsigned int divisor1;
359 unsigned int divisor2;
cf530aa4 360 volatile unsigned int count; /* number of analog input samples remaining */
25985edc 361 volatile unsigned int adc_fifo_bits; /* bits to write to interrupt/adcfifo register */
cf530aa4
BP
362 volatile unsigned int s5933_intcsr_bits; /* bits to write to amcc s5933 interrupt control/status register */
363 volatile unsigned int ao_control_bits; /* bits to write to ao control and status register */
790c5541
BP
364 short ai_buffer[AI_BUFFER_SIZE];
365 short ao_buffer[AO_BUFFER_SIZE];
cf530aa4 366 /* divisors of master clock for analog output pacing */
59c7dd3d
IM
367 unsigned int ao_divisor1;
368 unsigned int ao_divisor2;
cf530aa4
BP
369 volatile unsigned int ao_count; /* number of analog output samples remaining */
370 int ao_value[2]; /* remember what the analog outputs are set to, to allow readback */
371 unsigned int caldac_value[NUM_CHANNELS_8800]; /* for readback of caldac */
372 unsigned int trimpot_value[NUM_CHANNELS_8402]; /* for readback of trimpot */
59c7dd3d
IM
373 unsigned int dac08_value;
374 unsigned int calibration_source;
c77e2589 375};
59c7dd3d 376
814900c9 377static inline unsigned int cal_enable_bits(struct comedi_device *dev)
59c7dd3d 378{
82d8c74d
HS
379 struct cb_pcidas_private *devpriv = dev->private;
380
59c7dd3d
IM
381 return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
382}
383
59c7dd3d
IM
384/*
385 * "instructions" read/write data in "one-shot" or "software-triggered"
386 * mode.
387 */
0a85b6f0
MT
388static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
389 struct comedi_subdevice *s,
390 struct comedi_insn *insn, unsigned int *data)
59c7dd3d 391{
82d8c74d 392 struct cb_pcidas_private *devpriv = dev->private;
59c7dd3d
IM
393 int n, i;
394 unsigned int bits;
395 static const int timeout = 10000;
396 int channel;
cf530aa4 397 /* enable calibration input if appropriate */
59c7dd3d
IM
398 if (insn->chanspec & CR_ALT_SOURCE) {
399 outw(cal_enable_bits(dev),
0a85b6f0 400 devpriv->control_status + CALIBRATION_REG);
59c7dd3d
IM
401 channel = 0;
402 } else {
403 outw(0, devpriv->control_status + CALIBRATION_REG);
404 channel = CR_CHAN(insn->chanspec);
405 }
cf530aa4 406 /* set mux limits and gain */
59c7dd3d 407 bits = BEGIN_SCAN(channel) |
0a85b6f0 408 END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
cf530aa4 409 /* set unipolar/bipolar */
59c7dd3d
IM
410 if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
411 bits |= UNIP;
cf530aa4 412 /* set singleended/differential */
59c7dd3d
IM
413 if (CR_AREF(insn->chanspec) != AREF_DIFF)
414 bits |= SE;
415 outw(bits, devpriv->control_status + ADCMUX_CONT);
416
417 /* clear fifo */
418 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
419
420 /* convert n samples */
421 for (n = 0; n < insn->n; n++) {
422 /* trigger conversion */
423 outw(0, devpriv->adc_fifo + ADCDATA);
424
425 /* wait for conversion to end */
426 /* return -ETIMEDOUT if there is a timeout */
427 for (i = 0; i < timeout; i++) {
428 if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
429 break;
430 }
431 if (i == timeout)
432 return -ETIMEDOUT;
433
434 /* read data */
435 data[n] = inw(devpriv->adc_fifo + ADCDATA);
436 }
437
438 /* return the number of samples read/written */
439 return n;
440}
441
0a85b6f0
MT
442static int ai_config_calibration_source(struct comedi_device *dev,
443 unsigned int *data)
59c7dd3d 444{
82d8c74d 445 struct cb_pcidas_private *devpriv = dev->private;
59c7dd3d 446 static const int num_calibration_sources = 8;
790c5541 447 unsigned int source = data[1];
59c7dd3d
IM
448
449 if (source >= num_calibration_sources) {
f41ad667 450 dev_err(dev->class_dev, "invalid calibration source: %i\n",
94cc0b4a 451 source);
59c7dd3d
IM
452 return -EINVAL;
453 }
454
455 devpriv->calibration_source = source;
456
457 return 2;
458}
459
da91b269 460static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 461 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
462{
463 int id = data[0];
464
465 switch (id) {
466 case INSN_CONFIG_ALT_SOURCE:
467 return ai_config_calibration_source(dev, data);
468 break;
469 default:
470 return -EINVAL;
471 break;
472 }
473 return -EINVAL;
474}
475
cf530aa4 476/* analog output insn for pcidas-1000 and 1200 series */
0a85b6f0
MT
477static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
478 struct comedi_subdevice *s,
479 struct comedi_insn *insn,
480 unsigned int *data)
59c7dd3d 481{
82d8c74d 482 struct cb_pcidas_private *devpriv = dev->private;
59c7dd3d
IM
483 int channel;
484 unsigned long flags;
485
cf530aa4 486 /* set channel and range */
59c7dd3d 487 channel = CR_CHAN(insn->chanspec);
5f74ea14 488 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 489 devpriv->ao_control_bits &=
0a85b6f0 490 ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel);
59c7dd3d 491 devpriv->ao_control_bits |=
0a85b6f0 492 DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec));
59c7dd3d 493 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
5f74ea14 494 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 495
cf530aa4 496 /* remember value for readback */
59c7dd3d 497 devpriv->ao_value[channel] = data[0];
cf530aa4 498 /* send data */
59c7dd3d
IM
499 outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
500
501 return 1;
502}
503
cf530aa4 504/* analog output insn for pcidas-1602 series */
0a85b6f0
MT
505static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
506 struct comedi_subdevice *s,
507 struct comedi_insn *insn, unsigned int *data)
59c7dd3d 508{
82d8c74d 509 struct cb_pcidas_private *devpriv = dev->private;
59c7dd3d
IM
510 int channel;
511 unsigned long flags;
512
cf530aa4 513 /* clear dac fifo */
59c7dd3d
IM
514 outw(0, devpriv->ao_registers + DACFIFOCLR);
515
cf530aa4 516 /* set channel and range */
59c7dd3d 517 channel = CR_CHAN(insn->chanspec);
5f74ea14 518 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 519 devpriv->ao_control_bits &=
0a85b6f0
MT
520 ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) &
521 ~DAC_PACER_MASK;
59c7dd3d 522 devpriv->ao_control_bits |=
0a85b6f0
MT
523 DACEN | DAC_RANGE(channel,
524 CR_RANGE(insn->
525 chanspec)) | DAC_CHAN_EN(channel) |
526 DAC_START;
59c7dd3d 527 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
5f74ea14 528 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 529
cf530aa4 530 /* remember value for readback */
59c7dd3d 531 devpriv->ao_value[channel] = data[0];
cf530aa4 532 /* send data */
59c7dd3d
IM
533 outw(data[0], devpriv->ao_registers + DACDATA);
534
535 return 1;
536}
537
cf530aa4
BP
538/* analog output readback insn */
539/* XXX loses track of analog output value back after an analog ouput command is executed */
0a85b6f0
MT
540static int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
541 struct comedi_subdevice *s,
542 struct comedi_insn *insn,
543 unsigned int *data)
59c7dd3d 544{
82d8c74d
HS
545 struct cb_pcidas_private *devpriv = dev->private;
546
59c7dd3d
IM
547 data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
548
549 return 1;
550}
551
536af69e
HS
552static int wait_for_nvram_ready(unsigned long s5933_base_addr)
553{
554 static const int timeout = 1000;
555 unsigned int i;
556
557 for (i = 0; i < timeout; i++) {
558 if ((inb(s5933_base_addr +
559 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
560 == 0)
561 return 0;
562 udelay(1);
563 }
564 return -1;
565}
566
567static int nvram_read(struct comedi_device *dev, unsigned int address,
568 uint8_t *data)
569{
82d8c74d 570 struct cb_pcidas_private *devpriv = dev->private;
536af69e
HS
571 unsigned long iobase = devpriv->s5933_config;
572
573 if (wait_for_nvram_ready(iobase) < 0)
574 return -ETIMEDOUT;
575
576 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
577 iobase + AMCC_OP_REG_MCSR_NVCMD);
578 outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
579 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
580 iobase + AMCC_OP_REG_MCSR_NVCMD);
581 outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
582 outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
583
584 if (wait_for_nvram_ready(iobase) < 0)
585 return -ETIMEDOUT;
586
587 *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
588
589 return 0;
590}
591
0a85b6f0
MT
592static int eeprom_read_insn(struct comedi_device *dev,
593 struct comedi_subdevice *s,
594 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
595{
596 uint8_t nvram_data;
597 int retval;
598
599 retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
600 if (retval < 0)
601 return retval;
602
603 data[0] = nvram_data;
604
605 return 1;
606}
607
0c15d553
HS
608static void write_calibration_bitstream(struct comedi_device *dev,
609 unsigned int register_bits,
610 unsigned int bitstream,
611 unsigned int bitstream_length)
612{
82d8c74d 613 struct cb_pcidas_private *devpriv = dev->private;
0c15d553
HS
614 static const int write_delay = 1;
615 unsigned int bit;
616
617 for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
618 if (bitstream & bit)
619 register_bits |= SERIAL_DATA_IN_BIT;
620 else
621 register_bits &= ~SERIAL_DATA_IN_BIT;
622 udelay(write_delay);
623 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
624 }
625}
626
627static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
628 uint8_t value)
629{
82d8c74d 630 struct cb_pcidas_private *devpriv = dev->private;
0c15d553
HS
631 static const int num_caldac_channels = 8;
632 static const int bitstream_length = 11;
633 unsigned int bitstream = ((address & 0x7) << 8) | value;
634 static const int caldac_8800_udelay = 1;
635
636 if (address >= num_caldac_channels) {
637 comedi_error(dev, "illegal caldac channel");
638 return -1;
639 }
640
641 if (value == devpriv->caldac_value[address])
642 return 1;
643
644 devpriv->caldac_value[address] = value;
645
646 write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
647 bitstream_length);
648
649 udelay(caldac_8800_udelay);
650 outw(cal_enable_bits(dev) | SELECT_8800_BIT,
651 devpriv->control_status + CALIBRATION_REG);
652 udelay(caldac_8800_udelay);
653 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
654
655 return 1;
656}
657
0a85b6f0
MT
658static int caldac_write_insn(struct comedi_device *dev,
659 struct comedi_subdevice *s,
660 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
661{
662 const unsigned int channel = CR_CHAN(insn->chanspec);
663
664 return caldac_8800_write(dev, channel, data[0]);
665}
666
0a85b6f0
MT
667static int caldac_read_insn(struct comedi_device *dev,
668 struct comedi_subdevice *s,
669 struct comedi_insn *insn, unsigned int *data)
59c7dd3d 670{
82d8c74d
HS
671 struct cb_pcidas_private *devpriv = dev->private;
672
59c7dd3d
IM
673 data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
674
675 return 1;
676}
677
678/* 1602/16 pregain offset */
da91b269 679static int dac08_write(struct comedi_device *dev, unsigned int value)
59c7dd3d 680{
82d8c74d
HS
681 struct cb_pcidas_private *devpriv = dev->private;
682
59c7dd3d
IM
683 if (devpriv->dac08_value == value)
684 return 1;
685
686 devpriv->dac08_value = value;
687
688 outw(cal_enable_bits(dev) | (value & 0xff),
0a85b6f0 689 devpriv->control_status + CALIBRATION_REG);
5f74ea14 690 udelay(1);
59c7dd3d 691 outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff),
0a85b6f0 692 devpriv->control_status + CALIBRATION_REG);
5f74ea14 693 udelay(1);
59c7dd3d 694 outw(cal_enable_bits(dev) | (value & 0xff),
0a85b6f0 695 devpriv->control_status + CALIBRATION_REG);
5f74ea14 696 udelay(1);
59c7dd3d
IM
697
698 return 1;
699}
700
0a85b6f0
MT
701static int dac08_write_insn(struct comedi_device *dev,
702 struct comedi_subdevice *s,
703 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
704{
705 return dac08_write(dev, data[0]);
706}
707
0a85b6f0
MT
708static int dac08_read_insn(struct comedi_device *dev,
709 struct comedi_subdevice *s, struct comedi_insn *insn,
710 unsigned int *data)
59c7dd3d 711{
82d8c74d
HS
712 struct cb_pcidas_private *devpriv = dev->private;
713
59c7dd3d
IM
714 data[0] = devpriv->dac08_value;
715
716 return 1;
717}
718
20535c1f
HS
719static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
720{
82d8c74d 721 struct cb_pcidas_private *devpriv = dev->private;
20535c1f
HS
722 static const int bitstream_length = 7;
723 unsigned int bitstream = value & 0x7f;
724 unsigned int register_bits;
725 static const int ad7376_udelay = 1;
726
727 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
728 udelay(ad7376_udelay);
729 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
730
731 write_calibration_bitstream(dev, register_bits, bitstream,
732 bitstream_length);
733
734 udelay(ad7376_udelay);
735 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
736
737 return 0;
738}
739
740/* For 1602/16 only
741 * ch 0 : adc gain
742 * ch 1 : adc postgain offset */
743static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
744 uint8_t value)
745{
82d8c74d 746 struct cb_pcidas_private *devpriv = dev->private;
20535c1f
HS
747 static const int bitstream_length = 10;
748 unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
749 unsigned int register_bits;
750 static const int ad8402_udelay = 1;
751
752 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
753 udelay(ad8402_udelay);
754 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
755
756 write_calibration_bitstream(dev, register_bits, bitstream,
757 bitstream_length);
758
759 udelay(ad8402_udelay);
760 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
761
762 return 0;
763}
764
da91b269 765static int cb_pcidas_trimpot_write(struct comedi_device *dev,
0a85b6f0 766 unsigned int channel, unsigned int value)
59c7dd3d 767{
82d8c74d
HS
768 const struct cb_pcidas_board *thisboard = comedi_board(dev);
769 struct cb_pcidas_private *devpriv = dev->private;
770
59c7dd3d
IM
771 if (devpriv->trimpot_value[channel] == value)
772 return 1;
773
774 devpriv->trimpot_value[channel] = value;
775 switch (thisboard->trimpot) {
776 case AD7376:
777 trimpot_7376_write(dev, value);
778 break;
779 case AD8402:
780 trimpot_8402_write(dev, channel, value);
781 break;
782 default:
783 comedi_error(dev, "driver bug?");
784 return -1;
785 break;
786 }
787
788 return 1;
789}
790
0a85b6f0
MT
791static int trimpot_write_insn(struct comedi_device *dev,
792 struct comedi_subdevice *s,
793 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
794{
795 unsigned int channel = CR_CHAN(insn->chanspec);
796
797 return cb_pcidas_trimpot_write(dev, channel, data[0]);
798}
799
0a85b6f0
MT
800static int trimpot_read_insn(struct comedi_device *dev,
801 struct comedi_subdevice *s,
802 struct comedi_insn *insn, unsigned int *data)
59c7dd3d 803{
82d8c74d 804 struct cb_pcidas_private *devpriv = dev->private;
59c7dd3d
IM
805 unsigned int channel = CR_CHAN(insn->chanspec);
806
807 data[0] = devpriv->trimpot_value[channel];
808
809 return 1;
810}
811
0a85b6f0
MT
812static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
813 struct comedi_subdevice *s,
814 struct comedi_cmd *cmd)
59c7dd3d 815{
82d8c74d
HS
816 const struct cb_pcidas_board *thisboard = comedi_board(dev);
817 struct cb_pcidas_private *devpriv = dev->private;
59c7dd3d
IM
818 int err = 0;
819 int tmp;
820 int i, gain, start_chan;
821
822 /* cmdtest tests a particular command to see if it is valid.
823 * Using the cmdtest ioctl, a user can create a valid cmd
824 * and then have it executes by the cmd ioctl.
825 *
826 * cmdtest returns 1,2,3,4 or 0, depending on which tests
827 * the command passes. */
828
829 /* step 1: make sure trigger sources are trivially valid */
830
831 tmp = cmd->start_src;
832 cmd->start_src &= TRIG_NOW | TRIG_EXT;
833 if (!cmd->start_src || tmp != cmd->start_src)
834 err++;
835
836 tmp = cmd->scan_begin_src;
837 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
838 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
839 err++;
840
841 tmp = cmd->convert_src;
842 cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
843 if (!cmd->convert_src || tmp != cmd->convert_src)
844 err++;
845
846 tmp = cmd->scan_end_src;
847 cmd->scan_end_src &= TRIG_COUNT;
848 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
849 err++;
850
851 tmp = cmd->stop_src;
852 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
853 if (!cmd->stop_src || tmp != cmd->stop_src)
854 err++;
855
856 if (err)
857 return 1;
858
859 /* step 2: make sure trigger sources are unique and mutually compatible */
860
861 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
862 err++;
863 if (cmd->scan_begin_src != TRIG_FOLLOW &&
0a85b6f0
MT
864 cmd->scan_begin_src != TRIG_TIMER &&
865 cmd->scan_begin_src != TRIG_EXT)
59c7dd3d
IM
866 err++;
867 if (cmd->convert_src != TRIG_TIMER &&
0a85b6f0 868 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
59c7dd3d
IM
869 err++;
870 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
871 err++;
872
cf530aa4 873 /* make sure trigger sources are compatible with each other */
59c7dd3d
IM
874 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
875 err++;
876 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
877 err++;
878 if (cmd->start_src == TRIG_EXT &&
0a85b6f0 879 (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
59c7dd3d
IM
880 err++;
881
882 if (err)
883 return 2;
884
885 /* step 3: make sure arguments are trivially compatible */
886
f1bc4343
BD
887 switch (cmd->start_src) {
888 case TRIG_EXT:
889 /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
890 if ((cmd->start_arg
891 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
892 cmd->start_arg &=
893 ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
894 err++;
895 }
23e3cce3 896 if (!thisboard->is_1602 && (cmd->start_arg & CR_INVERT)) {
f1bc4343
BD
897 cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
898 err++;
899 }
900 break;
901 default:
902 if (cmd->start_arg != 0) {
903 cmd->start_arg = 0;
904 err++;
905 }
906 break;
59c7dd3d
IM
907 }
908
909 if (cmd->scan_begin_src == TRIG_TIMER) {
910 if (cmd->scan_begin_arg <
0a85b6f0 911 thisboard->ai_speed * cmd->chanlist_len) {
59c7dd3d 912 cmd->scan_begin_arg =
0a85b6f0 913 thisboard->ai_speed * cmd->chanlist_len;
59c7dd3d
IM
914 err++;
915 }
916 }
917 if (cmd->convert_src == TRIG_TIMER) {
918 if (cmd->convert_arg < thisboard->ai_speed) {
919 cmd->convert_arg = thisboard->ai_speed;
920 err++;
921 }
922 }
923
924 if (cmd->scan_end_arg != cmd->chanlist_len) {
925 cmd->scan_end_arg = cmd->chanlist_len;
926 err++;
927 }
928 if (cmd->stop_src == TRIG_NONE) {
929 /* TRIG_NONE */
930 if (cmd->stop_arg != 0) {
931 cmd->stop_arg = 0;
932 err++;
933 }
934 }
935
936 if (err)
937 return 3;
938
939 /* step 4: fix up any arguments */
940
941 if (cmd->scan_begin_src == TRIG_TIMER) {
942 tmp = cmd->scan_begin_arg;
943 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
944 &(devpriv->divisor1),
945 &(devpriv->divisor2),
946 &(cmd->scan_begin_arg),
947 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
948 if (tmp != cmd->scan_begin_arg)
949 err++;
950 }
951 if (cmd->convert_src == TRIG_TIMER) {
952 tmp = cmd->convert_arg;
953 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
954 &(devpriv->divisor1),
955 &(devpriv->divisor2),
956 &(cmd->convert_arg),
957 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
958 if (tmp != cmd->convert_arg)
959 err++;
960 }
961
962 if (err)
963 return 4;
964
cf530aa4 965 /* check channel/gain list against card's limitations */
59c7dd3d
IM
966 if (cmd->chanlist) {
967 gain = CR_RANGE(cmd->chanlist[0]);
968 start_chan = CR_CHAN(cmd->chanlist[0]);
969 for (i = 1; i < cmd->chanlist_len; i++) {
970 if (CR_CHAN(cmd->chanlist[i]) !=
0a85b6f0 971 (start_chan + i) % s->n_chan) {
59c7dd3d 972 comedi_error(dev,
0a85b6f0 973 "entries in chanlist must be consecutive channels, counting upwards\n");
59c7dd3d
IM
974 err++;
975 }
976 if (CR_RANGE(cmd->chanlist[i]) != gain) {
977 comedi_error(dev,
0a85b6f0 978 "entries in chanlist must all have the same gain\n");
59c7dd3d
IM
979 err++;
980 }
981 }
982 }
983
984 if (err)
985 return 5;
986
987 return 0;
988}
989
bb036943
HS
990static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
991 int rounding_flags)
992{
82d8c74d
HS
993 struct cb_pcidas_private *devpriv = dev->private;
994
bb036943
HS
995 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
996 &(devpriv->divisor2), ns,
997 rounding_flags & TRIG_ROUND_MASK);
998
999 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
1000 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
1001 devpriv->divisor1, 2);
1002 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
1003 devpriv->divisor2, 2);
1004}
1005
0a85b6f0
MT
1006static int cb_pcidas_ai_cmd(struct comedi_device *dev,
1007 struct comedi_subdevice *s)
59c7dd3d 1008{
82d8c74d
HS
1009 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1010 struct cb_pcidas_private *devpriv = dev->private;
d163679c 1011 struct comedi_async *async = s->async;
ea6d0d4c 1012 struct comedi_cmd *cmd = &async->cmd;
59c7dd3d
IM
1013 unsigned int bits;
1014 unsigned long flags;
1015
cf530aa4 1016 /* make sure CAL_EN_BIT is disabled */
59c7dd3d 1017 outw(0, devpriv->control_status + CALIBRATION_REG);
cf530aa4 1018 /* initialize before settings pacer source and count values */
59c7dd3d 1019 outw(0, devpriv->control_status + TRIG_CONTSTAT);
cf530aa4 1020 /* clear fifo */
59c7dd3d
IM
1021 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
1022
cf530aa4 1023 /* set mux limits, gain and pacer source */
59c7dd3d 1024 bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
0a85b6f0
MT
1025 END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
1026 GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
cf530aa4 1027 /* set unipolar/bipolar */
59c7dd3d
IM
1028 if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
1029 bits |= UNIP;
cf530aa4 1030 /* set singleended/differential */
59c7dd3d
IM
1031 if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
1032 bits |= SE;
cf530aa4 1033 /* set pacer source */
59c7dd3d
IM
1034 if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
1035 bits |= PACER_EXT_RISE;
1036 else
1037 bits |= PACER_INT;
1038 outw(bits, devpriv->control_status + ADCMUX_CONT);
1039
cf530aa4 1040 /* load counters */
59c7dd3d
IM
1041 if (cmd->convert_src == TRIG_TIMER)
1042 cb_pcidas_load_counters(dev, &cmd->convert_arg,
0a85b6f0 1043 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
1044 else if (cmd->scan_begin_src == TRIG_TIMER)
1045 cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
0a85b6f0 1046 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d 1047
cf530aa4 1048 /* set number of conversions */
2d238b29 1049 if (cmd->stop_src == TRIG_COUNT)
59c7dd3d 1050 devpriv->count = cmd->chanlist_len * cmd->stop_arg;
cf530aa4 1051 /* enable interrupts */
5f74ea14 1052 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d
IM
1053 devpriv->adc_fifo_bits |= INTE;
1054 devpriv->adc_fifo_bits &= ~INT_MASK;
1055 if (cmd->flags & TRIG_WAKE_EOS) {
1056 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
cf530aa4 1057 devpriv->adc_fifo_bits |= INT_EOS; /* interrupt end of burst */
59c7dd3d 1058 else
cf530aa4 1059 devpriv->adc_fifo_bits |= INT_FNE; /* interrupt fifo not empty */
59c7dd3d 1060 } else {
cf530aa4 1061 devpriv->adc_fifo_bits |= INT_FHF; /* interrupt fifo half full */
59c7dd3d 1062 }
193debd1 1063
cf530aa4 1064 /* enable (and clear) interrupts */
59c7dd3d 1065 outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
0a85b6f0 1066 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1067 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 1068
cf530aa4 1069 /* set start trigger and burst mode */
59c7dd3d
IM
1070 bits = 0;
1071 if (cmd->start_src == TRIG_NOW)
1072 bits |= SW_TRIGGER;
f1bc4343 1073 else if (cmd->start_src == TRIG_EXT) {
59c7dd3d 1074 bits |= EXT_TRIGGER | TGEN | XTRCL;
23e3cce3
HS
1075 if (thisboard->is_1602) {
1076 if (cmd->start_arg & CR_INVERT)
1077 bits |= TGPOL;
1078 if (cmd->start_arg & CR_EDGE)
1079 bits |= TGSEL;
1080 }
f1bc4343 1081 } else {
59c7dd3d
IM
1082 comedi_error(dev, "bug!");
1083 return -1;
1084 }
1085 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1086 bits |= BURSTE;
1087 outw(bits, devpriv->control_status + TRIG_CONTSTAT);
59c7dd3d
IM
1088
1089 return 0;
1090}
1091
0a85b6f0
MT
1092static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
1093 struct comedi_subdevice *s,
1094 struct comedi_cmd *cmd)
59c7dd3d 1095{
82d8c74d
HS
1096 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1097 struct cb_pcidas_private *devpriv = dev->private;
59c7dd3d
IM
1098 int err = 0;
1099 int tmp;
1100
1101 /* cmdtest tests a particular command to see if it is valid.
1102 * Using the cmdtest ioctl, a user can create a valid cmd
1103 * and then have it executes by the cmd ioctl.
1104 *
1105 * cmdtest returns 1,2,3,4 or 0, depending on which tests
1106 * the command passes. */
1107
1108 /* step 1: make sure trigger sources are trivially valid */
1109
1110 tmp = cmd->start_src;
1111 cmd->start_src &= TRIG_INT;
1112 if (!cmd->start_src || tmp != cmd->start_src)
1113 err++;
1114
1115 tmp = cmd->scan_begin_src;
1116 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
1117 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1118 err++;
1119
1120 tmp = cmd->convert_src;
1121 cmd->convert_src &= TRIG_NOW;
1122 if (!cmd->convert_src || tmp != cmd->convert_src)
1123 err++;
1124
1125 tmp = cmd->scan_end_src;
1126 cmd->scan_end_src &= TRIG_COUNT;
1127 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1128 err++;
1129
1130 tmp = cmd->stop_src;
1131 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1132 if (!cmd->stop_src || tmp != cmd->stop_src)
1133 err++;
1134
1135 if (err)
1136 return 1;
1137
1138 /* step 2: make sure trigger sources are unique and mutually compatible */
1139
1140 if (cmd->scan_begin_src != TRIG_TIMER &&
0a85b6f0 1141 cmd->scan_begin_src != TRIG_EXT)
59c7dd3d
IM
1142 err++;
1143 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1144 err++;
1145
1146 if (err)
1147 return 2;
1148
1149 /* step 3: make sure arguments are trivially compatible */
1150
1151 if (cmd->start_arg != 0) {
1152 cmd->start_arg = 0;
1153 err++;
1154 }
1155
1156 if (cmd->scan_begin_src == TRIG_TIMER) {
1157 if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
1158 cmd->scan_begin_arg = thisboard->ao_scan_speed;
1159 err++;
1160 }
1161 }
1162
1163 if (cmd->scan_end_arg != cmd->chanlist_len) {
1164 cmd->scan_end_arg = cmd->chanlist_len;
1165 err++;
1166 }
1167 if (cmd->stop_src == TRIG_NONE) {
1168 /* TRIG_NONE */
1169 if (cmd->stop_arg != 0) {
1170 cmd->stop_arg = 0;
1171 err++;
1172 }
1173 }
1174
1175 if (err)
1176 return 3;
1177
1178 /* step 4: fix up any arguments */
1179
1180 if (cmd->scan_begin_src == TRIG_TIMER) {
1181 tmp = cmd->scan_begin_arg;
1182 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
1183 &(devpriv->ao_divisor1),
1184 &(devpriv->ao_divisor2),
1185 &(cmd->scan_begin_arg),
1186 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
1187 if (tmp != cmd->scan_begin_arg)
1188 err++;
1189 }
1190
1191 if (err)
1192 return 4;
1193
cf530aa4 1194 /* check channel/gain list against card's limitations */
59c7dd3d
IM
1195 if (cmd->chanlist && cmd->chanlist_len > 1) {
1196 if (CR_CHAN(cmd->chanlist[0]) != 0 ||
0a85b6f0 1197 CR_CHAN(cmd->chanlist[1]) != 1) {
59c7dd3d 1198 comedi_error(dev,
0a85b6f0 1199 "channels must be ordered channel 0, channel 1 in chanlist\n");
59c7dd3d
IM
1200 err++;
1201 }
1202 }
1203
1204 if (err)
1205 return 5;
1206
1207 return 0;
1208}
1209
9a0f7631
HS
1210/* cancel analog input command */
1211static int cb_pcidas_cancel(struct comedi_device *dev,
1212 struct comedi_subdevice *s)
1213{
82d8c74d 1214 struct cb_pcidas_private *devpriv = dev->private;
9a0f7631
HS
1215 unsigned long flags;
1216
1217 spin_lock_irqsave(&dev->spinlock, flags);
1218 /* disable interrupts */
1219 devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
1220 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1221 spin_unlock_irqrestore(&dev->spinlock, flags);
1222
1223 /* disable start trigger source and burst mode */
1224 outw(0, devpriv->control_status + TRIG_CONTSTAT);
1225 /* software pacer source */
1226 outw(0, devpriv->control_status + ADCMUX_CONT);
1227
1228 return 0;
1229}
1230
1706fcc1
HS
1231static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1232 struct comedi_subdevice *s,
1233 unsigned int trig_num)
1234{
82d8c74d
HS
1235 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1236 struct cb_pcidas_private *devpriv = dev->private;
1706fcc1
HS
1237 unsigned int num_bytes, num_points = thisboard->fifo_size;
1238 struct comedi_async *async = s->async;
1239 struct comedi_cmd *cmd = &s->async->cmd;
1240 unsigned long flags;
1241
1242 if (trig_num != 0)
1243 return -EINVAL;
1244
1245 /* load up fifo */
1246 if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
1247 num_points = devpriv->ao_count;
1248
1249 num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1250 num_points * sizeof(short));
1251 num_points = num_bytes / sizeof(short);
1252
1253 if (cmd->stop_src == TRIG_COUNT)
1254 devpriv->ao_count -= num_points;
1255 /* write data to board's fifo */
1256 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
1257
1258 /* enable dac half-full and empty interrupts */
1259 spin_lock_irqsave(&dev->spinlock, flags);
1260 devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
193debd1 1261
1706fcc1
HS
1262 /* enable and clear interrupts */
1263 outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
1264 devpriv->control_status + INT_ADCFIFO);
1265
1266 /* start dac */
1267 devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
1268 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
193debd1 1269
1706fcc1
HS
1270 spin_unlock_irqrestore(&dev->spinlock, flags);
1271
1272 async->inttrig = NULL;
1273
1274 return 0;
1275}
1276
0a85b6f0
MT
1277static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1278 struct comedi_subdevice *s)
59c7dd3d 1279{
82d8c74d 1280 struct cb_pcidas_private *devpriv = dev->private;
d163679c 1281 struct comedi_async *async = s->async;
ea6d0d4c 1282 struct comedi_cmd *cmd = &async->cmd;
59c7dd3d
IM
1283 unsigned int i;
1284 unsigned long flags;
1285
cf530aa4 1286 /* set channel limits, gain */
5f74ea14 1287 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1288 for (i = 0; i < cmd->chanlist_len; i++) {
cf530aa4 1289 /* enable channel */
59c7dd3d 1290 devpriv->ao_control_bits |=
0a85b6f0 1291 DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
cf530aa4 1292 /* set range */
59c7dd3d 1293 devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
0a85b6f0
MT
1294 CR_RANGE(cmd->
1295 chanlist[i]));
59c7dd3d
IM
1296 }
1297
cf530aa4 1298 /* disable analog out before settings pacer source and count values */
59c7dd3d 1299 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
5f74ea14 1300 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 1301
cf530aa4 1302 /* clear fifo */
59c7dd3d
IM
1303 outw(0, devpriv->ao_registers + DACFIFOCLR);
1304
cf530aa4 1305 /* load counters */
59c7dd3d
IM
1306 if (cmd->scan_begin_src == TRIG_TIMER) {
1307 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
1308 &(devpriv->ao_divisor1),
1309 &(devpriv->ao_divisor2),
1310 &(cmd->scan_begin_arg),
1311 cmd->flags);
59c7dd3d
IM
1312
1313 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
1314 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
0a85b6f0 1315 devpriv->ao_divisor1, 2);
59c7dd3d 1316 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
0a85b6f0 1317 devpriv->ao_divisor2, 2);
59c7dd3d 1318 }
cf530aa4 1319 /* set number of conversions */
2d238b29 1320 if (cmd->stop_src == TRIG_COUNT)
59c7dd3d 1321 devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
cf530aa4 1322 /* set pacer source */
5f74ea14 1323 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d
IM
1324 switch (cmd->scan_begin_src) {
1325 case TRIG_TIMER:
1326 devpriv->ao_control_bits |= DAC_PACER_INT;
1327 break;
1328 case TRIG_EXT:
1329 devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
1330 break;
1331 default:
5f74ea14 1332 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1333 comedi_error(dev, "error setting dac pacer source");
1334 return -1;
1335 break;
1336 }
5f74ea14 1337 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1338
1339 async->inttrig = cb_pcidas_ao_inttrig;
1340
1341 return 0;
1342}
1343
0aa20304
HS
1344/* cancel analog output command */
1345static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1346 struct comedi_subdevice *s)
1347{
82d8c74d 1348 struct cb_pcidas_private *devpriv = dev->private;
0aa20304
HS
1349 unsigned long flags;
1350
1351 spin_lock_irqsave(&dev->spinlock, flags);
1352 /* disable interrupts */
1353 devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
1354 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1355
1356 /* disable output */
1357 devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
1358 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1359 spin_unlock_irqrestore(&dev->spinlock, flags);
1360
1361 return 0;
1362}
1363
9e11d05f
HS
1364static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
1365{
82d8c74d
HS
1366 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1367 struct cb_pcidas_private *devpriv = dev->private;
9e11d05f
HS
1368 struct comedi_subdevice *s = dev->write_subdev;
1369 struct comedi_async *async = s->async;
1370 struct comedi_cmd *cmd = &async->cmd;
1371 unsigned int half_fifo = thisboard->fifo_size / 2;
1372 unsigned int num_points;
1373 unsigned long flags;
1374
1375 async->events = 0;
1376
1377 if (status & DAEMI) {
1378 /* clear dac empty interrupt latch */
1379 spin_lock_irqsave(&dev->spinlock, flags);
1380 outw(devpriv->adc_fifo_bits | DAEMI,
1381 devpriv->control_status + INT_ADCFIFO);
1382 spin_unlock_irqrestore(&dev->spinlock, flags);
1383 if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
1384 if (cmd->stop_src == TRIG_NONE ||
1385 (cmd->stop_src == TRIG_COUNT
1386 && devpriv->ao_count)) {
1387 comedi_error(dev, "dac fifo underflow");
1388 cb_pcidas_ao_cancel(dev, s);
1389 async->events |= COMEDI_CB_ERROR;
1390 }
1391 async->events |= COMEDI_CB_EOA;
1392 }
1393 } else if (status & DAHFI) {
1394 unsigned int num_bytes;
1395
1396 /* figure out how many points we are writing to fifo */
1397 num_points = half_fifo;
1398 if (cmd->stop_src == TRIG_COUNT &&
1399 devpriv->ao_count < num_points)
1400 num_points = devpriv->ao_count;
1401 num_bytes =
1402 cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1403 num_points * sizeof(short));
1404 num_points = num_bytes / sizeof(short);
1405
1406 if (async->cmd.stop_src == TRIG_COUNT)
1407 devpriv->ao_count -= num_points;
1408 /* write data to board's fifo */
1409 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
1410 num_points);
1411 /* clear half-full interrupt latch */
1412 spin_lock_irqsave(&dev->spinlock, flags);
1413 outw(devpriv->adc_fifo_bits | DAHFI,
1414 devpriv->control_status + INT_ADCFIFO);
1415 spin_unlock_irqrestore(&dev->spinlock, flags);
1416 }
1417
1418 comedi_event(dev, s);
1419}
1420
70265d24 1421static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
59c7dd3d 1422{
0a85b6f0 1423 struct comedi_device *dev = (struct comedi_device *)d;
82d8c74d
HS
1424 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1425 struct cb_pcidas_private *devpriv = dev->private;
34c43922 1426 struct comedi_subdevice *s = dev->read_subdev;
d163679c 1427 struct comedi_async *async;
59c7dd3d
IM
1428 int status, s5933_status;
1429 int half_fifo = thisboard->fifo_size / 2;
1430 unsigned int num_samples, i;
1431 static const int timeout = 10000;
1432 unsigned long flags;
1433
2d238b29 1434 if (dev->attached == 0)
59c7dd3d 1435 return IRQ_NONE;
59c7dd3d
IM
1436
1437 async = s->async;
1438 async->events = 0;
1439
1440 s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
59c7dd3d
IM
1441
1442 if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
1443 return IRQ_NONE;
1444
cf530aa4 1445 /* make sure mailbox 4 is empty */
59c7dd3d 1446 inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
cf530aa4 1447 /* clear interrupt on amcc s5933 */
59c7dd3d 1448 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
0a85b6f0 1449 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
59c7dd3d
IM
1450
1451 status = inw(devpriv->control_status + INT_ADCFIFO);
59c7dd3d 1452
cf530aa4 1453 /* check for analog output interrupt */
2d238b29 1454 if (status & (DAHFI | DAEMI))
59c7dd3d 1455 handle_ao_interrupt(dev, status);
cf530aa4
BP
1456 /* check for analog input interrupts */
1457 /* if fifo half-full */
59c7dd3d 1458 if (status & ADHFI) {
cf530aa4 1459 /* read data */
59c7dd3d
IM
1460 num_samples = half_fifo;
1461 if (async->cmd.stop_src == TRIG_COUNT &&
0a85b6f0 1462 num_samples > devpriv->count) {
59c7dd3d
IM
1463 num_samples = devpriv->count;
1464 }
1465 insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
0a85b6f0 1466 num_samples);
59c7dd3d 1467 cfc_write_array_to_buffer(s, devpriv->ai_buffer,
0a85b6f0 1468 num_samples * sizeof(short));
59c7dd3d
IM
1469 devpriv->count -= num_samples;
1470 if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
1471 async->events |= COMEDI_CB_EOA;
1472 cb_pcidas_cancel(dev, s);
1473 }
cf530aa4 1474 /* clear half-full interrupt latch */
5f74ea14 1475 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1476 outw(devpriv->adc_fifo_bits | INT,
0a85b6f0 1477 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1478 spin_unlock_irqrestore(&dev->spinlock, flags);
cf530aa4 1479 /* else if fifo not empty */
59c7dd3d
IM
1480 } else if (status & (ADNEI | EOBI)) {
1481 for (i = 0; i < timeout; i++) {
cf530aa4 1482 /* break if fifo is empty */
59c7dd3d 1483 if ((ADNE & inw(devpriv->control_status +
0a85b6f0 1484 INT_ADCFIFO)) == 0)
59c7dd3d
IM
1485 break;
1486 cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
1487 if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) { /* end of acquisition */
1488 cb_pcidas_cancel(dev, s);
1489 async->events |= COMEDI_CB_EOA;
1490 break;
1491 }
1492 }
cf530aa4 1493 /* clear not-empty interrupt latch */
5f74ea14 1494 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1495 outw(devpriv->adc_fifo_bits | INT,
0a85b6f0 1496 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1497 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1498 } else if (status & EOAI) {
1499 comedi_error(dev,
25985edc 1500 "bug! encountered end of acquisition interrupt?");
cf530aa4 1501 /* clear EOA interrupt latch */
5f74ea14 1502 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1503 outw(devpriv->adc_fifo_bits | EOAI,
0a85b6f0 1504 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1505 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 1506 }
cf530aa4 1507 /* check for fifo overflow */
59c7dd3d
IM
1508 if (status & LADFUL) {
1509 comedi_error(dev, "fifo overflow");
cf530aa4 1510 /* clear overflow interrupt latch */
5f74ea14 1511 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1512 outw(devpriv->adc_fifo_bits | LADFUL,
0a85b6f0 1513 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1514 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1515 cb_pcidas_cancel(dev, s);
1516 async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
1517 }
1518
1519 comedi_event(dev, s);
1520
1521 return IRQ_HANDLED;
1522}
1523
327be979
HS
1524static struct pci_dev *cb_pcidas_find_pci_device(struct comedi_device *dev,
1525 struct comedi_devconfig *it)
e74f209c 1526{
82d8c74d 1527 const struct cb_pcidas_board *thisboard;
e74f209c 1528 struct pci_dev *pcidev = NULL;
327be979
HS
1529 int bus = it->options[0];
1530 int slot = it->options[1];
e74f209c 1531 int i;
e74f209c
HS
1532
1533 for_each_pci_dev(pcidev) {
1534 /* is it not a computer boards card? */
1535 if (pcidev->vendor != PCI_VENDOR_ID_CB)
1536 continue;
1537 /* loop through cards supported by this driver */
327be979
HS
1538 for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
1539 thisboard = &cb_pcidas_boards[i];
1540 if (thisboard->device_id != pcidev->device)
e74f209c
HS
1541 continue;
1542 /* was a particular bus/slot requested? */
327be979 1543 if (bus || slot) {
e74f209c 1544 /* are we on the wrong bus/slot? */
327be979
HS
1545 if (pcidev->bus->number != bus ||
1546 PCI_SLOT(pcidev->devfn) != slot) {
e74f209c
HS
1547 continue;
1548 }
1549 }
327be979
HS
1550 dev->board_ptr = thisboard;
1551 return pcidev;
e74f209c
HS
1552 }
1553 }
327be979
HS
1554 return NULL;
1555}
1556
1557static int cb_pcidas_attach(struct comedi_device *dev,
1558 struct comedi_devconfig *it)
1559{
1560 const struct cb_pcidas_board *thisboard;
1561 struct cb_pcidas_private *devpriv;
1562 struct comedi_subdevice *s;
1563 int i;
1564 int ret;
e74f209c 1565
327be979
HS
1566 if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
1567 return -ENOMEM;
1568 devpriv = dev->private;
1569
1570 devpriv->pci_dev = cb_pcidas_find_pci_device(dev, it);
1571 if (!devpriv->pci_dev) {
1572 dev_err(dev->class_dev, "No supported card found\n");
1573 return -EIO;
1574 }
e74f209c 1575
82d8c74d 1576 thisboard = comedi_board(dev);
e74f209c 1577 dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n",
327be979
HS
1578 thisboard->name, devpriv->pci_dev->bus->number,
1579 PCI_SLOT(devpriv->pci_dev->devfn));
e74f209c 1580
327be979 1581 if (comedi_pci_enable(devpriv->pci_dev, "cb_pcidas")) {
e74f209c
HS
1582 dev_err(dev->class_dev,
1583 "Failed to enable PCI device and request regions\n");
1584 return -EIO;
1585 }
7302abef
HS
1586
1587 devpriv->s5933_config = pci_resource_start(devpriv->pci_dev, 0);
1588 devpriv->control_status = pci_resource_start(devpriv->pci_dev, 1);
1589 devpriv->adc_fifo = pci_resource_start(devpriv->pci_dev, 2);
1590 devpriv->pacer_counter_dio = pci_resource_start(devpriv->pci_dev, 3);
1591 if (thisboard->ao_nchan)
1592 devpriv->ao_registers = pci_resource_start(devpriv->pci_dev, 4);
1593
e74f209c
HS
1594 /* disable and clear interrupts on amcc s5933 */
1595 outl(INTCSR_INBOX_INTR_STATUS,
1596 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1597
e74f209c
HS
1598 if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
1599 IRQF_SHARED, "cb_pcidas", dev)) {
1600 dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
1601 devpriv->pci_dev->irq);
1602 return -EINVAL;
1603 }
1604 dev->irq = devpriv->pci_dev->irq;
1605
e74f209c
HS
1606 dev->board_name = thisboard->name;
1607
1608 ret = comedi_alloc_subdevices(dev, 7);
1609 if (ret)
1610 return ret;
1611
1612 s = dev->subdevices + 0;
1613 /* analog input subdevice */
1614 dev->read_subdev = s;
1615 s->type = COMEDI_SUBD_AI;
1616 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
1617 /* WARNING: Number of inputs in differential mode is ignored */
8f608fc8
HS
1618 s->n_chan = thisboard->ai_nchan;
1619 s->len_chanlist = thisboard->ai_nchan;
e74f209c
HS
1620 s->maxdata = (1 << thisboard->ai_bits) - 1;
1621 s->range_table = thisboard->ranges;
1622 s->insn_read = cb_pcidas_ai_rinsn;
1623 s->insn_config = ai_config_insn;
1624 s->do_cmd = cb_pcidas_ai_cmd;
1625 s->do_cmdtest = cb_pcidas_ai_cmdtest;
1626 s->cancel = cb_pcidas_cancel;
1627
1628 /* analog output subdevice */
1629 s = dev->subdevices + 1;
1630 if (thisboard->ao_nchan) {
1631 s->type = COMEDI_SUBD_AO;
1632 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
1633 s->n_chan = thisboard->ao_nchan;
1634 /* analog out resolution is the same as analog input resolution, so use ai_bits */
1635 s->maxdata = (1 << thisboard->ai_bits) - 1;
1636 s->range_table = &cb_pcidas_ao_ranges;
1637 s->insn_read = cb_pcidas_ao_readback_insn;
1638 if (thisboard->has_ao_fifo) {
1639 dev->write_subdev = s;
1640 s->subdev_flags |= SDF_CMD_WRITE;
1641 s->insn_write = cb_pcidas_ao_fifo_winsn;
1642 s->do_cmdtest = cb_pcidas_ao_cmdtest;
1643 s->do_cmd = cb_pcidas_ao_cmd;
1644 s->cancel = cb_pcidas_ao_cancel;
1645 } else {
1646 s->insn_write = cb_pcidas_ao_nofifo_winsn;
1647 }
1648 } else {
1649 s->type = COMEDI_SUBD_UNUSED;
1650 }
1651
1652 /* 8255 */
1653 s = dev->subdevices + 2;
1654 subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
1655
1656 /* serial EEPROM, */
1657 s = dev->subdevices + 3;
1658 s->type = COMEDI_SUBD_MEMORY;
1659 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
1660 s->n_chan = 256;
1661 s->maxdata = 0xff;
1662 s->insn_read = eeprom_read_insn;
1663
1664 /* 8800 caldac */
1665 s = dev->subdevices + 4;
1666 s->type = COMEDI_SUBD_CALIB;
1667 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1668 s->n_chan = NUM_CHANNELS_8800;
1669 s->maxdata = 0xff;
1670 s->insn_read = caldac_read_insn;
1671 s->insn_write = caldac_write_insn;
1672 for (i = 0; i < s->n_chan; i++)
1673 caldac_8800_write(dev, i, s->maxdata / 2);
1674
1675 /* trim potentiometer */
1676 s = dev->subdevices + 5;
1677 s->type = COMEDI_SUBD_CALIB;
1678 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1679 if (thisboard->trimpot == AD7376) {
1680 s->n_chan = NUM_CHANNELS_7376;
1681 s->maxdata = 0x7f;
1682 } else {
1683 s->n_chan = NUM_CHANNELS_8402;
1684 s->maxdata = 0xff;
1685 }
1686 s->insn_read = trimpot_read_insn;
1687 s->insn_write = trimpot_write_insn;
1688 for (i = 0; i < s->n_chan; i++)
1689 cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
1690
1691 /* dac08 caldac */
1692 s = dev->subdevices + 6;
1693 if (thisboard->has_dac08) {
1694 s->type = COMEDI_SUBD_CALIB;
1695 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1696 s->n_chan = NUM_CHANNELS_DAC08;
1697 s->insn_read = dac08_read_insn;
1698 s->insn_write = dac08_write_insn;
1699 s->maxdata = 0xff;
1700 dac08_write(dev, s->maxdata / 2);
1701 } else
1702 s->type = COMEDI_SUBD_UNUSED;
1703
1704 /* make sure mailbox 4 is empty */
1705 inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1706 /* Set bits to enable incoming mailbox interrupts on amcc s5933. */
1707 devpriv->s5933_intcsr_bits =
1708 INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1709 INTCSR_INBOX_FULL_INT;
1710 /* clear and enable interrupt on amcc s5933 */
1711 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1712 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1713
1714 return 1;
1715}
1716
1717static void cb_pcidas_detach(struct comedi_device *dev)
1718{
82d8c74d
HS
1719 struct cb_pcidas_private *devpriv = dev->private;
1720
e74f209c
HS
1721 if (devpriv) {
1722 if (devpriv->s5933_config) {
1723 outl(INTCSR_INBOX_INTR_STATUS,
1724 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1725 }
1726 }
1727 if (dev->irq)
1728 free_irq(dev->irq, dev);
1729 if (dev->subdevices)
1730 subdev_8255_cleanup(dev, dev->subdevices + 2);
1731 if (devpriv && devpriv->pci_dev) {
1732 if (devpriv->s5933_config)
1733 comedi_pci_disable(devpriv->pci_dev);
1734 pci_dev_put(devpriv->pci_dev);
1735 }
1736}
1737
715b2284
HS
1738static struct comedi_driver cb_pcidas_driver = {
1739 .driver_name = "cb_pcidas",
1740 .module = THIS_MODULE,
1741 .attach = cb_pcidas_attach,
1742 .detach = cb_pcidas_detach,
1743};
1744
1745static int __devinit cb_pcidas_pci_probe(struct pci_dev *dev,
1746 const struct pci_device_id *ent)
727b286b 1747{
715b2284 1748 return comedi_pci_auto_config(dev, &cb_pcidas_driver);
727b286b
AT
1749}
1750
715b2284 1751static void __devexit cb_pcidas_pci_remove(struct pci_dev *dev)
727b286b
AT
1752{
1753 comedi_pci_auto_unconfig(dev);
1754}
1755
715b2284
HS
1756static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
1757 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
1758 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
1759 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
1760 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
1761 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
1762 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
1763 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
1764 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
1765 { 0 }
727b286b 1766};
715b2284 1767MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
727b286b 1768
715b2284
HS
1769static struct pci_driver cb_pcidas_pci_driver = {
1770 .name = "cb_pcidas",
1771 .id_table = cb_pcidas_pci_table,
1772 .probe = cb_pcidas_pci_probe,
1773 .remove = __devexit_p(cb_pcidas_pci_remove)
1774};
1775module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
90f703d3
AT
1776
1777MODULE_AUTHOR("Comedi http://www.comedi.org");
1778MODULE_DESCRIPTION("Comedi low-level driver");
1779MODULE_LICENSE("GPL");