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