Constified ranges, board structures, and miscellaneous data.
[comedi.git] / comedi / drivers / amplc_pci230.c
1  /*
2     comedi/drivers/amplc_pci230.c
3     Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
4
5     Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
6
7     COMEDI - Linux Control and Measurement Device Interface
8     Copyright (C) 2000 David A. Schleef <ds@schleef.org>
9
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.
14
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.
19
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.
23 */
24 /*
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)
31 Status: works
32
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
37           will be used.
38 */
39 /*
40 extra triggered scan functionality, interrupt bug-fix added by Steve Sharples
41 */
42 #include <linux/comedidev.h>
43
44 #include <linux/delay.h>
45 #include <linux/pci.h>
46
47 #include "8253.h"
48 #include "8255.h"
49
50
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
56
57 #define PCI230_IO1_SIZE 32              /* Size of I/O space 1 */
58 #define PCI230_IO2_SIZE 16              /* Size of I/O space 2 */
59
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 */
72
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
82
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. */
87
88 /* DACCON values. */
89 #define PCI230_DAC_BUSY_BIT             1
90 #define PCI230_DAC_BIP_BIT              0
91
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 */
114
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)
120
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). */
134
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) */
144
145
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. */
151
152
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
159
160 #define PCI230_TEST_BIT(val, n) ((val>>n)&1)    /* Assumes bits numbered with zero offset, ie. 0-15 */
161
162 /*
163  * Board descriptions for the two boards supported.
164  */
165
166 typedef struct pci230_board_struct{
167         const char *name;
168         unsigned short id;
169         int ai_chans;
170         int ai_bits;
171         int have_ao;
172         int ao_chans;
173         int ao_bits;
174         int have_dio;
175 }pci230_board;
176 static const pci230_board pci230_boards[] = {
177         {
178         name:           "pci230",
179         id:             PCI_DEVICE_ID_PCI230,
180         ai_chans:       16,
181         ai_bits:        12,
182         have_ao:        1,
183         ao_chans:       2,
184         ao_bits:        12,
185         have_dio:       1,
186         },
187         {
188         name:           "pci260",
189         id:             PCI_DEVICE_ID_PCI260,
190         ai_chans:       16,
191         ai_bits:        12,
192         have_ao:        0,
193         ao_chans:       0,
194         ao_bits:        0,
195         have_dio:       0,
196         },
197         {
198         name:           "amplc_pci230", /* Legacy name matches any above */
199         id:             PCI_DEVICE_ID_INVALID,
200         },
201 };
202
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 },
206         { 0 }
207 };
208 MODULE_DEVICE_TABLE(pci, pci230_pci_table);
209 /*
210  * Useful for shorthand access to the particular board structure
211  */
212 #define n_pci230_boards (sizeof(pci230_boards)/sizeof(pci230_boards[0]))
213 #define thisboard ((const pci230_board *)dev->board_ptr)
214
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. */
237 };
238
239 #define devpriv ((struct pci230_private *)dev->private)
240
241 /* PCI230 analogue input range table */
242 static const comedi_lrange pci230_ai_range = { 7, {
243         BIP_RANGE(10),
244         BIP_RANGE(5),
245         BIP_RANGE(2.5),
246         BIP_RANGE(1.25),
247         UNI_RANGE(10),
248         UNI_RANGE(5),
249         UNI_RANGE(2.5)
250 }};
251
252 /* PCI230 analogue output range table */
253 static const comedi_lrange pci230_ao_range = { 2, {
254         UNI_RANGE(10),
255         BIP_RANGE(10)
256 }};
257
258 /*
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
262  * the device code.
263  */
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",
268         module:         THIS_MODULE,
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]),
274 };
275 COMEDI_INITCLEANUP(driver_amplc_pci230);
276
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);
282 #if 0
283 static void pci230_ns_to_timer(unsigned int *ns,int round);
284 #endif
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);
288 #if 0
289 static void pci230_z2_ct0(comedi_device *dev, unsigned int *ns,int round);
290 #endif
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);
293 #if 0
294 static void pci230_cancel_ct0(comedi_device *dev);
295 #endif
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);
309
310 static sampl_t pci230_ai_read(comedi_device *dev)
311 {
312         /* Read sample. */
313         sampl_t data = (sampl_t) inw(dev->iobase + PCI230_ADCDATA);
314
315         /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower four bits reserved for expansion). */
316         data = data>>4;
317
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);
321         }
322         return data;
323 }
324
325 static void pci230_ao_write(comedi_device *dev, sampl_t data, int chan)
326 {
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);
330         }
331
332         /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower four bits reserved for expansion). */
333         data = data<<4;
334
335         /* Write data. */
336         outw((unsigned int) data, dev->iobase + (((chan) == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
337 }
338
339 /*
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
343  * address.
344  */
345 static int pci230_attach(comedi_device *dev,comedi_devconfig *it)
346 {
347         comedi_subdevice *s;
348         unsigned long pci_iobase, iobase;               /* PCI230's I/O spaces 1 and 2 respectively. */
349         struct pci_dev *pci_dev;
350         int i=0,irq_hdl;
351
352         printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
353                         thisboard->name, it->options[0], it->options[1]);
354
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){
358                 return -ENOMEM;
359         }
360         /* Find card */
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))
367                                 continue;
368                 }
369                 if(pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
370                         continue;
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
375                          * PCI device ID. */
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];
380                                         break;
381                                 }
382                         }
383                         if(i<n_pci230_boards)break;
384                 }else{
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;
389                 }
390         }
391         if(!pci_dev){
392                 printk("comedi%d: No %s card found\n",dev->minor, thisboard->name);
393                 return -EIO;
394         }
395         devpriv->pci_dev = pci_dev;
396
397 /*
398  * Initialize dev->board_name.
399  */
400         dev->board_name = thisboard->name;
401
402         /* Read base addressses of the PCI230's two I/O regions from PCI configuration register. */
403         if(pci_enable_device(pci_dev)<0){
404                 return -EIO;
405         }
406
407         pci_iobase = pci_resource_start(pci_dev, 2);
408         iobase = pci_resource_start(pci_dev, 3);
409
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);
413                 return -EIO;
414         }
415
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);
418
419         devpriv->pci_iobase = pci_iobase;
420         dev->iobase = iobase;
421
422         /* Disable board's interrupts. */
423         outb(0, devpriv->pci_iobase + PCI230_INT_SCE);
424
425         /* Register the interrupt handler. */
426         irq_hdl = comedi_request_irq(devpriv->pci_dev->irq, pci230_interrupt, IRQF_SHARED, "amplc_pci230", dev);
427         if(irq_hdl<0) {
428                 printk("comedi%d: unable to register irq, commands will not be available %d\n", dev->minor, devpriv->pci_dev->irq);
429         }
430         else {
431                 dev->irq = devpriv->pci_dev->irq;
432                 printk("comedi%d: registered irq %u\n", dev->minor, devpriv->pci_dev->irq);
433         }
434
435 /*
436  * Allocate the subdevice structures.  alloc_subdevice() is a
437  * convenient macro defined in comedidev.h.
438  */
439         if(alloc_subdevices(dev, 4)<0)
440                 return -ENOMEM;
441
442         s=dev->subdevices+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. */
452         if(irq_hdl==0) {
453                 dev->read_subdev=s;
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;
458         }
459
460         s=dev->subdevices+1;
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. */
471         if(irq_hdl==0) {
472                 dev->write_subdev=s;
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;
477         }
478
479         s=dev->subdevices+2;
480         /* digital i/o subdevice */
481         if(thisboard->have_dio){
482                 subdev_8255_init(dev,s,NULL,(devpriv->pci_iobase + PCI230_PPI_X_A));
483         }else{
484                 s->type = COMEDI_SUBD_UNUSED;
485         }
486
487         s=dev->subdevices+3;
488         /* timer subdevice */
489         s->type=COMEDI_SUBD_TIMER;
490         s->subdev_flags=SDF_READABLE;
491         s->n_chan=1;
492         s->maxdata=0xffff;
493         s->range_table=&range_digital;
494         s->insn_config = pci230_ct_insn_config;
495         s->insn_read = &pci230_ct_rinsn;
496
497         printk("comedi%d: attached\n",dev->minor);
498
499         return 1;
500 }
501
502
503 /*
504  * _detach is called to deconfigure a device.  It should deallocate
505  * resources.
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.
510  */
511 static int pci230_detach(comedi_device *dev)
512 {
513         printk("comedi%d: amplc_pci230: remove\n",dev->minor);
514
515         if(dev->subdevices && thisboard->have_dio)
516                 subdev_8255_cleanup(dev,dev->subdevices + 2);   /* Clean up dio subdevice. */
517
518         if(dev->irq)
519                 comedi_free_irq(dev->irq, dev);
520
521         if(devpriv){
522                 if(devpriv->pci_dev){
523                         if(dev->iobase)
524                         {
525                                 pci_release_regions(devpriv->pci_dev);
526                                 pci_disable_device(devpriv->pci_dev);
527                         }
528                         pci_dev_put(devpriv->pci_dev);
529                 }
530         }
531
532         return 0;
533 }
534
535 /*
536  *  COMEDI_SUBD_AI instruction;
537  */
538 static int pci230_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
539 {
540         int n,i;
541         int chan, range, aref;
542         unsigned int status;
543         unsigned int adccon, adcen, adcg;
544
545         /* Unpack channel and range. */
546         chan = CR_CHAN(insn->chanspec);
547         range = CR_RANGE(insn->chanspec);
548         aref = CR_AREF(insn->chanspec);
549
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) {
554                 /* Differential. */
555                 adcen = 3<<2*chan;
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);
560                 }
561                 else {
562                         adccon |= PCI230_ADC_IR_UNI;
563                         adcg = ((range&(~4))+1)<<(2*chan-2*chan%2);
564                 }
565         }
566         else {
567                 /* Single ended. */
568                 adcen = 1<<chan;
569                 adccon |= PCI230_ADC_IM_SE;
570                 if (devpriv->ai_bipolar) {
571                         adccon |= PCI230_ADC_IR_BIP;
572                         adcg = range<<(chan-chan%2);
573                 }
574                 else {
575                         adccon |= PCI230_ADC_IR_UNI;
576                         adcg = ((range&(~4))+1)<<(chan-chan%2);
577                 }
578         }
579
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);
582
583         /* Set gain for channel. */
584         outw_p(adcg, dev->iobase + PCI230_ADCG);
585
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);
588
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);
593
594 #define TIMEOUT 100
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;
599                 }
600                 if(i==TIMEOUT){
601                         /* rt_printk() should be used instead of printk()
602                          * whenever the code can be called from real-time. */
603                         rt_printk("timeout\n");
604                         return -ETIMEDOUT;
605                 }
606
607                 /* read data */
608                 data[n] = pci230_ai_read(dev);
609         }
610
611         /* return the number of samples read/written */
612         return n;
613 }
614
615 /*
616  *  COMEDI_SUBD_AO instructions;
617  */
618 static int pci230_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
619 {
620         int i;
621         int chan, range;
622
623         /* Unpack channel and range. */
624         chan = CR_CHAN(insn->chanspec);
625         range = CR_RANGE(insn->chanspec);
626
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);
630
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];
636
637                 /* Write value to DAC. */
638                 pci230_ao_write(dev, data[i], chan);
639         }
640
641         /* return the number of samples read/written */
642         return i;
643 }
644
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)
648 {
649         int i;
650         int chan = CR_CHAN(insn->chanspec);
651
652         for(i=0;i<insn->n;i++)
653                 data[i] = devpriv->ao_readback[chan];
654
655         return i;
656 }
657
658 /*
659  *  COMEDI_SUBD_TIMER instructions;
660  *
661  *  insn_config allows user to start and stop counter/timer 2 (SK1 pin 21).
662  *  Period specified in ns.
663  *
664  *  rinsn returns counter/timer's actual period in ns.
665  */
666 static int pci230_ct_insn_config(comedi_device *dev,comedi_subdevice *s,
667         comedi_insn *insn,lsampl_t *data)
668 {
669         unsigned int ns;
670
671         if(insn->n!=1)return -EINVAL;
672
673         ns = data[0];
674         if (ns == 0) {
675                 //Stop counter/timer 2.
676                 pci230_cancel_ct2(dev);
677         }
678         else {
679                 //Start conter/timer 2 with period ns.
680                 pci230_z2_ct2(dev, &ns, TRIG_ROUND_MASK);
681         }
682
683         return 1;
684 }
685
686 static int pci230_ct_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
687 {
688         if(insn->n!=1)return -EINVAL;
689
690         /* Return the actual period set in ns. */
691         data[0] = PCI230_TIMEBASE_10MHZ*devpriv->divisor1*devpriv->divisor2;
692         return 1;
693 }
694
695 static int pci230_ao_cmdtest(comedi_device *dev,comedi_subdevice *s,
696         comedi_cmd *cmd)
697 {
698         int err=0;
699         int tmp;
700
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.
704          *
705          * cmdtest returns 1,2,3,4 or 0, depending on which tests
706          * the command passes. */
707
708         /* Step 1: make sure trigger sources are trivially valid.
709          * "invalid source" returned by comedilib to user mode process
710          * if this fails. */
711
712         tmp=cmd->start_src;
713         cmd->start_src &= TRIG_INT;
714         if(!cmd->start_src || tmp!=cmd->start_src)err++;
715
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++;
719
720         tmp=cmd->convert_src;
721         cmd->convert_src &= TRIG_NOW;
722         if(!cmd->convert_src || tmp!=cmd->convert_src)err++;
723
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++;
727
728         tmp=cmd->stop_src;
729         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
730         if(!cmd->stop_src || tmp!=cmd->stop_src)err++;
731
732         if(err)return 1;
733
734         /* Step 2: make sure trigger sources are unique and mutually compatible
735          * "source conflict" returned by comedilib to user mode process
736          * if this fails. */
737
738         if(cmd->stop_src!=TRIG_COUNT &&
739            cmd->stop_src!=TRIG_NONE)err++;
740
741         if(err)return 2;
742
743         /* Step 3: make sure arguments are trivially compatible.
744          * "invalid argument" returned by comedilib to user mode process
745          * if this fails. */
746
747         if(cmd->start_arg!=0){
748                 cmd->start_arg=0;
749                 err++;
750         }
751
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 */
754
755         if(cmd->scan_begin_src==TRIG_TIMER){
756                 if(cmd->scan_begin_arg<MAX_SPEED){
757                         cmd->scan_begin_arg=MAX_SPEED;
758                         err++;
759                 }
760                 if(cmd->scan_begin_arg>MIN_SPEED){
761                         cmd->scan_begin_arg=MIN_SPEED;
762                         err++;
763                 }
764         }
765
766         if(cmd->scan_end_arg!=cmd->chanlist_len){
767                 cmd->scan_end_arg=cmd->chanlist_len;
768                 err++;
769         }
770         if(cmd->stop_src==TRIG_NONE){
771                 /* TRIG_NONE */
772                 if(cmd->stop_arg!=0){
773                         cmd->stop_arg=0;
774                         err++;
775                 }
776         }
777
778         if(err)return 3;
779
780         /* Step 4: fix up any arguments.
781          * "argument conflict" returned by comedilib to user mode process
782          * if this fails. */
783
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++;
788         }
789
790         if(err)return 4;
791
792         return 0;
793 }
794
795 static int pci230_ao_inttrig(comedi_device *dev,comedi_subdevice *s,
796                 unsigned int trig_num)
797 {
798         if(trig_num != 0)
799                 return -EINVAL;
800
801         /* Enable DAC interrupt. */
802         devpriv->ier |= PCI230_INT_ZCLK_CT1;
803         outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
804
805         s->async->inttrig=NULL;
806
807         return 1;
808 }
809
810 static int pci230_ao_cmd(comedi_device *dev,comedi_subdevice *s)
811 {
812         int range;
813
814         /* Get the command. */
815         comedi_cmd *cmd=&s->async->cmd;
816
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;
821         }
822         else {
823                 /* TRIG_NONE, user calls cancel. */
824                 devpriv->ao_count = 0;
825                 devpriv->ao_stop = 1;
826         }
827
828         /* Disable DAC interrupt. */
829         devpriv->ier &= ~PCI230_INT_ZCLK_CT1;
830         outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
831
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);
836
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?
841          *
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).
844          */
845         pci230_z2_ct1(dev, &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); /* cmd->convert_arg is sampling period in ns */
846
847         s->async->inttrig=pci230_ao_inttrig;
848
849         return 0;
850 }
851
852 static int pci230_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,
853         comedi_cmd *cmd)
854 {
855         int err=0;
856         int tmp;
857
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.
861          *
862          * cmdtest returns 1,2,3,4 or 0, depending on which tests
863          * the command passes. */
864
865         /* Step 1: make sure trigger sources are trivially valid.
866          * "invalid source" returned by comedilib to user mode process
867          * if this fails. */
868
869         tmp=cmd->start_src;
870         cmd->start_src &= TRIG_NOW;
871         if(!cmd->start_src || tmp!=cmd->start_src)err++;
872
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;
879                 }
880         else{
881                 cmd->scan_begin_src &= TRIG_FOLLOW;
882                 }
883         if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;
884
885         tmp=cmd->convert_src;
886         cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
887         if(!cmd->convert_src || tmp!=cmd->convert_src)err++;
888
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++;
892
893         tmp=cmd->stop_src;
894         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
895         if(!cmd->stop_src || tmp!=cmd->stop_src)err++;
896
897         if(err)return 1;
898
899         /* Step 2: make sure trigger sources are unique and mutually compatible
900          * "source conflict" returned by comedilib to user mode process
901          * if this fails. */
902
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++;
910
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++;
919
920         if(err)return 2;
921
922         /* Step 3: make sure arguments are trivially compatible.
923          * "invalid argument" returned by comedilib to user mode process
924          * if this fails. */
925
926         if(cmd->start_arg!=0){
927                 cmd->start_arg=0;
928                 err++;
929         }
930
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 */
933
934         if(cmd->convert_src==TRIG_TIMER){
935                 if(cmd->convert_arg<MAX_SPEED){
936                         cmd->convert_arg=MAX_SPEED;
937                         err++;
938                 }
939                 if(cmd->convert_arg>MIN_SPEED){
940                         cmd->convert_arg=MIN_SPEED;
941                         err++;
942                 }
943         }else{
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. */
949                         err++;
950                 }
951         }
952
953         if(cmd->scan_end_arg!=cmd->chanlist_len){
954                 cmd->scan_end_arg=cmd->chanlist_len;
955                 err++;
956         }
957         if(cmd->stop_src==TRIG_NONE){
958                 /* TRIG_NONE */
959                 if(cmd->stop_arg!=0){
960                         cmd->stop_arg=0;
961                         err++;
962                 }
963         }
964
965
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) */
972                         err++;
973                 }
974         }
975
976         if(err)return 3;
977
978         /* Step 4: fix up any arguments.
979          * "argument conflict" returned by comedilib to user mode process
980          * if this fails. */
981
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++;
986         }
987
988         if(err)return 4;
989
990         return 0;
991 }
992
993 static int pci230_ai_cmd(comedi_device *dev,comedi_subdevice *s)
994 {
995         int i, chan, range, diff;
996         unsigned int adccon, adcen, adcg;
997         unsigned int zgat;
998
999         /* Get the command. */
1000         comedi_async *async = s->async;
1001         comedi_cmd *cmd = &async->cmd;
1002
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;
1007         }
1008         else {
1009                 /* TRIG_NONE, user calls cancel. */
1010                 devpriv->ai_count = 0;
1011                 devpriv->ai_stop = 1;
1012         }
1013
1014         /* Steps;
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.
1023          */
1024
1025         /* Disable ADC interrupt. */
1026         devpriv->ier &= ~PCI230_INT_ADC;
1027         outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1028
1029         if (CR_AREF(cmd->chanlist[0])==AREF_DIFF) {
1030                 /* Differential - all channels must be differential. */
1031                 diff = 1;
1032                 adccon = PCI230_ADC_IM_DIF;
1033         }
1034         else {
1035                 /* Single ended - all channels must be single-ended. */
1036                 diff = 0;
1037                 adccon = PCI230_ADC_IM_SE;
1038         }
1039
1040         adccon |= PCI230_ADC_FIFO_RESET | PCI230_ADC_FIFO_EN;
1041         //adccon |= PCI230_ADC_FIFO_RESET;
1042         adcg = 0;
1043         adcen = 0;
1044
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]);
1053                         if (diff) {
1054                                 adcg |= range<<(2*chan-2*chan%2);
1055                                 adcen |= 3<<2*chan;
1056                         }
1057                         else {
1058                                 adcg |= range<<(chan-chan%2);
1059                                 adcen |= 1<<chan;
1060                         }
1061                 }
1062         }
1063         else {
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]);
1068                         if (diff) {
1069                                 adcg |= ((range&(~4))+1)<<(2*chan-2*chan%2);
1070                                 adcen |= 3<<2*chan;
1071                         }
1072                         else {
1073                                 adcg |= ((range&(~4))+1)<<(chan-chan%2);
1074                                 adcen |= 1<<chan;
1075                         }
1076                 }
1077         }
1078
1079         /* Set channel scan list. */
1080         outw(adcen, dev->iobase + PCI230_ADCEN);
1081
1082         /* Set channel gains. */
1083         outw(adcg, dev->iobase + PCI230_ADCG);
1084
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);
1087
1088         /* Delay */
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
1093          * slightly. */
1094         comedi_udelay(25);
1095
1096         /* Enable ADC (conversion complete) interrupt. */
1097         devpriv->ier |= PCI230_INT_ADC;
1098         outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1099
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
1103                  *
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
1112                  * convert source.
1113                  *
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.
1119                  *
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 */
1129
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);
1133
1134                 zgat = PCI230_ZGAT_CT2 | PCI230_ZGAT_SRC_GND;
1135                 outb(zgat, devpriv->pci_iobase + PCI230_ZGAT_SCE);
1136
1137                 pci230_setup_monostable_ct0(dev, cmd->convert_arg, cmd->chanlist_len);
1138
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);
1142
1143                 zgat = PCI230_ZGAT_CT2 | PCI230_ZGAT_SRC_OUTNP1;
1144                 outb(zgat, devpriv->pci_iobase + PCI230_ZGAT_SCE);
1145         }
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);
1149         }
1150
1151         /* Set start conversion source. */
1152         if(cmd->convert_src == TRIG_TIMER) {
1153                 /* Onboard counter/timer 2. */
1154                 adccon = adccon | PCI230_ADC_TRIG_Z2CT2;
1155
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 */
1158         }
1159         else {
1160                 /* TRIG_EXT - external trigger. */
1161                 if (cmd->convert_arg) {
1162                         /* Trigger on +ve edge. */
1163                         adccon = adccon | PCI230_ADC_TRIG_EXTP;
1164                 }
1165                 else {
1166                         /* Trigger on -ve edge. */
1167                         adccon = adccon | PCI230_ADC_TRIG_EXTN;
1168                 }
1169         }
1170
1171
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;
1176                 }
1177                 else {
1178                         adccon = adccon | PCI230_ADC_INT_FIFO_HALF;
1179                 }
1180         }
1181         else {
1182                 /* TRIG_NONE - trigger on half-full FIFO. */
1183                 adccon = adccon | PCI230_ADC_INT_FIFO_HALF;
1184         }
1185
1186         //adccon = adccon | PCI230_ADC_FIFO_EN;
1187         outw(adccon, dev->iobase + PCI230_ADCCON);
1188
1189         return 0;
1190 }
1191
1192
1193 #if 0
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)
1200 {
1201         unsigned int divisor0, divisor1;
1202         i8253_cascade_ns_to_timer_2div(PCI230_TIMEBASE_10MHZ, &divisor0, &divisor1, ns, TRIG_ROUND_MASK);
1203         return;
1204 }
1205 #endif
1206
1207
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)
1214 {
1215         unsigned int clk_src=0;
1216
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 */
1221
1222         if(clk_src == 0){
1223                 printk("comedi: dodgy clock source chosen, using 10MHz\n");
1224                 clk_src=PCI230_TIMEBASE_10MHZ;
1225                 }
1226         return clk_src;
1227 }
1228
1229 static void pci230_ns_to_single_timer(unsigned int *ns,int round)
1230 {
1231         unsigned int divisor;
1232         unsigned int clk_src;
1233
1234         clk_src=pci230_choose_clk_src(*ns);
1235         i8253_single_ns_to_timer(clk_src, &divisor, ns, TRIG_ROUND_MASK);
1236         return;
1237 }
1238
1239 static void i8253_single_ns_to_timer(unsigned int i8253_osc_base, unsigned int *d, unsigned int *nanosec, int round_mode)
1240 {
1241         unsigned int div;
1242
1243         /* exit early if everything is already correct (this can save time
1244          * since this function may be called repeatedly during command tests
1245          * and execution) */
1246         if(*d * i8253_osc_base == *nanosec &&
1247                 *d > 1 && *d < 0x10000)
1248         {
1249                 return;
1250         }
1251
1252         round_mode &= TRIG_ROUND_MASK;
1253         switch (round_mode) {
1254         case TRIG_ROUND_NEAREST:
1255         default:
1256                 div=(*nanosec + i8253_osc_base / 2) / i8253_osc_base;
1257                 break;
1258         case TRIG_ROUND_UP:
1259                 div=(*nanosec)  / i8253_osc_base;
1260                 break;
1261         case TRIG_ROUND_DOWN:
1262                 div=(*nanosec + i8253_osc_base + 1 )  / i8253_osc_base;
1263                 break;
1264         }
1265
1266         *nanosec = div * i8253_osc_base;
1267         *d = div & 0xffff;    // masking is done since counter maps zero to 0x10000
1268
1269         return;
1270 }
1271
1272 static void pci230_setup_monostable_ct0(comedi_device *dev, unsigned int ns, unsigned int n_chan)
1273 {
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 */
1277
1278         unsigned int pulse_duration;
1279
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! */
1282
1283         devpriv->divisor0=pulse_duration/devpriv->clk_src0;
1284
1285         i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 0, devpriv->divisor0, 1);       /* Counter 1, mode 1 */
1286
1287         /* PCI 230 specific - ties up counter clk input with correct clk source */
1288         switch (devpriv->clk_src0) {
1289         case PCI230_TIMEBASE_10MHZ:
1290         default:
1291                 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE);   /* Program counter 0's input clock source. */
1292                 break;
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. */
1295                 break;
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. */
1298                 break;
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. */
1301                 break;
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. */
1304                 break;
1305         }
1306
1307         return;
1308 }
1309
1310
1311 #if 0
1312 /*
1313  *  Set ZCLK_CT0 to square wave mode with period of ns.
1314  */
1315 static void pci230_z2_ct0(comedi_device *dev, unsigned int *ns,int round)
1316 {
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);
1319
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). */
1322
1323         /* PCI 230 specific - ties up counter clk input with clk source */
1324         switch (devpriv->clk_src0) {
1325         case PCI230_TIMEBASE_10MHZ:
1326         default:
1327                 outb(PCI230_ZCLK_CT0 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE);   /* Program counter 0's input clock source. */
1328                 break;
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. */
1331                 break;
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. */
1334                 break;
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. */
1337                 break;
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. */
1340                 break;
1341         }
1342         return;
1343 }
1344 #endif
1345
1346 #if 0
1347 static void pci230_cancel_ct0(comedi_device *dev)
1348 {
1349         devpriv->divisor0 = 0;
1350         i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 0, devpriv->divisor0, 0);       /* Counter 0, divisor0, 8254 mode 0. */
1351 }
1352 #endif
1353
1354 /*
1355  *  Set ZCLK_CT1 to square wave mode with period of ns.
1356  *  Default clk source for DAC.
1357  */
1358 static void pci230_z2_ct1(comedi_device *dev, unsigned int *ns,int round)
1359 {
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);
1362
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). */
1365
1366         /* PCI 230 specific - ties up counter clk input with clk source */
1367         switch (devpriv->clk_src1) {
1368         case PCI230_TIMEBASE_10MHZ:
1369         default:
1370                 outb(PCI230_ZCLK_CT1 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE);   /* Program counter 1's input clock source. */
1371                 break;
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. */
1374                 break;
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. */
1377                 break;
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. */
1380                 break;
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. */
1383                 break;
1384         }
1385         return;
1386 }
1387
1388 static void pci230_cancel_ct1(comedi_device *dev)
1389 {
1390         devpriv->divisor1 = 0;
1391         i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 1, devpriv->divisor1, 0);       /* Counter 1, divisor1, 8254 mode 0. */
1392 }
1393
1394 /*
1395  *  Set ZCLK_CT2 to square wave mode with period of ns.
1396  *  Default clk source for ADC.
1397  */
1398 static void pci230_z2_ct2(comedi_device *dev, unsigned int *ns,int round)
1399 {
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);
1402
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). */
1405
1406         /* PCI 230 specific - ties up counter clk input with clk source */
1407         switch (devpriv->clk_src2) {
1408         case PCI230_TIMEBASE_10MHZ:
1409         default:
1410                 outb(PCI230_ZCLK_CT2 | PCI230_ZCLK_SRC_10MHZ, devpriv->pci_iobase + PCI230_ZCLK_SCE);   /* Program counter 2's input clock source. */
1411                 break;
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. */
1414                 break;
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. */
1417                 break;
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. */
1420                 break;
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. */
1423                 break;
1424         }
1425         return;
1426 }
1427
1428 static void pci230_cancel_ct2(comedi_device *dev)
1429 {
1430         devpriv->divisor2 = 0;
1431         i8254_load(devpriv->pci_iobase + PCI230_Z2_CT0, 2, devpriv->divisor2, 0);       /* Counter 2, divisor2, 8254 mode 0. */
1432 }
1433
1434 /* Interrupt handler */
1435 static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
1436 {
1437         int status_int;
1438         comedi_device *dev = (comedi_device*) d;
1439         comedi_subdevice *s;
1440
1441         /* Read interrupt status/enable register. */
1442         status_int = inb(devpriv->pci_iobase + PCI230_INT_SCE);
1443
1444         if (status_int == PCI230_INT_DISABLE) {
1445                 return IRQ_NONE;
1446         }
1447
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);
1452
1453         /*
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.
1458          */
1459
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;
1466         }
1467
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;
1474         }
1475
1476         return IRQ_HANDLED;
1477 }
1478
1479 static void pci230_handle_ao(comedi_device *dev, comedi_subdevice *s) {
1480         sampl_t data;
1481         int i, ret;
1482         comedi_async *async = s->async;
1483         comedi_cmd *cmd = &async->cmd;
1484
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);
1488                 if(ret < 0) {
1489                         comedi_error(dev, "buffer underrun");
1490                         return;                                                                         // XXX does comedi_buf_get set s->async->events with appropriate flags in this instance?
1491                 }
1492                 /* Write value to DAC. */
1493                 pci230_ao_write(dev, data, cmd->chanlist[i]);
1494
1495                 if(async->cmd.stop_src == TRIG_COUNT) {
1496                         if(devpriv->ao_count > 0) devpriv->ao_count--;
1497                         if(devpriv->ao_count == 0) break;
1498                 }
1499         }
1500
1501         if(devpriv->ao_count == 0 && devpriv->ao_stop == 0) {
1502                 /* End of DAC. */
1503                 async->events |= COMEDI_CB_EOA;
1504                 pci230_ao_cancel(dev, s);
1505         }
1506         else {
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);
1512         }
1513         return;
1514 }
1515
1516 static void pci230_handle_ai(comedi_device *dev, comedi_subdevice *s) {
1517         int error = 0;
1518         int status_fifo;
1519
1520         /* Read FIFO state. */
1521         status_fifo = inw(dev->iobase + PCI230_ADCCON);
1522
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");
1526                 error++;
1527         }
1528         else if (status_fifo & PCI230_ADC_FIFO_HALF) {
1529                 /* FIFO is at least half full. */
1530                 pci230_handle_fifo_half_full(dev, s);
1531         }
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);
1535         }
1536         else {
1537                 /* FIFO is less than half full, but not empty. */
1538                 pci230_handle_fifo_not_empty(dev, s);
1539         }
1540
1541         if (error) {
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 */
1549         }else {
1550                 /* More samples required, tell Comedi to block. */
1551                 s->async->events |= COMEDI_CB_BLOCK;
1552
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);
1556         }
1557         return;
1558 }
1559
1560 static void pci230_handle_fifo_half_full(comedi_device *dev, comedi_subdevice *s) {
1561         int i;
1562
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));
1566
1567                 if(s->async->cmd.stop_src == TRIG_COUNT)
1568                 {
1569                         if(--devpriv->ai_count == 0) {
1570                                 /* Acquisition complete. */
1571                                 return;
1572                         }
1573                 }
1574         }
1575         /* More samples required. */
1576         return;
1577 }
1578
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. */
1583                         return;
1584                 }
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));
1587
1588                 if(devpriv->ai_count > 0) devpriv->ai_count--;
1589         }
1590         /* Acquisition complete. */
1591         return;
1592 }
1593
1594
1595 static int pci230_ao_cancel(comedi_device *dev, comedi_subdevice *s) {
1596         devpriv->ao_count = 0;
1597         devpriv->ao_stop = 0;
1598
1599         /* Stop counter/timers. */
1600         pci230_cancel_ct1(dev);
1601
1602         /* Disable DAC interrupt. */
1603         devpriv->ier &= ~PCI230_INT_ZCLK_CT1;
1604         outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1605
1606         return 0;
1607 }
1608
1609 static int pci230_ai_cancel(comedi_device *dev, comedi_subdevice *s) {
1610         devpriv->ai_count = 0;
1611         devpriv->ai_stop = 0;
1612
1613         /* Stop counter/timers. */
1614         pci230_cancel_ct2(dev);
1615
1616         /* Disable ADC interrupt. */
1617         devpriv->ier &= ~PCI230_INT_ADC;
1618         outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);
1619
1620         /* Reset FIFO and set start conversion source to none. */
1621         outw(PCI230_ADC_FIFO_RESET | PCI230_ADC_TRIG_NONE, dev->iobase + PCI230_ADCCON);
1622
1623         /* Clear channel scan list. */
1624         outw(0x0000, dev->iobase + PCI230_ADCEN);
1625
1626         /* Clear channel gains. */
1627         outw(0x0000, dev->iobase + PCI230_ADCG);
1628
1629         return 0;
1630 }
1631
1632