2 comedi/drivers/pcl818.c
4 Author: Michal Dobes <dobes@tesnet.cz>
6 hardware driver for Advantech cards:
7 card: PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718
8 driver: pcl818l, pcl818h, pcl818hd, pcl818hg, pcl818, pcl718
12 Description: Advantech PCL-818 cards, PCL-718
13 Author: Michal Dobes <dobes@tesnet.cz>
14 Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h),
15 PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818),
19 All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO.
20 Differences are only at maximal sample speed, range list and FIFO
22 The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support
23 only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0.
24 PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO
25 but this code is untested.
26 A word or two about DMA. Driver support DMA operations at two ways:
27 1) DMA uses two buffers and after one is filled then is generated
28 INT and DMA restart with second buffer. With this mode I'm unable run
29 more that 80Ksamples/secs without data dropouts on K6/233.
30 2) DMA uses one buffer and run in autoinit mode and the data are
31 from DMA buffer moved on the fly with 2kHz interrupts from RTC.
32 This mode is used if the interrupt 8 is available for allocation.
33 If not, then first DMA mode is used. With this I can run at
34 full speed one card (100ksamples/secs) or two cards with
35 60ksamples/secs each (more is problem on account of ISA limitations).
36 To use this mode you must have compiled kernel with disabled
37 "Enhanced Real Time Clock Support".
38 Maybe you can have problems if you use xntpd or similar.
39 If you've data dropouts with DMA mode 2 then:
41 b) switch text mode console to fb.
45 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
46 [2] - DMA (0=disable, 1, 3)
47 [3] - 0, 10=10MHz clock for 8254
48 1= 1MHz clock for 8254
49 [4] - 0, 5=A/D input -5V.. +5V
50 1, 10=A/D input -10V..+10V
51 [5] - 0, 5=D/A output 0-5V (internal reference -5V)
52 1, 10=D/A output 0-10V (internal reference -10V)
53 2 =D/A output unknown (external reference)
55 Options for PCL-818, PCL-818H:
57 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
58 [2] - DMA (0=disable, 1, 3)
59 [3] - 0, 10=10MHz clock for 8254
60 1= 1MHz clock for 8254
61 [4] - 0, 5=D/A output 0-5V (internal reference -5V)
62 1, 10=D/A output 0-10V (internal reference -10V)
63 2 =D/A output unknown (external reference)
65 Options for PCL-818HD, PCL-818HG:
67 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
68 [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA,
69 1=use DMA ch 1, 3=use DMA ch 3)
70 [3] - 0, 10=10MHz clock for 8254
71 1= 1MHz clock for 8254
72 [4] - 0, 5=D/A output 0-5V (internal reference -5V)
73 1, 10=D/A output 0-10V (internal reference -10V)
74 2 =D/A output unknown (external reference)
78 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
79 [2] - DMA (0=disable, 1, 3)
80 [3] - 0, 10=10MHz clock for 8254
81 1= 1MHz clock for 8254
82 [4] - 0=A/D Range is +/-10V
87 5= user defined bipolar
92 10= user defined unipolar
93 [5] - 0, 5=D/A outputs 0-5V (internal reference -5V)
94 1, 10=D/A outputs 0-10V (internal reference -10V)
95 2=D/A outputs unknown (external reference)
96 [6] - 0, 60=max 60kHz A/D sampling
97 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed)
101 #include "../comedidev.h"
103 #include <linux/ioport.h>
104 #include <linux/mc146818rtc.h>
105 #include <linux/gfp.h>
106 #include <linux/delay.h>
107 #include <linux/io.h>
112 /* #define PCL818_MODE13_AO 1 */
114 /* boards constants */
116 #define boardPCL818L 0
117 #define boardPCL818H 1
118 #define boardPCL818HD 2
119 #define boardPCL818HG 3
120 #define boardPCL818 4
121 #define boardPCL718 5
124 #define PCLx1x_RANGE 16
125 /* IO space len if we use FIFO */
126 #define PCLx1xFIFO_RANGE 32
128 /* W: clear INT request */
129 #define PCL818_CLRINT 8
130 /* R: return status byte */
131 #define PCL818_STATUS 8
132 /* R: A/D high byte W: A/D range control */
133 #define PCL818_RANGE 1
134 /* R: next mux scan channel W: mux scan channel & range control pointer */
136 /* R/W: operation control register */
137 #define PCL818_CONTROL 9
138 /* W: counter enable */
139 #define PCL818_CNTENABLE 10
141 /* R: low byte of A/D W: soft A/D trigger */
142 #define PCL818_AD_LO 0
143 /* R: high byte of A/D W: A/D range control */
144 #define PCL818_AD_HI 1
145 /* W: D/A low&high byte */
146 #define PCL818_DA_LO 4
147 #define PCL818_DA_HI 5
148 /* R: low&high byte of DI */
149 #define PCL818_DI_LO 3
150 #define PCL818_DI_HI 11
151 /* W: low&high byte of DO */
152 #define PCL818_DO_LO 3
153 #define PCL818_DO_HI 11
154 /* W: PCL718 second D/A */
155 #define PCL718_DA2_LO 6
156 #define PCL718_DA2_HI 7
158 #define PCL818_CTR0 12
159 #define PCL818_CTR1 13
160 #define PCL818_CTR2 14
161 /* W: counter control */
162 #define PCL818_CTRCTL 15
164 /* W: fifo enable/disable */
165 #define PCL818_FI_ENABLE 6
166 /* W: fifo interrupt clear */
167 #define PCL818_FI_INTCLR 20
168 /* W: fifo interrupt clear */
169 #define PCL818_FI_FLUSH 25
171 #define PCL818_FI_STATUS 25
172 /* R: one record from FIFO */
173 #define PCL818_FI_DATALO 23
174 #define PCL818_FI_DATAHI 23
176 /* type of interrupt handler */
177 #define INT_TYPE_AI1_INT 1
178 #define INT_TYPE_AI1_DMA 2
179 #define INT_TYPE_AI1_FIFO 3
180 #define INT_TYPE_AI3_INT 4
181 #define INT_TYPE_AI3_DMA 5
182 #define INT_TYPE_AI3_FIFO 6
183 #ifdef PCL818_MODE13_AO
184 #define INT_TYPE_AO1_INT 7
185 #define INT_TYPE_AO3_INT 8
190 #define INT_TYPE_AI1_DMA_RTC 9
191 #define INT_TYPE_AI3_DMA_RTC 10
194 #define RTC_IO_EXTENT 0x10
197 #define MAGIC_DMA_WORD 0x5a5a
199 static const struct comedi_lrange range_pcl818h_ai = { 9, {
212 static const struct comedi_lrange range_pcl818hg_ai = { 10, {
228 static const struct comedi_lrange range_pcl818l_l_ai = { 4, {
236 static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
244 static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
245 static const struct comedi_lrange range718_bipolar0_5 =
246 { 1, {BIP_RANGE(0.5),} };
247 static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
248 static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
251 static int RTC_lock; /* RTC lock */
252 static int RTC_timer_lock; /* RTC int lock */
255 struct pcl818_board {
257 const char *name; /* driver name */
258 int n_ranges; /* len of range list */
259 int n_aichan_se; /* num of A/D chans in single ended mode */
260 int n_aichan_diff; /* num of A/D chans in diferencial mode */
261 unsigned int ns_min; /* minimal allowed delay between samples (in ns) */
262 int n_aochan; /* num of D/A chans */
263 int n_dichan; /* num of DI chans */
264 int n_dochan; /* num of DO chans */
265 const struct comedi_lrange *ai_range_type; /* default A/D rangelist */
266 const struct comedi_lrange *ao_range_type; /* default D/A rangelist */
267 unsigned int io_range; /* len of IO space */
268 unsigned int IRQbits; /* allowed interrupts */
269 unsigned int DMAbits; /* allowed DMA chans */
270 int ai_maxdata; /* maxdata for A/D */
271 int ao_maxdata; /* maxdata for D/A */
272 unsigned char fifo; /* 1=board has FIFO */
276 struct pcl818_private {
278 unsigned int dma; /* used DMA, 0=don't use DMA */
279 int dma_rtc; /* 1=RTC used with DMA, 0=no RTC alloc */
280 unsigned int io_range;
282 unsigned long rtc_iobase; /* RTC port region */
283 unsigned int rtc_iosize;
284 unsigned int rtc_irq;
285 struct timer_list rtc_irq_timer; /* timer for RTC sanity check */
286 unsigned long rtc_freq; /* RTC int freq */
287 int rtc_irq_blocked; /* 1=we now do AI with DMA&RTC */
289 unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */
290 unsigned int dmapages[2]; /* len of DMA buffers in PAGE_SIZEs */
291 unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */
292 unsigned int hwdmasize[2]; /* len of DMA buffers in Bytes */
293 unsigned int dmasamplsize; /* size in samples hwdmasize[0]/2 */
294 unsigned int last_top_dma; /* DMA pointer in last RTC int */
295 int next_dma_buf; /* which DMA buffer will be used next round */
296 long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */
297 unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */
298 unsigned char neverending_ai; /* if=1, then we do neverending record (you must use cancel()) */
299 unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */
300 int i8253_osc_base; /* 1/frequency of on board oscilator in ns */
301 int irq_free; /* 1=have allocated IRQ */
302 int irq_blocked; /* 1=IRQ now uses any subdev */
303 int irq_was_now_closed; /* when IRQ finish, there's stored int818_mode for last interrupt */
304 int ai_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
305 struct comedi_subdevice *last_int_sub; /* ptr to subdevice which now finish */
306 int ai_act_scan; /* how many scans we finished */
307 int ai_act_chan; /* actual position in actual scan */
308 unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */
309 unsigned int act_chanlist_len; /* how long is actual MUX list */
310 unsigned int act_chanlist_pos; /* actual position in MUX list */
311 unsigned int ai_scans; /* len of scanlist */
312 unsigned int ai_n_chan; /* how many channels is measured */
313 unsigned int *ai_chanlist; /* actaul chanlist */
314 unsigned int ai_flags; /* flaglist */
315 unsigned int ai_data_len; /* len of data buffer */
316 short *ai_data; /* data buffer */
317 unsigned int ai_timer1; /* timers */
318 unsigned int ai_timer2;
319 struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */
320 unsigned char usefifo; /* 1=use fifo */
321 unsigned int ao_readback[2];
324 static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, /* used for gain list programming */
325 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
328 #define devpriv ((struct pcl818_private *)dev->private)
331 ==============================================================================
333 static void setup_channel_list(struct comedi_device *dev,
334 struct comedi_subdevice *s,
335 unsigned int *chanlist, unsigned int n_chan,
336 unsigned int seglen);
337 static int check_channel_list(struct comedi_device *dev,
338 struct comedi_subdevice *s,
339 unsigned int *chanlist, unsigned int n_chan);
341 static int pcl818_ai_cancel(struct comedi_device *dev,
342 struct comedi_subdevice *s);
343 static void start_pacer(struct comedi_device *dev, int mode,
344 unsigned int divisor1, unsigned int divisor2);
347 static int set_rtc_irq_bit(unsigned char bit);
348 static void rtc_dropped_irq(unsigned long data);
349 static int rtc_setfreq_irq(int freq);
353 ==============================================================================
354 ANALOG INPUT MODE0, 818 cards, slow version
356 static int pcl818_ai_insn_read(struct comedi_device *dev,
357 struct comedi_subdevice *s,
358 struct comedi_insn *insn, unsigned int *data)
363 /* software trigger, DMA and INT off */
364 outb(0, dev->iobase + PCL818_CONTROL);
367 outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX);
370 outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE);
372 for (n = 0; n < insn->n; n++) {
374 /* clear INT (conversion end) flag */
375 outb(0, dev->iobase + PCL818_CLRINT);
377 /* start conversion */
378 outb(0, dev->iobase + PCL818_AD_LO);
382 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
386 comedi_error(dev, "A/D insn timeout");
387 /* clear INT (conversion end) flag */
388 outb(0, dev->iobase + PCL818_CLRINT);
392 data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
393 (inb(dev->iobase + PCL818_AD_LO) >> 4));
400 ==============================================================================
401 ANALOG OUTPUT MODE0, 818 cards
402 only one sample per call is supported
404 static int pcl818_ao_insn_read(struct comedi_device *dev,
405 struct comedi_subdevice *s,
406 struct comedi_insn *insn, unsigned int *data)
409 int chan = CR_CHAN(insn->chanspec);
411 for (n = 0; n < insn->n; n++)
412 data[n] = devpriv->ao_readback[chan];
417 static int pcl818_ao_insn_write(struct comedi_device *dev,
418 struct comedi_subdevice *s,
419 struct comedi_insn *insn, unsigned int *data)
422 int chan = CR_CHAN(insn->chanspec);
424 for (n = 0; n < insn->n; n++) {
425 devpriv->ao_readback[chan] = data[n];
426 outb((data[n] & 0x000f) << 4, dev->iobase +
427 (chan ? PCL718_DA2_LO : PCL818_DA_LO));
428 outb((data[n] & 0x0ff0) >> 4, dev->iobase +
429 (chan ? PCL718_DA2_HI : PCL818_DA_HI));
436 ==============================================================================
437 DIGITAL INPUT MODE0, 818 cards
439 only one sample per call is supported
441 static int pcl818_di_insn_bits(struct comedi_device *dev,
442 struct comedi_subdevice *s,
443 struct comedi_insn *insn, unsigned int *data)
448 data[1] = inb(dev->iobase + PCL818_DI_LO) |
449 (inb(dev->iobase + PCL818_DI_HI) << 8);
455 ==============================================================================
456 DIGITAL OUTPUT MODE0, 818 cards
458 only one sample per call is supported
460 static int pcl818_do_insn_bits(struct comedi_device *dev,
461 struct comedi_subdevice *s,
462 struct comedi_insn *insn, unsigned int *data)
467 s->state &= ~data[0];
468 s->state |= (data[0] & data[1]);
470 outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
471 outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
479 ==============================================================================
480 analog input interrupt mode 1 & 3, 818 cards
481 one sample per interrupt version
483 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
485 struct comedi_device *dev = d;
486 struct comedi_subdevice *s = dev->subdevices + 0;
488 int timeout = 50; /* wait max 50us */
491 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
495 outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */
496 comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
497 pcl818_ai_cancel(dev, s);
498 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
499 comedi_event(dev, s);
503 low = inb(dev->iobase + PCL818_AD_LO);
504 comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4))); /* get one sample */
505 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
507 if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
509 ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
511 devpriv->act_chanlist[devpriv->act_chanlist_pos]);
512 pcl818_ai_cancel(dev, s);
513 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
514 comedi_event(dev, s);
517 devpriv->act_chanlist_pos++;
518 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
519 devpriv->act_chanlist_pos = 0;
521 s->async->cur_chan++;
522 if (s->async->cur_chan >= devpriv->ai_n_chan) {
524 s->async->cur_chan = 0;
525 devpriv->ai_act_scan--;
528 if (!devpriv->neverending_ai) {
529 if (devpriv->ai_act_scan == 0) { /* all data sampled */
530 pcl818_ai_cancel(dev, s);
531 s->async->events |= COMEDI_CB_EOA;
534 comedi_event(dev, s);
539 ==============================================================================
540 analog input dma mode 1 & 3, 818 cards
542 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
544 struct comedi_device *dev = d;
545 struct comedi_subdevice *s = dev->subdevices + 0;
550 disable_dma(devpriv->dma);
551 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
552 if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) { /* switch dma bufs */
553 set_dma_mode(devpriv->dma, DMA_MODE_READ);
554 flags = claim_dma_lock();
555 set_dma_addr(devpriv->dma,
556 devpriv->hwdmaptr[devpriv->next_dma_buf]);
557 if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
558 set_dma_count(devpriv->dma,
559 devpriv->hwdmasize[devpriv->
562 set_dma_count(devpriv->dma, devpriv->last_dma_run);
564 release_dma_lock(flags);
565 enable_dma(devpriv->dma);
567 printk("comedi: A/D mode1/3 IRQ \n");
569 devpriv->dma_runs_to_end--;
570 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
571 ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
573 len = devpriv->hwdmasize[0] >> 1;
576 for (i = 0; i < len; i++) {
577 if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
579 ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
581 devpriv->act_chanlist[devpriv->act_chanlist_pos],
582 devpriv->act_chanlist_pos);
583 pcl818_ai_cancel(dev, s);
584 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
585 comedi_event(dev, s);
589 comedi_buf_put(s->async, ptr[bufptr++] >> 4); /* get one sample */
591 devpriv->act_chanlist_pos++;
592 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
593 devpriv->act_chanlist_pos = 0;
595 s->async->cur_chan++;
596 if (s->async->cur_chan >= devpriv->ai_n_chan) {
597 s->async->cur_chan = 0;
598 devpriv->ai_act_scan--;
601 if (!devpriv->neverending_ai)
602 if (devpriv->ai_act_scan == 0) { /* all data sampled */
603 pcl818_ai_cancel(dev, s);
604 s->async->events |= COMEDI_CB_EOA;
605 comedi_event(dev, s);
606 /* printk("done int ai13 dma\n"); */
612 comedi_event(dev, s);
618 ==============================================================================
619 analog input dma mode 1 & 3 over RTC, 818 cards
621 static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
623 struct comedi_device *dev = d;
624 struct comedi_subdevice *s = dev->subdevices + 0;
626 unsigned int top1, top2, i, bufptr;
628 short *dmabuf = (short *)devpriv->dmabuf[0];
631 switch (devpriv->ai_mode) {
632 case INT_TYPE_AI1_DMA_RTC:
633 case INT_TYPE_AI3_DMA_RTC:
634 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
635 mod_timer(&devpriv->rtc_irq_timer,
636 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
638 for (i = 0; i < 10; i++) {
639 top1 = get_dma_residue(devpriv->dma);
640 top2 = get_dma_residue(devpriv->dma);
647 top1 = devpriv->hwdmasize[0] - top1; /* where is now DMA in buffer */
649 ofs_dats = top1 - devpriv->last_top_dma; /* new samples from last call */
651 ofs_dats = (devpriv->dmasamplsize) + ofs_dats;
653 return IRQ_HANDLED; /* exit=no new samples from last call */
655 i = devpriv->last_top_dma - 1;
656 i &= (devpriv->dmasamplsize - 1);
658 if (dmabuf[i] != MAGIC_DMA_WORD) { /* DMA overflow! */
659 comedi_error(dev, "A/D mode1/3 DMA buffer overflow!");
660 /* printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */
661 pcl818_ai_cancel(dev, s);
662 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
663 comedi_event(dev, s);
666 /* printk("r %ld ",ofs_dats); */
668 bufptr = devpriv->last_top_dma;
670 for (i = 0; i < ofs_dats; i++) {
671 if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
673 ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
674 (dmabuf[bufptr] & 0xf),
676 act_chanlist[devpriv->act_chanlist_pos]);
677 pcl818_ai_cancel(dev, s);
679 COMEDI_CB_EOA | COMEDI_CB_ERROR;
680 comedi_event(dev, s);
684 comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); /* get one sample */
685 bufptr &= (devpriv->dmasamplsize - 1);
687 devpriv->act_chanlist_pos++;
688 if (devpriv->act_chanlist_pos >=
689 devpriv->act_chanlist_len) {
690 devpriv->act_chanlist_pos = 0;
692 s->async->cur_chan++;
693 if (s->async->cur_chan >= devpriv->ai_n_chan) {
694 s->async->cur_chan = 0;
695 devpriv->ai_act_scan--;
698 if (!devpriv->neverending_ai)
699 if (devpriv->ai_act_scan == 0) { /* all data sampled */
700 pcl818_ai_cancel(dev, s);
701 s->async->events |= COMEDI_CB_EOA;
702 comedi_event(dev, s);
703 /* printk("done int ai13 dma\n"); */
708 devpriv->last_top_dma = bufptr;
710 bufptr &= (devpriv->dmasamplsize - 1);
711 dmabuf[bufptr] = MAGIC_DMA_WORD;
712 comedi_event(dev, s);
723 ==============================================================================
724 analog input interrupt mode 1 & 3, 818HD/HG cards
726 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
728 struct comedi_device *dev = d;
729 struct comedi_subdevice *s = dev->subdevices + 0;
732 outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */
734 lo = inb(dev->iobase + PCL818_FI_STATUS);
737 comedi_error(dev, "A/D mode1/3 FIFO overflow!");
738 pcl818_ai_cancel(dev, s);
739 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
740 comedi_event(dev, s);
745 comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
746 pcl818_ai_cancel(dev, s);
747 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
748 comedi_event(dev, s);
757 for (i = 0; i < len; i++) {
758 lo = inb(dev->iobase + PCL818_FI_DATALO);
759 if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
761 ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
763 devpriv->act_chanlist[devpriv->act_chanlist_pos]);
764 pcl818_ai_cancel(dev, s);
765 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
766 comedi_event(dev, s);
770 comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); /* get one sample */
772 devpriv->act_chanlist_pos++;
773 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
774 devpriv->act_chanlist_pos = 0;
776 s->async->cur_chan++;
777 if (s->async->cur_chan >= devpriv->ai_n_chan) {
778 s->async->cur_chan = 0;
779 devpriv->ai_act_scan--;
782 if (!devpriv->neverending_ai)
783 if (devpriv->ai_act_scan == 0) { /* all data sampled */
784 pcl818_ai_cancel(dev, s);
785 s->async->events |= COMEDI_CB_EOA;
786 comedi_event(dev, s);
792 comedi_event(dev, s);
797 ==============================================================================
800 static irqreturn_t interrupt_pcl818(int irq, void *d)
802 struct comedi_device *dev = d;
804 if (!dev->attached) {
805 comedi_error(dev, "premature interrupt");
810 if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
811 if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
812 devpriv->ai_act_scan > 0)) &&
813 (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
814 devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
815 /* The cleanup from ai_cancel() has been delayed
816 until now because the card doesn't seem to like
817 being reprogrammed while a DMA transfer is in
820 struct comedi_subdevice *s = dev->subdevices + 0;
821 devpriv->ai_act_scan = 0;
822 devpriv->neverending_ai = 0;
823 pcl818_ai_cancel(dev, s);
826 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
831 switch (devpriv->ai_mode) {
832 case INT_TYPE_AI1_DMA:
833 case INT_TYPE_AI3_DMA:
834 return interrupt_pcl818_ai_mode13_dma(irq, d);
835 case INT_TYPE_AI1_INT:
836 case INT_TYPE_AI3_INT:
837 return interrupt_pcl818_ai_mode13_int(irq, d);
838 case INT_TYPE_AI1_FIFO:
839 case INT_TYPE_AI3_FIFO:
840 return interrupt_pcl818_ai_mode13_fifo(irq, d);
841 #ifdef PCL818_MODE13_AO
842 case INT_TYPE_AO1_INT:
843 case INT_TYPE_AO3_INT:
844 return interrupt_pcl818_ao_mode13_int(irq, d);
850 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
852 if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
853 || (!devpriv->ai_mode)) {
854 comedi_error(dev, "bad IRQ!");
858 comedi_error(dev, "IRQ from unknown source!");
863 ==============================================================================
864 ANALOG INPUT MODE 1 or 3 DMA , 818 cards
866 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
867 struct comedi_subdevice *s)
872 printk("mode13dma_int, mode: %d\n", mode);
873 disable_dma(devpriv->dma); /* disable dma */
874 bytes = devpriv->hwdmasize[0];
875 if (!devpriv->neverending_ai) {
876 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /* how many */
877 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; /* how many DMA pages we must fiil */
878 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; /* on last dma transfer must be moved */
879 devpriv->dma_runs_to_end--;
880 if (devpriv->dma_runs_to_end >= 0)
881 bytes = devpriv->hwdmasize[0];
884 devpriv->next_dma_buf = 0;
885 set_dma_mode(devpriv->dma, DMA_MODE_READ);
886 flags = claim_dma_lock();
887 clear_dma_ff(devpriv->dma);
888 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
889 set_dma_count(devpriv->dma, bytes);
890 release_dma_lock(flags);
891 enable_dma(devpriv->dma);
894 devpriv->ai_mode = INT_TYPE_AI1_DMA;
895 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ+DMA */
897 devpriv->ai_mode = INT_TYPE_AI3_DMA;
898 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */
904 ==============================================================================
905 ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
907 static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
908 struct comedi_subdevice *s)
913 set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
914 flags = claim_dma_lock();
915 clear_dma_ff(devpriv->dma);
916 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
917 set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
918 release_dma_lock(flags);
919 enable_dma(devpriv->dma);
920 devpriv->last_top_dma = 0; /* devpriv->hwdmasize[0]; */
921 pole = (short *)devpriv->dmabuf[0];
922 devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
923 pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
925 devpriv->rtc_freq = rtc_setfreq_irq(2048);
926 devpriv->rtc_irq_timer.expires =
927 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
928 devpriv->rtc_irq_timer.data = (unsigned long)dev;
929 devpriv->rtc_irq_timer.function = rtc_dropped_irq;
931 add_timer(&devpriv->rtc_irq_timer);
935 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
936 outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */
938 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
939 outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */
945 ==============================================================================
946 ANALOG INPUT MODE 1 or 3, 818 cards
948 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
949 struct comedi_subdevice *s)
951 struct comedi_cmd *cmd = &s->async->cmd;
952 int divisor1 = 0, divisor2 = 0;
955 dev_dbg(dev->hw_dev, "pcl818_ai_cmd_mode()\n");
956 if ((!dev->irq) && (!devpriv->dma_rtc)) {
957 comedi_error(dev, "IRQ not defined!");
961 if (devpriv->irq_blocked)
964 start_pacer(dev, -1, 0, 0); /* stop pacer */
966 seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
970 setup_channel_list(dev, s, devpriv->ai_chanlist,
971 devpriv->ai_n_chan, seglen);
975 devpriv->ai_act_scan = devpriv->ai_scans;
976 devpriv->ai_act_chan = 0;
977 devpriv->irq_blocked = 1;
978 devpriv->irq_was_now_closed = 0;
979 devpriv->neverending_ai = 0;
980 devpriv->act_chanlist_pos = 0;
981 devpriv->dma_runs_to_end = 0;
983 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
984 devpriv->neverending_ai = 1; /* well, user want neverending */
987 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
988 &divisor2, &cmd->convert_arg,
990 if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */
1000 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1002 switch (devpriv->dma) {
1005 if (devpriv->dma_rtc == 0) {
1006 pcl818_ai_mode13dma_int(mode, dev, s);
1010 pcl818_ai_mode13dma_rtc(mode, dev, s);
1019 if (!devpriv->usefifo) {
1021 /* printk("IRQ\n"); */
1023 devpriv->ai_mode = INT_TYPE_AI1_INT;
1025 outb(0x83 | (dev->irq << 4),
1026 dev->iobase + PCL818_CONTROL);
1028 devpriv->ai_mode = INT_TYPE_AI3_INT;
1030 outb(0x82 | (dev->irq << 4),
1031 dev->iobase + PCL818_CONTROL);
1036 outb(1, dev->iobase + PCL818_FI_ENABLE);
1038 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1040 outb(0x03, dev->iobase + PCL818_CONTROL);
1042 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1043 outb(0x02, dev->iobase + PCL818_CONTROL);
1048 start_pacer(dev, mode, divisor1, divisor2);
1051 switch (devpriv->ai_mode) {
1052 case INT_TYPE_AI1_DMA_RTC:
1053 case INT_TYPE_AI3_DMA_RTC:
1054 set_rtc_irq_bit(1); /* start RTC */
1058 dev_dbg(dev->hw_dev, "pcl818_ai_cmd_mode() end\n");
1064 ==============================================================================
1065 ANALOG OUTPUT MODE 1 or 3, 818 cards
1067 #ifdef PCL818_MODE13_AO
1068 static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
1069 struct comedi_subdevice *s, comedi_trig * it)
1071 int divisor1 = 0, divisor2 = 0;
1074 comedi_error(dev, "IRQ not defined!");
1078 if (devpriv->irq_blocked)
1081 start_pacer(dev, -1, 0, 0); /* stop pacer */
1083 devpriv->int13_act_scan = it->n;
1084 devpriv->int13_act_chan = 0;
1085 devpriv->irq_blocked = 1;
1086 devpriv->irq_was_now_closed = 0;
1087 devpriv->neverending_ai = 0;
1088 devpriv->act_chanlist_pos = 0;
1091 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1092 &divisor2, &it->trigvar,
1093 TRIG_ROUND_NEAREST);
1094 if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */
1098 if (divisor2 == 1) {
1104 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1106 devpriv->int818_mode = INT_TYPE_AO1_INT;
1107 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */
1109 devpriv->int818_mode = INT_TYPE_AO3_INT;
1110 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */
1113 start_pacer(dev, mode, divisor1, divisor2);
1119 ==============================================================================
1120 ANALOG OUTPUT MODE 1, 818 cards
1122 static int pcl818_ao_mode1(struct comedi_device *dev,
1123 struct comedi_subdevice *s, comedi_trig * it)
1125 return pcl818_ao_mode13(1, dev, s, it);
1129 ==============================================================================
1130 ANALOG OUTPUT MODE 3, 818 cards
1132 static int pcl818_ao_mode3(struct comedi_device *dev,
1133 struct comedi_subdevice *s, comedi_trig * it)
1135 return pcl818_ao_mode13(3, dev, s, it);
1141 ==============================================================================
1142 Start/stop pacer onboard pacer
1144 static void start_pacer(struct comedi_device *dev, int mode,
1145 unsigned int divisor1, unsigned int divisor2)
1147 outb(0xb4, dev->iobase + PCL818_CTRCTL);
1148 outb(0x74, dev->iobase + PCL818_CTRCTL);
1152 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1153 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1154 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1155 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1160 ==============================================================================
1161 Check if channel list from user is builded correctly
1162 If it's ok, then program scan/gain logic
1164 static int check_channel_list(struct comedi_device *dev,
1165 struct comedi_subdevice *s,
1166 unsigned int *chanlist, unsigned int n_chan)
1168 unsigned int chansegment[16];
1169 unsigned int i, nowmustbechan, seglen, segpos;
1171 /* correct channel and range number check itself comedi/range.c */
1173 comedi_error(dev, "range/channel list is empty!");
1178 /* first channel is every time ok */
1179 chansegment[0] = chanlist[0];
1180 /* build part of chanlist */
1181 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1183 /* printk("%d. %d * %d\n",i,
1184 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1186 /* we detect loop, this must by finish */
1188 if (chanlist[0] == chanlist[i])
1191 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1192 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */
1194 ("comedi%d: pcl818: channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
1195 dev->minor, i, CR_CHAN(chanlist[i]),
1196 nowmustbechan, CR_CHAN(chanlist[0]));
1199 /* well, this is next correct channel in list */
1200 chansegment[i] = chanlist[i];
1203 /* check whole chanlist */
1204 for (i = 0, segpos = 0; i < n_chan; i++) {
1205 /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); */
1206 if (chanlist[i] != chansegment[i % seglen]) {
1208 ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1209 dev->minor, i, CR_CHAN(chansegment[i]),
1210 CR_RANGE(chansegment[i]),
1211 CR_AREF(chansegment[i]),
1212 CR_CHAN(chanlist[i % seglen]),
1213 CR_RANGE(chanlist[i % seglen]),
1214 CR_AREF(chansegment[i % seglen]));
1215 return 0; /* chan/gain list is strange */
1221 printk("check_channel_list: seglen %d\n", seglen);
1225 static void setup_channel_list(struct comedi_device *dev,
1226 struct comedi_subdevice *s,
1227 unsigned int *chanlist, unsigned int n_chan,
1228 unsigned int seglen)
1232 devpriv->act_chanlist_len = seglen;
1233 devpriv->act_chanlist_pos = 0;
1235 for (i = 0; i < seglen; i++) { /* store range list to card */
1236 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1237 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX); /* select channel */
1238 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE); /* select gain */
1243 /* select channel interval to scan */
1244 outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1246 dev->iobase + PCL818_MUX);
1250 ==============================================================================
1251 Check if board is switched to SE (1) or DIFF(0) mode
1253 static int check_single_ended(unsigned int port)
1255 if (inb(port + PCL818_STATUS) & 0x20)
1261 ==============================================================================
1263 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1264 struct comedi_cmd *cmd)
1266 const struct pcl818_board *board = comedi_board(dev);
1268 int tmp, divisor1 = 0, divisor2 = 0;
1270 /* step 1: make sure trigger sources are trivially valid */
1272 tmp = cmd->start_src;
1273 cmd->start_src &= TRIG_NOW;
1274 if (!cmd->start_src || tmp != cmd->start_src)
1277 tmp = cmd->scan_begin_src;
1278 cmd->scan_begin_src &= TRIG_FOLLOW;
1279 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1282 tmp = cmd->convert_src;
1283 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1284 if (!cmd->convert_src || tmp != cmd->convert_src)
1287 tmp = cmd->scan_end_src;
1288 cmd->scan_end_src &= TRIG_COUNT;
1289 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1292 tmp = cmd->stop_src;
1293 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1294 if (!cmd->stop_src || tmp != cmd->stop_src)
1300 /* step 2: make sure trigger sources are unique and mutually compatible */
1302 if (cmd->start_src != TRIG_NOW) {
1303 cmd->start_src = TRIG_NOW;
1306 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1307 cmd->scan_begin_src = TRIG_FOLLOW;
1310 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1313 if (cmd->scan_end_src != TRIG_COUNT) {
1314 cmd->scan_end_src = TRIG_COUNT;
1318 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1324 /* step 3: make sure arguments are trivially compatible */
1326 if (cmd->start_arg != 0) {
1331 if (cmd->scan_begin_arg != 0) {
1332 cmd->scan_begin_arg = 0;
1336 if (cmd->convert_src == TRIG_TIMER) {
1337 if (cmd->convert_arg < board->ns_min) {
1338 cmd->convert_arg = board->ns_min;
1341 } else { /* TRIG_EXT */
1342 if (cmd->convert_arg != 0) {
1343 cmd->convert_arg = 0;
1348 if (cmd->scan_end_arg != cmd->chanlist_len) {
1349 cmd->scan_end_arg = cmd->chanlist_len;
1352 if (cmd->stop_src == TRIG_COUNT) {
1353 if (!cmd->stop_arg) {
1357 } else { /* TRIG_NONE */
1358 if (cmd->stop_arg != 0) {
1367 /* step 4: fix up any arguments */
1369 if (cmd->convert_src == TRIG_TIMER) {
1370 tmp = cmd->convert_arg;
1371 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1372 &divisor2, &cmd->convert_arg,
1373 cmd->flags & TRIG_ROUND_MASK);
1374 if (cmd->convert_arg < board->ns_min)
1375 cmd->convert_arg = board->ns_min;
1376 if (tmp != cmd->convert_arg)
1383 /* step 5: complain about special chanlist considerations */
1385 if (cmd->chanlist) {
1386 if (!check_channel_list(dev, s, cmd->chanlist,
1388 return 5; /* incorrect channels list */
1395 ==============================================================================
1397 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1399 struct comedi_cmd *cmd = &s->async->cmd;
1402 dev_dbg(dev->hw_dev, "pcl818_ai_cmd()\n");
1403 devpriv->ai_n_chan = cmd->chanlist_len;
1404 devpriv->ai_chanlist = cmd->chanlist;
1405 devpriv->ai_flags = cmd->flags;
1406 devpriv->ai_data_len = s->async->prealloc_bufsz;
1407 devpriv->ai_data = s->async->prealloc_buf;
1408 devpriv->ai_timer1 = 0;
1409 devpriv->ai_timer2 = 0;
1411 if (cmd->stop_src == TRIG_COUNT)
1412 devpriv->ai_scans = cmd->stop_arg;
1414 devpriv->ai_scans = 0;
1416 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 3 */
1417 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */
1418 devpriv->ai_timer1 = cmd->convert_arg;
1419 retval = pcl818_ai_cmd_mode(1, dev, s);
1420 dev_dbg(dev->hw_dev, "pcl818_ai_cmd() end\n");
1423 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */
1424 return pcl818_ai_cmd_mode(3, dev, s);
1432 ==============================================================================
1433 cancel any mode 1-4 AI
1435 static int pcl818_ai_cancel(struct comedi_device *dev,
1436 struct comedi_subdevice *s)
1438 if (devpriv->irq_blocked > 0) {
1439 dev_dbg(dev->hw_dev, "pcl818_ai_cancel()\n");
1440 devpriv->irq_was_now_closed = 1;
1442 switch (devpriv->ai_mode) {
1444 case INT_TYPE_AI1_DMA_RTC:
1445 case INT_TYPE_AI3_DMA_RTC:
1446 set_rtc_irq_bit(0); /* stop RTC */
1447 del_timer(&devpriv->rtc_irq_timer);
1449 case INT_TYPE_AI1_DMA:
1450 case INT_TYPE_AI3_DMA:
1451 if (devpriv->neverending_ai ||
1452 (!devpriv->neverending_ai &&
1453 devpriv->ai_act_scan > 0)) {
1454 /* wait for running dma transfer to end, do cleanup in interrupt */
1457 disable_dma(devpriv->dma);
1458 case INT_TYPE_AI1_INT:
1459 case INT_TYPE_AI3_INT:
1460 case INT_TYPE_AI1_FIFO:
1461 case INT_TYPE_AI3_FIFO:
1462 #ifdef PCL818_MODE13_AO
1463 case INT_TYPE_AO1_INT:
1464 case INT_TYPE_AO3_INT:
1466 outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL); /* Stop A/D */
1468 start_pacer(dev, -1, 0, 0);
1469 outb(0, dev->iobase + PCL818_AD_LO);
1470 inb(dev->iobase + PCL818_AD_LO);
1471 inb(dev->iobase + PCL818_AD_HI);
1472 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
1473 outb(0, dev->iobase + PCL818_CONTROL); /* Stop A/D */
1474 if (devpriv->usefifo) { /* FIFO shutdown */
1475 outb(0, dev->iobase + PCL818_FI_INTCLR);
1476 outb(0, dev->iobase + PCL818_FI_FLUSH);
1477 outb(0, dev->iobase + PCL818_FI_ENABLE);
1479 devpriv->irq_blocked = 0;
1480 devpriv->last_int_sub = s;
1481 devpriv->neverending_ai = 0;
1482 devpriv->ai_mode = 0;
1483 devpriv->irq_was_now_closed = 0;
1489 dev_dbg(dev->hw_dev, "pcl818_ai_cancel() end\n");
1494 ==============================================================================
1497 static int pcl818_check(unsigned long iobase)
1499 outb(0x00, iobase + PCL818_MUX);
1501 if (inb(iobase + PCL818_MUX) != 0x00)
1502 return 1; /* there isn't card */
1503 outb(0x55, iobase + PCL818_MUX);
1505 if (inb(iobase + PCL818_MUX) != 0x55)
1506 return 1; /* there isn't card */
1507 outb(0x00, iobase + PCL818_MUX);
1509 outb(0x18, iobase + PCL818_CONTROL);
1511 if (inb(iobase + PCL818_CONTROL) != 0x18)
1512 return 1; /* there isn't card */
1513 return 0; /* ok, card exist */
1517 ==============================================================================
1518 reset whole PCL-818 cards
1520 static void pcl818_reset(struct comedi_device *dev)
1522 const struct pcl818_board *board = comedi_board(dev);
1524 if (devpriv->usefifo) { /* FIFO shutdown */
1525 outb(0, dev->iobase + PCL818_FI_INTCLR);
1526 outb(0, dev->iobase + PCL818_FI_FLUSH);
1527 outb(0, dev->iobase + PCL818_FI_ENABLE);
1529 outb(0, dev->iobase + PCL818_DA_LO); /* DAC=0V */
1530 outb(0, dev->iobase + PCL818_DA_HI);
1532 outb(0, dev->iobase + PCL818_DO_HI); /* DO=$0000 */
1533 outb(0, dev->iobase + PCL818_DO_LO);
1535 outb(0, dev->iobase + PCL818_CONTROL);
1536 outb(0, dev->iobase + PCL818_CNTENABLE);
1537 outb(0, dev->iobase + PCL818_MUX);
1538 outb(0, dev->iobase + PCL818_CLRINT);
1539 outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */
1540 outb(0x70, dev->iobase + PCL818_CTRCTL);
1541 outb(0x30, dev->iobase + PCL818_CTRCTL);
1542 if (board->is_818) {
1543 outb(0, dev->iobase + PCL818_RANGE);
1545 outb(0, dev->iobase + PCL718_DA2_LO);
1546 outb(0, dev->iobase + PCL718_DA2_HI);
1552 ==============================================================================
1553 Enable(1)/disable(0) periodic interrupts from RTC
1555 static int set_rtc_irq_bit(unsigned char bit)
1558 unsigned long flags;
1562 if (RTC_timer_lock > 1)
1566 if (RTC_timer_lock < 0)
1568 if (RTC_timer_lock > 0)
1574 val = CMOS_READ(RTC_CONTROL);
1580 CMOS_WRITE(val, RTC_CONTROL);
1581 CMOS_READ(RTC_INTR_FLAGS);
1582 restore_flags(flags);
1587 ==============================================================================
1588 Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1590 static void rtc_dropped_irq(unsigned long data)
1592 struct comedi_device *dev = (void *)data;
1593 unsigned long flags, tmp;
1595 switch (devpriv->int818_mode) {
1596 case INT_TYPE_AI1_DMA_RTC:
1597 case INT_TYPE_AI3_DMA_RTC:
1598 mod_timer(&devpriv->rtc_irq_timer,
1599 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1602 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */
1603 restore_flags(flags);
1609 ==============================================================================
1610 Set frequency of interrupts from RTC
1612 static int rtc_setfreq_irq(int freq)
1617 unsigned long flags;
1624 while (freq > (1 << tmp))
1627 rtc_freq = 1 << tmp;
1631 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1633 CMOS_WRITE(val, RTC_FREQ_SELECT);
1634 restore_flags(flags);
1639 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1641 const struct pcl818_board *board = comedi_board(dev);
1643 unsigned long iobase;
1646 unsigned long pages;
1647 struct comedi_subdevice *s;
1649 ret = alloc_private(dev, sizeof(struct pcl818_private));
1651 return ret; /* Can't alloc mem */
1653 /* claim our I/O space */
1654 iobase = it->options[0];
1656 ("comedi%d: pcl818: board=%s, ioport=0x%03lx",
1657 dev->minor, board->name, iobase);
1658 devpriv->io_range = board->io_range;
1659 if ((board->fifo) && (it->options[2] == -1)) {
1660 /* we've board with FIFO and we want to use FIFO */
1661 devpriv->io_range = PCLx1xFIFO_RANGE;
1662 devpriv->usefifo = 1;
1664 if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1665 comedi_error(dev, "I/O port conflict\n");
1669 dev->iobase = iobase;
1671 if (pcl818_check(iobase)) {
1672 comedi_error(dev, "I can't detect board. FAIL!\n");
1676 dev->board_name = board->name;
1680 if (board->IRQbits != 0) { /* board support IRQ */
1681 irq = it->options[1];
1682 if (irq) { /* we want to use IRQ */
1683 if (((1 << irq) & board->IRQbits) == 0) {
1685 (", IRQ %u is out of allowed range, DISABLING IT",
1687 irq = 0; /* Bad IRQ */
1690 (irq, interrupt_pcl818, 0, "pcl818", dev)) {
1692 (", unable to allocate IRQ %u, DISABLING IT",
1694 irq = 0; /* Can't use IRQ */
1696 printk(KERN_DEBUG "irq=%u", irq);
1704 devpriv->irq_free = 1; /* 1=we have allocated irq */
1706 devpriv->irq_free = 0;
1708 devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */
1709 devpriv->ai_mode = 0; /* mode of irq */
1712 /* grab RTC for DMA operations */
1713 devpriv->dma_rtc = 0;
1714 if (it->options[2] > 0) { /* we want to use DMA */
1715 if (RTC_lock == 0) {
1716 if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1720 devpriv->rtc_iobase = RTC_PORT(0);
1721 devpriv->rtc_iosize = RTC_IO_EXTENT;
1723 if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0,
1724 "pcl818 DMA (RTC)", dev)) {
1725 devpriv->dma_rtc = 1;
1726 devpriv->rtc_irq = RTC_IRQ;
1727 printk(KERN_DEBUG "dma_irq=%u", devpriv->rtc_irq);
1730 if (RTC_lock == 0) {
1731 if (devpriv->rtc_iobase)
1732 release_region(devpriv->rtc_iobase,
1733 devpriv->rtc_iosize);
1735 devpriv->rtc_iobase = 0;
1736 devpriv->rtc_iosize = 0;
1745 if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1746 goto no_dma; /* if we haven't IRQ, we can't use DMA */
1747 if (board->DMAbits != 0) { /* board support DMA */
1748 dma = it->options[2];
1750 goto no_dma; /* DMA disabled */
1751 if (((1 << dma) & board->DMAbits) == 0) {
1752 printk(KERN_ERR "DMA is out of allowed range, FAIL!\n");
1753 return -EINVAL; /* Bad DMA */
1755 ret = request_dma(dma, "pcl818");
1757 return -EBUSY; /* DMA isn't free */
1759 pages = 2; /* we need 16KB */
1760 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1761 if (!devpriv->dmabuf[0])
1762 /* maybe experiment with try_to_free_pages() will help .... */
1763 return -EBUSY; /* no buffer :-( */
1764 devpriv->dmapages[0] = pages;
1765 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1766 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1767 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1768 if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */
1769 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1770 if (!devpriv->dmabuf[1])
1772 devpriv->dmapages[1] = pages;
1773 devpriv->hwdmaptr[1] =
1774 virt_to_bus((void *)devpriv->dmabuf[1]);
1775 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1781 ret = comedi_alloc_subdevices(dev, 4);
1785 s = dev->subdevices + 0;
1786 if (!board->n_aichan_se) {
1787 s->type = COMEDI_SUBD_UNUSED;
1789 s->type = COMEDI_SUBD_AI;
1790 devpriv->sub_ai = s;
1791 s->subdev_flags = SDF_READABLE;
1792 if (check_single_ended(dev->iobase)) {
1793 s->n_chan = board->n_aichan_se;
1794 s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1795 printk(", %dchans S.E. DAC", s->n_chan);
1797 s->n_chan = board->n_aichan_diff;
1798 s->subdev_flags |= SDF_DIFF;
1799 printk(", %dchans DIFF DAC", s->n_chan);
1801 s->maxdata = board->ai_maxdata;
1802 s->len_chanlist = s->n_chan;
1803 s->range_table = board->ai_range_type;
1804 s->cancel = pcl818_ai_cancel;
1805 s->insn_read = pcl818_ai_insn_read;
1806 if ((irq) || (devpriv->dma_rtc)) {
1807 dev->read_subdev = s;
1808 s->subdev_flags |= SDF_CMD_READ;
1809 s->do_cmdtest = ai_cmdtest;
1812 if (board->is_818) {
1813 if ((it->options[4] == 1) || (it->options[4] == 10))
1814 s->range_table = &range_pcl818l_h_ai; /* secondary range list jumper selectable */
1816 switch (it->options[4]) {
1818 s->range_table = &range_bipolar10;
1821 s->range_table = &range_bipolar5;
1824 s->range_table = &range_bipolar2_5;
1827 s->range_table = &range718_bipolar1;
1830 s->range_table = &range718_bipolar0_5;
1833 s->range_table = &range_unipolar10;
1836 s->range_table = &range_unipolar5;
1839 s->range_table = &range718_unipolar2;
1842 s->range_table = &range718_unipolar1;
1845 s->range_table = &range_unknown;
1851 s = dev->subdevices + 1;
1852 if (!board->n_aochan) {
1853 s->type = COMEDI_SUBD_UNUSED;
1855 s->type = COMEDI_SUBD_AO;
1856 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1857 s->n_chan = board->n_aochan;
1858 s->maxdata = board->ao_maxdata;
1859 s->len_chanlist = board->n_aochan;
1860 s->range_table = board->ao_range_type;
1861 s->insn_read = pcl818_ao_insn_read;
1862 s->insn_write = pcl818_ao_insn_write;
1864 #ifdef PCL818_MODE13_AO
1866 s->trig[1] = pcl818_ao_mode1;
1867 s->trig[3] = pcl818_ao_mode3;
1871 if (board->is_818) {
1872 if ((it->options[4] == 1) || (it->options[4] == 10))
1873 s->range_table = &range_unipolar10;
1874 if (it->options[4] == 2)
1875 s->range_table = &range_unknown;
1877 if ((it->options[5] == 1) || (it->options[5] == 10))
1878 s->range_table = &range_unipolar10;
1879 if (it->options[5] == 2)
1880 s->range_table = &range_unknown;
1884 s = dev->subdevices + 2;
1885 if (!board->n_dichan) {
1886 s->type = COMEDI_SUBD_UNUSED;
1888 s->type = COMEDI_SUBD_DI;
1889 s->subdev_flags = SDF_READABLE;
1890 s->n_chan = board->n_dichan;
1892 s->len_chanlist = board->n_dichan;
1893 s->range_table = &range_digital;
1894 s->insn_bits = pcl818_di_insn_bits;
1897 s = dev->subdevices + 3;
1898 if (!board->n_dochan) {
1899 s->type = COMEDI_SUBD_UNUSED;
1901 s->type = COMEDI_SUBD_DO;
1902 s->subdev_flags = SDF_WRITABLE;
1903 s->n_chan = board->n_dochan;
1905 s->len_chanlist = board->n_dochan;
1906 s->range_table = &range_digital;
1907 s->insn_bits = pcl818_do_insn_bits;
1910 /* select 1/10MHz oscilator */
1911 if ((it->options[3] == 0) || (it->options[3] == 10))
1912 devpriv->i8253_osc_base = 100;
1914 devpriv->i8253_osc_base = 1000;
1916 /* max sampling speed */
1917 devpriv->ns_min = board->ns_min;
1919 if (!board->is_818) {
1920 if ((it->options[6] == 1) || (it->options[6] == 100))
1921 devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */
1931 static void pcl818_detach(struct comedi_device *dev)
1934 pcl818_ai_cancel(dev, devpriv->sub_ai);
1937 free_dma(devpriv->dma);
1938 if (devpriv->dmabuf[0])
1939 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1940 if (devpriv->dmabuf[1])
1941 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1943 if (devpriv->rtc_irq)
1944 free_irq(devpriv->rtc_irq, dev);
1945 if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1946 if (devpriv->rtc_iobase)
1947 release_region(devpriv->rtc_iobase,
1948 devpriv->rtc_iosize);
1950 if (devpriv->dma_rtc)
1955 free_irq(dev->irq, dev);
1957 release_region(dev->iobase, devpriv->io_range);
1960 static const struct pcl818_board boardtypes[] = {
1961 {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
1962 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1963 0x0a, 0xfff, 0xfff, 0, 1},
1964 {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1965 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1966 0x0a, 0xfff, 0xfff, 0, 1},
1967 {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1968 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1969 0x0a, 0xfff, 0xfff, 1, 1},
1970 {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
1971 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1972 0x0a, 0xfff, 0xfff, 1, 1},
1973 {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
1974 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1975 0x0a, 0xfff, 0xfff, 0, 1},
1976 {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
1977 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1978 0x0a, 0xfff, 0xfff, 0, 0},
1980 {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
1981 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1982 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
1985 static struct comedi_driver pcl818_driver = {
1986 .driver_name = "pcl818",
1987 .module = THIS_MODULE,
1988 .attach = pcl818_attach,
1989 .detach = pcl818_detach,
1990 .board_name = &boardtypes[0].name,
1991 .num_names = ARRAY_SIZE(boardtypes),
1992 .offset = sizeof(struct pcl818_board),
1994 module_comedi_driver(pcl818_driver);
1996 MODULE_AUTHOR("Comedi http://www.comedi.org");
1997 MODULE_DESCRIPTION("Comedi low-level driver");
1998 MODULE_LICENSE("GPL");