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