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/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 =
244 { 1, {BIP_RANGE(0.5),} };
245 static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
246 static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
248 static int pcl818_attach(struct comedi_device *dev,
249 struct comedi_devconfig *it);
250 static int pcl818_detach(struct comedi_device *dev);
253 static int RTC_lock = 0; /* RTC lock */
254 static int RTC_timer_lock = 0; /* RTC int lock */
257 struct pcl818_board {
259 const char *name; /* driver name */
260 int n_ranges; /* len of range list */
261 int n_aichan_se; /* num of A/D chans in single ended mode */
262 int n_aichan_diff; /* num of A/D chans in diferencial mode */
263 unsigned int ns_min; /* minimal alllowed delay between samples (in ns) */
264 int n_aochan; /* num of D/A chans */
265 int n_dichan; /* num of DI chans */
266 int n_dochan; /* num of DO chans */
267 const struct comedi_lrange *ai_range_type; /* default A/D rangelist */
268 const struct comedi_lrange *ao_range_type; /* default D/A rangelist */
269 unsigned int io_range; /* len of IO space */
270 unsigned int IRQbits; /* allowed interrupts */
271 unsigned int DMAbits; /* allowed DMA chans */
272 int ai_maxdata; /* maxdata for A/D */
273 int ao_maxdata; /* maxdata for D/A */
274 unsigned char fifo; /* 1=board has FIFO */
278 static const struct pcl818_board boardtypes[] = {
279 {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
280 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
281 0x0a, 0xfff, 0xfff, 0, 1},
282 {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
283 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
284 0x0a, 0xfff, 0xfff, 0, 1},
285 {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
286 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
287 0x0a, 0xfff, 0xfff, 1, 1},
288 {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
289 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
290 0x0a, 0xfff, 0xfff, 1, 1},
291 {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
292 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
293 0x0a, 0xfff, 0xfff, 0, 1},
294 {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
295 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
296 0x0a, 0xfff, 0xfff, 0, 0},
298 {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
299 &range_unipolar5, PCLx1x_RANGE, 0x00fc,
300 0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
303 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board))
305 static struct comedi_driver driver_pcl818 = {
306 .driver_name = "pcl818",
307 .module = THIS_MODULE,
308 .attach = pcl818_attach,
309 .detach = pcl818_detach,
310 .board_name = &boardtypes[0].name,
311 .num_names = n_boardtypes,
312 .offset = sizeof(struct pcl818_board),
315 COMEDI_INITCLEANUP(driver_pcl818);
317 struct pcl818_private {
319 unsigned int dma; /* used DMA, 0=don't use DMA */
320 int dma_rtc; /* 1=RTC used with DMA, 0=no RTC alloc */
321 unsigned int io_range;
323 unsigned long rtc_iobase; /* RTC port region */
324 unsigned int rtc_iosize;
325 unsigned int rtc_irq;
326 struct timer_list rtc_irq_timer; /* timer for RTC sanity check */
327 unsigned long rtc_freq; /* RTC int freq */
328 int rtc_irq_blocked; /* 1=we now do AI with DMA&RTC */
330 unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */
331 unsigned int dmapages[2]; /* len of DMA buffers in PAGE_SIZEs */
332 unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */
333 unsigned int hwdmasize[2]; /* len of DMA buffers in Bytes */
334 unsigned int dmasamplsize; /* size in samples hwdmasize[0]/2 */
335 unsigned int last_top_dma; /* DMA pointer in last RTC int */
336 int next_dma_buf; /* which DMA buffer will be used next round */
337 long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */
338 unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */
339 unsigned char neverending_ai; /* if=1, then we do neverending record (you must use cancel()) */
340 unsigned int ns_min; /* manimal alllowed delay between samples (in us) for actual card */
341 int i8253_osc_base; /* 1/frequency of on board oscilator in ns */
342 int irq_free; /* 1=have allocated IRQ */
343 int irq_blocked; /* 1=IRQ now uses any subdev */
344 int irq_was_now_closed; /* when IRQ finish, there's stored int818_mode for last interrupt */
345 int ai_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
346 struct comedi_subdevice *last_int_sub; /* ptr to subdevice which now finish */
347 int ai_act_scan; /* how many scans we finished */
348 int ai_act_chan; /* actual position in actual scan */
349 unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */
350 unsigned int act_chanlist_len; /* how long is actual MUX list */
351 unsigned int act_chanlist_pos; /* actual position in MUX list */
352 unsigned int ai_scans; /* len of scanlist */
353 unsigned int ai_n_chan; /* how many channels is measured */
354 unsigned int *ai_chanlist; /* actaul chanlist */
355 unsigned int ai_flags; /* flaglist */
356 unsigned int ai_data_len; /* len of data buffer */
357 short *ai_data; /* data buffer */
358 unsigned int ai_timer1; /* timers */
359 unsigned int ai_timer2;
360 struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */
361 unsigned char usefifo; /* 1=use fifo */
362 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,
376 struct comedi_subdevice *s,
377 unsigned int *chanlist, unsigned int n_chan,
378 unsigned int seglen);
379 static int check_channel_list(struct comedi_device *dev,
380 struct comedi_subdevice *s,
381 unsigned int *chanlist, unsigned int n_chan);
383 static int pcl818_ai_cancel(struct comedi_device *dev,
384 struct comedi_subdevice *s);
385 static void start_pacer(struct comedi_device *dev, int mode,
386 unsigned int divisor1, unsigned int divisor2);
389 static int set_rtc_irq_bit(unsigned char bit);
390 static void rtc_dropped_irq(unsigned long data);
391 static int rtc_setfreq_irq(int freq);
395 ==============================================================================
396 ANALOG INPUT MODE0, 818 cards, slow version
398 static int pcl818_ai_insn_read(struct comedi_device *dev,
399 struct comedi_subdevice *s,
400 struct comedi_insn *insn, unsigned int *data)
405 /* software trigger, DMA and INT off */
406 outb(0, dev->iobase + PCL818_CONTROL);
409 outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX);
412 outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE);
414 for (n = 0; n < insn->n; n++) {
416 /* clear INT (conversion end) flag */
417 outb(0, dev->iobase + PCL818_CLRINT);
419 /* start conversion */
420 outb(0, dev->iobase + PCL818_AD_LO);
424 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
428 comedi_error(dev, "A/D insn timeout");
429 /* clear INT (conversion end) flag */
430 outb(0, dev->iobase + PCL818_CLRINT);
434 data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
435 (inb(dev->iobase + PCL818_AD_LO) >> 4));
442 ==============================================================================
443 ANALOG OUTPUT MODE0, 818 cards
444 only one sample per call is supported
446 static int pcl818_ao_insn_read(struct comedi_device *dev,
447 struct comedi_subdevice *s,
448 struct comedi_insn *insn, unsigned int *data)
451 int chan = CR_CHAN(insn->chanspec);
453 for (n = 0; n < insn->n; n++) {
454 data[n] = devpriv->ao_readback[chan];
460 static int pcl818_ao_insn_write(struct comedi_device *dev,
461 struct comedi_subdevice *s,
462 struct comedi_insn *insn, unsigned int *data)
465 int chan = CR_CHAN(insn->chanspec);
467 for (n = 0; n < insn->n; n++) {
468 devpriv->ao_readback[chan] = data[n];
469 outb((data[n] & 0x000f) << 4, dev->iobase +
470 (chan ? PCL718_DA2_LO : PCL818_DA_LO));
471 outb((data[n] & 0x0ff0) >> 4, dev->iobase +
472 (chan ? PCL718_DA2_HI : PCL818_DA_HI));
479 ==============================================================================
480 DIGITAL INPUT MODE0, 818 cards
482 only one sample per call is supported
484 static int pcl818_di_insn_bits(struct comedi_device *dev,
485 struct comedi_subdevice *s,
486 struct comedi_insn *insn, unsigned int *data)
491 data[1] = inb(dev->iobase + PCL818_DI_LO) |
492 (inb(dev->iobase + PCL818_DI_HI) << 8);
498 ==============================================================================
499 DIGITAL OUTPUT MODE0, 818 cards
501 only one sample per call is supported
503 static int pcl818_do_insn_bits(struct comedi_device *dev,
504 struct comedi_subdevice *s,
505 struct comedi_insn *insn, unsigned int *data)
510 s->state &= ~data[0];
511 s->state |= (data[0] & data[1]);
513 outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
514 outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
522 ==============================================================================
523 analog input interrupt mode 1 & 3, 818 cards
524 one sample per interrupt version
526 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
528 struct comedi_device *dev = d;
529 struct comedi_subdevice *s = dev->subdevices + 0;
531 int timeout = 50; /* wait max 50us */
534 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
538 outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */
539 comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
540 pcl818_ai_cancel(dev, s);
541 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
542 comedi_event(dev, s);
546 low = inb(dev->iobase + PCL818_AD_LO);
547 comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4))); /* get one sample */
548 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
550 if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
552 ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
554 devpriv->act_chanlist[devpriv->act_chanlist_pos]);
555 pcl818_ai_cancel(dev, s);
556 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
557 comedi_event(dev, s);
560 devpriv->act_chanlist_pos++;
561 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
562 devpriv->act_chanlist_pos = 0;
564 s->async->cur_chan++;
565 if (s->async->cur_chan >= devpriv->ai_n_chan) {
567 s->async->cur_chan = 0;
568 devpriv->ai_act_scan--;
571 if (!devpriv->neverending_ai) {
572 if (devpriv->ai_act_scan == 0) { /* all data sampled */
573 pcl818_ai_cancel(dev, s);
574 s->async->events |= COMEDI_CB_EOA;
577 comedi_event(dev, s);
582 ==============================================================================
583 analog input dma mode 1 & 3, 818 cards
585 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
587 struct comedi_device *dev = d;
588 struct comedi_subdevice *s = dev->subdevices + 0;
593 disable_dma(devpriv->dma);
594 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
595 if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) { /* switch dma bufs */
596 set_dma_mode(devpriv->dma, DMA_MODE_READ);
597 flags = claim_dma_lock();
598 set_dma_addr(devpriv->dma,
599 devpriv->hwdmaptr[devpriv->next_dma_buf]);
600 if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
601 set_dma_count(devpriv->dma,
602 devpriv->hwdmasize[devpriv->
605 set_dma_count(devpriv->dma, devpriv->last_dma_run);
607 release_dma_lock(flags);
608 enable_dma(devpriv->dma);
610 printk("comedi: A/D mode1/3 IRQ \n");
612 devpriv->dma_runs_to_end--;
613 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
614 ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
616 len = devpriv->hwdmasize[0] >> 1;
619 for (i = 0; i < len; i++) {
620 if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
622 ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
624 devpriv->act_chanlist[devpriv->act_chanlist_pos],
625 devpriv->act_chanlist_pos);
626 pcl818_ai_cancel(dev, s);
627 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
628 comedi_event(dev, s);
632 comedi_buf_put(s->async, ptr[bufptr++] >> 4); /* get one sample */
634 devpriv->act_chanlist_pos++;
635 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
636 devpriv->act_chanlist_pos = 0;
638 s->async->cur_chan++;
639 if (s->async->cur_chan >= devpriv->ai_n_chan) {
640 s->async->cur_chan = 0;
641 devpriv->ai_act_scan--;
644 if (!devpriv->neverending_ai)
645 if (devpriv->ai_act_scan == 0) { /* all data sampled */
646 pcl818_ai_cancel(dev, s);
647 s->async->events |= COMEDI_CB_EOA;
648 comedi_event(dev, s);
649 /* printk("done int ai13 dma\n"); */
655 comedi_event(dev, s);
661 ==============================================================================
662 analog input dma mode 1 & 3 over RTC, 818 cards
664 static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
666 struct comedi_device *dev = d;
667 struct comedi_subdevice *s = dev->subdevices + 0;
669 unsigned int top1, top2, i, bufptr;
671 short *dmabuf = (short *)devpriv->dmabuf[0];
674 switch (devpriv->ai_mode) {
675 case INT_TYPE_AI1_DMA_RTC:
676 case INT_TYPE_AI3_DMA_RTC:
677 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
678 mod_timer(&devpriv->rtc_irq_timer,
679 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
681 for (i = 0; i < 10; i++) {
682 top1 = get_dma_residue(devpriv->dma);
683 top2 = get_dma_residue(devpriv->dma);
690 top1 = devpriv->hwdmasize[0] - top1; /* where is now DMA in buffer */
692 ofs_dats = top1 - devpriv->last_top_dma; /* new samples from last call */
694 ofs_dats = (devpriv->dmasamplsize) + ofs_dats;
696 return IRQ_HANDLED; /* exit=no new samples from last call */
698 i = devpriv->last_top_dma - 1;
699 i &= (devpriv->dmasamplsize - 1);
701 if (dmabuf[i] != MAGIC_DMA_WORD) { /* DMA overflow! */
702 comedi_error(dev, "A/D mode1/3 DMA buffer overflow!");
703 /* printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */
704 pcl818_ai_cancel(dev, s);
705 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
706 comedi_event(dev, s);
709 /* printk("r %ld ",ofs_dats); */
711 bufptr = devpriv->last_top_dma;
713 for (i = 0; i < ofs_dats; i++) {
714 if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
716 ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
717 (dmabuf[bufptr] & 0xf),
719 act_chanlist[devpriv->act_chanlist_pos]);
720 pcl818_ai_cancel(dev, s);
722 COMEDI_CB_EOA | COMEDI_CB_ERROR;
723 comedi_event(dev, s);
727 comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); /* get one sample */
728 bufptr &= (devpriv->dmasamplsize - 1);
730 devpriv->act_chanlist_pos++;
731 if (devpriv->act_chanlist_pos >=
732 devpriv->act_chanlist_len) {
733 devpriv->act_chanlist_pos = 0;
735 s->async->cur_chan++;
736 if (s->async->cur_chan >= devpriv->ai_n_chan) {
737 s->async->cur_chan = 0;
738 devpriv->ai_act_scan--;
741 if (!devpriv->neverending_ai)
742 if (devpriv->ai_act_scan == 0) { /* all data sampled */
743 pcl818_ai_cancel(dev, s);
744 s->async->events |= COMEDI_CB_EOA;
745 comedi_event(dev, s);
746 /* printk("done int ai13 dma\n"); */
751 devpriv->last_top_dma = bufptr;
753 bufptr &= (devpriv->dmasamplsize - 1);
754 dmabuf[bufptr] = MAGIC_DMA_WORD;
755 comedi_event(dev, s);
766 ==============================================================================
767 analog input interrupt mode 1 & 3, 818HD/HG cards
769 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
771 struct comedi_device *dev = d;
772 struct comedi_subdevice *s = dev->subdevices + 0;
775 outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */
777 lo = inb(dev->iobase + PCL818_FI_STATUS);
780 comedi_error(dev, "A/D mode1/3 FIFO overflow!");
781 pcl818_ai_cancel(dev, s);
782 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
783 comedi_event(dev, s);
788 comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
789 pcl818_ai_cancel(dev, s);
790 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
791 comedi_event(dev, s);
801 for (i = 0; i < len; i++) {
802 lo = inb(dev->iobase + PCL818_FI_DATALO);
803 if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
805 ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
807 devpriv->act_chanlist[devpriv->act_chanlist_pos]);
808 pcl818_ai_cancel(dev, s);
809 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
810 comedi_event(dev, s);
814 comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); /* get one sample */
816 devpriv->act_chanlist_pos++;
817 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
818 devpriv->act_chanlist_pos = 0;
820 s->async->cur_chan++;
821 if (s->async->cur_chan >= devpriv->ai_n_chan) {
822 s->async->cur_chan = 0;
823 devpriv->ai_act_scan--;
826 if (!devpriv->neverending_ai)
827 if (devpriv->ai_act_scan == 0) { /* all data sampled */
828 pcl818_ai_cancel(dev, s);
829 s->async->events |= COMEDI_CB_EOA;
830 comedi_event(dev, s);
836 comedi_event(dev, s);
841 ==============================================================================
844 static irqreturn_t interrupt_pcl818(int irq, void *d)
846 struct comedi_device *dev = d;
848 if (!dev->attached) {
849 comedi_error(dev, "premature interrupt");
854 if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
855 if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
856 devpriv->ai_act_scan > 0)) &&
857 (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
858 devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
859 /* The cleanup from ai_cancel() has been delayed
860 until now because the card doesn't seem to like
861 being reprogrammed while a DMA transfer is in
864 struct comedi_subdevice *s = dev->subdevices + 0;
865 devpriv->ai_act_scan = 0;
866 devpriv->neverending_ai = 0;
867 pcl818_ai_cancel(dev, s);
870 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
875 switch (devpriv->ai_mode) {
876 case INT_TYPE_AI1_DMA:
877 case INT_TYPE_AI3_DMA:
878 return interrupt_pcl818_ai_mode13_dma(irq, d);
879 case INT_TYPE_AI1_INT:
880 case INT_TYPE_AI3_INT:
881 return interrupt_pcl818_ai_mode13_int(irq, d);
882 case INT_TYPE_AI1_FIFO:
883 case INT_TYPE_AI3_FIFO:
884 return interrupt_pcl818_ai_mode13_fifo(irq, d);
885 #ifdef PCL818_MODE13_AO
886 case INT_TYPE_AO1_INT:
887 case INT_TYPE_AO3_INT:
888 return interrupt_pcl818_ao_mode13_int(irq, d);
894 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
896 if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
897 || (!devpriv->ai_mode)) {
898 comedi_error(dev, "bad IRQ!");
902 comedi_error(dev, "IRQ from unknown source!");
907 ==============================================================================
908 ANALOG INPUT MODE 1 or 3 DMA , 818 cards
910 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
911 struct comedi_subdevice *s)
916 printk("mode13dma_int, mode: %d\n", mode);
917 disable_dma(devpriv->dma); /* disable dma */
918 bytes = devpriv->hwdmasize[0];
919 if (!devpriv->neverending_ai) {
920 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /* how many */
921 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; /* how many DMA pages we must fiil */
922 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; /* on last dma transfer must be moved */
923 devpriv->dma_runs_to_end--;
924 if (devpriv->dma_runs_to_end >= 0)
925 bytes = devpriv->hwdmasize[0];
928 devpriv->next_dma_buf = 0;
929 set_dma_mode(devpriv->dma, DMA_MODE_READ);
930 flags = claim_dma_lock();
931 clear_dma_ff(devpriv->dma);
932 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
933 set_dma_count(devpriv->dma, bytes);
934 release_dma_lock(flags);
935 enable_dma(devpriv->dma);
938 devpriv->ai_mode = INT_TYPE_AI1_DMA;
939 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ+DMA */
941 devpriv->ai_mode = INT_TYPE_AI3_DMA;
942 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */
948 ==============================================================================
949 ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
951 static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
952 struct comedi_subdevice *s)
957 set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
958 flags = claim_dma_lock();
959 clear_dma_ff(devpriv->dma);
960 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
961 set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
962 release_dma_lock(flags);
963 enable_dma(devpriv->dma);
964 devpriv->last_top_dma = 0; /* devpriv->hwdmasize[0]; */
965 pole = (short *)devpriv->dmabuf[0];
966 devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
967 pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
969 devpriv->rtc_freq = rtc_setfreq_irq(2048);
970 devpriv->rtc_irq_timer.expires =
971 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
972 devpriv->rtc_irq_timer.data = (unsigned long)dev;
973 devpriv->rtc_irq_timer.function = rtc_dropped_irq;
975 add_timer(&devpriv->rtc_irq_timer);
979 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
980 outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */
982 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
983 outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */
989 ==============================================================================
990 ANALOG INPUT MODE 1 or 3, 818 cards
992 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
993 struct comedi_subdevice *s)
995 struct comedi_cmd *cmd = &s->async->cmd;
996 int divisor1 = 0, divisor2 = 0;
999 printk("pcl818_ai_cmd_mode()\n");
1000 if ((!dev->irq) && (!devpriv->dma_rtc)) {
1001 comedi_error(dev, "IRQ not defined!");
1005 if (devpriv->irq_blocked)
1008 start_pacer(dev, -1, 0, 0); /* stop pacer */
1010 seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
1011 devpriv->ai_n_chan);
1014 setup_channel_list(dev, s, devpriv->ai_chanlist,
1015 devpriv->ai_n_chan, seglen);
1019 devpriv->ai_act_scan = devpriv->ai_scans;
1020 devpriv->ai_act_chan = 0;
1021 devpriv->irq_blocked = 1;
1022 devpriv->irq_was_now_closed = 0;
1023 devpriv->neverending_ai = 0;
1024 devpriv->act_chanlist_pos = 0;
1025 devpriv->dma_runs_to_end = 0;
1027 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
1028 devpriv->neverending_ai = 1; /* well, user want neverending */
1031 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1032 &divisor2, &cmd->convert_arg,
1033 TRIG_ROUND_NEAREST);
1034 if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */
1038 if (divisor2 == 1) {
1044 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1046 switch (devpriv->dma) {
1049 if (devpriv->dma_rtc == 0) {
1050 pcl818_ai_mode13dma_int(mode, dev, s);
1054 pcl818_ai_mode13dma_rtc(mode, dev, s);
1063 if (!devpriv->usefifo) {
1065 /* printk("IRQ\n"); */
1067 devpriv->ai_mode = INT_TYPE_AI1_INT;
1069 outb(0x83 | (dev->irq << 4),
1070 dev->iobase + PCL818_CONTROL);
1072 devpriv->ai_mode = INT_TYPE_AI3_INT;
1074 outb(0x82 | (dev->irq << 4),
1075 dev->iobase + PCL818_CONTROL);
1080 outb(1, dev->iobase + PCL818_FI_ENABLE);
1082 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1084 outb(0x03, dev->iobase + PCL818_CONTROL);
1086 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1087 outb(0x02, dev->iobase + PCL818_CONTROL);
1092 start_pacer(dev, mode, divisor1, divisor2);
1095 switch (devpriv->ai_mode) {
1096 case INT_TYPE_AI1_DMA_RTC:
1097 case INT_TYPE_AI3_DMA_RTC:
1098 set_rtc_irq_bit(1); /* start RTC */
1102 printk("pcl818_ai_cmd_mode() end\n");
1108 ==============================================================================
1109 ANALOG OUTPUT MODE 1 or 3, 818 cards
1111 #ifdef PCL818_MODE13_AO
1112 static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
1113 struct comedi_subdevice *s, comedi_trig * it)
1115 int divisor1 = 0, divisor2 = 0;
1118 comedi_error(dev, "IRQ not defined!");
1122 if (devpriv->irq_blocked)
1125 start_pacer(dev, -1, 0, 0); /* stop pacer */
1127 devpriv->int13_act_scan = it->n;
1128 devpriv->int13_act_chan = 0;
1129 devpriv->irq_blocked = 1;
1130 devpriv->irq_was_now_closed = 0;
1131 devpriv->neverending_ai = 0;
1132 devpriv->act_chanlist_pos = 0;
1135 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1136 &divisor2, &it->trigvar,
1137 TRIG_ROUND_NEAREST);
1138 if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */
1142 if (divisor2 == 1) {
1148 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1150 devpriv->int818_mode = INT_TYPE_AO1_INT;
1151 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */
1153 devpriv->int818_mode = INT_TYPE_AO3_INT;
1154 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */
1157 start_pacer(dev, mode, divisor1, divisor2);
1163 ==============================================================================
1164 ANALOG OUTPUT MODE 1, 818 cards
1166 static int pcl818_ao_mode1(struct comedi_device *dev,
1167 struct comedi_subdevice *s, comedi_trig * it)
1169 return pcl818_ao_mode13(1, dev, s, it);
1173 ==============================================================================
1174 ANALOG OUTPUT MODE 3, 818 cards
1176 static int pcl818_ao_mode3(struct comedi_device *dev,
1177 struct comedi_subdevice *s, comedi_trig * it)
1179 return pcl818_ao_mode13(3, dev, s, it);
1185 ==============================================================================
1186 Start/stop pacer onboard pacer
1188 static void start_pacer(struct comedi_device *dev, int mode,
1189 unsigned int divisor1, unsigned int divisor2)
1191 outb(0xb4, dev->iobase + PCL818_CTRCTL);
1192 outb(0x74, dev->iobase + PCL818_CTRCTL);
1196 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1197 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1198 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1199 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1204 ==============================================================================
1205 Check if channel list from user is builded correctly
1206 If it's ok, then program scan/gain logic
1208 static int check_channel_list(struct comedi_device *dev,
1209 struct comedi_subdevice *s,
1210 unsigned int *chanlist, unsigned int n_chan)
1212 unsigned int chansegment[16];
1213 unsigned int i, nowmustbechan, seglen, segpos;
1215 /* correct channel and range number check itself comedi/range.c */
1217 comedi_error(dev, "range/channel list is empty!");
1222 /* first channel is everytime ok */
1223 chansegment[0] = chanlist[0];
1224 /* build part of chanlist */
1225 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1227 /* printk("%d. %d * %d\n",i,
1228 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1230 /* we detect loop, this must by finish */
1232 if (chanlist[0] == chanlist[i])
1235 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1236 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */
1238 ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1239 dev->minor, i, CR_CHAN(chanlist[i]),
1240 nowmustbechan, CR_CHAN(chanlist[0]));
1243 /* well, this is next correct channel in list */
1244 chansegment[i] = chanlist[i];
1247 /* check whole chanlist */
1248 for (i = 0, segpos = 0; i < n_chan; i++) {
1249 /* 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])); */
1250 if (chanlist[i] != chansegment[i % seglen]) {
1252 ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1253 dev->minor, i, CR_CHAN(chansegment[i]),
1254 CR_RANGE(chansegment[i]),
1255 CR_AREF(chansegment[i]),
1256 CR_CHAN(chanlist[i % seglen]),
1257 CR_RANGE(chanlist[i % seglen]),
1258 CR_AREF(chansegment[i % seglen]));
1259 return 0; /* chan/gain list is strange */
1265 printk("check_channel_list: seglen %d\n", seglen);
1269 static void setup_channel_list(struct comedi_device *dev,
1270 struct comedi_subdevice *s,
1271 unsigned int *chanlist, unsigned int n_chan,
1272 unsigned int seglen)
1276 devpriv->act_chanlist_len = seglen;
1277 devpriv->act_chanlist_pos = 0;
1279 for (i = 0; i < seglen; i++) { /* store range list to card */
1280 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1281 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX); /* select channel */
1282 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE); /* select gain */
1287 /* select channel interval to scan */
1288 outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1290 dev->iobase + PCL818_MUX);
1294 ==============================================================================
1295 Check if board is switched to SE (1) or DIFF(0) mode
1297 static int check_single_ended(unsigned int port)
1299 if (inb(port + PCL818_STATUS) & 0x20) {
1307 ==============================================================================
1309 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1310 struct comedi_cmd *cmd)
1313 int tmp, divisor1 = 0, divisor2 = 0;
1315 /* step 1: make sure trigger sources are trivially valid */
1317 tmp = cmd->start_src;
1318 cmd->start_src &= TRIG_NOW;
1319 if (!cmd->start_src || tmp != cmd->start_src)
1322 tmp = cmd->scan_begin_src;
1323 cmd->scan_begin_src &= TRIG_FOLLOW;
1324 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1327 tmp = cmd->convert_src;
1328 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1329 if (!cmd->convert_src || tmp != cmd->convert_src)
1332 tmp = cmd->scan_end_src;
1333 cmd->scan_end_src &= TRIG_COUNT;
1334 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1337 tmp = cmd->stop_src;
1338 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1339 if (!cmd->stop_src || tmp != cmd->stop_src)
1346 /* step 2: make sure trigger sources are unique and mutually compatible */
1348 if (cmd->start_src != TRIG_NOW) {
1349 cmd->start_src = TRIG_NOW;
1352 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1353 cmd->scan_begin_src = TRIG_FOLLOW;
1356 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1359 if (cmd->scan_end_src != TRIG_COUNT) {
1360 cmd->scan_end_src = TRIG_COUNT;
1364 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1371 /* step 3: make sure arguments are trivially compatible */
1373 if (cmd->start_arg != 0) {
1378 if (cmd->scan_begin_arg != 0) {
1379 cmd->scan_begin_arg = 0;
1383 if (cmd->convert_src == TRIG_TIMER) {
1384 if (cmd->convert_arg < this_board->ns_min) {
1385 cmd->convert_arg = this_board->ns_min;
1388 } else { /* TRIG_EXT */
1389 if (cmd->convert_arg != 0) {
1390 cmd->convert_arg = 0;
1395 if (cmd->scan_end_arg != cmd->chanlist_len) {
1396 cmd->scan_end_arg = cmd->chanlist_len;
1399 if (cmd->stop_src == TRIG_COUNT) {
1400 if (!cmd->stop_arg) {
1404 } else { /* TRIG_NONE */
1405 if (cmd->stop_arg != 0) {
1415 /* step 4: fix up any arguments */
1417 if (cmd->convert_src == TRIG_TIMER) {
1418 tmp = cmd->convert_arg;
1419 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1420 &divisor2, &cmd->convert_arg,
1421 cmd->flags & TRIG_ROUND_MASK);
1422 if (cmd->convert_arg < this_board->ns_min)
1423 cmd->convert_arg = this_board->ns_min;
1424 if (tmp != cmd->convert_arg)
1432 /* step 5: complain about special chanlist considerations */
1434 if (cmd->chanlist) {
1435 if (!check_channel_list(dev, s, cmd->chanlist,
1437 return 5; /* incorrect channels list */
1444 ==============================================================================
1446 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1448 struct comedi_cmd *cmd = &s->async->cmd;
1451 printk("pcl818_ai_cmd()\n");
1452 devpriv->ai_n_chan = cmd->chanlist_len;
1453 devpriv->ai_chanlist = cmd->chanlist;
1454 devpriv->ai_flags = cmd->flags;
1455 devpriv->ai_data_len = s->async->prealloc_bufsz;
1456 devpriv->ai_data = s->async->prealloc_buf;
1457 devpriv->ai_timer1 = 0;
1458 devpriv->ai_timer2 = 0;
1460 if (cmd->stop_src == TRIG_COUNT) {
1461 devpriv->ai_scans = cmd->stop_arg;
1463 devpriv->ai_scans = 0;
1466 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 3 */
1467 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */
1468 devpriv->ai_timer1 = cmd->convert_arg;
1469 retval = pcl818_ai_cmd_mode(1, dev, s);
1470 printk("pcl818_ai_cmd() end\n");
1473 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */
1474 return pcl818_ai_cmd_mode(3, dev, s);
1482 ==============================================================================
1483 cancel any mode 1-4 AI
1485 static int pcl818_ai_cancel(struct comedi_device *dev,
1486 struct comedi_subdevice *s)
1488 if (devpriv->irq_blocked > 0) {
1489 printk("pcl818_ai_cancel()\n");
1490 devpriv->irq_was_now_closed = 1;
1492 switch (devpriv->ai_mode) {
1494 case INT_TYPE_AI1_DMA_RTC:
1495 case INT_TYPE_AI3_DMA_RTC:
1496 set_rtc_irq_bit(0); /* stop RTC */
1497 del_timer(&devpriv->rtc_irq_timer);
1499 case INT_TYPE_AI1_DMA:
1500 case INT_TYPE_AI3_DMA:
1501 if (devpriv->neverending_ai ||
1502 (!devpriv->neverending_ai &&
1503 devpriv->ai_act_scan > 0)) {
1504 /* wait for running dma transfer to end, do cleanup in interrupt */
1507 disable_dma(devpriv->dma);
1508 case INT_TYPE_AI1_INT:
1509 case INT_TYPE_AI3_INT:
1510 case INT_TYPE_AI1_FIFO:
1511 case INT_TYPE_AI3_FIFO:
1512 #ifdef PCL818_MODE13_AO
1513 case INT_TYPE_AO1_INT:
1514 case INT_TYPE_AO3_INT:
1516 outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL); /* Stop A/D */
1518 start_pacer(dev, -1, 0, 0);
1519 outb(0, dev->iobase + PCL818_AD_LO);
1520 inb(dev->iobase + PCL818_AD_LO);
1521 inb(dev->iobase + PCL818_AD_HI);
1522 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
1523 outb(0, dev->iobase + PCL818_CONTROL); /* Stop A/D */
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 devpriv->irq_blocked = 0;
1530 devpriv->last_int_sub = s;
1531 devpriv->neverending_ai = 0;
1532 devpriv->ai_mode = 0;
1533 devpriv->irq_was_now_closed = 0;
1539 printk("pcl818_ai_cancel() end\n");
1544 ==============================================================================
1547 static int pcl818_check(unsigned long iobase)
1549 outb(0x00, iobase + PCL818_MUX);
1551 if (inb(iobase + PCL818_MUX) != 0x00)
1552 return 1; /* there isn't card */
1553 outb(0x55, iobase + PCL818_MUX);
1555 if (inb(iobase + PCL818_MUX) != 0x55)
1556 return 1; /* there isn't card */
1557 outb(0x00, iobase + PCL818_MUX);
1559 outb(0x18, iobase + PCL818_CONTROL);
1561 if (inb(iobase + PCL818_CONTROL) != 0x18)
1562 return 1; /* there isn't card */
1563 return 0; /* ok, card exist */
1567 ==============================================================================
1568 reset whole PCL-818 cards
1570 static void pcl818_reset(struct comedi_device *dev)
1572 if (devpriv->usefifo) { /* FIFO shutdown */
1573 outb(0, dev->iobase + PCL818_FI_INTCLR);
1574 outb(0, dev->iobase + PCL818_FI_FLUSH);
1575 outb(0, dev->iobase + PCL818_FI_ENABLE);
1577 outb(0, dev->iobase + PCL818_DA_LO); /* DAC=0V */
1578 outb(0, dev->iobase + PCL818_DA_HI);
1580 outb(0, dev->iobase + PCL818_DO_HI); /* DO=$0000 */
1581 outb(0, dev->iobase + PCL818_DO_LO);
1583 outb(0, dev->iobase + PCL818_CONTROL);
1584 outb(0, dev->iobase + PCL818_CNTENABLE);
1585 outb(0, dev->iobase + PCL818_MUX);
1586 outb(0, dev->iobase + PCL818_CLRINT);
1587 outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */
1588 outb(0x70, dev->iobase + PCL818_CTRCTL);
1589 outb(0x30, dev->iobase + PCL818_CTRCTL);
1590 if (this_board->is_818) {
1591 outb(0, dev->iobase + PCL818_RANGE);
1593 outb(0, dev->iobase + PCL718_DA2_LO);
1594 outb(0, dev->iobase + PCL718_DA2_HI);
1600 ==============================================================================
1601 Enable(1)/disable(0) periodic interrupts from RTC
1603 static int set_rtc_irq_bit(unsigned char bit)
1606 unsigned long flags;
1610 if (RTC_timer_lock > 1)
1614 if (RTC_timer_lock < 0)
1616 if (RTC_timer_lock > 0)
1622 val = CMOS_READ(RTC_CONTROL);
1628 CMOS_WRITE(val, RTC_CONTROL);
1629 CMOS_READ(RTC_INTR_FLAGS);
1630 restore_flags(flags);
1635 ==============================================================================
1636 Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1638 static void rtc_dropped_irq(unsigned long data)
1640 struct comedi_device *dev = (void *)data;
1641 unsigned long flags, tmp;
1643 switch (devpriv->int818_mode) {
1644 case INT_TYPE_AI1_DMA_RTC:
1645 case INT_TYPE_AI3_DMA_RTC:
1646 mod_timer(&devpriv->rtc_irq_timer,
1647 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1650 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */
1651 restore_flags(flags);
1657 ==============================================================================
1658 Set frequency of interrupts from RTC
1660 static int rtc_setfreq_irq(int freq)
1665 unsigned long flags;
1672 while (freq > (1 << tmp))
1675 rtc_freq = 1 << tmp;
1679 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1681 CMOS_WRITE(val, RTC_FREQ_SELECT);
1682 restore_flags(flags);
1688 ==============================================================================
1689 Free any resources that we have claimed
1691 static void free_resources(struct comedi_device *dev)
1693 /* printk("free_resource()\n"); */
1695 pcl818_ai_cancel(dev, devpriv->sub_ai);
1698 free_dma(devpriv->dma);
1699 if (devpriv->dmabuf[0])
1700 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1701 if (devpriv->dmabuf[1])
1702 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1704 if (devpriv->rtc_irq)
1705 free_irq(devpriv->rtc_irq, dev);
1706 if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1707 if (devpriv->rtc_iobase)
1708 release_region(devpriv->rtc_iobase,
1709 devpriv->rtc_iosize);
1711 if (devpriv->dma_rtc)
1717 free_irq(dev->irq, dev);
1719 release_region(dev->iobase, devpriv->io_range);
1720 /* printk("free_resource() end\n"); */
1724 ==============================================================================
1729 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1732 unsigned long iobase;
1735 unsigned long pages;
1736 struct comedi_subdevice *s;
1738 ret = alloc_private(dev, sizeof(struct pcl818_private));
1740 return ret; /* Can't alloc mem */
1742 /* claim our I/O space */
1743 iobase = it->options[0];
1744 printk("comedi%d: pcl818: board=%s, ioport=0x%03lx",
1745 dev->minor, this_board->name, iobase);
1746 devpriv->io_range = this_board->io_range;
1747 if ((this_board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */
1748 devpriv->io_range = PCLx1xFIFO_RANGE;
1749 devpriv->usefifo = 1;
1751 if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1752 printk("I/O port conflict\n");
1756 dev->iobase = iobase;
1758 if (pcl818_check(iobase)) {
1759 printk(", I can't detect board. FAIL!\n");
1763 /* set up some name stuff */
1764 dev->board_name = this_board->name;
1767 if (this_board->IRQbits != 0) { /* board support IRQ */
1768 irq = it->options[1];
1769 if (irq) { /* we want to use IRQ */
1770 if (((1 << irq) & this_board->IRQbits) == 0) {
1772 (", IRQ %u is out of allowed range, DISABLING IT",
1774 irq = 0; /* Bad IRQ */
1777 (irq, interrupt_pcl818, 0, "pcl818", dev)) {
1779 (", unable to allocate IRQ %u, DISABLING IT",
1781 irq = 0; /* Can't use IRQ */
1783 printk(", irq=%u", irq);
1791 devpriv->irq_free = 1;
1792 } /* 1=we have allocated irq */
1794 devpriv->irq_free = 0;
1796 devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */
1797 devpriv->ai_mode = 0; /* mode of irq */
1800 /* grab RTC for DMA operations */
1801 devpriv->dma_rtc = 0;
1802 if (it->options[2] > 0) { /* we want to use DMA */
1803 if (RTC_lock == 0) {
1804 if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1808 devpriv->rtc_iobase = RTC_PORT(0);
1809 devpriv->rtc_iosize = RTC_IO_EXTENT;
1811 if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0,
1812 "pcl818 DMA (RTC)", dev)) {
1813 devpriv->dma_rtc = 1;
1814 devpriv->rtc_irq = RTC_IRQ;
1815 printk(", dma_irq=%u", devpriv->rtc_irq);
1818 if (RTC_lock == 0) {
1819 if (devpriv->rtc_iobase)
1820 release_region(devpriv->rtc_iobase,
1821 devpriv->rtc_iosize);
1823 devpriv->rtc_iobase = 0;
1824 devpriv->rtc_iosize = 0;
1833 if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1834 goto no_dma; /* if we haven't IRQ, we can't use DMA */
1835 if (this_board->DMAbits != 0) { /* board support DMA */
1836 dma = it->options[2];
1838 goto no_dma; /* DMA disabled */
1839 if (((1 << dma) & this_board->DMAbits) == 0) {
1840 printk(", DMA is out of allowed range, FAIL!\n");
1841 return -EINVAL; /* Bad DMA */
1843 ret = request_dma(dma, "pcl818");
1845 printk(", unable to allocate DMA %u, FAIL!\n", dma);
1846 return -EBUSY; /* DMA isn't free */
1849 printk(", dma=%u", dma);
1850 pages = 2; /* we need 16KB */
1851 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1852 if (!devpriv->dmabuf[0]) {
1853 printk(", unable to allocate DMA buffer, FAIL!\n");
1854 /* maybe experiment with try_to_free_pages() will help .... */
1855 return -EBUSY; /* no buffer :-( */
1857 devpriv->dmapages[0] = pages;
1858 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1859 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1860 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1861 if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */
1862 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1863 if (!devpriv->dmabuf[1]) {
1865 (", unable to allocate DMA buffer, FAIL!\n");
1868 devpriv->dmapages[1] = pages;
1869 devpriv->hwdmaptr[1] =
1870 virt_to_bus((void *)devpriv->dmabuf[1]);
1871 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1877 ret = alloc_subdevices(dev, 4);
1881 s = dev->subdevices + 0;
1882 if (!this_board->n_aichan_se) {
1883 s->type = COMEDI_SUBD_UNUSED;
1885 s->type = COMEDI_SUBD_AI;
1886 devpriv->sub_ai = s;
1887 s->subdev_flags = SDF_READABLE;
1888 if (check_single_ended(dev->iobase)) {
1889 s->n_chan = this_board->n_aichan_se;
1890 s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1891 printk(", %dchans S.E. DAC", s->n_chan);
1893 s->n_chan = this_board->n_aichan_diff;
1894 s->subdev_flags |= SDF_DIFF;
1895 printk(", %dchans DIFF DAC", s->n_chan);
1897 s->maxdata = this_board->ai_maxdata;
1898 s->len_chanlist = s->n_chan;
1899 s->range_table = this_board->ai_range_type;
1900 s->cancel = pcl818_ai_cancel;
1901 s->insn_read = pcl818_ai_insn_read;
1902 if ((irq) || (devpriv->dma_rtc)) {
1903 dev->read_subdev = s;
1904 s->subdev_flags |= SDF_CMD_READ;
1905 s->do_cmdtest = ai_cmdtest;
1908 if (this_board->is_818) {
1909 if ((it->options[4] == 1) || (it->options[4] == 10))
1910 s->range_table = &range_pcl818l_h_ai; /* secondary range list jumper selectable */
1912 switch (it->options[4]) {
1914 s->range_table = &range_bipolar10;
1917 s->range_table = &range_bipolar5;
1920 s->range_table = &range_bipolar2_5;
1923 s->range_table = &range718_bipolar1;
1926 s->range_table = &range718_bipolar0_5;
1929 s->range_table = &range_unipolar10;
1932 s->range_table = &range_unipolar5;
1935 s->range_table = &range718_unipolar2;
1938 s->range_table = &range718_unipolar1;
1941 s->range_table = &range_unknown;
1947 s = dev->subdevices + 1;
1948 if (!this_board->n_aochan) {
1949 s->type = COMEDI_SUBD_UNUSED;
1951 s->type = COMEDI_SUBD_AO;
1952 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1953 s->n_chan = this_board->n_aochan;
1954 s->maxdata = this_board->ao_maxdata;
1955 s->len_chanlist = this_board->n_aochan;
1956 s->range_table = this_board->ao_range_type;
1957 s->insn_read = pcl818_ao_insn_read;
1958 s->insn_write = pcl818_ao_insn_write;
1960 #ifdef PCL818_MODE13_AO
1962 s->trig[1] = pcl818_ao_mode1;
1963 s->trig[3] = pcl818_ao_mode3;
1967 if (this_board->is_818) {
1968 if ((it->options[4] == 1) || (it->options[4] == 10))
1969 s->range_table = &range_unipolar10;
1970 if (it->options[4] == 2)
1971 s->range_table = &range_unknown;
1973 if ((it->options[5] == 1) || (it->options[5] == 10))
1974 s->range_table = &range_unipolar10;
1975 if (it->options[5] == 2)
1976 s->range_table = &range_unknown;
1980 s = dev->subdevices + 2;
1981 if (!this_board->n_dichan) {
1982 s->type = COMEDI_SUBD_UNUSED;
1984 s->type = COMEDI_SUBD_DI;
1985 s->subdev_flags = SDF_READABLE;
1986 s->n_chan = this_board->n_dichan;
1988 s->len_chanlist = this_board->n_dichan;
1989 s->range_table = &range_digital;
1990 s->insn_bits = pcl818_di_insn_bits;
1993 s = dev->subdevices + 3;
1994 if (!this_board->n_dochan) {
1995 s->type = COMEDI_SUBD_UNUSED;
1997 s->type = COMEDI_SUBD_DO;
1998 s->subdev_flags = SDF_WRITABLE;
1999 s->n_chan = this_board->n_dochan;
2001 s->len_chanlist = this_board->n_dochan;
2002 s->range_table = &range_digital;
2003 s->insn_bits = pcl818_do_insn_bits;
2006 /* select 1/10MHz oscilator */
2007 if ((it->options[3] == 0) || (it->options[3] == 10)) {
2008 devpriv->i8253_osc_base = 100;
2010 devpriv->i8253_osc_base = 1000;
2013 /* max sampling speed */
2014 devpriv->ns_min = this_board->ns_min;
2016 if (!this_board->is_818) {
2017 if ((it->options[6] == 1) || (it->options[6] == 100))
2018 devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */
2029 ==============================================================================
2032 static int pcl818_detach(struct comedi_device *dev)
2034 /* printk("comedi%d: pcl818: remove\n", dev->minor); */
2035 free_resources(dev);