staging: comedi: cb_pcidas: remove forward declarations 2
[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 void handle_ao_interrupt(struct comedi_device *dev, unsigned int status);
0a85b6f0
MT
451static int cb_pcidas_cancel(struct comedi_device *dev,
452 struct comedi_subdevice *s);
453static int cb_pcidas_ao_cancel(struct comedi_device *dev,
454 struct comedi_subdevice *s);
814900c9 455static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
0a85b6f0 456 int round_flags);
814900c9 457static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
0a85b6f0 458 uint8_t value);
814900c9
BP
459static int trimpot_7376_write(struct comedi_device *dev, uint8_t value);
460static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
0a85b6f0 461 uint8_t value);
814900c9 462static int nvram_read(struct comedi_device *dev, unsigned int address,
2d238b29 463 uint8_t *data);
59c7dd3d 464
814900c9 465static inline unsigned int cal_enable_bits(struct comedi_device *dev)
59c7dd3d
IM
466{
467 return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
468}
469
59c7dd3d
IM
470/*
471 * "instructions" read/write data in "one-shot" or "software-triggered"
472 * mode.
473 */
0a85b6f0
MT
474static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
475 struct comedi_subdevice *s,
476 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
477{
478 int n, i;
479 unsigned int bits;
480 static const int timeout = 10000;
481 int channel;
cf530aa4 482 /* enable calibration input if appropriate */
59c7dd3d
IM
483 if (insn->chanspec & CR_ALT_SOURCE) {
484 outw(cal_enable_bits(dev),
0a85b6f0 485 devpriv->control_status + CALIBRATION_REG);
59c7dd3d
IM
486 channel = 0;
487 } else {
488 outw(0, devpriv->control_status + CALIBRATION_REG);
489 channel = CR_CHAN(insn->chanspec);
490 }
cf530aa4 491 /* set mux limits and gain */
59c7dd3d 492 bits = BEGIN_SCAN(channel) |
0a85b6f0 493 END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
cf530aa4 494 /* set unipolar/bipolar */
59c7dd3d
IM
495 if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
496 bits |= UNIP;
cf530aa4 497 /* set singleended/differential */
59c7dd3d
IM
498 if (CR_AREF(insn->chanspec) != AREF_DIFF)
499 bits |= SE;
500 outw(bits, devpriv->control_status + ADCMUX_CONT);
501
502 /* clear fifo */
503 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
504
505 /* convert n samples */
506 for (n = 0; n < insn->n; n++) {
507 /* trigger conversion */
508 outw(0, devpriv->adc_fifo + ADCDATA);
509
510 /* wait for conversion to end */
511 /* return -ETIMEDOUT if there is a timeout */
512 for (i = 0; i < timeout; i++) {
513 if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
514 break;
515 }
516 if (i == timeout)
517 return -ETIMEDOUT;
518
519 /* read data */
520 data[n] = inw(devpriv->adc_fifo + ADCDATA);
521 }
522
523 /* return the number of samples read/written */
524 return n;
525}
526
0a85b6f0
MT
527static int ai_config_calibration_source(struct comedi_device *dev,
528 unsigned int *data)
59c7dd3d
IM
529{
530 static const int num_calibration_sources = 8;
790c5541 531 unsigned int source = data[1];
59c7dd3d
IM
532
533 if (source >= num_calibration_sources) {
f41ad667 534 dev_err(dev->class_dev, "invalid calibration source: %i\n",
94cc0b4a 535 source);
59c7dd3d
IM
536 return -EINVAL;
537 }
538
539 devpriv->calibration_source = source;
540
541 return 2;
542}
543
da91b269 544static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 545 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
546{
547 int id = data[0];
548
549 switch (id) {
550 case INSN_CONFIG_ALT_SOURCE:
551 return ai_config_calibration_source(dev, data);
552 break;
553 default:
554 return -EINVAL;
555 break;
556 }
557 return -EINVAL;
558}
559
cf530aa4 560/* analog output insn for pcidas-1000 and 1200 series */
0a85b6f0
MT
561static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
562 struct comedi_subdevice *s,
563 struct comedi_insn *insn,
564 unsigned int *data)
59c7dd3d
IM
565{
566 int channel;
567 unsigned long flags;
568
cf530aa4 569 /* set channel and range */
59c7dd3d 570 channel = CR_CHAN(insn->chanspec);
5f74ea14 571 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 572 devpriv->ao_control_bits &=
0a85b6f0 573 ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel);
59c7dd3d 574 devpriv->ao_control_bits |=
0a85b6f0 575 DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec));
59c7dd3d 576 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
5f74ea14 577 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 578
cf530aa4 579 /* remember value for readback */
59c7dd3d 580 devpriv->ao_value[channel] = data[0];
cf530aa4 581 /* send data */
59c7dd3d
IM
582 outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
583
584 return 1;
585}
586
cf530aa4 587/* analog output insn for pcidas-1602 series */
0a85b6f0
MT
588static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
589 struct comedi_subdevice *s,
590 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
591{
592 int channel;
593 unsigned long flags;
594
cf530aa4 595 /* clear dac fifo */
59c7dd3d
IM
596 outw(0, devpriv->ao_registers + DACFIFOCLR);
597
cf530aa4 598 /* set channel and range */
59c7dd3d 599 channel = CR_CHAN(insn->chanspec);
5f74ea14 600 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 601 devpriv->ao_control_bits &=
0a85b6f0
MT
602 ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) &
603 ~DAC_PACER_MASK;
59c7dd3d 604 devpriv->ao_control_bits |=
0a85b6f0
MT
605 DACEN | DAC_RANGE(channel,
606 CR_RANGE(insn->
607 chanspec)) | DAC_CHAN_EN(channel) |
608 DAC_START;
59c7dd3d 609 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
5f74ea14 610 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 611
cf530aa4 612 /* remember value for readback */
59c7dd3d 613 devpriv->ao_value[channel] = data[0];
cf530aa4 614 /* send data */
59c7dd3d
IM
615 outw(data[0], devpriv->ao_registers + DACDATA);
616
617 return 1;
618}
619
cf530aa4
BP
620/* analog output readback insn */
621/* XXX loses track of analog output value back after an analog ouput command is executed */
0a85b6f0
MT
622static int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
623 struct comedi_subdevice *s,
624 struct comedi_insn *insn,
625 unsigned int *data)
59c7dd3d
IM
626{
627 data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
628
629 return 1;
630}
631
0a85b6f0
MT
632static int eeprom_read_insn(struct comedi_device *dev,
633 struct comedi_subdevice *s,
634 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
635{
636 uint8_t nvram_data;
637 int retval;
638
639 retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
640 if (retval < 0)
641 return retval;
642
643 data[0] = nvram_data;
644
645 return 1;
646}
647
0a85b6f0
MT
648static int caldac_write_insn(struct comedi_device *dev,
649 struct comedi_subdevice *s,
650 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
651{
652 const unsigned int channel = CR_CHAN(insn->chanspec);
653
654 return caldac_8800_write(dev, channel, data[0]);
655}
656
0a85b6f0
MT
657static int caldac_read_insn(struct comedi_device *dev,
658 struct comedi_subdevice *s,
659 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
660{
661 data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
662
663 return 1;
664}
665
666/* 1602/16 pregain offset */
da91b269 667static int dac08_write(struct comedi_device *dev, unsigned int value)
59c7dd3d
IM
668{
669 if (devpriv->dac08_value == value)
670 return 1;
671
672 devpriv->dac08_value = value;
673
674 outw(cal_enable_bits(dev) | (value & 0xff),
0a85b6f0 675 devpriv->control_status + CALIBRATION_REG);
5f74ea14 676 udelay(1);
59c7dd3d 677 outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff),
0a85b6f0 678 devpriv->control_status + CALIBRATION_REG);
5f74ea14 679 udelay(1);
59c7dd3d 680 outw(cal_enable_bits(dev) | (value & 0xff),
0a85b6f0 681 devpriv->control_status + CALIBRATION_REG);
5f74ea14 682 udelay(1);
59c7dd3d
IM
683
684 return 1;
685}
686
0a85b6f0
MT
687static int dac08_write_insn(struct comedi_device *dev,
688 struct comedi_subdevice *s,
689 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
690{
691 return dac08_write(dev, data[0]);
692}
693
0a85b6f0
MT
694static int dac08_read_insn(struct comedi_device *dev,
695 struct comedi_subdevice *s, struct comedi_insn *insn,
696 unsigned int *data)
59c7dd3d
IM
697{
698 data[0] = devpriv->dac08_value;
699
700 return 1;
701}
702
da91b269 703static int cb_pcidas_trimpot_write(struct comedi_device *dev,
0a85b6f0 704 unsigned int channel, unsigned int value)
59c7dd3d
IM
705{
706 if (devpriv->trimpot_value[channel] == value)
707 return 1;
708
709 devpriv->trimpot_value[channel] = value;
710 switch (thisboard->trimpot) {
711 case AD7376:
712 trimpot_7376_write(dev, value);
713 break;
714 case AD8402:
715 trimpot_8402_write(dev, channel, value);
716 break;
717 default:
718 comedi_error(dev, "driver bug?");
719 return -1;
720 break;
721 }
722
723 return 1;
724}
725
0a85b6f0
MT
726static int trimpot_write_insn(struct comedi_device *dev,
727 struct comedi_subdevice *s,
728 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
729{
730 unsigned int channel = CR_CHAN(insn->chanspec);
731
732 return cb_pcidas_trimpot_write(dev, channel, data[0]);
733}
734
0a85b6f0
MT
735static int trimpot_read_insn(struct comedi_device *dev,
736 struct comedi_subdevice *s,
737 struct comedi_insn *insn, unsigned int *data)
59c7dd3d
IM
738{
739 unsigned int channel = CR_CHAN(insn->chanspec);
740
741 data[0] = devpriv->trimpot_value[channel];
742
743 return 1;
744}
745
0a85b6f0
MT
746static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
747 struct comedi_subdevice *s,
748 struct comedi_cmd *cmd)
59c7dd3d
IM
749{
750 int err = 0;
751 int tmp;
752 int i, gain, start_chan;
753
754 /* cmdtest tests a particular command to see if it is valid.
755 * Using the cmdtest ioctl, a user can create a valid cmd
756 * and then have it executes by the cmd ioctl.
757 *
758 * cmdtest returns 1,2,3,4 or 0, depending on which tests
759 * the command passes. */
760
761 /* step 1: make sure trigger sources are trivially valid */
762
763 tmp = cmd->start_src;
764 cmd->start_src &= TRIG_NOW | TRIG_EXT;
765 if (!cmd->start_src || tmp != cmd->start_src)
766 err++;
767
768 tmp = cmd->scan_begin_src;
769 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
770 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
771 err++;
772
773 tmp = cmd->convert_src;
774 cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
775 if (!cmd->convert_src || tmp != cmd->convert_src)
776 err++;
777
778 tmp = cmd->scan_end_src;
779 cmd->scan_end_src &= TRIG_COUNT;
780 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
781 err++;
782
783 tmp = cmd->stop_src;
784 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
785 if (!cmd->stop_src || tmp != cmd->stop_src)
786 err++;
787
788 if (err)
789 return 1;
790
791 /* step 2: make sure trigger sources are unique and mutually compatible */
792
793 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
794 err++;
795 if (cmd->scan_begin_src != TRIG_FOLLOW &&
0a85b6f0
MT
796 cmd->scan_begin_src != TRIG_TIMER &&
797 cmd->scan_begin_src != TRIG_EXT)
59c7dd3d
IM
798 err++;
799 if (cmd->convert_src != TRIG_TIMER &&
0a85b6f0 800 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
59c7dd3d
IM
801 err++;
802 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
803 err++;
804
cf530aa4 805 /* make sure trigger sources are compatible with each other */
59c7dd3d
IM
806 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
807 err++;
808 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
809 err++;
810 if (cmd->start_src == TRIG_EXT &&
0a85b6f0 811 (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
59c7dd3d
IM
812 err++;
813
814 if (err)
815 return 2;
816
817 /* step 3: make sure arguments are trivially compatible */
818
f1bc4343
BD
819 switch (cmd->start_src) {
820 case TRIG_EXT:
821 /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
822 if ((cmd->start_arg
823 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
824 cmd->start_arg &=
825 ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
826 err++;
827 }
828 if (!thisboard->has_ai_trig_invert &&
829 (cmd->start_arg & CR_INVERT)) {
830 cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
831 err++;
832 }
833 break;
834 default:
835 if (cmd->start_arg != 0) {
836 cmd->start_arg = 0;
837 err++;
838 }
839 break;
59c7dd3d
IM
840 }
841
842 if (cmd->scan_begin_src == TRIG_TIMER) {
843 if (cmd->scan_begin_arg <
0a85b6f0 844 thisboard->ai_speed * cmd->chanlist_len) {
59c7dd3d 845 cmd->scan_begin_arg =
0a85b6f0 846 thisboard->ai_speed * cmd->chanlist_len;
59c7dd3d
IM
847 err++;
848 }
849 }
850 if (cmd->convert_src == TRIG_TIMER) {
851 if (cmd->convert_arg < thisboard->ai_speed) {
852 cmd->convert_arg = thisboard->ai_speed;
853 err++;
854 }
855 }
856
857 if (cmd->scan_end_arg != cmd->chanlist_len) {
858 cmd->scan_end_arg = cmd->chanlist_len;
859 err++;
860 }
861 if (cmd->stop_src == TRIG_NONE) {
862 /* TRIG_NONE */
863 if (cmd->stop_arg != 0) {
864 cmd->stop_arg = 0;
865 err++;
866 }
867 }
868
869 if (err)
870 return 3;
871
872 /* step 4: fix up any arguments */
873
874 if (cmd->scan_begin_src == TRIG_TIMER) {
875 tmp = cmd->scan_begin_arg;
876 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
877 &(devpriv->divisor1),
878 &(devpriv->divisor2),
879 &(cmd->scan_begin_arg),
880 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
881 if (tmp != cmd->scan_begin_arg)
882 err++;
883 }
884 if (cmd->convert_src == TRIG_TIMER) {
885 tmp = cmd->convert_arg;
886 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
887 &(devpriv->divisor1),
888 &(devpriv->divisor2),
889 &(cmd->convert_arg),
890 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
891 if (tmp != cmd->convert_arg)
892 err++;
893 }
894
895 if (err)
896 return 4;
897
cf530aa4 898 /* check channel/gain list against card's limitations */
59c7dd3d
IM
899 if (cmd->chanlist) {
900 gain = CR_RANGE(cmd->chanlist[0]);
901 start_chan = CR_CHAN(cmd->chanlist[0]);
902 for (i = 1; i < cmd->chanlist_len; i++) {
903 if (CR_CHAN(cmd->chanlist[i]) !=
0a85b6f0 904 (start_chan + i) % s->n_chan) {
59c7dd3d 905 comedi_error(dev,
0a85b6f0 906 "entries in chanlist must be consecutive channels, counting upwards\n");
59c7dd3d
IM
907 err++;
908 }
909 if (CR_RANGE(cmd->chanlist[i]) != gain) {
910 comedi_error(dev,
0a85b6f0 911 "entries in chanlist must all have the same gain\n");
59c7dd3d
IM
912 err++;
913 }
914 }
915 }
916
917 if (err)
918 return 5;
919
920 return 0;
921}
922
0a85b6f0
MT
923static int cb_pcidas_ai_cmd(struct comedi_device *dev,
924 struct comedi_subdevice *s)
59c7dd3d 925{
d163679c 926 struct comedi_async *async = s->async;
ea6d0d4c 927 struct comedi_cmd *cmd = &async->cmd;
59c7dd3d
IM
928 unsigned int bits;
929 unsigned long flags;
930
cf530aa4 931 /* make sure CAL_EN_BIT is disabled */
59c7dd3d 932 outw(0, devpriv->control_status + CALIBRATION_REG);
cf530aa4 933 /* initialize before settings pacer source and count values */
59c7dd3d 934 outw(0, devpriv->control_status + TRIG_CONTSTAT);
cf530aa4 935 /* clear fifo */
59c7dd3d
IM
936 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
937
cf530aa4 938 /* set mux limits, gain and pacer source */
59c7dd3d 939 bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
0a85b6f0
MT
940 END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
941 GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
cf530aa4 942 /* set unipolar/bipolar */
59c7dd3d
IM
943 if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
944 bits |= UNIP;
cf530aa4 945 /* set singleended/differential */
59c7dd3d
IM
946 if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
947 bits |= SE;
cf530aa4 948 /* set pacer source */
59c7dd3d
IM
949 if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
950 bits |= PACER_EXT_RISE;
951 else
952 bits |= PACER_INT;
953 outw(bits, devpriv->control_status + ADCMUX_CONT);
954
955#ifdef CB_PCIDAS_DEBUG
f41ad667 956 dev_dbg(dev->class_dev, "sent 0x%x to adcmux control\n", bits);
59c7dd3d
IM
957#endif
958
cf530aa4 959 /* load counters */
59c7dd3d
IM
960 if (cmd->convert_src == TRIG_TIMER)
961 cb_pcidas_load_counters(dev, &cmd->convert_arg,
0a85b6f0 962 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
963 else if (cmd->scan_begin_src == TRIG_TIMER)
964 cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
0a85b6f0 965 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d 966
cf530aa4 967 /* set number of conversions */
2d238b29 968 if (cmd->stop_src == TRIG_COUNT)
59c7dd3d 969 devpriv->count = cmd->chanlist_len * cmd->stop_arg;
cf530aa4 970 /* enable interrupts */
5f74ea14 971 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d
IM
972 devpriv->adc_fifo_bits |= INTE;
973 devpriv->adc_fifo_bits &= ~INT_MASK;
974 if (cmd->flags & TRIG_WAKE_EOS) {
975 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
cf530aa4 976 devpriv->adc_fifo_bits |= INT_EOS; /* interrupt end of burst */
59c7dd3d 977 else
cf530aa4 978 devpriv->adc_fifo_bits |= INT_FNE; /* interrupt fifo not empty */
59c7dd3d 979 } else {
cf530aa4 980 devpriv->adc_fifo_bits |= INT_FHF; /* interrupt fifo half full */
59c7dd3d
IM
981 }
982#ifdef CB_PCIDAS_DEBUG
f41ad667 983 dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n",
aa4b8c72 984 devpriv->adc_fifo_bits);
59c7dd3d 985#endif
cf530aa4 986 /* enable (and clear) interrupts */
59c7dd3d 987 outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
0a85b6f0 988 devpriv->control_status + INT_ADCFIFO);
5f74ea14 989 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 990
cf530aa4 991 /* set start trigger and burst mode */
59c7dd3d
IM
992 bits = 0;
993 if (cmd->start_src == TRIG_NOW)
994 bits |= SW_TRIGGER;
f1bc4343 995 else if (cmd->start_src == TRIG_EXT) {
59c7dd3d 996 bits |= EXT_TRIGGER | TGEN | XTRCL;
f1bc4343
BD
997 if (thisboard->has_ai_trig_invert
998 && (cmd->start_arg & CR_INVERT))
999 bits |= TGPOL;
1000 if (thisboard->has_ai_trig_gated && (cmd->start_arg & CR_EDGE))
1001 bits |= TGSEL;
1002 } else {
59c7dd3d
IM
1003 comedi_error(dev, "bug!");
1004 return -1;
1005 }
1006 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1007 bits |= BURSTE;
1008 outw(bits, devpriv->control_status + TRIG_CONTSTAT);
1009#ifdef CB_PCIDAS_DEBUG
f41ad667 1010 dev_dbg(dev->class_dev, "sent 0x%x to trig control\n", bits);
59c7dd3d
IM
1011#endif
1012
1013 return 0;
1014}
1015
0a85b6f0
MT
1016static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
1017 struct comedi_subdevice *s,
1018 struct comedi_cmd *cmd)
59c7dd3d
IM
1019{
1020 int err = 0;
1021 int tmp;
1022
1023 /* cmdtest tests a particular command to see if it is valid.
1024 * Using the cmdtest ioctl, a user can create a valid cmd
1025 * and then have it executes by the cmd ioctl.
1026 *
1027 * cmdtest returns 1,2,3,4 or 0, depending on which tests
1028 * the command passes. */
1029
1030 /* step 1: make sure trigger sources are trivially valid */
1031
1032 tmp = cmd->start_src;
1033 cmd->start_src &= TRIG_INT;
1034 if (!cmd->start_src || tmp != cmd->start_src)
1035 err++;
1036
1037 tmp = cmd->scan_begin_src;
1038 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
1039 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1040 err++;
1041
1042 tmp = cmd->convert_src;
1043 cmd->convert_src &= TRIG_NOW;
1044 if (!cmd->convert_src || tmp != cmd->convert_src)
1045 err++;
1046
1047 tmp = cmd->scan_end_src;
1048 cmd->scan_end_src &= TRIG_COUNT;
1049 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1050 err++;
1051
1052 tmp = cmd->stop_src;
1053 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1054 if (!cmd->stop_src || tmp != cmd->stop_src)
1055 err++;
1056
1057 if (err)
1058 return 1;
1059
1060 /* step 2: make sure trigger sources are unique and mutually compatible */
1061
1062 if (cmd->scan_begin_src != TRIG_TIMER &&
0a85b6f0 1063 cmd->scan_begin_src != TRIG_EXT)
59c7dd3d
IM
1064 err++;
1065 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1066 err++;
1067
1068 if (err)
1069 return 2;
1070
1071 /* step 3: make sure arguments are trivially compatible */
1072
1073 if (cmd->start_arg != 0) {
1074 cmd->start_arg = 0;
1075 err++;
1076 }
1077
1078 if (cmd->scan_begin_src == TRIG_TIMER) {
1079 if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
1080 cmd->scan_begin_arg = thisboard->ao_scan_speed;
1081 err++;
1082 }
1083 }
1084
1085 if (cmd->scan_end_arg != cmd->chanlist_len) {
1086 cmd->scan_end_arg = cmd->chanlist_len;
1087 err++;
1088 }
1089 if (cmd->stop_src == TRIG_NONE) {
1090 /* TRIG_NONE */
1091 if (cmd->stop_arg != 0) {
1092 cmd->stop_arg = 0;
1093 err++;
1094 }
1095 }
1096
1097 if (err)
1098 return 3;
1099
1100 /* step 4: fix up any arguments */
1101
1102 if (cmd->scan_begin_src == TRIG_TIMER) {
1103 tmp = cmd->scan_begin_arg;
1104 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
1105 &(devpriv->ao_divisor1),
1106 &(devpriv->ao_divisor2),
1107 &(cmd->scan_begin_arg),
1108 cmd->flags & TRIG_ROUND_MASK);
59c7dd3d
IM
1109 if (tmp != cmd->scan_begin_arg)
1110 err++;
1111 }
1112
1113 if (err)
1114 return 4;
1115
cf530aa4 1116 /* check channel/gain list against card's limitations */
59c7dd3d
IM
1117 if (cmd->chanlist && cmd->chanlist_len > 1) {
1118 if (CR_CHAN(cmd->chanlist[0]) != 0 ||
0a85b6f0 1119 CR_CHAN(cmd->chanlist[1]) != 1) {
59c7dd3d 1120 comedi_error(dev,
0a85b6f0 1121 "channels must be ordered channel 0, channel 1 in chanlist\n");
59c7dd3d
IM
1122 err++;
1123 }
1124 }
1125
1126 if (err)
1127 return 5;
1128
1129 return 0;
1130}
1131
1706fcc1
HS
1132static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1133 struct comedi_subdevice *s,
1134 unsigned int trig_num)
1135{
1136 unsigned int num_bytes, num_points = thisboard->fifo_size;
1137 struct comedi_async *async = s->async;
1138 struct comedi_cmd *cmd = &s->async->cmd;
1139 unsigned long flags;
1140
1141 if (trig_num != 0)
1142 return -EINVAL;
1143
1144 /* load up fifo */
1145 if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
1146 num_points = devpriv->ao_count;
1147
1148 num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1149 num_points * sizeof(short));
1150 num_points = num_bytes / sizeof(short);
1151
1152 if (cmd->stop_src == TRIG_COUNT)
1153 devpriv->ao_count -= num_points;
1154 /* write data to board's fifo */
1155 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
1156
1157 /* enable dac half-full and empty interrupts */
1158 spin_lock_irqsave(&dev->spinlock, flags);
1159 devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
1160#ifdef CB_PCIDAS_DEBUG
1161 dev_dbg(dev->class_dev, "adc_fifo_bits are 0x%x\n",
1162 devpriv->adc_fifo_bits);
1163#endif
1164 /* enable and clear interrupts */
1165 outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
1166 devpriv->control_status + INT_ADCFIFO);
1167
1168 /* start dac */
1169 devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
1170 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1171#ifdef CB_PCIDAS_DEBUG
1172 dev_dbg(dev->class_dev, "sent 0x%x to dac control\n",
1173 devpriv->ao_control_bits);
1174#endif
1175 spin_unlock_irqrestore(&dev->spinlock, flags);
1176
1177 async->inttrig = NULL;
1178
1179 return 0;
1180}
1181
0a85b6f0
MT
1182static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1183 struct comedi_subdevice *s)
59c7dd3d 1184{
d163679c 1185 struct comedi_async *async = s->async;
ea6d0d4c 1186 struct comedi_cmd *cmd = &async->cmd;
59c7dd3d
IM
1187 unsigned int i;
1188 unsigned long flags;
1189
cf530aa4 1190 /* set channel limits, gain */
5f74ea14 1191 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1192 for (i = 0; i < cmd->chanlist_len; i++) {
cf530aa4 1193 /* enable channel */
59c7dd3d 1194 devpriv->ao_control_bits |=
0a85b6f0 1195 DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
cf530aa4 1196 /* set range */
59c7dd3d 1197 devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
0a85b6f0
MT
1198 CR_RANGE(cmd->
1199 chanlist[i]));
59c7dd3d
IM
1200 }
1201
cf530aa4 1202 /* disable analog out before settings pacer source and count values */
59c7dd3d 1203 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
5f74ea14 1204 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 1205
cf530aa4 1206 /* clear fifo */
59c7dd3d
IM
1207 outw(0, devpriv->ao_registers + DACFIFOCLR);
1208
cf530aa4 1209 /* load counters */
59c7dd3d
IM
1210 if (cmd->scan_begin_src == TRIG_TIMER) {
1211 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
0a85b6f0
MT
1212 &(devpriv->ao_divisor1),
1213 &(devpriv->ao_divisor2),
1214 &(cmd->scan_begin_arg),
1215 cmd->flags);
59c7dd3d
IM
1216
1217 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
1218 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
0a85b6f0 1219 devpriv->ao_divisor1, 2);
59c7dd3d 1220 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
0a85b6f0 1221 devpriv->ao_divisor2, 2);
59c7dd3d 1222 }
cf530aa4 1223 /* set number of conversions */
2d238b29 1224 if (cmd->stop_src == TRIG_COUNT)
59c7dd3d 1225 devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
cf530aa4 1226 /* set pacer source */
5f74ea14 1227 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d
IM
1228 switch (cmd->scan_begin_src) {
1229 case TRIG_TIMER:
1230 devpriv->ao_control_bits |= DAC_PACER_INT;
1231 break;
1232 case TRIG_EXT:
1233 devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
1234 break;
1235 default:
5f74ea14 1236 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1237 comedi_error(dev, "error setting dac pacer source");
1238 return -1;
1239 break;
1240 }
5f74ea14 1241 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1242
1243 async->inttrig = cb_pcidas_ao_inttrig;
1244
1245 return 0;
1246}
1247
70265d24 1248static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
59c7dd3d 1249{
0a85b6f0 1250 struct comedi_device *dev = (struct comedi_device *)d;
34c43922 1251 struct comedi_subdevice *s = dev->read_subdev;
d163679c 1252 struct comedi_async *async;
59c7dd3d
IM
1253 int status, s5933_status;
1254 int half_fifo = thisboard->fifo_size / 2;
1255 unsigned int num_samples, i;
1256 static const int timeout = 10000;
1257 unsigned long flags;
1258
2d238b29 1259 if (dev->attached == 0)
59c7dd3d 1260 return IRQ_NONE;
59c7dd3d
IM
1261
1262 async = s->async;
1263 async->events = 0;
1264
1265 s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1266#ifdef CB_PCIDAS_DEBUG
f41ad667
IA
1267 dev_dbg(dev->class_dev, "intcsr 0x%x\n", s5933_status);
1268 dev_dbg(dev->class_dev, "mbef 0x%x\n",
94cc0b4a 1269 inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
59c7dd3d
IM
1270#endif
1271
1272 if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
1273 return IRQ_NONE;
1274
cf530aa4 1275 /* make sure mailbox 4 is empty */
59c7dd3d 1276 inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
cf530aa4 1277 /* clear interrupt on amcc s5933 */
59c7dd3d 1278 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
0a85b6f0 1279 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
59c7dd3d
IM
1280
1281 status = inw(devpriv->control_status + INT_ADCFIFO);
1282#ifdef CB_PCIDAS_DEBUG
2d238b29 1283 if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0)
59c7dd3d 1284 comedi_error(dev, "spurious interrupt");
59c7dd3d
IM
1285#endif
1286
cf530aa4 1287 /* check for analog output interrupt */
2d238b29 1288 if (status & (DAHFI | DAEMI))
59c7dd3d 1289 handle_ao_interrupt(dev, status);
cf530aa4
BP
1290 /* check for analog input interrupts */
1291 /* if fifo half-full */
59c7dd3d 1292 if (status & ADHFI) {
cf530aa4 1293 /* read data */
59c7dd3d
IM
1294 num_samples = half_fifo;
1295 if (async->cmd.stop_src == TRIG_COUNT &&
0a85b6f0 1296 num_samples > devpriv->count) {
59c7dd3d
IM
1297 num_samples = devpriv->count;
1298 }
1299 insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
0a85b6f0 1300 num_samples);
59c7dd3d 1301 cfc_write_array_to_buffer(s, devpriv->ai_buffer,
0a85b6f0 1302 num_samples * sizeof(short));
59c7dd3d
IM
1303 devpriv->count -= num_samples;
1304 if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
1305 async->events |= COMEDI_CB_EOA;
1306 cb_pcidas_cancel(dev, s);
1307 }
cf530aa4 1308 /* clear half-full interrupt latch */
5f74ea14 1309 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1310 outw(devpriv->adc_fifo_bits | INT,
0a85b6f0 1311 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1312 spin_unlock_irqrestore(&dev->spinlock, flags);
cf530aa4 1313 /* else if fifo not empty */
59c7dd3d
IM
1314 } else if (status & (ADNEI | EOBI)) {
1315 for (i = 0; i < timeout; i++) {
cf530aa4 1316 /* break if fifo is empty */
59c7dd3d 1317 if ((ADNE & inw(devpriv->control_status +
0a85b6f0 1318 INT_ADCFIFO)) == 0)
59c7dd3d
IM
1319 break;
1320 cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
1321 if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) { /* end of acquisition */
1322 cb_pcidas_cancel(dev, s);
1323 async->events |= COMEDI_CB_EOA;
1324 break;
1325 }
1326 }
cf530aa4 1327 /* clear not-empty interrupt latch */
5f74ea14 1328 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1329 outw(devpriv->adc_fifo_bits | INT,
0a85b6f0 1330 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1331 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1332 } else if (status & EOAI) {
1333 comedi_error(dev,
25985edc 1334 "bug! encountered end of acquisition interrupt?");
cf530aa4 1335 /* clear EOA interrupt latch */
5f74ea14 1336 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1337 outw(devpriv->adc_fifo_bits | EOAI,
0a85b6f0 1338 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1339 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 1340 }
cf530aa4 1341 /* check for fifo overflow */
59c7dd3d
IM
1342 if (status & LADFUL) {
1343 comedi_error(dev, "fifo overflow");
cf530aa4 1344 /* clear overflow interrupt latch */
5f74ea14 1345 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1346 outw(devpriv->adc_fifo_bits | LADFUL,
0a85b6f0 1347 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1348 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1349 cb_pcidas_cancel(dev, s);
1350 async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
1351 }
1352
1353 comedi_event(dev, s);
1354
1355 return IRQ_HANDLED;
1356}
1357
da91b269 1358static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
59c7dd3d 1359{
34c43922 1360 struct comedi_subdevice *s = dev->write_subdev;
d163679c 1361 struct comedi_async *async = s->async;
ea6d0d4c 1362 struct comedi_cmd *cmd = &async->cmd;
59c7dd3d
IM
1363 unsigned int half_fifo = thisboard->fifo_size / 2;
1364 unsigned int num_points;
3a5e32dd 1365 unsigned long flags;
59c7dd3d
IM
1366
1367 async->events = 0;
1368
1369 if (status & DAEMI) {
cf530aa4 1370 /* clear dac empty interrupt latch */
5f74ea14 1371 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1372 outw(devpriv->adc_fifo_bits | DAEMI,
0a85b6f0 1373 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1374 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1375 if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
1376 if (cmd->stop_src == TRIG_NONE ||
0a85b6f0
MT
1377 (cmd->stop_src == TRIG_COUNT
1378 && devpriv->ao_count)) {
59c7dd3d
IM
1379 comedi_error(dev, "dac fifo underflow");
1380 cb_pcidas_ao_cancel(dev, s);
1381 async->events |= COMEDI_CB_ERROR;
1382 }
1383 async->events |= COMEDI_CB_EOA;
1384 }
1385 } else if (status & DAHFI) {
1386 unsigned int num_bytes;
1387
cf530aa4 1388 /* figure out how many points we are writing to fifo */
59c7dd3d
IM
1389 num_points = half_fifo;
1390 if (cmd->stop_src == TRIG_COUNT &&
0a85b6f0 1391 devpriv->ao_count < num_points)
59c7dd3d
IM
1392 num_points = devpriv->ao_count;
1393 num_bytes =
0a85b6f0
MT
1394 cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1395 num_points * sizeof(short));
790c5541 1396 num_points = num_bytes / sizeof(short);
59c7dd3d 1397
2d238b29 1398 if (async->cmd.stop_src == TRIG_COUNT)
59c7dd3d 1399 devpriv->ao_count -= num_points;
cf530aa4 1400 /* write data to board's fifo */
59c7dd3d 1401 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
0a85b6f0 1402 num_points);
cf530aa4 1403 /* clear half-full interrupt latch */
5f74ea14 1404 spin_lock_irqsave(&dev->spinlock, flags);
59c7dd3d 1405 outw(devpriv->adc_fifo_bits | DAHFI,
0a85b6f0 1406 devpriv->control_status + INT_ADCFIFO);
5f74ea14 1407 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1408 }
1409
1410 comedi_event(dev, s);
1411}
1412
d163679c 1413/* cancel analog input command */
0a85b6f0
MT
1414static int cb_pcidas_cancel(struct comedi_device *dev,
1415 struct comedi_subdevice *s)
59c7dd3d
IM
1416{
1417 unsigned long flags;
1418
5f74ea14 1419 spin_lock_irqsave(&dev->spinlock, flags);
cf530aa4 1420 /* disable interrupts */
59c7dd3d
IM
1421 devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
1422 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
5f74ea14 1423 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d 1424
cf530aa4 1425 /* disable start trigger source and burst mode */
59c7dd3d 1426 outw(0, devpriv->control_status + TRIG_CONTSTAT);
cf530aa4 1427 /* software pacer source */
59c7dd3d
IM
1428 outw(0, devpriv->control_status + ADCMUX_CONT);
1429
1430 return 0;
1431}
1432
d163679c
BP
1433/* cancel analog output command */
1434static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1435 struct comedi_subdevice *s)
59c7dd3d
IM
1436{
1437 unsigned long flags;
1438
5f74ea14 1439 spin_lock_irqsave(&dev->spinlock, flags);
cf530aa4 1440 /* disable interrupts */
59c7dd3d
IM
1441 devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
1442 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1443
cf530aa4 1444 /* disable output */
59c7dd3d
IM
1445 devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
1446 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
5f74ea14 1447 spin_unlock_irqrestore(&dev->spinlock, flags);
59c7dd3d
IM
1448
1449 return 0;
1450}
1451
da91b269 1452static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
0a85b6f0 1453 int rounding_flags)
59c7dd3d
IM
1454{
1455 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
0a85b6f0
MT
1456 &(devpriv->divisor2), ns,
1457 rounding_flags & TRIG_ROUND_MASK);
59c7dd3d
IM
1458
1459 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
1460 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
0a85b6f0 1461 devpriv->divisor1, 2);
59c7dd3d 1462 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
0a85b6f0 1463 devpriv->divisor2, 2);
59c7dd3d
IM
1464}
1465
da91b269 1466static void write_calibration_bitstream(struct comedi_device *dev,
0a85b6f0
MT
1467 unsigned int register_bits,
1468 unsigned int bitstream,
1469 unsigned int bitstream_length)
59c7dd3d
IM
1470{
1471 static const int write_delay = 1;
1472 unsigned int bit;
1473
1474 for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
1475 if (bitstream & bit)
1476 register_bits |= SERIAL_DATA_IN_BIT;
1477 else
1478 register_bits &= ~SERIAL_DATA_IN_BIT;
5f74ea14 1479 udelay(write_delay);
59c7dd3d
IM
1480 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
1481 }
1482}
1483
da91b269 1484static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
0a85b6f0 1485 uint8_t value)
59c7dd3d
IM
1486{
1487 static const int num_caldac_channels = 8;
1488 static const int bitstream_length = 11;
1489 unsigned int bitstream = ((address & 0x7) << 8) | value;
5f74ea14 1490 static const int caldac_8800_udelay = 1;
59c7dd3d
IM
1491
1492 if (address >= num_caldac_channels) {
1493 comedi_error(dev, "illegal caldac channel");
1494 return -1;
1495 }
1496
1497 if (value == devpriv->caldac_value[address])
1498 return 1;
1499
1500 devpriv->caldac_value[address] = value;
1501
1502 write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
0a85b6f0 1503 bitstream_length);
59c7dd3d 1504
5f74ea14 1505 udelay(caldac_8800_udelay);
59c7dd3d 1506 outw(cal_enable_bits(dev) | SELECT_8800_BIT,
0a85b6f0 1507 devpriv->control_status + CALIBRATION_REG);
5f74ea14 1508 udelay(caldac_8800_udelay);
59c7dd3d
IM
1509 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
1510
1511 return 1;
1512}
1513
da91b269 1514static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
59c7dd3d
IM
1515{
1516 static const int bitstream_length = 7;
1517 unsigned int bitstream = value & 0x7f;
1518 unsigned int register_bits;
5f74ea14 1519 static const int ad7376_udelay = 1;
59c7dd3d
IM
1520
1521 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
5f74ea14 1522 udelay(ad7376_udelay);
59c7dd3d
IM
1523 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
1524
1525 write_calibration_bitstream(dev, register_bits, bitstream,
0a85b6f0 1526 bitstream_length);
59c7dd3d 1527
5f74ea14 1528 udelay(ad7376_udelay);
59c7dd3d
IM
1529 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
1530
1531 return 0;
1532}
1533
1534/* For 1602/16 only
1535 * ch 0 : adc gain
1536 * ch 1 : adc postgain offset */
da91b269 1537static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
0a85b6f0 1538 uint8_t value)
59c7dd3d
IM
1539{
1540 static const int bitstream_length = 10;
1541 unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
1542 unsigned int register_bits;
5f74ea14 1543 static const int ad8402_udelay = 1;
59c7dd3d
IM
1544
1545 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
5f74ea14 1546 udelay(ad8402_udelay);
59c7dd3d
IM
1547 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
1548
1549 write_calibration_bitstream(dev, register_bits, bitstream,
0a85b6f0 1550 bitstream_length);
59c7dd3d 1551
5f74ea14 1552 udelay(ad8402_udelay);
59c7dd3d
IM
1553 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
1554
1555 return 0;
1556}
1557
1558static int wait_for_nvram_ready(unsigned long s5933_base_addr)
1559{
1560 static const int timeout = 1000;
1561 unsigned int i;
1562
1563 for (i = 0; i < timeout; i++) {
1564 if ((inb(s5933_base_addr +
0a85b6f0
MT
1565 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
1566 == 0)
59c7dd3d 1567 return 0;
5f74ea14 1568 udelay(1);
59c7dd3d
IM
1569 }
1570 return -1;
1571}
1572
0a85b6f0 1573static int nvram_read(struct comedi_device *dev, unsigned int address,
2d238b29 1574 uint8_t *data)
59c7dd3d
IM
1575{
1576 unsigned long iobase = devpriv->s5933_config;
1577
1578 if (wait_for_nvram_ready(iobase) < 0)
1579 return -ETIMEDOUT;
1580
1581 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
0a85b6f0 1582 iobase + AMCC_OP_REG_MCSR_NVCMD);
59c7dd3d
IM
1583 outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
1584 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
0a85b6f0 1585 iobase + AMCC_OP_REG_MCSR_NVCMD);
59c7dd3d
IM
1586 outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
1587 outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
1588
1589 if (wait_for_nvram_ready(iobase) < 0)
1590 return -ETIMEDOUT;
1591
1592 *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
1593
1594 return 0;
1595}
1596
e74f209c
HS
1597static int cb_pcidas_attach(struct comedi_device *dev,
1598 struct comedi_devconfig *it)
1599{
1600 struct comedi_subdevice *s;
1601 struct pci_dev *pcidev = NULL;
1602 int index;
1603 int i;
1604 int ret;
1605
1606/*
1607 * Allocate the private structure area.
1608 */
1609 if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
1610 return -ENOMEM;
1611
1612/*
1613 * Probe the device to determine what device in the series it is.
1614 */
1615
1616 for_each_pci_dev(pcidev) {
1617 /* is it not a computer boards card? */
1618 if (pcidev->vendor != PCI_VENDOR_ID_CB)
1619 continue;
1620 /* loop through cards supported by this driver */
1621 for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) {
1622 if (cb_pcidas_boards[index].device_id != pcidev->device)
1623 continue;
1624 /* was a particular bus/slot requested? */
1625 if (it->options[0] || it->options[1]) {
1626 /* are we on the wrong bus/slot? */
1627 if (pcidev->bus->number != it->options[0] ||
1628 PCI_SLOT(pcidev->devfn) != it->options[1]) {
1629 continue;
1630 }
1631 }
1632 devpriv->pci_dev = pcidev;
1633 dev->board_ptr = cb_pcidas_boards + index;
1634 goto found;
1635 }
1636 }
1637
1638 dev_err(dev->class_dev,
1639 "No supported ComputerBoards/MeasurementComputing card found on requested position\n");
1640 return -EIO;
1641
1642found:
1643
1644 dev_dbg(dev->class_dev, "Found %s on bus %i, slot %i\n",
1645 cb_pcidas_boards[index].name, pcidev->bus->number,
1646 PCI_SLOT(pcidev->devfn));
1647
1648 /*
1649 * Enable PCI device and reserve I/O ports.
1650 */
1651 if (comedi_pci_enable(pcidev, "cb_pcidas")) {
1652 dev_err(dev->class_dev,
1653 "Failed to enable PCI device and request regions\n");
1654 return -EIO;
1655 }
1656 /*
1657 * Initialize devpriv->control_status and devpriv->adc_fifo to point to
1658 * their base address.
1659 */
1660 devpriv->s5933_config =
1661 pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
1662 devpriv->control_status =
1663 pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
1664 devpriv->adc_fifo =
1665 pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
1666 devpriv->pacer_counter_dio =
1667 pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
1668 if (thisboard->ao_nchan) {
1669 devpriv->ao_registers =
1670 pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
1671 }
1672 /* disable and clear interrupts on amcc s5933 */
1673 outl(INTCSR_INBOX_INTR_STATUS,
1674 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1675
1676 /* get irq */
1677 if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
1678 IRQF_SHARED, "cb_pcidas", dev)) {
1679 dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
1680 devpriv->pci_dev->irq);
1681 return -EINVAL;
1682 }
1683 dev->irq = devpriv->pci_dev->irq;
1684
1685 /* Initialize dev->board_name */
1686 dev->board_name = thisboard->name;
1687
1688 ret = comedi_alloc_subdevices(dev, 7);
1689 if (ret)
1690 return ret;
1691
1692 s = dev->subdevices + 0;
1693 /* analog input subdevice */
1694 dev->read_subdev = s;
1695 s->type = COMEDI_SUBD_AI;
1696 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
1697 /* WARNING: Number of inputs in differential mode is ignored */
1698 s->n_chan = thisboard->ai_se_chans;
1699 s->len_chanlist = thisboard->ai_se_chans;
1700 s->maxdata = (1 << thisboard->ai_bits) - 1;
1701 s->range_table = thisboard->ranges;
1702 s->insn_read = cb_pcidas_ai_rinsn;
1703 s->insn_config = ai_config_insn;
1704 s->do_cmd = cb_pcidas_ai_cmd;
1705 s->do_cmdtest = cb_pcidas_ai_cmdtest;
1706 s->cancel = cb_pcidas_cancel;
1707
1708 /* analog output subdevice */
1709 s = dev->subdevices + 1;
1710 if (thisboard->ao_nchan) {
1711 s->type = COMEDI_SUBD_AO;
1712 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
1713 s->n_chan = thisboard->ao_nchan;
1714 /* analog out resolution is the same as analog input resolution, so use ai_bits */
1715 s->maxdata = (1 << thisboard->ai_bits) - 1;
1716 s->range_table = &cb_pcidas_ao_ranges;
1717 s->insn_read = cb_pcidas_ao_readback_insn;
1718 if (thisboard->has_ao_fifo) {
1719 dev->write_subdev = s;
1720 s->subdev_flags |= SDF_CMD_WRITE;
1721 s->insn_write = cb_pcidas_ao_fifo_winsn;
1722 s->do_cmdtest = cb_pcidas_ao_cmdtest;
1723 s->do_cmd = cb_pcidas_ao_cmd;
1724 s->cancel = cb_pcidas_ao_cancel;
1725 } else {
1726 s->insn_write = cb_pcidas_ao_nofifo_winsn;
1727 }
1728 } else {
1729 s->type = COMEDI_SUBD_UNUSED;
1730 }
1731
1732 /* 8255 */
1733 s = dev->subdevices + 2;
1734 subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
1735
1736 /* serial EEPROM, */
1737 s = dev->subdevices + 3;
1738 s->type = COMEDI_SUBD_MEMORY;
1739 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
1740 s->n_chan = 256;
1741 s->maxdata = 0xff;
1742 s->insn_read = eeprom_read_insn;
1743
1744 /* 8800 caldac */
1745 s = dev->subdevices + 4;
1746 s->type = COMEDI_SUBD_CALIB;
1747 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1748 s->n_chan = NUM_CHANNELS_8800;
1749 s->maxdata = 0xff;
1750 s->insn_read = caldac_read_insn;
1751 s->insn_write = caldac_write_insn;
1752 for (i = 0; i < s->n_chan; i++)
1753 caldac_8800_write(dev, i, s->maxdata / 2);
1754
1755 /* trim potentiometer */
1756 s = dev->subdevices + 5;
1757 s->type = COMEDI_SUBD_CALIB;
1758 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1759 if (thisboard->trimpot == AD7376) {
1760 s->n_chan = NUM_CHANNELS_7376;
1761 s->maxdata = 0x7f;
1762 } else {
1763 s->n_chan = NUM_CHANNELS_8402;
1764 s->maxdata = 0xff;
1765 }
1766 s->insn_read = trimpot_read_insn;
1767 s->insn_write = trimpot_write_insn;
1768 for (i = 0; i < s->n_chan; i++)
1769 cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
1770
1771 /* dac08 caldac */
1772 s = dev->subdevices + 6;
1773 if (thisboard->has_dac08) {
1774 s->type = COMEDI_SUBD_CALIB;
1775 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1776 s->n_chan = NUM_CHANNELS_DAC08;
1777 s->insn_read = dac08_read_insn;
1778 s->insn_write = dac08_write_insn;
1779 s->maxdata = 0xff;
1780 dac08_write(dev, s->maxdata / 2);
1781 } else
1782 s->type = COMEDI_SUBD_UNUSED;
1783
1784 /* make sure mailbox 4 is empty */
1785 inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1786 /* Set bits to enable incoming mailbox interrupts on amcc s5933. */
1787 devpriv->s5933_intcsr_bits =
1788 INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1789 INTCSR_INBOX_FULL_INT;
1790 /* clear and enable interrupt on amcc s5933 */
1791 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1792 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1793
1794 return 1;
1795}
1796
1797static void cb_pcidas_detach(struct comedi_device *dev)
1798{
1799 if (devpriv) {
1800 if (devpriv->s5933_config) {
1801 outl(INTCSR_INBOX_INTR_STATUS,
1802 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1803 }
1804 }
1805 if (dev->irq)
1806 free_irq(dev->irq, dev);
1807 if (dev->subdevices)
1808 subdev_8255_cleanup(dev, dev->subdevices + 2);
1809 if (devpriv && devpriv->pci_dev) {
1810 if (devpriv->s5933_config)
1811 comedi_pci_disable(devpriv->pci_dev);
1812 pci_dev_put(devpriv->pci_dev);
1813 }
1814}
1815
715b2284
HS
1816static struct comedi_driver cb_pcidas_driver = {
1817 .driver_name = "cb_pcidas",
1818 .module = THIS_MODULE,
1819 .attach = cb_pcidas_attach,
1820 .detach = cb_pcidas_detach,
1821};
1822
1823static int __devinit cb_pcidas_pci_probe(struct pci_dev *dev,
1824 const struct pci_device_id *ent)
727b286b 1825{
715b2284 1826 return comedi_pci_auto_config(dev, &cb_pcidas_driver);
727b286b
AT
1827}
1828
715b2284 1829static void __devexit cb_pcidas_pci_remove(struct pci_dev *dev)
727b286b
AT
1830{
1831 comedi_pci_auto_unconfig(dev);
1832}
1833
715b2284
HS
1834static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
1835 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
1836 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
1837 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
1838 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
1839 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
1840 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
1841 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
1842 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
1843 { 0 }
727b286b 1844};
715b2284 1845MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
727b286b 1846
715b2284
HS
1847static struct pci_driver cb_pcidas_pci_driver = {
1848 .name = "cb_pcidas",
1849 .id_table = cb_pcidas_pci_table,
1850 .probe = cb_pcidas_pci_probe,
1851 .remove = __devexit_p(cb_pcidas_pci_remove)
1852};
1853module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
90f703d3
AT
1854
1855MODULE_AUTHOR("Comedi http://www.comedi.org");
1856MODULE_DESCRIPTION("Comedi low-level driver");
1857MODULE_LICENSE("GPL");
This page took 0.394859 seconds and 5 git commands to generate.