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