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