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