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 unknow (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 unknow (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 unknow (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 unknow (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/delay.h>
110 /* #define PCL818_MODE13_AO 1 */
112 /* boards constants */
114 #define boardPCL818L 0
115 #define boardPCL818H 1
116 #define boardPCL818HD 2
117 #define boardPCL818HG 3
118 #define boardPCL818 4
119 #define boardPCL718 5
122 #define PCLx1x_RANGE 16
123 /* IO space len if we use FIFO */
124 #define PCLx1xFIFO_RANGE 32
126 /* W: clear INT request */
127 #define PCL818_CLRINT 8
128 /* R: return status byte */
129 #define PCL818_STATUS 8
130 /* R: A/D high byte W: A/D range control */
131 #define PCL818_RANGE 1
132 /* R: next mux scan channel W: mux scan channel & range control pointer */
134 /* R/W: operation control register */
135 #define PCL818_CONTROL 9
136 /* W: counter enable */
137 #define PCL818_CNTENABLE 10
139 /* R: low byte of A/D W: soft A/D trigger */
140 #define PCL818_AD_LO 0
141 /* R: high byte of A/D W: A/D range control */
142 #define PCL818_AD_HI 1
143 /* W: D/A low&high byte */
144 #define PCL818_DA_LO 4
145 #define PCL818_DA_HI 5
146 /* R: low&high byte of DI */
147 #define PCL818_DI_LO 3
148 #define PCL818_DI_HI 11
149 /* W: low&high byte of DO */
150 #define PCL818_DO_LO 3
151 #define PCL818_DO_HI 11
152 /* W: PCL718 second D/A */
153 #define PCL718_DA2_LO 6
154 #define PCL718_DA2_HI 7
156 #define PCL818_CTR0 12
157 #define PCL818_CTR1 13
158 #define PCL818_CTR2 14
159 /* W: counter control */
160 #define PCL818_CTRCTL 15
162 /* W: fifo enable/disable */
163 #define PCL818_FI_ENABLE 6
164 /* W: fifo interrupt clear */
165 #define PCL818_FI_INTCLR 20
166 /* W: fifo interrupt clear */
167 #define PCL818_FI_FLUSH 25
169 #define PCL818_FI_STATUS 25
170 /* R: one record from FIFO */
171 #define PCL818_FI_DATALO 23
172 #define PCL818_FI_DATAHI 23
174 /* type of interrupt handler */
175 #define INT_TYPE_AI1_INT 1
176 #define INT_TYPE_AI1_DMA 2
177 #define INT_TYPE_AI1_FIFO 3
178 #define INT_TYPE_AI3_INT 4
179 #define INT_TYPE_AI3_DMA 5
180 #define INT_TYPE_AI3_FIFO 6
181 #ifdef PCL818_MODE13_AO
182 #define INT_TYPE_AO1_INT 7
183 #define INT_TYPE_AO3_INT 8
188 #define INT_TYPE_AI1_DMA_RTC 9
189 #define INT_TYPE_AI3_DMA_RTC 10
192 #define RTC_IO_EXTENT 0x10
195 #define MAGIC_DMA_WORD 0x5a5a
197 static const struct comedi_lrange range_pcl818h_ai = { 9, {
210 static const struct comedi_lrange range_pcl818hg_ai = { 10, {
226 static const struct comedi_lrange range_pcl818l_l_ai = { 4, {
234 static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
242 static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
243 static const struct comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} };
244 static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
245 static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
247 static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it);
248 static int pcl818_detach(struct comedi_device * dev);
251 static int RTC_lock = 0; /* RTC lock */
252 static int RTC_timer_lock = 0; /* 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 alllowed 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 */
277 static const struct pcl818_board boardtypes[] = {
278 {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
279 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
280 0x0a, 0xfff, 0xfff, 0, 1},
281 {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
282 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
283 0x0a, 0xfff, 0xfff, 0, 1},
284 {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
285 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
286 0x0a, 0xfff, 0xfff, 1, 1},
287 {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
288 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
289 0x0a, 0xfff, 0xfff, 1, 1},
290 {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
291 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
292 0x0a, 0xfff, 0xfff, 0, 1},
293 {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
294 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
295 0x0a, 0xfff, 0xfff, 0, 0},
297 {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
298 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
299 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
302 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board))
304 static struct comedi_driver driver_pcl818 = {
305 driver_name:"pcl818",
307 attach:pcl818_attach,
308 detach:pcl818_detach,
309 board_name:&boardtypes[0].name,
310 num_names:n_boardtypes,
311 offset:sizeof(struct pcl818_board),
314 COMEDI_INITCLEANUP(driver_pcl818);
316 struct pcl818_private {
318 unsigned int dma; /* used DMA, 0=don't use DMA */
319 int dma_rtc; /* 1=RTC used with DMA, 0=no RTC alloc */
320 unsigned int io_range;
322 unsigned long rtc_iobase; /* RTC port region */
323 unsigned int rtc_iosize;
324 unsigned int rtc_irq;
325 struct timer_list rtc_irq_timer; /* timer for RTC sanity check */
326 unsigned long rtc_freq; /* RTC int freq */
327 int rtc_irq_blocked; /* 1=we now do AI with DMA&RTC */
329 unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */
330 unsigned int dmapages[2]; /* len of DMA buffers in PAGE_SIZEs */
331 unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */
332 unsigned int hwdmasize[2]; /* len of DMA buffers in Bytes */
333 unsigned int dmasamplsize; /* size in samples hwdmasize[0]/2 */
334 unsigned int last_top_dma; /* DMA pointer in last RTC int */
335 int next_dma_buf; /* which DMA buffer will be used next round */
336 long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */
337 unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */
338 unsigned char neverending_ai; /* if=1, then we do neverending record (you must use cancel()) */
339 unsigned int ns_min; /* manimal alllowed delay between samples (in us) for actual card */
340 int i8253_osc_base; /* 1/frequency of on board oscilator in ns */
341 int irq_free; /* 1=have allocated IRQ */
342 int irq_blocked; /* 1=IRQ now uses any subdev */
343 int irq_was_now_closed; /* when IRQ finish, there's stored int818_mode for last interrupt */
344 int ai_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
345 struct comedi_subdevice *last_int_sub; /* ptr to subdevice which now finish */
346 int ai_act_scan; /* how many scans we finished */
347 int ai_act_chan; /* actual position in actual scan */
348 unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */
349 unsigned int act_chanlist_len; /* how long is actual MUX list */
350 unsigned int act_chanlist_pos; /* actual position in MUX list */
351 unsigned int ai_scans; /* len of scanlist */
352 unsigned int ai_n_chan; /* how many channels is measured */
353 unsigned int *ai_chanlist; /* actaul chanlist */
354 unsigned int ai_flags; /* flaglist */
355 unsigned int ai_data_len; /* len of data buffer */
356 short *ai_data; /* data buffer */
357 unsigned int ai_timer1; /* timers */
358 unsigned int ai_timer2;
359 struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */
360 unsigned char usefifo; /* 1=use fifo */
361 unsigned int ao_readback[2];
365 static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, /* used for gain list programming */
366 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
369 #define devpriv ((struct pcl818_private *)dev->private)
370 #define this_board ((const struct pcl818_board *)dev->board_ptr)
373 ==============================================================================
375 static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
376 unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
377 static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
378 unsigned int *chanlist, unsigned int n_chan);
380 static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
381 static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
382 unsigned int divisor2);
385 static int set_rtc_irq_bit(unsigned char bit);
386 static void rtc_dropped_irq(unsigned long data);
387 static int rtc_setfreq_irq(int freq);
391 ==============================================================================
392 ANALOG INPUT MODE0, 818 cards, slow version
394 static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
395 struct comedi_insn * insn, unsigned int * data)
400 /* software trigger, DMA and INT off */
401 outb(0, dev->iobase + PCL818_CONTROL);
404 outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX);
407 outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE);
409 for (n = 0; n < insn->n; n++) {
411 /* clear INT (conversion end) flag */
412 outb(0, dev->iobase + PCL818_CLRINT);
414 /* start conversion */
415 outb(0, dev->iobase + PCL818_AD_LO);
419 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
423 comedi_error(dev, "A/D insn timeout");
424 /* clear INT (conversion end) flag */
425 outb(0, dev->iobase + PCL818_CLRINT);
429 data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
430 (inb(dev->iobase + PCL818_AD_LO) >> 4));
437 ==============================================================================
438 ANALOG OUTPUT MODE0, 818 cards
439 only one sample per call is supported
441 static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
442 struct comedi_insn * insn, unsigned int * data)
445 int chan = CR_CHAN(insn->chanspec);
447 for (n = 0; n < insn->n; n++) {
448 data[n] = devpriv->ao_readback[chan];
454 static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
455 struct comedi_insn * insn, unsigned int * data)
458 int chan = CR_CHAN(insn->chanspec);
460 for (n = 0; n < insn->n; n++) {
461 devpriv->ao_readback[chan] = data[n];
462 outb((data[n] & 0x000f) << 4, dev->iobase +
463 (chan) ? PCL718_DA2_LO : PCL818_DA_LO);
464 outb((data[n] & 0x0ff0) >> 4, dev->iobase +
465 (chan) ? PCL718_DA2_HI : PCL818_DA_HI);
472 ==============================================================================
473 DIGITAL INPUT MODE0, 818 cards
475 only one sample per call is supported
477 static int pcl818_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
478 struct comedi_insn * insn, unsigned int * data)
483 data[1] = inb(dev->iobase + PCL818_DI_LO) |
484 (inb(dev->iobase + PCL818_DI_HI) << 8);
490 ==============================================================================
491 DIGITAL OUTPUT MODE0, 818 cards
493 only one sample per call is supported
495 static int pcl818_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
496 struct comedi_insn * insn, unsigned int * data)
501 s->state &= ~data[0];
502 s->state |= (data[0] & data[1]);
504 outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
505 outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
513 ==============================================================================
514 analog input interrupt mode 1 & 3, 818 cards
515 one sample per interrupt version
517 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
519 struct comedi_device *dev = d;
520 struct comedi_subdevice *s = dev->subdevices + 0;
522 int timeout = 50; /* wait max 50us */
525 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
529 outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */
530 comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
531 pcl818_ai_cancel(dev, s);
532 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
533 comedi_event(dev, s);
537 low = inb(dev->iobase + PCL818_AD_LO);
538 comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4))); /* get one sample */
539 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
541 if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
543 ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
545 devpriv->act_chanlist[devpriv->act_chanlist_pos]);
546 pcl818_ai_cancel(dev, s);
547 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
548 comedi_event(dev, s);
551 if (s->async->cur_chan == 0) {
552 /* rt_printk("E"); */
553 devpriv->ai_act_scan--;
556 if (!devpriv->neverending_ai) {
557 if (devpriv->ai_act_scan == 0) { /* all data sampled */
558 pcl818_ai_cancel(dev, s);
559 s->async->events |= COMEDI_CB_EOA;
562 comedi_event(dev, s);
567 ==============================================================================
568 analog input dma mode 1 & 3, 818 cards
570 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
572 struct comedi_device *dev = d;
573 struct comedi_subdevice *s = dev->subdevices + 0;
578 disable_dma(devpriv->dma);
579 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
580 if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) { /* switch dma bufs */
581 set_dma_mode(devpriv->dma, DMA_MODE_READ);
582 flags = claim_dma_lock();
583 set_dma_addr(devpriv->dma,
584 devpriv->hwdmaptr[devpriv->next_dma_buf]);
585 if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
586 set_dma_count(devpriv->dma,
587 devpriv->hwdmasize[devpriv->next_dma_buf]);
589 set_dma_count(devpriv->dma, devpriv->last_dma_run);
591 release_dma_lock(flags);
592 enable_dma(devpriv->dma);
594 rt_printk("comedi: A/D mode1/3 IRQ \n");
596 devpriv->dma_runs_to_end--;
597 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
598 ptr = (short *) devpriv->dmabuf[1 - devpriv->next_dma_buf];
600 len = devpriv->hwdmasize[0] >> 1;
603 for (i = 0; i < len; i++) {
604 if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
606 ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
608 devpriv->act_chanlist[devpriv->
610 devpriv->act_chanlist_pos);
611 pcl818_ai_cancel(dev, s);
612 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
613 comedi_event(dev, s);
617 comedi_buf_put(s->async, ptr[bufptr++] >> 4); /* get one sample */
619 devpriv->act_chanlist_pos++;
620 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
621 devpriv->ai_act_scan--;
622 devpriv->act_chanlist_pos = 0;
625 if (!devpriv->neverending_ai)
626 if (devpriv->ai_act_scan == 0) { /* all data sampled */
627 pcl818_ai_cancel(dev, s);
628 s->async->events |= COMEDI_CB_EOA;
629 comedi_event(dev, s);
630 /* printk("done int ai13 dma\n"); */
636 comedi_event(dev, s);
642 ==============================================================================
643 analog input dma mode 1 & 3 over RTC, 818 cards
645 static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
647 struct comedi_device *dev = d;
648 struct comedi_subdevice *s = dev->subdevices + 0;
650 unsigned int top1, top2, i, bufptr;
652 short *dmabuf = (short *) devpriv->dmabuf[0];
655 switch (devpriv->ai_mode) {
656 case INT_TYPE_AI1_DMA_RTC:
657 case INT_TYPE_AI3_DMA_RTC:
658 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
659 mod_timer(&devpriv->rtc_irq_timer,
660 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
662 for (i = 0; i < 10; i++) {
663 top1 = get_dma_residue(devpriv->dma);
664 top2 = get_dma_residue(devpriv->dma);
671 top1 = devpriv->hwdmasize[0] - top1; /* where is now DMA in buffer */
673 ofs_dats = top1 - devpriv->last_top_dma; /* new samples from last call */
675 ofs_dats = (devpriv->dmasamplsize) + ofs_dats;
677 return IRQ_HANDLED; /* exit=no new samples from last call */
679 i = devpriv->last_top_dma - 1;
680 i &= (devpriv->dmasamplsize - 1);
682 if (dmabuf[i] != MAGIC_DMA_WORD) { /* DMA overflow! */
683 comedi_error(dev, "A/D mode1/3 DMA buffer overflow!");
684 /* rt_printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */
685 pcl818_ai_cancel(dev, s);
686 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
687 comedi_event(dev, s);
690 /* rt_printk("r %ld ",ofs_dats); */
692 bufptr = devpriv->last_top_dma;
694 for (i = 0; i < ofs_dats; i++) {
695 if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
697 ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
698 (dmabuf[bufptr] & 0xf),
699 devpriv->act_chanlist[devpriv->
701 pcl818_ai_cancel(dev, s);
703 COMEDI_CB_EOA | COMEDI_CB_ERROR;
704 comedi_event(dev, s);
708 comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); /* get one sample */
709 bufptr &= (devpriv->dmasamplsize - 1);
711 if (s->async->cur_chan == 0) {
712 devpriv->ai_act_scan--;
715 if (!devpriv->neverending_ai)
716 if (devpriv->ai_act_scan == 0) { /* all data sampled */
717 pcl818_ai_cancel(dev, s);
718 s->async->events |= COMEDI_CB_EOA;
719 comedi_event(dev, s);
720 /* printk("done int ai13 dma\n"); */
725 devpriv->last_top_dma = bufptr;
727 bufptr &= (devpriv->dmasamplsize - 1);
728 dmabuf[bufptr] = MAGIC_DMA_WORD;
729 comedi_event(dev, s);
740 ==============================================================================
741 analog input interrupt mode 1 & 3, 818HD/HG cards
743 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
745 struct comedi_device *dev = d;
746 struct comedi_subdevice *s = dev->subdevices + 0;
749 outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */
751 lo = inb(dev->iobase + PCL818_FI_STATUS);
754 comedi_error(dev, "A/D mode1/3 FIFO overflow!");
755 pcl818_ai_cancel(dev, s);
756 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
757 comedi_event(dev, s);
762 comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
763 pcl818_ai_cancel(dev, s);
764 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
765 comedi_event(dev, s);
775 for (i = 0; i < len; i++) {
776 lo = inb(dev->iobase + PCL818_FI_DATALO);
777 if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
779 ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
781 devpriv->act_chanlist[devpriv->
783 pcl818_ai_cancel(dev, s);
784 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
785 comedi_event(dev, s);
789 comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); /* get one sample */
791 if (s->async->cur_chan == 0) {
792 devpriv->ai_act_scan--;
795 if (!devpriv->neverending_ai)
796 if (devpriv->ai_act_scan == 0) { /* all data sampled */
797 pcl818_ai_cancel(dev, s);
798 s->async->events |= COMEDI_CB_EOA;
799 comedi_event(dev, s);
805 comedi_event(dev, s);
810 ==============================================================================
813 static irqreturn_t interrupt_pcl818(int irq, void *d)
815 struct comedi_device *dev = d;
817 if (!dev->attached) {
818 comedi_error(dev, "premature interrupt");
821 /* rt_printk("I\n"); */
823 if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
824 if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
825 devpriv->ai_act_scan > 0)) &&
826 (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
827 devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
828 /* The cleanup from ai_cancel() has been delayed
829 until now because the card doesn't seem to like
830 being reprogrammed while a DMA transfer is in
833 struct comedi_subdevice *s = dev->subdevices + 0;
834 devpriv->ai_act_scan = 0;
835 devpriv->neverending_ai = 0;
836 pcl818_ai_cancel(dev, s);
839 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
844 switch (devpriv->ai_mode) {
845 case INT_TYPE_AI1_DMA:
846 case INT_TYPE_AI3_DMA:
847 return interrupt_pcl818_ai_mode13_dma(irq, d);
848 case INT_TYPE_AI1_INT:
849 case INT_TYPE_AI3_INT:
850 return interrupt_pcl818_ai_mode13_int(irq, d);
851 case INT_TYPE_AI1_FIFO:
852 case INT_TYPE_AI3_FIFO:
853 return interrupt_pcl818_ai_mode13_fifo(irq, d);
854 #ifdef PCL818_MODE13_AO
855 case INT_TYPE_AO1_INT:
856 case INT_TYPE_AO3_INT:
857 return interrupt_pcl818_ao_mode13_int(irq, d);
863 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
865 if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
866 || (!devpriv->ai_mode)) {
867 comedi_error(dev, "bad IRQ!");
871 comedi_error(dev, "IRQ from unknow source!");
876 ==============================================================================
877 ANALOG INPUT MODE 1 or 3 DMA , 818 cards
879 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
880 struct comedi_subdevice * s)
885 rt_printk("mode13dma_int, mode: %d\n", mode);
886 disable_dma(devpriv->dma); /* disable dma */
887 bytes = devpriv->hwdmasize[0];
888 if (!devpriv->neverending_ai) {
889 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /* how many */
890 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; /* how many DMA pages we must fiil */
891 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; /* on last dma transfer must be moved */
892 devpriv->dma_runs_to_end--;
893 if (devpriv->dma_runs_to_end >= 0)
894 bytes = devpriv->hwdmasize[0];
897 devpriv->next_dma_buf = 0;
898 set_dma_mode(devpriv->dma, DMA_MODE_READ);
899 flags = claim_dma_lock();
900 clear_dma_ff(devpriv->dma);
901 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
902 set_dma_count(devpriv->dma, bytes);
903 release_dma_lock(flags);
904 enable_dma(devpriv->dma);
907 devpriv->ai_mode = INT_TYPE_AI1_DMA;
908 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ+DMA */
910 devpriv->ai_mode = INT_TYPE_AI3_DMA;
911 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */
917 ==============================================================================
918 ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
920 static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
921 struct comedi_subdevice * s)
926 set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
927 flags = claim_dma_lock();
928 clear_dma_ff(devpriv->dma);
929 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
930 set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
931 release_dma_lock(flags);
932 enable_dma(devpriv->dma);
933 devpriv->last_top_dma = 0; /* devpriv->hwdmasize[0]; */
934 pole = (short *) devpriv->dmabuf[0];
935 devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
936 pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
938 devpriv->rtc_freq = rtc_setfreq_irq(2048);
939 devpriv->rtc_irq_timer.expires =
940 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
941 devpriv->rtc_irq_timer.data = (unsigned long)dev;
942 devpriv->rtc_irq_timer.function = rtc_dropped_irq;
944 add_timer(&devpriv->rtc_irq_timer);
948 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
949 outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */
951 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
952 outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */
958 ==============================================================================
959 ANALOG INPUT MODE 1 or 3, 818 cards
961 static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
962 struct comedi_subdevice * s)
964 struct comedi_cmd *cmd = &s->async->cmd;
965 int divisor1, divisor2;
968 rt_printk("pcl818_ai_cmd_mode()\n");
969 if ((!dev->irq) && (!devpriv->dma_rtc)) {
970 comedi_error(dev, "IRQ not defined!");
974 if (devpriv->irq_blocked)
977 start_pacer(dev, -1, 0, 0); /* stop pacer */
979 seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
983 setup_channel_list(dev, s, devpriv->ai_chanlist,
984 devpriv->ai_n_chan, seglen);
988 devpriv->ai_act_scan = devpriv->ai_scans;
989 devpriv->ai_act_chan = 0;
990 devpriv->irq_blocked = 1;
991 devpriv->irq_was_now_closed = 0;
992 devpriv->neverending_ai = 0;
993 devpriv->act_chanlist_pos = 0;
994 devpriv->dma_runs_to_end = 0;
996 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
997 devpriv->neverending_ai = 1; /* well, user want neverending */
1000 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1001 &divisor2, &cmd->convert_arg, TRIG_ROUND_NEAREST);
1002 if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */
1006 if (divisor2 == 1) {
1012 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1014 switch (devpriv->dma) {
1017 if (devpriv->dma_rtc == 0) {
1018 pcl818_ai_mode13dma_int(mode, dev, s);
1022 pcl818_ai_mode13dma_rtc(mode, dev, s);
1031 if (!devpriv->usefifo) {
1033 /* rt_printk("IRQ\n"); */
1035 devpriv->ai_mode = INT_TYPE_AI1_INT;
1037 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);
1039 devpriv->ai_mode = INT_TYPE_AI3_INT;
1041 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);
1046 outb(1, dev->iobase + PCL818_FI_ENABLE);
1048 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1050 outb(0x03, dev->iobase + PCL818_CONTROL);
1052 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1053 outb(0x02, dev->iobase + PCL818_CONTROL);
1058 start_pacer(dev, mode, divisor1, divisor2);
1061 switch (devpriv->ai_mode) {
1062 case INT_TYPE_AI1_DMA_RTC:
1063 case INT_TYPE_AI3_DMA_RTC:
1064 set_rtc_irq_bit(1); /* start RTC */
1068 rt_printk("pcl818_ai_cmd_mode() end\n");
1074 ==============================================================================
1075 ANALOG OUTPUT MODE 1 or 3, 818 cards
1077 #ifdef PCL818_MODE13_AO
1078 static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_subdevice * s,
1081 int divisor1, divisor2;
1084 comedi_error(dev, "IRQ not defined!");
1088 if (devpriv->irq_blocked)
1091 start_pacer(dev, -1, 0, 0); /* stop pacer */
1093 devpriv->int13_act_scan = it->n;
1094 devpriv->int13_act_chan = 0;
1095 devpriv->irq_blocked = 1;
1096 devpriv->irq_was_now_closed = 0;
1097 devpriv->neverending_ai = 0;
1098 devpriv->act_chanlist_pos = 0;
1101 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1102 &divisor2, &it->trigvar, TRIG_ROUND_NEAREST);
1103 if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */
1107 if (divisor2 == 1) {
1113 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1115 devpriv->int818_mode = INT_TYPE_AO1_INT;
1116 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */
1118 devpriv->int818_mode = INT_TYPE_AO3_INT;
1119 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */
1122 start_pacer(dev, mode, divisor1, divisor2);
1128 ==============================================================================
1129 ANALOG OUTPUT MODE 1, 818 cards
1131 static int pcl818_ao_mode1(struct comedi_device * dev, struct comedi_subdevice * s,
1134 return pcl818_ao_mode13(1, dev, s, it);
1138 ==============================================================================
1139 ANALOG OUTPUT MODE 3, 818 cards
1141 static int pcl818_ao_mode3(struct comedi_device * dev, struct comedi_subdevice * s,
1144 return pcl818_ao_mode13(3, dev, s, it);
1150 ==============================================================================
1151 Start/stop pacer onboard pacer
1153 static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
1154 unsigned int divisor2)
1156 outb(0xb4, dev->iobase + PCL818_CTRCTL);
1157 outb(0x74, dev->iobase + PCL818_CTRCTL);
1161 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1162 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1163 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1164 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1169 ==============================================================================
1170 Check if channel list from user is builded correctly
1171 If it's ok, then program scan/gain logic
1173 static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
1174 unsigned int *chanlist, unsigned int n_chan)
1176 unsigned int chansegment[16];
1177 unsigned int i, nowmustbechan, seglen, segpos;
1179 /* correct channel and range number check itself comedi/range.c */
1181 comedi_error(dev, "range/channel list is empty!");
1186 /* first channel is everytime ok */
1187 chansegment[0] = chanlist[0];
1188 /* build part of chanlist */
1189 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1191 /* rt_printk("%d. %d * %d\n",i,
1192 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1194 /* we detect loop, this must by finish */
1196 if (chanlist[0] == chanlist[i])
1199 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1200 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */
1202 ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1203 dev->minor, i, CR_CHAN(chanlist[i]),
1204 nowmustbechan, CR_CHAN(chanlist[0]));
1207 /* well, this is next correct channel in list */
1208 chansegment[i] = chanlist[i];
1211 /* check whole chanlist */
1212 for (i = 0, segpos = 0; i < n_chan; i++) {
1213 /* rt_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])); */
1214 if (chanlist[i] != chansegment[i % seglen]) {
1216 ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1217 dev->minor, i, CR_CHAN(chansegment[i]),
1218 CR_RANGE(chansegment[i]),
1219 CR_AREF(chansegment[i]),
1220 CR_CHAN(chanlist[i % seglen]),
1221 CR_RANGE(chanlist[i % seglen]),
1222 CR_AREF(chansegment[i % seglen]));
1223 return 0; /* chan/gain list is strange */
1229 rt_printk("check_channel_list: seglen %d\n", seglen);
1233 static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
1234 unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
1238 devpriv->act_chanlist_len = seglen;
1239 devpriv->act_chanlist_pos = 0;
1241 for (i = 0; i < seglen; i++) { /* store range list to card */
1242 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1243 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX); /* select channel */
1244 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE); /* select gain */
1249 /* select channel interval to scan */
1250 outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1251 1] << 4), dev->iobase + PCL818_MUX);
1255 ==============================================================================
1256 Check if board is switched to SE (1) or DIFF(0) mode
1258 static int check_single_ended(unsigned int port)
1260 if (inb(port + PCL818_STATUS) & 0x20) {
1268 ==============================================================================
1270 static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
1271 struct comedi_cmd * cmd)
1274 int tmp, divisor1, divisor2;
1276 /* step 1: make sure trigger sources are trivially valid */
1278 tmp = cmd->start_src;
1279 cmd->start_src &= TRIG_NOW;
1280 if (!cmd->start_src || tmp != cmd->start_src)
1283 tmp = cmd->scan_begin_src;
1284 cmd->scan_begin_src &= TRIG_FOLLOW;
1285 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1288 tmp = cmd->convert_src;
1289 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1290 if (!cmd->convert_src || tmp != cmd->convert_src)
1293 tmp = cmd->scan_end_src;
1294 cmd->scan_end_src &= TRIG_COUNT;
1295 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1298 tmp = cmd->stop_src;
1299 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1300 if (!cmd->stop_src || tmp != cmd->stop_src)
1307 /* step 2: make sure trigger sources are unique and mutually compatible */
1309 if (cmd->start_src != TRIG_NOW) {
1310 cmd->start_src = TRIG_NOW;
1313 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1314 cmd->scan_begin_src = TRIG_FOLLOW;
1317 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1320 if (cmd->scan_end_src != TRIG_COUNT) {
1321 cmd->scan_end_src = TRIG_COUNT;
1325 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1332 /* step 3: make sure arguments are trivially compatible */
1334 if (cmd->start_arg != 0) {
1339 if (cmd->scan_begin_arg != 0) {
1340 cmd->scan_begin_arg = 0;
1344 if (cmd->convert_src == TRIG_TIMER) {
1345 if (cmd->convert_arg < this_board->ns_min) {
1346 cmd->convert_arg = this_board->ns_min;
1349 } else { /* TRIG_EXT */
1350 if (cmd->convert_arg != 0) {
1351 cmd->convert_arg = 0;
1356 if (!cmd->chanlist_len) {
1357 cmd->chanlist_len = 1;
1360 if (cmd->chanlist_len > s->n_chan) {
1361 cmd->chanlist_len = s->n_chan;
1364 if (cmd->scan_end_arg != cmd->chanlist_len) {
1365 cmd->scan_end_arg = cmd->chanlist_len;
1368 if (cmd->stop_src == TRIG_COUNT) {
1369 if (!cmd->stop_arg) {
1373 } else { /* TRIG_NONE */
1374 if (cmd->stop_arg != 0) {
1384 /* step 4: fix up any arguments */
1386 if (cmd->convert_src == TRIG_TIMER) {
1387 tmp = cmd->convert_arg;
1388 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1389 &divisor2, &cmd->convert_arg,
1390 cmd->flags & TRIG_ROUND_MASK);
1391 if (cmd->convert_arg < this_board->ns_min)
1392 cmd->convert_arg = this_board->ns_min;
1393 if (tmp != cmd->convert_arg)
1401 /* step 5: complain about special chanlist considerations */
1403 if (cmd->chanlist) {
1404 if (!check_channel_list(dev, s, cmd->chanlist,
1406 return 5; /* incorrect channels list */
1413 ==============================================================================
1415 static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
1417 struct comedi_cmd *cmd = &s->async->cmd;
1420 rt_printk("pcl818_ai_cmd()\n");
1421 devpriv->ai_n_chan = cmd->chanlist_len;
1422 devpriv->ai_chanlist = cmd->chanlist;
1423 devpriv->ai_flags = cmd->flags;
1424 devpriv->ai_data_len = s->async->prealloc_bufsz;
1425 devpriv->ai_data = s->async->prealloc_buf;
1426 devpriv->ai_timer1 = 0;
1427 devpriv->ai_timer2 = 0;
1429 if (cmd->stop_src == TRIG_COUNT) {
1430 devpriv->ai_scans = cmd->stop_arg;
1432 devpriv->ai_scans = 0;
1435 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 3 */
1436 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */
1437 devpriv->ai_timer1 = cmd->convert_arg;
1438 retval = pcl818_ai_cmd_mode(1, dev, s);
1439 rt_printk("pcl818_ai_cmd() end\n");
1442 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */
1443 return pcl818_ai_cmd_mode(3, dev, s);
1451 ==============================================================================
1452 cancel any mode 1-4 AI
1454 static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
1456 if (devpriv->irq_blocked > 0) {
1457 rt_printk("pcl818_ai_cancel()\n");
1458 devpriv->irq_was_now_closed = 1;
1460 switch (devpriv->ai_mode) {
1462 case INT_TYPE_AI1_DMA_RTC:
1463 case INT_TYPE_AI3_DMA_RTC:
1464 set_rtc_irq_bit(0); /* stop RTC */
1465 del_timer(&devpriv->rtc_irq_timer);
1467 case INT_TYPE_AI1_DMA:
1468 case INT_TYPE_AI3_DMA:
1469 if (devpriv->neverending_ai ||
1470 (!devpriv->neverending_ai &&
1471 devpriv->ai_act_scan > 0)) {
1472 /* wait for running dma transfer to end, do cleanup in interrupt */
1475 disable_dma(devpriv->dma);
1476 case INT_TYPE_AI1_INT:
1477 case INT_TYPE_AI3_INT:
1478 case INT_TYPE_AI1_FIFO:
1479 case INT_TYPE_AI3_FIFO:
1480 #ifdef PCL818_MODE13_AO
1481 case INT_TYPE_AO1_INT:
1482 case INT_TYPE_AO3_INT:
1484 outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL); /* Stop A/D */
1486 start_pacer(dev, -1, 0, 0);
1487 outb(0, dev->iobase + PCL818_AD_LO);
1488 inb(dev->iobase + PCL818_AD_LO);
1489 inb(dev->iobase + PCL818_AD_HI);
1490 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
1491 outb(0, dev->iobase + PCL818_CONTROL); /* Stop A/D */
1492 if (devpriv->usefifo) { /* FIFO shutdown */
1493 outb(0, dev->iobase + PCL818_FI_INTCLR);
1494 outb(0, dev->iobase + PCL818_FI_FLUSH);
1495 outb(0, dev->iobase + PCL818_FI_ENABLE);
1497 devpriv->irq_blocked = 0;
1498 devpriv->last_int_sub = s;
1499 devpriv->neverending_ai = 0;
1500 devpriv->ai_mode = 0;
1501 devpriv->irq_was_now_closed = 0;
1507 rt_printk("pcl818_ai_cancel() end\n");
1512 ==============================================================================
1515 static int pcl818_check(unsigned long iobase)
1517 outb(0x00, iobase + PCL818_MUX);
1519 if (inb(iobase + PCL818_MUX) != 0x00)
1520 return 1; /* there isn't card */
1521 outb(0x55, iobase + PCL818_MUX);
1523 if (inb(iobase + PCL818_MUX) != 0x55)
1524 return 1; /* there isn't card */
1525 outb(0x00, iobase + PCL818_MUX);
1527 outb(0x18, iobase + PCL818_CONTROL);
1529 if (inb(iobase + PCL818_CONTROL) != 0x18)
1530 return 1; /* there isn't card */
1531 return 0; /* ok, card exist */
1535 ==============================================================================
1536 reset whole PCL-818 cards
1538 static void pcl818_reset(struct comedi_device * dev)
1540 if (devpriv->usefifo) { /* FIFO shutdown */
1541 outb(0, dev->iobase + PCL818_FI_INTCLR);
1542 outb(0, dev->iobase + PCL818_FI_FLUSH);
1543 outb(0, dev->iobase + PCL818_FI_ENABLE);
1545 outb(0, dev->iobase + PCL818_DA_LO); /* DAC=0V */
1546 outb(0, dev->iobase + PCL818_DA_HI);
1548 outb(0, dev->iobase + PCL818_DO_HI); /* DO=$0000 */
1549 outb(0, dev->iobase + PCL818_DO_LO);
1551 outb(0, dev->iobase + PCL818_CONTROL);
1552 outb(0, dev->iobase + PCL818_CNTENABLE);
1553 outb(0, dev->iobase + PCL818_MUX);
1554 outb(0, dev->iobase + PCL818_CLRINT);
1555 outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */
1556 outb(0x70, dev->iobase + PCL818_CTRCTL);
1557 outb(0x30, dev->iobase + PCL818_CTRCTL);
1558 if (this_board->is_818) {
1559 outb(0, dev->iobase + PCL818_RANGE);
1561 outb(0, dev->iobase + PCL718_DA2_LO);
1562 outb(0, dev->iobase + PCL718_DA2_HI);
1568 ==============================================================================
1569 Enable(1)/disable(0) periodic interrupts from RTC
1571 static int set_rtc_irq_bit(unsigned char bit)
1574 unsigned long flags;
1578 if (RTC_timer_lock > 1)
1582 if (RTC_timer_lock < 0)
1584 if (RTC_timer_lock > 0)
1590 val = CMOS_READ(RTC_CONTROL);
1596 CMOS_WRITE(val, RTC_CONTROL);
1597 CMOS_READ(RTC_INTR_FLAGS);
1598 restore_flags(flags);
1603 ==============================================================================
1604 Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1606 static void rtc_dropped_irq(unsigned long data)
1608 struct comedi_device *dev = (void *)data;
1609 unsigned long flags, tmp;
1611 switch (devpriv->int818_mode) {
1612 case INT_TYPE_AI1_DMA_RTC:
1613 case INT_TYPE_AI3_DMA_RTC:
1614 mod_timer(&devpriv->rtc_irq_timer,
1615 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1618 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */
1619 restore_flags(flags);
1625 ==============================================================================
1626 Set frequency of interrupts from RTC
1628 static int rtc_setfreq_irq(int freq)
1633 unsigned long flags;
1640 while (freq > (1 << tmp))
1643 rtc_freq = 1 << tmp;
1647 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1649 CMOS_WRITE(val, RTC_FREQ_SELECT);
1650 restore_flags(flags);
1656 ==============================================================================
1657 Free any resources that we have claimed
1659 static void free_resources(struct comedi_device * dev)
1661 /* rt_printk("free_resource()\n"); */
1663 pcl818_ai_cancel(dev, devpriv->sub_ai);
1666 free_dma(devpriv->dma);
1667 if (devpriv->dmabuf[0])
1668 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1669 if (devpriv->dmabuf[1])
1670 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1672 if (devpriv->rtc_irq)
1673 comedi_free_irq(devpriv->rtc_irq, dev);
1674 if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1675 if (devpriv->rtc_iobase)
1676 release_region(devpriv->rtc_iobase,
1677 devpriv->rtc_iosize);
1679 if (devpriv->dma_rtc)
1685 free_irq(dev->irq, dev);
1687 release_region(dev->iobase, devpriv->io_range);
1688 /* rt_printk("free_resource() end\n"); */
1692 ==============================================================================
1697 static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it)
1700 unsigned long iobase;
1703 unsigned long pages;
1704 struct comedi_subdevice *s;
1706 if ((ret = alloc_private(dev, sizeof(struct pcl818_private))) < 0)
1707 return ret; /* Can't alloc mem */
1709 /* claim our I/O space */
1710 iobase = it->options[0];
1711 printk("comedi%d: pcl818: board=%s, ioport=0x%03lx",
1712 dev->minor, this_board->name, iobase);
1713 devpriv->io_range = this_board->io_range;
1714 if ((this_board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */
1715 devpriv->io_range = PCLx1xFIFO_RANGE;
1716 devpriv->usefifo = 1;
1718 if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1719 rt_printk("I/O port conflict\n");
1723 dev->iobase = iobase;
1725 if (pcl818_check(iobase)) {
1726 rt_printk(", I can't detect board. FAIL!\n");
1730 /* set up some name stuff */
1731 dev->board_name = this_board->name;
1734 if (this_board->IRQbits != 0) { /* board support IRQ */
1735 irq = it->options[1];
1736 if (irq) { /* we want to use IRQ */
1737 if (((1 << irq) & this_board->IRQbits) == 0) {
1739 (", IRQ %u is out of allowed range, DISABLING IT",
1741 irq = 0; /* Bad IRQ */
1743 if (comedi_request_irq(irq, interrupt_pcl818, 0,
1746 (", unable to allocate IRQ %u, DISABLING IT",
1748 irq = 0; /* Can't use IRQ */
1750 rt_printk(", irq=%u", irq);
1758 devpriv->irq_free = 1;
1759 } /* 1=we have allocated irq */
1761 devpriv->irq_free = 0;
1763 devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */
1764 devpriv->ai_mode = 0; /* mode of irq */
1767 /* grab RTC for DMA operations */
1768 devpriv->dma_rtc = 0;
1769 if (it->options[2] > 0) { /* we want to use DMA */
1770 if (RTC_lock == 0) {
1771 if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1775 devpriv->rtc_iobase = RTC_PORT(0);
1776 devpriv->rtc_iosize = RTC_IO_EXTENT;
1778 if (!comedi_request_irq(RTC_IRQ,
1779 interrupt_pcl818_ai_mode13_dma_rtc, 0,
1780 "pcl818 DMA (RTC)", dev)) {
1781 devpriv->dma_rtc = 1;
1782 devpriv->rtc_irq = RTC_IRQ;
1783 rt_printk(", dma_irq=%u", devpriv->rtc_irq);
1786 if (RTC_lock == 0) {
1787 if (devpriv->rtc_iobase)
1788 release_region(devpriv->rtc_iobase,
1789 devpriv->rtc_iosize);
1791 devpriv->rtc_iobase = 0;
1792 devpriv->rtc_iosize = 0;
1801 if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1802 goto no_dma; /* if we haven't IRQ, we can't use DMA */
1803 if (this_board->DMAbits != 0) { /* board support DMA */
1804 dma = it->options[2];
1806 goto no_dma; /* DMA disabled */
1807 if (((1 << dma) & this_board->DMAbits) == 0) {
1808 rt_printk(", DMA is out of allowed range, FAIL!\n");
1809 return -EINVAL; /* Bad DMA */
1811 ret = request_dma(dma, "pcl818");
1813 rt_printk(", unable to allocate DMA %u, FAIL!\n", dma);
1814 return -EBUSY; /* DMA isn't free */
1817 rt_printk(", dma=%u", dma);
1818 pages = 2; /* we need 16KB */
1819 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1820 if (!devpriv->dmabuf[0]) {
1821 rt_printk(", unable to allocate DMA buffer, FAIL!\n");
1822 /* maybe experiment with try_to_free_pages() will help .... */
1823 return -EBUSY; /* no buffer :-( */
1825 devpriv->dmapages[0] = pages;
1826 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1827 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1828 /* rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1829 if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */
1830 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1831 if (!devpriv->dmabuf[1]) {
1833 (", unable to allocate DMA buffer, FAIL!\n");
1836 devpriv->dmapages[1] = pages;
1837 devpriv->hwdmaptr[1] =
1838 virt_to_bus((void *)devpriv->dmabuf[1]);
1839 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1845 if ((ret = alloc_subdevices(dev, 4)) < 0)
1848 s = dev->subdevices + 0;
1849 if (!this_board->n_aichan_se) {
1850 s->type = COMEDI_SUBD_UNUSED;
1852 s->type = COMEDI_SUBD_AI;
1853 devpriv->sub_ai = s;
1854 s->subdev_flags = SDF_READABLE;
1855 if (check_single_ended(dev->iobase)) {
1856 s->n_chan = this_board->n_aichan_se;
1857 s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1858 printk(", %dchans S.E. DAC", s->n_chan);
1860 s->n_chan = this_board->n_aichan_diff;
1861 s->subdev_flags |= SDF_DIFF;
1862 printk(", %dchans DIFF DAC", s->n_chan);
1864 s->maxdata = this_board->ai_maxdata;
1865 s->len_chanlist = s->n_chan;
1866 s->range_table = this_board->ai_range_type;
1867 s->cancel = pcl818_ai_cancel;
1868 s->insn_read = pcl818_ai_insn_read;
1869 if ((irq) || (devpriv->dma_rtc)) {
1870 dev->read_subdev = s;
1871 s->subdev_flags |= SDF_CMD_READ;
1872 s->do_cmdtest = ai_cmdtest;
1875 if (this_board->is_818) {
1876 if ((it->options[4] == 1) || (it->options[4] == 10))
1877 s->range_table = &range_pcl818l_h_ai; /* secondary range list jumper selectable */
1879 switch (it->options[4]) {
1881 s->range_table = &range_bipolar10;
1884 s->range_table = &range_bipolar5;
1887 s->range_table = &range_bipolar2_5;
1890 s->range_table = &range718_bipolar1;
1893 s->range_table = &range718_bipolar0_5;
1896 s->range_table = &range_unipolar10;
1899 s->range_table = &range_unipolar5;
1902 s->range_table = &range718_unipolar2;
1905 s->range_table = &range718_unipolar1;
1908 s->range_table = &range_unknown;
1914 s = dev->subdevices + 1;
1915 if (!this_board->n_aochan) {
1916 s->type = COMEDI_SUBD_UNUSED;
1918 s->type = COMEDI_SUBD_AO;
1919 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1920 s->n_chan = this_board->n_aochan;
1921 s->maxdata = this_board->ao_maxdata;
1922 s->len_chanlist = this_board->n_aochan;
1923 s->range_table = this_board->ao_range_type;
1924 s->insn_read = pcl818_ao_insn_read;
1925 s->insn_write = pcl818_ao_insn_write;
1927 #ifdef PCL818_MODE13_AO
1929 s->trig[1] = pcl818_ao_mode1;
1930 s->trig[3] = pcl818_ao_mode3;
1934 if (this_board->is_818) {
1935 if ((it->options[4] == 1) || (it->options[4] == 10))
1936 s->range_table = &range_unipolar10;
1937 if (it->options[4] == 2)
1938 s->range_table = &range_unknown;
1940 if ((it->options[5] == 1) || (it->options[5] == 10))
1941 s->range_table = &range_unipolar10;
1942 if (it->options[5] == 2)
1943 s->range_table = &range_unknown;
1947 s = dev->subdevices + 2;
1948 if (!this_board->n_dichan) {
1949 s->type = COMEDI_SUBD_UNUSED;
1951 s->type = COMEDI_SUBD_DI;
1952 s->subdev_flags = SDF_READABLE;
1953 s->n_chan = this_board->n_dichan;
1955 s->len_chanlist = this_board->n_dichan;
1956 s->range_table = &range_digital;
1957 s->insn_bits = pcl818_di_insn_bits;
1960 s = dev->subdevices + 3;
1961 if (!this_board->n_dochan) {
1962 s->type = COMEDI_SUBD_UNUSED;
1964 s->type = COMEDI_SUBD_DO;
1965 s->subdev_flags = SDF_WRITABLE;
1966 s->n_chan = this_board->n_dochan;
1968 s->len_chanlist = this_board->n_dochan;
1969 s->range_table = &range_digital;
1970 s->insn_bits = pcl818_do_insn_bits;
1973 /* select 1/10MHz oscilator */
1974 if ((it->options[3] == 0) || (it->options[3] == 10)) {
1975 devpriv->i8253_osc_base = 100;
1977 devpriv->i8253_osc_base = 1000;
1980 /* max sampling speed */
1981 devpriv->ns_min = this_board->ns_min;
1983 if (!this_board->is_818) {
1984 if ((it->options[6] == 1) || (it->options[6] == 100))
1985 devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */
1996 ==============================================================================
1999 static int pcl818_detach(struct comedi_device * dev)
2001 /* rt_printk("comedi%d: pcl818: remove\n", dev->minor); */
2002 free_resources(dev);