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