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