2 comedi/drivers/amplc_pci230.c
3 Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
5 Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
7 COMEDI - Linux Control and Measurement Device Interface
8 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 Driver: amplc_pci230.o
26 Description: Amplicom PCI230, PCI260 Multifunction I/O boards
27 Author: Allan Willcox <allanwillcox@ozemail.com.au>, Steve D Sharples <steve.sharples@nottingham.ac.uk>
28 Updated: Wed, 27 Jun 2007 15:21:41 +0100
29 Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
30 PCI260 (pci260 or amplc_pci230)
33 Configuration options:
34 [0] - PCI bus of device (optional).
35 [1] - PCI slot of device (optional).
36 If bus/slot is not specified, the first available PCI device
40 extra triggered scan functionality, interrupt bug-fix added by Steve Sharples
42 #include <linux/comedidev.h>
44 #include <linux/delay.h>
45 #include <linux/pci.h>
51 /* PCI230 PCI configuration register information */
52 #define PCI_VENDOR_ID_AMPLICON 0x14dc
53 #define PCI_DEVICE_ID_PCI230 0x0000
54 #define PCI_DEVICE_ID_PCI260 0x0006
55 #define PCI_DEVICE_ID_INVALID 0xffff
57 #define PCI230_IO1_SIZE 32 /* Size of I/O space 1 */
58 #define PCI230_IO2_SIZE 16 /* Size of I/O space 2 */
60 /* PCI230 i/o space 1 registers. */
61 #define PCI230_PPI_X_A 0x00 /* User PPI port A */
62 #define PCI230_PPI_X_B 0x01 /* User PPI port B */
63 #define PCI230_PPI_X_C 0x02 /* User PPI port C */
64 #define PCI230_PPI_X_CMD 0x03 /* User PPI control word */
65 #define PCI230_Z2_CT0 0x14 /* 82C54 counter/timer 0 */
66 #define PCI230_Z2_CT1 0x15 /* 82C54 counter/timer 1 */
67 #define PCI230_Z2_CT2 0x16 /* 82C54 counter/timer 2 */
68 #define PCI230_Z2_CTC 0x17 /* 82C54 counter/timer control word */
69 #define PCI230_ZCLK_SCE 0x1A /* Group Z Clock Configuration Register */
70 #define PCI230_ZGAT_SCE 0x1D /* Group Z Gate Configuration Register */
71 #define PCI230_INT_SCE 0x1E /* ISR Interrupt source mask register/Interrupt status */
73 /* PCI230 i/o space 2 registers. */
74 #define PCI230_DACCON 0x00
75 #define PCI230_DACOUT1 0x02
76 #define PCI230_DACOUT2 0x04
77 #define PCI230_DACOUT3 0x06
78 #define PCI230_ADCDATA 0x08
79 #define PCI230_ADCCON 0x0A
80 #define PCI230_ADCEN 0x0C
81 #define PCI230_ADCG 0x0E
83 /* Convertor related constants. */
84 #define PCI230_DAC_SETTLE 5 /* Analogue output settling time in µs (DAC itself is 1µs nominally). */
85 #define PCI230_ADC_SETTLE 1 /* Analogue input settling time in µs (ADC itself is 1.6µs nominally but we poll anyway). */
86 #define PCI230_MUX_SETTLE 10 /* ADC MUX settling time in µS - 10µs for se, 20µs de. */
89 #define PCI230_DAC_BUSY_BIT 1
90 #define PCI230_DAC_BIP_BIT 0
92 /* ADCCON write values. */
93 #define PCI230_ADC_TRIG_NONE 0
94 #define PCI230_ADC_TRIG_SW 1
95 #define PCI230_ADC_TRIG_EXTP 2
96 #define PCI230_ADC_TRIG_EXTN 3
97 #define PCI230_ADC_TRIG_Z2CT0 4
98 #define PCI230_ADC_TRIG_Z2CT1 5
99 #define PCI230_ADC_TRIG_Z2CT2 6
100 #define PCI230_ADC_IR_UNI (0<<3) /* Input range unipolar */
101 #define PCI230_ADC_IR_BIP (1<<3) /* Input range bipolar */
102 #define PCI230_ADC_IM_SE (0<<4) /* Input mode single ended */
103 #define PCI230_ADC_IM_DIF (1<<4) /* Input mode differential */
104 #define PCI230_ADC_FIFO_EN (1<<8)
105 #define PCI230_ADC_INT_FIFO_EMPTY 0
106 #define PCI230_ADC_INT_FIFO_NEMPTY (1<<9)
107 #define PCI230_ADC_INT_FIFO_NHALF (2<<9)
108 #define PCI230_ADC_INT_FIFO_HALF (3<<9)
109 #define PCI230_ADC_INT_FIFO_NFULL (4<<9)
110 #define PCI230_ADC_INT_FIFO_FULL (5<<9)
111 #define PCI230_ADC_FIFO_RESET (1<<12)
112 #define PCI230_ADC_GLOB_RESET (1<<13)
113 #define PCI230_ADC_CONV 0xffff /* Value to write to ADCDATA to trigger ADC conversion in sotware trigger mode */
115 /* ADCCON read values. */
116 #define PCI230_ADC_BUSY_BIT 15
117 #define PCI230_ADC_FIFO_EMPTY (1<<12)
118 #define PCI230_ADC_FIFO_FULL (1<<13)
119 #define PCI230_ADC_FIFO_HALF (1<<14)
121 /* Group Z clock configuration register values. */
122 #define PCI230_ZCLK_CT0 0
123 #define PCI230_ZCLK_CT1 8
124 #define PCI230_ZCLK_CT2 16
125 #define PCI230_ZCLK_RES 24
126 #define PCI230_ZCLK_SRC_PPCN 0 /* The counter/timer's CLK input from the SK1 connector. */
127 #define PCI230_ZCLK_SRC_10MHZ 1 /* The internal 10MHz clock. */
128 #define PCI230_ZCLK_SRC_1MHZ 2 /* The internal 1MHz clock. */
129 #define PCI230_ZCLK_SRC_100KHZ 3 /* The internal 100kHz clock. */
130 #define PCI230_ZCLK_SRC_10KHZ 4 /* The internal 10kHz clock. */
131 #define PCI230_ZCLK_SRC_1KHZ 5 /* The internal 1kHz clock. */
132 #define PCI230_ZCLK_SRC_OUTNM1 6 /* The output of the preceding counter/timer channel (OUT n-1). */
133 #define PCI230_ZCLK_SRC_EXTCLK 7 /* The dedicated external clock input for the group (X1/X2, Y1/Y2, Z1/Z2). */
135 /* Group Z gate configuration register values. */
136 #define PCI230_ZGAT_CT0 0
137 #define PCI230_ZGAT_CT1 8
138 #define PCI230_ZGAT_CT2 16
139 #define PCI230_ZGAT_RES 24
140 #define PCI230_ZGAT_SRC_VCC 0 /* The counter/timer's GAT input is VCC (ie enabled) */
141 #define PCI230_ZGAT_SRC_GND 1 /* GAT input is GND (ie disabled) */
142 #define PCI230_ZGAT_SRC_PPCN 2 /* GAT input is DIO port Cn, where n is the number of the counter/timer */
143 #define PCI230_ZGAT_SRC_OUTNP1 3 /* GAT input is the output of the next counter/timer channel (OUT n+1) */
146 #define PCI230_TIMEBASE_10MHZ 100 /* 10MHz => 100ns. */
147 #define PCI230_TIMEBASE_1MHZ 1000 /* 1MHz => 1000ns. */
148 #define PCI230_TIMEBASE_100KHZ 10000 /* 100kHz => 10000ns. */
149 #define PCI230_TIMEBASE_10KHZ 100000 /* 10kHz => 100000ns. */
150 #define PCI230_TIMEBASE_1KHZ 1000000 /* 1kHz => 1000000ns. */
153 /* Interrupt enables/status register values. */
154 #define PCI230_INT_DISABLE 0
155 #define PCI230_INT_PPI_C0 1
156 #define PCI230_INT_PPI_C3 2
157 #define PCI230_INT_ADC 4
158 #define PCI230_INT_ZCLK_CT1 32
160 #define PCI230_TEST_BIT(val, n) ((val>>n)&1) /* Assumes bits numbered with zero offset, ie. 0-15 */
163 * Board descriptions for the two boards supported.
166 typedef struct pci230_board_struct{
176 static const pci230_board pci230_boards[] = {
179 id: PCI_DEVICE_ID_PCI230,
189 id: PCI_DEVICE_ID_PCI260,
198 name: "amplc_pci230", /* Legacy name matches any above */
199 id: PCI_DEVICE_ID_INVALID,
203 static struct pci_device_id pci230_pci_table[] __devinitdata = {
204 { PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
205 { PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
208 MODULE_DEVICE_TABLE(pci, pci230_pci_table);
210 * Useful for shorthand access to the particular board structure
212 #define n_pci230_boards (sizeof(pci230_boards)/sizeof(pci230_boards[0]))
213 #define thisboard ((const pci230_board *)dev->board_ptr)
215 /* this structure is for data unique to this hardware driver. If
216 several hardware drivers keep similar information in this structure,
217 feel free to suggest moving the variable to the comedi_device struct. */
218 struct pci230_private{
219 struct pci_dev *pci_dev;
220 lsampl_t ao_readback[2]; /* Used for AO readback */
221 unsigned long pci_iobase; /* PCI230's I/O space 1 */
222 /* Divisors for 8254 counter/timer. */
223 unsigned int clk_src0; /* which clock to use for the counter/timers: 10MHz, 1MHz, 100kHz etc */
224 unsigned int clk_src1;
225 unsigned int clk_src2;
226 unsigned int divisor0;
227 unsigned int divisor1;
228 unsigned int divisor2;
229 unsigned int int_en; /* Interrupt enables bits. */
230 unsigned int ai_count; /* Number of analogue input samples remaining. */
231 unsigned int ao_count; /* Number of analogue output samples remaining. */
232 unsigned int ai_stop; /* Flag set when cmd->stop_src == TRIG_NONE - user chooses to stop continuous conversion by cancelation. */
233 unsigned int ao_stop; /* Flag set when cmd->stop_src == TRIG_NONE - user chooses to stop continuous conversion by cancelation. */
234 unsigned int ai_bipolar; /* Set if bipolar input range so we know to mangle it. */
235 unsigned int ao_bipolar; /* Set if bipolar output range so we know to mangle it. */
236 unsigned int ier; /* Copy of interrupt enables/status register. */
239 #define devpriv ((struct pci230_private *)dev->private)
241 /* PCI230 analogue input range table */
242 static const comedi_lrange pci230_ai_range = { 7, {
252 /* PCI230 analogue output range table */
253 static const comedi_lrange pci230_ao_range = { 2, {
259 * The comedi_driver structure tells the Comedi core module
260 * which functions to call to configure/deconfigure (attach/detach)
261 * the board, and also about the kernel module that contains
264 static int pci230_attach(comedi_device *dev,comedi_devconfig *it);
265 static int pci230_detach(comedi_device *dev);
266 static comedi_driver driver_amplc_pci230={
267 driver_name: "amplc_pci230",
269 attach: pci230_attach,
270 detach: pci230_detach,
271 board_name: &pci230_boards[0].name,
272 offset: sizeof(pci230_boards[0]),
273 num_names: sizeof(pci230_boards) / sizeof(pci230_boards[0]),
275 COMEDI_INITCLEANUP(driver_amplc_pci230);
277 static int pci230_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
278 static int pci230_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
279 static int pci230_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
280 static int pci230_ct_insn_config(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
281 static int pci230_ct_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
283 static void pci230_ns_to_timer(unsigned int *ns,int round);
285 static void pci230_ns_to_single_timer(unsigned int *ns,int round);
286 static void i8253_single_ns_to_timer(unsigned int i8253_osc_base, unsigned int *d, unsigned int *nanosec, int round_mode);
287 static void pci230_setup_monostable_ct0(comedi_device *dev, unsigned int ns, unsigned int n_chan);
289 static void pci230_z2_ct0(comedi_device *dev, unsigned int *ns,int round);
291 static void pci230_z2_ct1(comedi_device *dev, unsigned int *ns,int round);
292 static void pci230_z2_ct2(comedi_device *dev, unsigned int *ns,int round);
294 static void pci230_cancel_ct0(comedi_device *dev);
296 static void pci230_cancel_ct1(comedi_device *dev);
297 static void pci230_cancel_ct2(comedi_device *dev);
298 static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG);
299 static int pci230_ao_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
300 static int pci230_ao_cmd(comedi_device *dev, comedi_subdevice *s);
301 static int pci230_ao_cancel(comedi_device *dev, comedi_subdevice *s);
302 static void pci230_handle_ao(comedi_device *dev, comedi_subdevice *s);
303 static int pci230_ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);
304 static int pci230_ai_cmd(comedi_device *dev, comedi_subdevice *s);
305 static int pci230_ai_cancel(comedi_device *dev, comedi_subdevice *s);
306 static void pci230_handle_ai(comedi_device *dev, comedi_subdevice *s);
307 static void pci230_handle_fifo_half_full(comedi_device *dev, comedi_subdevice *s);
308 static void pci230_handle_fifo_not_empty(comedi_device *dev, comedi_subdevice *s);
310 static sampl_t pci230_ai_read(comedi_device *dev)
313 sampl_t data = (sampl_t) inw(dev->iobase + PCI230_ADCDATA);
315 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower four bits reserved for expansion). */
318 /* If a bipolar range was specified, mangle it (twos complement->straight binary). */
319 if (devpriv->ai_bipolar) {
320 data ^= 1<<(thisboard->ai_bits-1);
325 static void pci230_ao_write(comedi_device *dev, sampl_t data, int chan)
327 /* If a bipolar range was specified, mangle it (straight binary->twos complement). */
328 if (devpriv->ao_bipolar) {
329 data ^= 1<<(thisboard->ao_bits-1);
332 /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower four bits reserved for expansion). */
336 outw((unsigned int) data, dev->iobase + (((chan) == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
340 * Attach is called by the Comedi core to configure the driver
341 * for a particular board. If you specified a board_name array
342 * in the driver structure, dev->board_ptr contains that
345 static int pci230_attach(comedi_device *dev,comedi_devconfig *it)
348 unsigned long pci_iobase, iobase; /* PCI230's I/O spaces 1 and 2 respectively. */
349 struct pci_dev *pci_dev;
352 printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
353 thisboard->name, it->options[0], it->options[1]);
355 /* Allocate the private structure area using alloc_private().
356 * Macro defined in comedidev.h - memsets struct fields to 0. */
357 if((alloc_private(dev,sizeof(struct pci230_private)))<0){
361 for(pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pci_dev != NULL ;
362 pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
363 if(it->options[0] || it->options[1]){
364 /* Match against bus/slot options. */
365 if(it->options[0] != pci_dev->bus->number ||
366 it->options[1] != PCI_SLOT(pci_dev->devfn))
369 if(pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
371 if(thisboard->id == PCI_DEVICE_ID_INVALID){
372 /* The name was specified as "amplc_pci230" which is
373 * used to match any supported device. Replace the
374 * current dev->board_ptr with one that matches the
376 for(i=0;i<n_pci230_boards;i++){
377 if(pci_dev->device == pci230_boards[i].id){
378 /* Change board_ptr to matched board */
379 dev->board_ptr = &pci230_boards[i];
383 if(i<n_pci230_boards)break;
385 /* The name was specified as a specific device name.
386 * The current dev->board_ptr is correct. Check
387 * whether it matches the PCI device ID. */
388 if(thisboard->id == pci_dev->device) break;
392 printk("comedi%d: No %s card found\n",dev->minor, thisboard->name);
395 devpriv->pci_dev = pci_dev;
398 * Initialize dev->board_name.
400 dev->board_name = thisboard->name;
402 /* Read base addressses of the PCI230's two I/O regions from PCI configuration register. */
403 if(pci_enable_device(pci_dev)<0){
407 pci_iobase = pci_resource_start(pci_dev, 2);
408 iobase = pci_resource_start(pci_dev, 3);
410 /* Reserve I/O spaces. */
411 if(pci_request_regions(pci_dev,"amplc_pci230")<0){
412 printk("comedi%d: I/O space conflict\n",dev->minor);
416 printk("comedi%d: %s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
417 dev->minor, dev->board_name, pci_iobase, iobase);
419 devpriv->pci_iobase = pci_iobase;
420 dev->iobase = iobase;
422 /* Disable board's interrupts. */
423 outb(0, devpriv->pci_iobase + PCI230_INT_SCE);
425 /* Register the interrupt handler. */
426 irq_hdl = comedi_request_irq(devpriv->pci_dev->irq, pci230_interrupt, IRQF_SHARED, "amplc_pci230", dev);
428 printk("comedi%d: unable to register irq, commands will not be available %d\n", dev->minor, devpriv->pci_dev->irq);
431 dev->irq = devpriv->pci_dev->irq;
432 printk("comedi%d: registered irq %u\n", dev->minor, devpriv->pci_dev->irq);
436 * Allocate the subdevice structures. alloc_subdevice() is a
437 * convenient macro defined in comedidev.h.
439 if(alloc_subdevices(dev, 4)<0)
443 /* analog input subdevice */
444 s->type=COMEDI_SUBD_AI;
445 s->subdev_flags=SDF_READABLE|SDF_DIFF|SDF_GROUND;
446 s->n_chan=thisboard->ai_chans;
447 s->maxdata=(1<<thisboard->ai_bits)-1;
448 s->range_table=&pci230_ai_range;
449 s->insn_read = &pci230_ai_rinsn;
450 s->len_chanlist = thisboard->ai_chans;
451 /* Only register commands if the interrupt handler is installed. */
454 s->subdev_flags |= SDF_CMD_READ;
455 s->do_cmd = &pci230_ai_cmd;
456 s->do_cmdtest = &pci230_ai_cmdtest;
457 s->cancel = pci230_ai_cancel;
461 /* analog output subdevice */
462 s->type=COMEDI_SUBD_AO;
463 s->subdev_flags=SDF_WRITABLE;
464 s->n_chan=thisboard->ao_chans;;
465 s->maxdata=(1<<thisboard->ao_bits)-1;
466 s->range_table=&pci230_ao_range;
467 s->insn_write = &pci230_ao_winsn;
468 s->insn_read = &pci230_ao_rinsn;
469 s->len_chanlist = thisboard->ao_chans;
470 /* Only register commands if the interrupt handler is installed. */
473 s->subdev_flags |= SDF_CMD_WRITE;
474 s->do_cmd = &pci230_ao_cmd;
475 s->do_cmdtest = &pci230_ao_cmdtest;
476 s->cancel = pci230_ao_cancel;
480 /* digital i/o subdevice */
481 if(thisboard->have_dio){
482 subdev_8255_init(dev,s,NULL,(devpriv->pci_iobase + PCI230_PPI_X_A));
484 s->type = COMEDI_SUBD_UNUSED;
488 /* timer subdevice */
489 s->type=COMEDI_SUBD_TIMER;
490 s->subdev_flags=SDF_READABLE;
493 s->range_table=&range_digital;
494 s->insn_config = pci230_ct_insn_config;
495 s->insn_read = &pci230_ct_rinsn;
497 printk("comedi%d: attached\n",dev->minor);
504 * _detach is called to deconfigure a device. It should deallocate
506 * This function is also called when _attach() fails, so it should be
507 * careful not to release resources that were not necessarily
508 * allocated by _attach(). dev->private and dev->subdevices are
509 * deallocated automatically by the core.
511 static int pci230_detach(comedi_device *dev)
513 printk("comedi%d: amplc_pci230: remove\n",dev->minor);
515 if(dev->subdevices && thisboard->have_dio)
516 subdev_8255_cleanup(dev,dev->subdevices + 2); /* Clean up dio subdevice. */
519 comedi_free_irq(dev->irq, dev);
522 if(devpriv->pci_dev){
525 pci_release_regions(devpriv->pci_dev);
526 pci_disable_device(devpriv->pci_dev);
528 pci_dev_put(devpriv->pci_dev);
536 * COMEDI_SUBD_AI instruction;
538 static int pci230_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
541 int chan, range, aref;
543 unsigned int adccon, adcen, adcg;
545 /* Unpack channel and range. */
546 chan = CR_CHAN(insn->chanspec);
547 range = CR_RANGE(insn->chanspec);
548 aref = CR_AREF(insn->chanspec);
550 /* If bit 2 of range unset, range is referring to bipolar element in range table */
551 adccon = PCI230_ADC_TRIG_SW | PCI230_ADC_FIFO_RESET;
552 devpriv->ai_bipolar = !PCI230_TEST_BIT(range, 2);
553 if (aref==AREF_DIFF) {
556 adccon |= PCI230_ADC_IM_DIF;
557 if (devpriv->ai_bipolar) {
558 adccon |= PCI230_ADC_IR_BIP;
559 adcg = range<<(2*chan-2*chan%2);
562 adccon |= PCI230_ADC_IR_UNI;
563 adcg = ((range&(~4))+1)<<(2*chan-2*chan%2);
569 adccon |= PCI230_ADC_IM_SE;
570 if (devpriv->ai_bipolar) {
571 adccon |= PCI230_ADC_IR_BIP;
572 adcg = range<<(chan-chan%2);
575 adccon |= PCI230_ADC_IR_UNI;
576 adcg = ((range&(~4))+1)<<(chan-chan%2);
580 /* Enable only this channel in the scan list - otherwise by default we'll get one sample from each channel. */
581 outw_p(adcen, dev->iobase + PCI230_ADCEN);
583 /* Set gain for channel. */
584 outw_p(adcg, dev->iobase + PCI230_ADCG);
586 /* Specify uni/bip, se/diff, s/w conversion, and reset FIFO (even though we're not using it - MEV says so). */
587 outw_p(adccon, dev->iobase + PCI230_ADCCON);
589 /* Convert n samples */
590 for(n=0;n<insn->n;n++){
591 /* trigger conversion */
592 outw_p(PCI230_ADC_CONV,dev->iobase + PCI230_ADCDATA);
595 /* wait for conversion to end */
596 for(i=0;i<TIMEOUT;i++){
597 status = inw(dev->iobase + PCI230_ADCCON);
598 if(!PCI230_TEST_BIT(status, PCI230_ADC_BUSY_BIT)) break;
601 /* rt_printk() should be used instead of printk()
602 * whenever the code can be called from real-time. */
603 rt_printk("timeout\n");
608 data[n] = pci230_ai_read(dev);
611 /* return the number of samples read/written */
616 * COMEDI_SUBD_AO instructions;
618 static int pci230_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
623 /* Unpack channel and range. */
624 chan = CR_CHAN(insn->chanspec);
625 range = CR_RANGE(insn->chanspec);
627 /* Set range - see analogue output range table; 0 => unipolar 10V, 1 => bipolar +/-10V range scale */
628 devpriv->ao_bipolar = PCI230_TEST_BIT(range, PCI230_DAC_BIP_BIT);
629 outw(range, dev->iobase + PCI230_DACCON);
631 /* Writing a list of values to an AO channel is probably not
632 * very useful, but that's how the interface is defined. */
633 for(i=0;i<insn->n;i++){
634 /* Store the value to be written to the DAC in our pci230_private struct before mangling it. */
635 devpriv->ao_readback[chan] = data[i];
637 /* Write value to DAC. */
638 pci230_ao_write(dev, data[i], chan);
641 /* return the number of samples read/written */
645 /* AO subdevices should have a read insn as well as a write insn.
646 * Usually this means copying a value stored in devpriv. */
647 static int pci230_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
650 int chan = CR_CHAN(insn->chanspec);
652 for(i=0;i<insn->n;i++)
653 data[i] = devpriv->ao_readback[chan];
659 * COMEDI_SUBD_TIMER instructions;
661 * insn_config allows user to start and stop counter/timer 2 (SK1 pin 21).
662 * Period specified in ns.
664 * rinsn returns counter/timer's actual period in ns.
666 static int pci230_ct_insn_config(comedi_device *dev,comedi_subdevice *s,
667 comedi_insn *insn,lsampl_t *data)
671 if(insn->n!=1)return -EINVAL;
675 //Stop counter/timer 2.
676 pci230_cancel_ct2(dev);
679 //Start conter/timer 2 with period ns.
680 pci230_z2_ct2(dev, &ns, TRIG_ROUND_MASK);
686 static int pci230_ct_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
688 if(insn->n!=1)return -EINVAL;
690 /* Return the actual period set in ns. */
691 data[0] = PCI230_TIMEBASE_10MHZ*devpriv->divisor1*devpriv->divisor2;
695 static int pci230_ao_cmdtest(comedi_device *dev,comedi_subdevice *s,
701 /* cmdtest tests a particular command to see if it is valid.
702 * Using the cmdtest ioctl, a user can create a valid cmd
703 * and then have it executes by the cmd ioctl.
705 * cmdtest returns 1,2,3,4 or 0, depending on which tests
706 * the command passes. */
708 /* Step 1: make sure trigger sources are trivially valid.
709 * "invalid source" returned by comedilib to user mode process
713 cmd->start_src &= TRIG_INT;
714 if(!cmd->start_src || tmp!=cmd->start_src)err++;
716 tmp=cmd->scan_begin_src;
717 cmd->scan_begin_src &= TRIG_TIMER;
718 if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;
720 tmp=cmd->convert_src;
721 cmd->convert_src &= TRIG_NOW;
722 if(!cmd->convert_src || tmp!=cmd->convert_src)err++;
724 tmp=cmd->scan_end_src;
725 cmd->scan_end_src &= TRIG_COUNT;
726 if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;
729 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
730 if(!cmd->stop_src || tmp!=cmd->stop_src)err++;
734 /* Step 2: make sure trigger sources are unique and mutually compatible
735 * "source conflict" returned by comedilib to user mode process
738 if(cmd->stop_src!=TRIG_COUNT &&
739 cmd->stop_src!=TRIG_NONE)err++;
743 /* Step 3: make sure arguments are trivially compatible.
744 * "invalid argument" returned by comedilib to user mode process
747 if(cmd->start_arg!=0){
752 #define MAX_SPEED 3200 /* 3200ns => 312.5kHz */
753 #define MIN_SPEED 4294967295u /* 4294967295ns = 4.29s - Comedi limit due to unsigned int cmd. Driver limit = 2^16 (16bit counter) * 1000000ns (1kHz onboard clock) = 65.536s */
755 if(cmd->scan_begin_src==TRIG_TIMER){
756 if(cmd->scan_begin_arg<MAX_SPEED){
757 cmd->scan_begin_arg=MAX_SPEED;
760 if(cmd->scan_begin_arg>MIN_SPEED){
761 cmd->scan_begin_arg=MIN_SPEED;
766 if(cmd->scan_end_arg!=cmd->chanlist_len){
767 cmd->scan_end_arg=cmd->chanlist_len;
770 if(cmd->stop_src==TRIG_NONE){
772 if(cmd->stop_arg!=0){
780 /* Step 4: fix up any arguments.
781 * "argument conflict" returned by comedilib to user mode process
784 if(cmd->scan_begin_src==TRIG_TIMER){
785 tmp=cmd->scan_begin_arg;
786 pci230_ns_to_single_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);
787 if(tmp!=cmd->scan_begin_arg)err++;
795 static int pci230_ao_inttrig(comedi_device *dev,comedi_subdevice *s,
796 unsigned int trig_num)
801 /* Enable DAC interrupt. */
802 devpriv->ier |= PCI230_INT_ZCLK_CT1;
803 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
805 s->async->inttrig=NULL;
810 static int pci230_ao_cmd(comedi_device *dev,comedi_subdevice *s)
814 /* Get the command. */
815 comedi_cmd *cmd=&s->async->cmd;
817 /* Calculate number of conversions required. */
818 if(cmd->stop_src == TRIG_COUNT) {
819 devpriv->ao_count = cmd->stop_arg * cmd->chanlist_len;
820 devpriv->ao_stop = 0;
823 /* TRIG_NONE, user calls cancel. */
824 devpriv->ao_count = 0;
825 devpriv->ao_stop = 1;
828 /* Disable DAC interrupt. */
829 devpriv->ier &= ~PCI230_INT_ZCLK_CT1;
830 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
832 /* Set range - see analogue output range table; 0 => unipolar 10V, 1 => bipolar +/-10V range scale */
833 range = CR_RANGE(cmd->chanlist[0]);
834 devpriv->ao_bipolar = PCI230_TEST_BIT(range, PCI230_DAC_BIP_BIT);
835 outw(range, dev->iobase + PCI230_DACCON);
837 /* Set the counter timers to the specified sampling frequency.
838 * TODO - when Comedi supports concurrent commands, this must be
839 * changed; using ct0 and ct1 for DAC will screw up ADC pacer
840 * which uses ct2 and ct0. Change to only use ct1 for DAC?
842 * <sds>: we may as well do this now, in the transition to using single
843 * counters for the analogue input (to accommodate triggered scans).
845 pci230_z2_ct1(dev, &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); /* cmd->convert_arg is sampling period in ns */
847 s->async->inttrig=pci230_ao_inttrig;
852 static int pci230_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,
858 /* cmdtest tests a particular command to see if it is valid.
859 * Using the cmdtest ioctl, a user can create a valid cmd
860 * and then have it executes by the cmd ioctl.
862 * cmdtest returns 1,2,3,4 or 0, depending on which tests
863 * the command passes. */
865 /* Step 1: make sure trigger sources are trivially valid.
866 * "invalid source" returned by comedilib to user mode process
870 cmd->start_src &= TRIG_NOW;
871 if(!cmd->start_src || tmp!=cmd->start_src)err++;
873 tmp=cmd->scan_begin_src;
874 /* Unfortunately, we cannot trigger a scan off an external source
875 * on the PCI260 board, since it uses the PPI0 (DIO) input, which
876 * isn't present on the PCI260 */
877 if(thisboard->have_dio){
878 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_EXT;
881 cmd->scan_begin_src &= TRIG_FOLLOW;
883 if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;
885 tmp=cmd->convert_src;
886 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
887 if(!cmd->convert_src || tmp!=cmd->convert_src)err++;
889 tmp=cmd->scan_end_src;
890 cmd->scan_end_src &= TRIG_COUNT;
891 if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;
894 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
895 if(!cmd->stop_src || tmp!=cmd->stop_src)err++;
899 /* Step 2: make sure trigger sources are unique and mutually compatible
900 * "source conflict" returned by comedilib to user mode process
903 if(cmd->start_src!=TRIG_NOW)err++;
904 if(cmd->scan_begin_src!=TRIG_FOLLOW &&
905 cmd->scan_begin_src!=TRIG_EXT)err++;
906 if(cmd->convert_src!=TRIG_TIMER &&
907 cmd->convert_src!=TRIG_EXT)err++;
908 if(cmd->stop_src!=TRIG_COUNT &&
909 cmd->stop_src!=TRIG_NONE)err++;
911 /* Although the scan and convert triggers come from different sources, the
912 * driver relies on the knowledge of convert rate to trigger the correct number
913 * of channels. If the is not known (ie if convert_src==TRIG_EXT) then the
914 * scan trigger will not work correctly.
915 * The convert trigger is the input into the "EXT TRIG" line (pin 25), whilst
916 * the scan trigger is "PPC0" (pin 49). */
917 if(cmd->scan_begin_src==TRIG_EXT &&
918 cmd->convert_src==TRIG_EXT)err++;
922 /* Step 3: make sure arguments are trivially compatible.
923 * "invalid argument" returned by comedilib to user mode process
926 if(cmd->start_arg!=0){
931 #define MAX_SPEED 3200 /* 3200ns => 312.5kHz */
932 #define MIN_SPEED 4294967295u /* 4294967295ns = 4.29s - Comedi limit due to unsigned int cmd. Driver limit = 2^16 (16bit counter) * 1000000ns (1kHz onboard clock) = 65.536s */
934 if(cmd->convert_src==TRIG_TIMER){
935 if(cmd->convert_arg<MAX_SPEED){
936 cmd->convert_arg=MAX_SPEED;
939 if(cmd->convert_arg>MIN_SPEED){
940 cmd->convert_arg=MIN_SPEED;
944 /* external trigger */
945 /* convert_arg == 0 => trigger on -ve edge. */
946 /* convert_arg == 1 => trigger on +ve edge. */
947 if(cmd->convert_arg>1){
948 cmd->convert_arg=1; /* Default to trigger on +ve edge. */
953 if(cmd->scan_end_arg!=cmd->chanlist_len){
954 cmd->scan_end_arg=cmd->chanlist_len;
957 if(cmd->stop_src==TRIG_NONE){
959 if(cmd->stop_arg!=0){
966 if(cmd->scan_begin_src==TRIG_EXT){
967 /* external "trigger" to begin each scan *
968 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate of CT2 *
969 * (sample convert trigger is CT2) */
970 if(cmd->scan_begin_arg!=0){
971 cmd->scan_begin_arg=0; /* default option, so you can monitor CT2 (only CT with an external output) */
978 /* Step 4: fix up any arguments.
979 * "argument conflict" returned by comedilib to user mode process
982 if(cmd->convert_src==TRIG_TIMER){
983 tmp=cmd->convert_arg;
984 pci230_ns_to_single_timer(&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);
985 if(tmp!=cmd->convert_arg)err++;
993 static int pci230_ai_cmd(comedi_device *dev,comedi_subdevice *s)
995 int i, chan, range, diff;
996 unsigned int adccon, adcen, adcg;
999 /* Get the command. */
1000 comedi_async *async = s->async;
1001 comedi_cmd *cmd = &async->cmd;
1003 /* Calculate number of conversions required. */
1004 if(cmd->stop_src == TRIG_COUNT) {
1005 devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len;
1006 devpriv->ai_stop = 0;
1009 /* TRIG_NONE, user calls cancel. */
1010 devpriv->ai_count = 0;
1011 devpriv->ai_stop = 1;
1015 * - Disable ADC interrupts.
1016 * - Set channel scan list.
1017 * - Set channel gains.
1018 * - Enable and reset FIFO, specify uni/bip, se/diff, and start conversion source to none.
1019 * - PAUSE (25us) - failure to do this leads to "dodgy data" for the first few channels at high convert rates.
1020 * - Enable conversion complete interrupt.
1021 * - Set the counter timers to the specified sampling frequency.
1022 * - Enable AND RESET FIFO (yes you do need to do this twice), set FIFO interrupt trigger level, set start conversion source to counter 2.
1025 /* Disable ADC interrupt. */
1026 devpriv->ier &= ~PCI230_INT_ADC;
1027 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1029 if (CR_AREF(cmd->chanlist[0])==AREF_DIFF) {
1030 /* Differential - all channels must be differential. */
1032 adccon = PCI230_ADC_IM_DIF;
1035 /* Single ended - all channels must be single-ended. */
1037 adccon = PCI230_ADC_IM_SE;
1040 adccon |= PCI230_ADC_FIFO_RESET | PCI230_ADC_FIFO_EN;
1041 //adccon |= PCI230_ADC_FIFO_RESET;
1045 /* If bit 2 of range unset, range is referring to bipolar element in range table */
1046 range = CR_RANGE(cmd->chanlist[0]);
1047 devpriv->ai_bipolar = !PCI230_TEST_BIT(range, 2);
1048 if (devpriv->ai_bipolar) {
1049 adccon |= PCI230_ADC_IR_BIP;
1050 for (i = 0; i < cmd->chanlist_len; i++) {
1051 chan = CR_CHAN(cmd->chanlist[i]);
1052 range = CR_RANGE(cmd->chanlist[i]);
1054 adcg |= range<<(2*chan-2*chan%2);
1058 adcg |= range<<(chan-chan%2);
1064 adccon |= PCI230_ADC_IR_UNI;
1065 for (i = 0; i < cmd->chanlist_len; i++) {
1066 chan = CR_CHAN(cmd->chanlist[i]);
1067 range = CR_RANGE(cmd->chanlist[i]);
1069 adcg |= ((range&(~4))+1)<<(2*chan-2*chan%2);
1073 adcg |= ((range&(~4))+1)<<(chan-chan%2);
1079 /* Set channel scan list. */
1080 outw(adcen, dev->iobase + PCI230_ADCEN);
1082 /* Set channel gains. */
1083 outw(adcg, dev->iobase + PCI230_ADCG);
1085 /* Enable and reset FIFO, specify FIFO trigger level full, specify uni/bip, se/diff, and start conversion source to none. */
1086 outw(adccon | PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_NONE, dev->iobase + PCI230_ADCCON);
1089 /* Failure to include this will result in the first few channels'-worth of data being corrupt,
1090 * normally manifesting itself by large negative voltages. It seems the board needs time to
1091 * settle between the first FIFO reset (above) and the second FIFO reset (below). Setting
1092 * the channel gains and scan list _before_ the first FIFO reset also helps, though only
1096 /* Enable ADC (conversion complete) interrupt. */
1097 devpriv->ier |= PCI230_INT_ADC;
1098 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1100 /* Set up the scan_begin_src (if it's NOT set to TRIG_FOLLOW) */
1101 if(cmd->scan_begin_src == TRIG_EXT){
1102 /* use PPC0 -> gate of CT0 (as monostable) -> gate of CT2
1104 * Note that the PCI230 card does not support "native" triggered scans,
1105 * although the _hardware_ can be set up to achieve this. This is _not_
1106 * software emulation within the driver, it is merely using the on-board
1107 * counters and one of the digital inputs to achieve the same thing.
1108 * The idea is to use a rising edge of a digital input (in this case PPC0)
1109 * to trigger a counter (set up as a monostable). This produces a pulse of
1110 * exactly the same length as the number of conversion pulses in your scan.
1111 * This pulse is then used as to gate the counter responsible for your
1114 * So, if your conversion rate is set to 100kHz (10us/conversion) and you
1115 * have 8 channels in your channel list, a positive edge on PPC0 will
1116 * trigger a pulse of length 80us (8 x 10us). Because the two counters
1117 * involved have the same clock source, the monostable pulse will always
1118 * be exactly the right length.
1120 * Previous versions of this driver used two cascaded counters to achieve
1121 * different conversion rates (the output of the first counter is the
1122 * clock input of the second counter). The use of the triggered scan
1123 * functionality necessitated using only one counter/timer for dividing
1124 * the internal clock down to the convert rate. In order to allow
1125 * relatively low convert rates (upto the comedi limit of 4.29s), the
1126 * driver now uses not only the 10MHz input clock, but also (depending on
1127 * the desired convert rate) a choice of 1MHz, 100kHz or 10kHz clocks.
1128 * - sds, 30 April 2004 */
1130 /* initialise the gates to sensible settings while we set everything up */
1131 zgat = PCI230_ZGAT_CT0 | PCI230_ZGAT_SRC_GND;
1132 outb(zgat, devpriv->pci_iobase + PCI230_ZGAT_SCE);
1134 zgat = PCI230_ZGAT_CT2 | PCI230_ZGAT_SRC_GND;
1135 outb(zgat, devpriv->pci_iobase + PCI230_ZGAT_SCE);
1137 pci230_setup_monostable_ct0(dev, cmd->convert_arg, cmd->chanlist_len);
1139 /* now set the gates up so that we can begin triggering */
1140 zgat = PCI230_ZGAT_CT0 | PCI230_ZGAT_SRC_PPCN;
1141 outb(zgat, devpriv->pci_iobase + PCI230_ZGAT_SCE);
1143 zgat = PCI230_ZGAT_CT2 | PCI230_ZGAT_SRC_OUTNP1;
1144 outb(zgat, devpriv->pci_iobase + PCI230_ZGAT_SCE);
1146 else{ /* must be using "TRIG_FOLLOW", so need to "ungate" CT2 */
1147 zgat = PCI230_ZGAT_CT2 | PCI230_ZGAT_SRC_VCC;
1148 outb(zgat, devpriv->pci_iobase + PCI230_ZGAT_SCE);
1151 /* Set start conversion source. */
1152 if(cmd->convert_src == TRIG_TIMER) {
1153 /* Onboard counter/timer 2. */
1154 adccon = adccon | PCI230_ADC_TRIG_Z2CT2;
1156 /* Set the counter timers to the specified sampling frequency. */
1157 pci230_z2_ct2(dev, &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); /* cmd->convert_arg is sampling period in ns */
1160 /* TRIG_EXT - external trigger. */
1161 if (cmd->convert_arg) {
1162 /* Trigger on +ve edge. */
1163 adccon = adccon | PCI230_ADC_TRIG_EXTP;
1166 /* Trigger on -ve edge. */
1167 adccon = adccon | PCI230_ADC_TRIG_EXTN;
1172 /* Set FIFO interrupt trigger level. */
1173 if(cmd->stop_src == TRIG_COUNT) {
1174 if (devpriv->ai_count < 2048) {
1175 adccon = adccon | PCI230_ADC_INT_FIFO_NEMPTY;
1178 adccon = adccon | PCI230_ADC_INT_FIFO_HALF;
1182 /* TRIG_NONE - trigger on half-full FIFO. */
1183 adccon = adccon | PCI230_ADC_INT_FIFO_HALF;
1186 //adccon = adccon | PCI230_ADC_FIFO_EN;
1187 outw(adccon, dev->iobase + PCI230_ADCCON);
1194 /* This function doesn't require a particular form, this is just
1195 * what happens to be used in some of the drivers. It should
1196 * convert ns nanoseconds to a counter value suitable for programming
1197 * the device. Also, it should adjust ns so that it cooresponds to
1198 * the actual time that the device will use. */
1199 static void pci230_ns_to_timer(unsigned int *ns,int round)
1201 unsigned int divisor0, divisor1;
1202 i8253_cascade_ns_to_timer_2div(PCI230_TIMEBASE_10MHZ, &divisor0, &divisor1, ns, TRIG_ROUND_MASK);
1208 /* This function is used for analogue input. Only one counter/timer can be used,
1209 * because for the triggered scan functionality to work, 2 counters with
1210 * identical clock inputs and divide ratios are required, so that the
1211 * correct number of channels are converted in each scan.
1212 * This is a very "noddy" way of doing this... apologies. (sds) */
1213 static unsigned int pci230_choose_clk_src(unsigned int ns)
1215 unsigned int clk_src=0;
1217 if(ns < 6553600) clk_src=PCI230_TIMEBASE_10MHZ;
1218 if(ns >= 6553600 && ns < 65536000) clk_src=PCI230_TIMEBASE_1MHZ;
1219 if(ns >= 65536000 && ns < 655360000) clk_src=PCI230_TIMEBASE_100KHZ;
1220 if(ns >=655360000 && ns <4294967295u) clk_src=PCI230_TIMEBASE_10KHZ; /* maximum limited by comedi = 4.29s */
1223 printk("comedi: dodgy clock source chosen, using 10MHz\n");
1224 clk_src=PCI230_TIMEBASE_10MHZ;
1229 static void pci230_ns_to_single_timer(unsigned int *ns,int round)
1231 unsigned int divisor;
1232 unsigned int clk_src;
1234 clk_src=pci230_choose_clk_src(*ns);
1235 i8253_single_ns_to_timer(clk_src, &divisor, ns, TRIG_ROUND_MASK);
1239 static void i8253_single_ns_to_timer(unsigned int i8253_osc_base, unsigned int *d, unsigned int *nanosec, int round_mode)
1243 /* exit early if everything is already correct (this can save time
1244 * since this function may be called repeatedly during command tests
1246 if(*d * i8253_osc_base == *nanosec &&
1247 *d > 1 && *d < 0x10000)
1252 round_mode &= TRIG_ROUND_MASK;
1253 switch (round_mode) {
1254 case TRIG_ROUND_NEAREST:
1256 div=(*nanosec + i8253_osc_base / 2) / i8253_osc_base;
1259 div=(*nanosec) / i8253_osc_base;
1261 case TRIG_ROUND_DOWN:
1262 div=(*nanosec + i8253_osc_base + 1 ) / i8253_osc_base;
1266 *nanosec = div * i8253_osc_base;
1267 *d = div & 0xffff; // masking is done since counter maps zero to 0x10000
1272 static void pci230_setup_monostable_ct0(comedi_device *dev, unsigned int ns, unsigned int n_chan)
1274 /* ns is the convert period, n_chan is the no of channels per scan.
1275 * We must make the output of the counter equal in time to the amount of time
1276 * it takes to acquire n_chan*ns */
1278 unsigned int pulse_duration;
1280 pulse_duration = ns*n_chan;
1281 devpriv->clk_src0=pci230_choose_clk_src(pulse_duration); /* let's hope that if devpriv->clk_src0 != devpriv->clk_src2, then one is divided down from the other! */
1283 devpriv->divisor0=pulse_duration/devpriv->clk_src0;
1285 i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 0, devpriv->divisor0, 1); /* Counter 1, mode 1 */
1287 /* PCI 230 specific - ties up counter clk input with correct clk source */
1288 switch (devpriv->clk_src0) {
1289 case PCI230_TIMEBASE_10MHZ:
1291 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1293 case PCI230_TIMEBASE_1MHZ:
1294 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_1MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1296 case PCI230_TIMEBASE_100KHZ:
1297 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_100KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1299 case PCI230_TIMEBASE_10KHZ:
1300 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_10KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1302 case PCI230_TIMEBASE_1KHZ:
1303 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_1KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1313 * Set ZCLK_CT0 to square wave mode with period of ns.
1315 static void pci230_z2_ct0(comedi_device *dev, unsigned int *ns,int round)
1317 devpriv->clk_src0=pci230_choose_clk_src(*ns); /* choose a suitable clock source from the range available, given the desired period in ns */
1318 i8253_single_ns_to_timer(devpriv->clk_src0, &devpriv->divisor0, ns, TRIG_ROUND_MASK);
1320 /* Generic i8254_load calls; program counters' divide ratios. */
1321 i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 0, devpriv->divisor0, 3); /* Counter 0, divisor0, square wave (8254 mode 3). */
1323 /* PCI 230 specific - ties up counter clk input with clk source */
1324 switch (devpriv->clk_src0) {
1325 case PCI230_TIMEBASE_10MHZ:
1327 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1329 case PCI230_TIMEBASE_1MHZ:
1330 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_1MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1332 case PCI230_TIMEBASE_100KHZ:
1333 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_100KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1335 case PCI230_TIMEBASE_10KHZ:
1336 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_10KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1338 case PCI230_TIMEBASE_1KHZ:
1339 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_1KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 0's input clock source. */
1347 static void pci230_cancel_ct0(comedi_device *dev)
1349 devpriv->divisor0 = 0;
1350 i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 0, devpriv->divisor0, 0); /* Counter 0, divisor0, 8254 mode 0. */
1355 * Set ZCLK_CT1 to square wave mode with period of ns.
1356 * Default clk source for DAC.
1358 static void pci230_z2_ct1(comedi_device *dev, unsigned int *ns,int round)
1360 devpriv->clk_src1=pci230_choose_clk_src(*ns); /* choose a suitable clock source from the range available, given the desired period in ns */
1361 i8253_single_ns_to_timer(devpriv->clk_src1, &devpriv->divisor1, ns, TRIG_ROUND_MASK);
1363 /* Generic i8254_load calls; program counters' divide ratios. */
1364 i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 1, devpriv->divisor1, 3); /* Counter 1, divisor1, square wave (8254 mode 3). */
1366 /* PCI 230 specific - ties up counter clk input with clk source */
1367 switch (devpriv->clk_src1) {
1368 case PCI230_TIMEBASE_10MHZ:
1370 outb(PCI230_ZCLK_CT1 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 1's input clock source. */
1372 case PCI230_TIMEBASE_1MHZ:
1373 outb(PCI230_ZCLK_CT1 | PCI230_ZCLK_SRC_1MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 1's input clock source. */
1375 case PCI230_TIMEBASE_100KHZ:
1376 outb(PCI230_ZCLK_CT1 | PCI230_ZCLK_SRC_100KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 1's input clock source. */
1378 case PCI230_TIMEBASE_10KHZ:
1379 outb(PCI230_ZCLK_CT1 | PCI230_ZCLK_SRC_10KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 1's input clock source. */
1381 case PCI230_TIMEBASE_1KHZ:
1382 outb(PCI230_ZCLK_CT1 | PCI230_ZCLK_SRC_1KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 1's input clock source. */
1388 static void pci230_cancel_ct1(comedi_device *dev)
1390 devpriv->divisor1 = 0;
1391 i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 1, devpriv->divisor1, 0); /* Counter 1, divisor1, 8254 mode 0. */
1395 * Set ZCLK_CT2 to square wave mode with period of ns.
1396 * Default clk source for ADC.
1398 static void pci230_z2_ct2(comedi_device *dev, unsigned int *ns,int round)
1400 devpriv->clk_src2=pci230_choose_clk_src(*ns); /* choose a suitable clock source from the range available, given the desired period in ns */
1401 i8253_single_ns_to_timer(devpriv->clk_src2, &devpriv->divisor2, ns, TRIG_ROUND_MASK);
1403 /* Generic i8254_load calls; program counters' divide ratios. */
1404 i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 2, devpriv->divisor2, 3); /* Counter 2, divisor2, square wave (8254 mode 3). */
1406 /* PCI 230 specific - ties up counter clk input with clk source */
1407 switch (devpriv->clk_src2) {
1408 case PCI230_TIMEBASE_10MHZ:
1410 outb(PCI230_ZCLK_CT2 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 2's input clock source. */
1412 case PCI230_TIMEBASE_1MHZ:
1413 outb(PCI230_ZCLK_CT2 | PCI230_ZCLK_SRC_1MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 2's input clock source. */
1415 case PCI230_TIMEBASE_100KHZ:
1416 outb(PCI230_ZCLK_CT2 | PCI230_ZCLK_SRC_100KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 2's input clock source. */
1418 case PCI230_TIMEBASE_10KHZ:
1419 outb(PCI230_ZCLK_CT2 | PCI230_ZCLK_SRC_10KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 2's input clock source. */
1421 case PCI230_TIMEBASE_1KHZ:
1422 outb(PCI230_ZCLK_CT2 | PCI230_ZCLK_SRC_1KHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE); /* Program counter 2's input clock source. */
1428 static void pci230_cancel_ct2(comedi_device *dev)
1430 devpriv->divisor2 = 0;
1431 i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 2, devpriv->divisor2, 0); /* Counter 2, divisor2, 8254 mode 0. */
1434 /* Interrupt handler */
1435 static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
1438 comedi_device *dev = (comedi_device*) d;
1439 comedi_subdevice *s;
1441 /* Read interrupt status/enable register. */
1442 status_int = inb(devpriv->pci_iobase + PCI230_INT_SCE);
1444 if (status_int == PCI230_INT_DISABLE) {
1448 /* Disable all of board's interrupts.
1449 * (Only those interrrupts that need re-enabling, are, later in the handler). */
1450 devpriv->ier = PCI230_INT_DISABLE;
1451 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1454 * Check the source of interrupt and handle it.
1455 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3 interrupts.
1456 * However, at present (Comedi-0.7.60) does not allow concurrent
1457 * execution of commands, instructions or a mixture of the two.
1460 if (status_int & PCI230_INT_ZCLK_CT1) {
1461 s = dev->write_subdev;
1462 s->async->events = 0;
1463 pci230_handle_ao(dev, s);
1464 comedi_event(dev, s, s->async->events);
1465 s->async->events = 0;
1468 if (status_int & PCI230_INT_ADC) {
1469 s = dev->read_subdev;
1470 s->async->events = 0;
1471 pci230_handle_ai(dev, s);
1472 comedi_event(dev, s, s->async->events);
1473 s->async->events = 0;
1479 static void pci230_handle_ao(comedi_device *dev, comedi_subdevice *s) {
1482 comedi_async *async = s->async;
1483 comedi_cmd *cmd = &async->cmd;
1485 for (i = 0; i < cmd->chanlist_len; i++) {
1486 /* Read sample from Comedi's circular buffer. */
1487 ret = comedi_buf_get(s->async, &data);
1489 comedi_error(dev, "buffer underrun");
1490 return; // XXX does comedi_buf_get set s->async->events with appropriate flags in this instance?
1492 /* Write value to DAC. */
1493 pci230_ao_write(dev, data, cmd->chanlist[i]);
1495 if(async->cmd.stop_src == TRIG_COUNT) {
1496 if(devpriv->ao_count > 0) devpriv->ao_count--;
1497 if(devpriv->ao_count == 0) break;
1501 if(devpriv->ao_count == 0 && devpriv->ao_stop == 0) {
1503 async->events |= COMEDI_CB_EOA;
1504 pci230_ao_cancel(dev, s);
1507 /* More samples required, tell Comedi to block. */
1508 async->events |= COMEDI_CB_BLOCK;
1509 /* Enable DAC (conversion complete) interrupt (and leave any other enabled interrupts as they are). */
1510 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1511 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1516 static void pci230_handle_ai(comedi_device *dev, comedi_subdevice *s) {
1520 /* Read FIFO state. */
1521 status_fifo = inw(dev->iobase + PCI230_ADCCON);
1523 if (status_fifo & PCI230_ADC_FIFO_FULL) {
1524 /* Report error otherwise FIFO overruns will go unnoticed by the caller. */
1525 comedi_error(dev, "FIFO overrun");
1528 else if (status_fifo & PCI230_ADC_FIFO_HALF) {
1529 /* FIFO is at least half full. */
1530 pci230_handle_fifo_half_full(dev, s);
1532 else if (status_fifo & PCI230_ADC_FIFO_EMPTY) {
1533 /* FIFO empty but we got an interrupt. */
1534 printk("comedi%d: amplc_pci230::pci230_handle_ai FIFO empty - spurious interrupt\n",dev->minor);
1537 /* FIFO is less than half full, but not empty. */
1538 pci230_handle_fifo_not_empty(dev, s);
1542 /* Cancel sampled conversion. */
1543 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1544 pci230_ai_cancel(dev, s);
1545 }else if(devpriv->ai_count == 0 && devpriv->ai_stop == 0) {
1546 /* Acquisition complete. */
1547 s->async->events |= COMEDI_CB_EOA;
1548 pci230_ai_cancel(dev, s); /* disable hardware conversions */
1550 /* More samples required, tell Comedi to block. */
1551 s->async->events |= COMEDI_CB_BLOCK;
1553 /* Enable ADC (conversion complete) interrupt (and leave any other enabled interrupts as they are). */
1554 devpriv->ier |= PCI230_INT_ADC;
1555 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1560 static void pci230_handle_fifo_half_full(comedi_device *dev, comedi_subdevice *s) {
1563 for (i = 0; i < 2048; i++) {
1564 /* Read sample and store in Comedi's circular buffer. */
1565 comedi_buf_put(s->async, pci230_ai_read(dev));
1567 if(s->async->cmd.stop_src == TRIG_COUNT)
1569 if(--devpriv->ai_count == 0) {
1570 /* Acquisition complete. */
1575 /* More samples required. */
1579 static void pci230_handle_fifo_not_empty(comedi_device *dev, comedi_subdevice *s) {
1580 while (devpriv->ai_count != 0) {
1581 if (inw(dev->iobase + PCI230_ADCCON) & PCI230_ADC_FIFO_EMPTY) {
1582 /* The FIFO is empty, block. */
1585 /* There are sample(s) to read from FIFO, read one and store in Comedi's circular buffer. */
1586 comedi_buf_put(s->async, pci230_ai_read(dev));
1588 if(devpriv->ai_count > 0) devpriv->ai_count--;
1590 /* Acquisition complete. */
1595 static int pci230_ao_cancel(comedi_device *dev, comedi_subdevice *s) {
1596 devpriv->ao_count = 0;
1597 devpriv->ao_stop = 0;
1599 /* Stop counter/timers. */
1600 pci230_cancel_ct1(dev);
1602 /* Disable DAC interrupt. */
1603 devpriv->ier &= ~PCI230_INT_ZCLK_CT1;
1604 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1609 static int pci230_ai_cancel(comedi_device *dev, comedi_subdevice *s) {
1610 devpriv->ai_count = 0;
1611 devpriv->ai_stop = 0;
1613 /* Stop counter/timers. */
1614 pci230_cancel_ct2(dev);
1616 /* Disable ADC interrupt. */
1617 devpriv->ier &= ~PCI230_INT_ADC;
1618 outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1620 /* Reset FIFO and set start conversion source to none. */
1621 outw(PCI230_ADC_FIFO_RESET | PCI230_ADC_TRIG_NONE, dev->iobase + PCI230_ADCCON);
1623 /* Clear channel scan list. */
1624 outw(0x0000, dev->iobase + PCI230_ADCEN);
1626 /* Clear channel gains. */
1627 outw(0x0000, dev->iobase + PCI230_ADCG);