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 =
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 if (s->async->cur_chan == 0) {
562 devpriv->ai_act_scan--;
565 if (!devpriv->neverending_ai) {
566 if (devpriv->ai_act_scan == 0) { /* all data sampled */
567 pcl818_ai_cancel(dev, s);
568 s->async->events |= COMEDI_CB_EOA;
571 comedi_event(dev, s);
576 ==============================================================================
577 analog input dma mode 1 & 3, 818 cards
579 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
581 struct comedi_device *dev = d;
582 struct comedi_subdevice *s = dev->subdevices + 0;
587 disable_dma(devpriv->dma);
588 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
589 if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) { /* switch dma bufs */
590 set_dma_mode(devpriv->dma, DMA_MODE_READ);
591 flags = claim_dma_lock();
592 set_dma_addr(devpriv->dma,
593 devpriv->hwdmaptr[devpriv->next_dma_buf]);
594 if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
595 set_dma_count(devpriv->dma,
596 devpriv->hwdmasize[devpriv->
599 set_dma_count(devpriv->dma, devpriv->last_dma_run);
601 release_dma_lock(flags);
602 enable_dma(devpriv->dma);
604 printk("comedi: A/D mode1/3 IRQ \n");
606 devpriv->dma_runs_to_end--;
607 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
608 ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
610 len = devpriv->hwdmasize[0] >> 1;
613 for (i = 0; i < len; i++) {
614 if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
616 ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
618 devpriv->act_chanlist[devpriv->act_chanlist_pos],
619 devpriv->act_chanlist_pos);
620 pcl818_ai_cancel(dev, s);
621 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
622 comedi_event(dev, s);
626 comedi_buf_put(s->async, ptr[bufptr++] >> 4); /* get one sample */
628 devpriv->act_chanlist_pos++;
629 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
630 devpriv->ai_act_scan--;
631 devpriv->act_chanlist_pos = 0;
634 if (!devpriv->neverending_ai)
635 if (devpriv->ai_act_scan == 0) { /* all data sampled */
636 pcl818_ai_cancel(dev, s);
637 s->async->events |= COMEDI_CB_EOA;
638 comedi_event(dev, s);
639 /* printk("done int ai13 dma\n"); */
645 comedi_event(dev, s);
651 ==============================================================================
652 analog input dma mode 1 & 3 over RTC, 818 cards
654 static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
656 struct comedi_device *dev = d;
657 struct comedi_subdevice *s = dev->subdevices + 0;
659 unsigned int top1, top2, i, bufptr;
661 short *dmabuf = (short *)devpriv->dmabuf[0];
664 switch (devpriv->ai_mode) {
665 case INT_TYPE_AI1_DMA_RTC:
666 case INT_TYPE_AI3_DMA_RTC:
667 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
668 mod_timer(&devpriv->rtc_irq_timer,
669 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
671 for (i = 0; i < 10; i++) {
672 top1 = get_dma_residue(devpriv->dma);
673 top2 = get_dma_residue(devpriv->dma);
680 top1 = devpriv->hwdmasize[0] - top1; /* where is now DMA in buffer */
682 ofs_dats = top1 - devpriv->last_top_dma; /* new samples from last call */
684 ofs_dats = (devpriv->dmasamplsize) + ofs_dats;
686 return IRQ_HANDLED; /* exit=no new samples from last call */
688 i = devpriv->last_top_dma - 1;
689 i &= (devpriv->dmasamplsize - 1);
691 if (dmabuf[i] != MAGIC_DMA_WORD) { /* DMA overflow! */
692 comedi_error(dev, "A/D mode1/3 DMA buffer overflow!");
693 /* printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */
694 pcl818_ai_cancel(dev, s);
695 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
696 comedi_event(dev, s);
699 /* printk("r %ld ",ofs_dats); */
701 bufptr = devpriv->last_top_dma;
703 for (i = 0; i < ofs_dats; i++) {
704 if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
706 ("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
707 (dmabuf[bufptr] & 0xf),
709 act_chanlist[devpriv->act_chanlist_pos]);
710 pcl818_ai_cancel(dev, s);
712 COMEDI_CB_EOA | COMEDI_CB_ERROR;
713 comedi_event(dev, s);
717 comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); /* get one sample */
718 bufptr &= (devpriv->dmasamplsize - 1);
720 if (s->async->cur_chan == 0) {
721 devpriv->ai_act_scan--;
724 if (!devpriv->neverending_ai)
725 if (devpriv->ai_act_scan == 0) { /* all data sampled */
726 pcl818_ai_cancel(dev, s);
727 s->async->events |= COMEDI_CB_EOA;
728 comedi_event(dev, s);
729 /* printk("done int ai13 dma\n"); */
734 devpriv->last_top_dma = bufptr;
736 bufptr &= (devpriv->dmasamplsize - 1);
737 dmabuf[bufptr] = MAGIC_DMA_WORD;
738 comedi_event(dev, s);
749 ==============================================================================
750 analog input interrupt mode 1 & 3, 818HD/HG cards
752 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
754 struct comedi_device *dev = d;
755 struct comedi_subdevice *s = dev->subdevices + 0;
758 outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */
760 lo = inb(dev->iobase + PCL818_FI_STATUS);
763 comedi_error(dev, "A/D mode1/3 FIFO overflow!");
764 pcl818_ai_cancel(dev, s);
765 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
766 comedi_event(dev, s);
771 comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
772 pcl818_ai_cancel(dev, s);
773 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
774 comedi_event(dev, s);
784 for (i = 0; i < len; i++) {
785 lo = inb(dev->iobase + PCL818_FI_DATALO);
786 if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */
788 ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
790 devpriv->act_chanlist[devpriv->act_chanlist_pos]);
791 pcl818_ai_cancel(dev, s);
792 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
793 comedi_event(dev, s);
797 comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); /* get one sample */
799 if (s->async->cur_chan == 0) {
800 devpriv->ai_act_scan--;
803 if (!devpriv->neverending_ai)
804 if (devpriv->ai_act_scan == 0) { /* all data sampled */
805 pcl818_ai_cancel(dev, s);
806 s->async->events |= COMEDI_CB_EOA;
807 comedi_event(dev, s);
813 comedi_event(dev, s);
818 ==============================================================================
821 static irqreturn_t interrupt_pcl818(int irq, void *d)
823 struct comedi_device *dev = d;
825 if (!dev->attached) {
826 comedi_error(dev, "premature interrupt");
831 if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
832 if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
833 devpriv->ai_act_scan > 0)) &&
834 (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
835 devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
836 /* The cleanup from ai_cancel() has been delayed
837 until now because the card doesn't seem to like
838 being reprogrammed while a DMA transfer is in
841 struct comedi_subdevice *s = dev->subdevices + 0;
842 devpriv->ai_act_scan = 0;
843 devpriv->neverending_ai = 0;
844 pcl818_ai_cancel(dev, s);
847 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
852 switch (devpriv->ai_mode) {
853 case INT_TYPE_AI1_DMA:
854 case INT_TYPE_AI3_DMA:
855 return interrupt_pcl818_ai_mode13_dma(irq, d);
856 case INT_TYPE_AI1_INT:
857 case INT_TYPE_AI3_INT:
858 return interrupt_pcl818_ai_mode13_int(irq, d);
859 case INT_TYPE_AI1_FIFO:
860 case INT_TYPE_AI3_FIFO:
861 return interrupt_pcl818_ai_mode13_fifo(irq, d);
862 #ifdef PCL818_MODE13_AO
863 case INT_TYPE_AO1_INT:
864 case INT_TYPE_AO3_INT:
865 return interrupt_pcl818_ao_mode13_int(irq, d);
871 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
873 if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
874 || (!devpriv->ai_mode)) {
875 comedi_error(dev, "bad IRQ!");
879 comedi_error(dev, "IRQ from unknow source!");
884 ==============================================================================
885 ANALOG INPUT MODE 1 or 3 DMA , 818 cards
887 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
888 struct comedi_subdevice *s)
893 printk("mode13dma_int, mode: %d\n", mode);
894 disable_dma(devpriv->dma); /* disable dma */
895 bytes = devpriv->hwdmasize[0];
896 if (!devpriv->neverending_ai) {
897 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /* how many */
898 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0]; /* how many DMA pages we must fiil */
899 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0]; /* on last dma transfer must be moved */
900 devpriv->dma_runs_to_end--;
901 if (devpriv->dma_runs_to_end >= 0)
902 bytes = devpriv->hwdmasize[0];
905 devpriv->next_dma_buf = 0;
906 set_dma_mode(devpriv->dma, DMA_MODE_READ);
907 flags = claim_dma_lock();
908 clear_dma_ff(devpriv->dma);
909 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
910 set_dma_count(devpriv->dma, bytes);
911 release_dma_lock(flags);
912 enable_dma(devpriv->dma);
915 devpriv->ai_mode = INT_TYPE_AI1_DMA;
916 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ+DMA */
918 devpriv->ai_mode = INT_TYPE_AI3_DMA;
919 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ+DMA */
925 ==============================================================================
926 ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
928 static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
929 struct comedi_subdevice *s)
934 set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
935 flags = claim_dma_lock();
936 clear_dma_ff(devpriv->dma);
937 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
938 set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
939 release_dma_lock(flags);
940 enable_dma(devpriv->dma);
941 devpriv->last_top_dma = 0; /* devpriv->hwdmasize[0]; */
942 pole = (short *)devpriv->dmabuf[0];
943 devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
944 pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
946 devpriv->rtc_freq = rtc_setfreq_irq(2048);
947 devpriv->rtc_irq_timer.expires =
948 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
949 devpriv->rtc_irq_timer.data = (unsigned long)dev;
950 devpriv->rtc_irq_timer.function = rtc_dropped_irq;
952 add_timer(&devpriv->rtc_irq_timer);
956 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
957 outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+DMA */
959 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
960 outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+DMA */
966 ==============================================================================
967 ANALOG INPUT MODE 1 or 3, 818 cards
969 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
970 struct comedi_subdevice *s)
972 struct comedi_cmd *cmd = &s->async->cmd;
973 int divisor1 = 0, divisor2 = 0;
976 printk("pcl818_ai_cmd_mode()\n");
977 if ((!dev->irq) && (!devpriv->dma_rtc)) {
978 comedi_error(dev, "IRQ not defined!");
982 if (devpriv->irq_blocked)
985 start_pacer(dev, -1, 0, 0); /* stop pacer */
987 seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
991 setup_channel_list(dev, s, devpriv->ai_chanlist,
992 devpriv->ai_n_chan, seglen);
996 devpriv->ai_act_scan = devpriv->ai_scans;
997 devpriv->ai_act_chan = 0;
998 devpriv->irq_blocked = 1;
999 devpriv->irq_was_now_closed = 0;
1000 devpriv->neverending_ai = 0;
1001 devpriv->act_chanlist_pos = 0;
1002 devpriv->dma_runs_to_end = 0;
1004 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
1005 devpriv->neverending_ai = 1; /* well, user want neverending */
1008 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1009 &divisor2, &cmd->convert_arg,
1010 TRIG_ROUND_NEAREST);
1011 if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */
1015 if (divisor2 == 1) {
1021 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1023 switch (devpriv->dma) {
1026 if (devpriv->dma_rtc == 0) {
1027 pcl818_ai_mode13dma_int(mode, dev, s);
1031 pcl818_ai_mode13dma_rtc(mode, dev, s);
1040 if (!devpriv->usefifo) {
1042 /* printk("IRQ\n"); */
1044 devpriv->ai_mode = INT_TYPE_AI1_INT;
1046 outb(0x83 | (dev->irq << 4),
1047 dev->iobase + PCL818_CONTROL);
1049 devpriv->ai_mode = INT_TYPE_AI3_INT;
1051 outb(0x82 | (dev->irq << 4),
1052 dev->iobase + PCL818_CONTROL);
1057 outb(1, dev->iobase + PCL818_FI_ENABLE);
1059 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1061 outb(0x03, dev->iobase + PCL818_CONTROL);
1063 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1064 outb(0x02, dev->iobase + PCL818_CONTROL);
1069 start_pacer(dev, mode, divisor1, divisor2);
1072 switch (devpriv->ai_mode) {
1073 case INT_TYPE_AI1_DMA_RTC:
1074 case INT_TYPE_AI3_DMA_RTC:
1075 set_rtc_irq_bit(1); /* start RTC */
1079 printk("pcl818_ai_cmd_mode() end\n");
1085 ==============================================================================
1086 ANALOG OUTPUT MODE 1 or 3, 818 cards
1088 #ifdef PCL818_MODE13_AO
1089 static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
1090 struct comedi_subdevice *s, comedi_trig * it)
1092 int divisor1 = 0, divisor2 = 0;
1095 comedi_error(dev, "IRQ not defined!");
1099 if (devpriv->irq_blocked)
1102 start_pacer(dev, -1, 0, 0); /* stop pacer */
1104 devpriv->int13_act_scan = it->n;
1105 devpriv->int13_act_chan = 0;
1106 devpriv->irq_blocked = 1;
1107 devpriv->irq_was_now_closed = 0;
1108 devpriv->neverending_ai = 0;
1109 devpriv->act_chanlist_pos = 0;
1112 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1113 &divisor2, &it->trigvar,
1114 TRIG_ROUND_NEAREST);
1115 if (divisor1 == 1) { /* PCL818 crash if any divisor is set to 1 */
1119 if (divisor2 == 1) {
1125 outb(0, dev->iobase + PCL818_CNTENABLE); /* enable pacer */
1127 devpriv->int818_mode = INT_TYPE_AO1_INT;
1128 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Pacer+IRQ */
1130 devpriv->int818_mode = INT_TYPE_AO3_INT;
1131 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL); /* Ext trig+IRQ */
1134 start_pacer(dev, mode, divisor1, divisor2);
1140 ==============================================================================
1141 ANALOG OUTPUT MODE 1, 818 cards
1143 static int pcl818_ao_mode1(struct comedi_device *dev,
1144 struct comedi_subdevice *s, comedi_trig * it)
1146 return pcl818_ao_mode13(1, dev, s, it);
1150 ==============================================================================
1151 ANALOG OUTPUT MODE 3, 818 cards
1153 static int pcl818_ao_mode3(struct comedi_device *dev,
1154 struct comedi_subdevice *s, comedi_trig * it)
1156 return pcl818_ao_mode13(3, dev, s, it);
1162 ==============================================================================
1163 Start/stop pacer onboard pacer
1165 static void start_pacer(struct comedi_device *dev, int mode,
1166 unsigned int divisor1, unsigned int divisor2)
1168 outb(0xb4, dev->iobase + PCL818_CTRCTL);
1169 outb(0x74, dev->iobase + PCL818_CTRCTL);
1173 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1174 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1175 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1176 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1181 ==============================================================================
1182 Check if channel list from user is builded correctly
1183 If it's ok, then program scan/gain logic
1185 static int check_channel_list(struct comedi_device *dev,
1186 struct comedi_subdevice *s,
1187 unsigned int *chanlist, unsigned int n_chan)
1189 unsigned int chansegment[16];
1190 unsigned int i, nowmustbechan, seglen, segpos;
1192 /* correct channel and range number check itself comedi/range.c */
1194 comedi_error(dev, "range/channel list is empty!");
1199 /* first channel is everytime ok */
1200 chansegment[0] = chanlist[0];
1201 /* build part of chanlist */
1202 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1204 /* printk("%d. %d * %d\n",i,
1205 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1207 /* we detect loop, this must by finish */
1209 if (chanlist[0] == chanlist[i])
1212 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1213 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continous :-( */
1215 ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1216 dev->minor, i, CR_CHAN(chanlist[i]),
1217 nowmustbechan, CR_CHAN(chanlist[0]));
1220 /* well, this is next correct channel in list */
1221 chansegment[i] = chanlist[i];
1224 /* check whole chanlist */
1225 for (i = 0, segpos = 0; i < n_chan; i++) {
1226 /* 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])); */
1227 if (chanlist[i] != chansegment[i % seglen]) {
1229 ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1230 dev->minor, i, CR_CHAN(chansegment[i]),
1231 CR_RANGE(chansegment[i]),
1232 CR_AREF(chansegment[i]),
1233 CR_CHAN(chanlist[i % seglen]),
1234 CR_RANGE(chanlist[i % seglen]),
1235 CR_AREF(chansegment[i % seglen]));
1236 return 0; /* chan/gain list is strange */
1242 printk("check_channel_list: seglen %d\n", seglen);
1246 static void setup_channel_list(struct comedi_device *dev,
1247 struct comedi_subdevice *s,
1248 unsigned int *chanlist, unsigned int n_chan,
1249 unsigned int seglen)
1253 devpriv->act_chanlist_len = seglen;
1254 devpriv->act_chanlist_pos = 0;
1256 for (i = 0; i < seglen; i++) { /* store range list to card */
1257 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1258 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX); /* select channel */
1259 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE); /* select gain */
1264 /* select channel interval to scan */
1265 outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1267 dev->iobase + PCL818_MUX);
1271 ==============================================================================
1272 Check if board is switched to SE (1) or DIFF(0) mode
1274 static int check_single_ended(unsigned int port)
1276 if (inb(port + PCL818_STATUS) & 0x20) {
1284 ==============================================================================
1286 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1287 struct comedi_cmd *cmd)
1290 int tmp, divisor1 = 0, divisor2 = 0;
1292 /* step 1: make sure trigger sources are trivially valid */
1294 tmp = cmd->start_src;
1295 cmd->start_src &= TRIG_NOW;
1296 if (!cmd->start_src || tmp != cmd->start_src)
1299 tmp = cmd->scan_begin_src;
1300 cmd->scan_begin_src &= TRIG_FOLLOW;
1301 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1304 tmp = cmd->convert_src;
1305 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1306 if (!cmd->convert_src || tmp != cmd->convert_src)
1309 tmp = cmd->scan_end_src;
1310 cmd->scan_end_src &= TRIG_COUNT;
1311 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1314 tmp = cmd->stop_src;
1315 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1316 if (!cmd->stop_src || tmp != cmd->stop_src)
1323 /* step 2: make sure trigger sources are unique and mutually compatible */
1325 if (cmd->start_src != TRIG_NOW) {
1326 cmd->start_src = TRIG_NOW;
1329 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1330 cmd->scan_begin_src = TRIG_FOLLOW;
1333 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1336 if (cmd->scan_end_src != TRIG_COUNT) {
1337 cmd->scan_end_src = TRIG_COUNT;
1341 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1348 /* step 3: make sure arguments are trivially compatible */
1350 if (cmd->start_arg != 0) {
1355 if (cmd->scan_begin_arg != 0) {
1356 cmd->scan_begin_arg = 0;
1360 if (cmd->convert_src == TRIG_TIMER) {
1361 if (cmd->convert_arg < this_board->ns_min) {
1362 cmd->convert_arg = this_board->ns_min;
1365 } else { /* TRIG_EXT */
1366 if (cmd->convert_arg != 0) {
1367 cmd->convert_arg = 0;
1372 if (!cmd->chanlist_len) {
1373 cmd->chanlist_len = 1;
1376 if (cmd->chanlist_len > s->n_chan) {
1377 cmd->chanlist_len = s->n_chan;
1380 if (cmd->scan_end_arg != cmd->chanlist_len) {
1381 cmd->scan_end_arg = cmd->chanlist_len;
1384 if (cmd->stop_src == TRIG_COUNT) {
1385 if (!cmd->stop_arg) {
1389 } else { /* TRIG_NONE */
1390 if (cmd->stop_arg != 0) {
1400 /* step 4: fix up any arguments */
1402 if (cmd->convert_src == TRIG_TIMER) {
1403 tmp = cmd->convert_arg;
1404 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1405 &divisor2, &cmd->convert_arg,
1406 cmd->flags & TRIG_ROUND_MASK);
1407 if (cmd->convert_arg < this_board->ns_min)
1408 cmd->convert_arg = this_board->ns_min;
1409 if (tmp != cmd->convert_arg)
1417 /* step 5: complain about special chanlist considerations */
1419 if (cmd->chanlist) {
1420 if (!check_channel_list(dev, s, cmd->chanlist,
1422 return 5; /* incorrect channels list */
1429 ==============================================================================
1431 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1433 struct comedi_cmd *cmd = &s->async->cmd;
1436 printk("pcl818_ai_cmd()\n");
1437 devpriv->ai_n_chan = cmd->chanlist_len;
1438 devpriv->ai_chanlist = cmd->chanlist;
1439 devpriv->ai_flags = cmd->flags;
1440 devpriv->ai_data_len = s->async->prealloc_bufsz;
1441 devpriv->ai_data = s->async->prealloc_buf;
1442 devpriv->ai_timer1 = 0;
1443 devpriv->ai_timer2 = 0;
1445 if (cmd->stop_src == TRIG_COUNT) {
1446 devpriv->ai_scans = cmd->stop_arg;
1448 devpriv->ai_scans = 0;
1451 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 3 */
1452 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 */
1453 devpriv->ai_timer1 = cmd->convert_arg;
1454 retval = pcl818_ai_cmd_mode(1, dev, s);
1455 printk("pcl818_ai_cmd() end\n");
1458 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */
1459 return pcl818_ai_cmd_mode(3, dev, s);
1467 ==============================================================================
1468 cancel any mode 1-4 AI
1470 static int pcl818_ai_cancel(struct comedi_device *dev,
1471 struct comedi_subdevice *s)
1473 if (devpriv->irq_blocked > 0) {
1474 printk("pcl818_ai_cancel()\n");
1475 devpriv->irq_was_now_closed = 1;
1477 switch (devpriv->ai_mode) {
1479 case INT_TYPE_AI1_DMA_RTC:
1480 case INT_TYPE_AI3_DMA_RTC:
1481 set_rtc_irq_bit(0); /* stop RTC */
1482 del_timer(&devpriv->rtc_irq_timer);
1484 case INT_TYPE_AI1_DMA:
1485 case INT_TYPE_AI3_DMA:
1486 if (devpriv->neverending_ai ||
1487 (!devpriv->neverending_ai &&
1488 devpriv->ai_act_scan > 0)) {
1489 /* wait for running dma transfer to end, do cleanup in interrupt */
1492 disable_dma(devpriv->dma);
1493 case INT_TYPE_AI1_INT:
1494 case INT_TYPE_AI3_INT:
1495 case INT_TYPE_AI1_FIFO:
1496 case INT_TYPE_AI3_FIFO:
1497 #ifdef PCL818_MODE13_AO
1498 case INT_TYPE_AO1_INT:
1499 case INT_TYPE_AO3_INT:
1501 outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL); /* Stop A/D */
1503 start_pacer(dev, -1, 0, 0);
1504 outb(0, dev->iobase + PCL818_AD_LO);
1505 inb(dev->iobase + PCL818_AD_LO);
1506 inb(dev->iobase + PCL818_AD_HI);
1507 outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */
1508 outb(0, dev->iobase + PCL818_CONTROL); /* Stop A/D */
1509 if (devpriv->usefifo) { /* FIFO shutdown */
1510 outb(0, dev->iobase + PCL818_FI_INTCLR);
1511 outb(0, dev->iobase + PCL818_FI_FLUSH);
1512 outb(0, dev->iobase + PCL818_FI_ENABLE);
1514 devpriv->irq_blocked = 0;
1515 devpriv->last_int_sub = s;
1516 devpriv->neverending_ai = 0;
1517 devpriv->ai_mode = 0;
1518 devpriv->irq_was_now_closed = 0;
1524 printk("pcl818_ai_cancel() end\n");
1529 ==============================================================================
1532 static int pcl818_check(unsigned long iobase)
1534 outb(0x00, iobase + PCL818_MUX);
1536 if (inb(iobase + PCL818_MUX) != 0x00)
1537 return 1; /* there isn't card */
1538 outb(0x55, iobase + PCL818_MUX);
1540 if (inb(iobase + PCL818_MUX) != 0x55)
1541 return 1; /* there isn't card */
1542 outb(0x00, iobase + PCL818_MUX);
1544 outb(0x18, iobase + PCL818_CONTROL);
1546 if (inb(iobase + PCL818_CONTROL) != 0x18)
1547 return 1; /* there isn't card */
1548 return 0; /* ok, card exist */
1552 ==============================================================================
1553 reset whole PCL-818 cards
1555 static void pcl818_reset(struct comedi_device *dev)
1557 if (devpriv->usefifo) { /* FIFO shutdown */
1558 outb(0, dev->iobase + PCL818_FI_INTCLR);
1559 outb(0, dev->iobase + PCL818_FI_FLUSH);
1560 outb(0, dev->iobase + PCL818_FI_ENABLE);
1562 outb(0, dev->iobase + PCL818_DA_LO); /* DAC=0V */
1563 outb(0, dev->iobase + PCL818_DA_HI);
1565 outb(0, dev->iobase + PCL818_DO_HI); /* DO=$0000 */
1566 outb(0, dev->iobase + PCL818_DO_LO);
1568 outb(0, dev->iobase + PCL818_CONTROL);
1569 outb(0, dev->iobase + PCL818_CNTENABLE);
1570 outb(0, dev->iobase + PCL818_MUX);
1571 outb(0, dev->iobase + PCL818_CLRINT);
1572 outb(0xb0, dev->iobase + PCL818_CTRCTL); /* Stop pacer */
1573 outb(0x70, dev->iobase + PCL818_CTRCTL);
1574 outb(0x30, dev->iobase + PCL818_CTRCTL);
1575 if (this_board->is_818) {
1576 outb(0, dev->iobase + PCL818_RANGE);
1578 outb(0, dev->iobase + PCL718_DA2_LO);
1579 outb(0, dev->iobase + PCL718_DA2_HI);
1585 ==============================================================================
1586 Enable(1)/disable(0) periodic interrupts from RTC
1588 static int set_rtc_irq_bit(unsigned char bit)
1591 unsigned long flags;
1595 if (RTC_timer_lock > 1)
1599 if (RTC_timer_lock < 0)
1601 if (RTC_timer_lock > 0)
1607 val = CMOS_READ(RTC_CONTROL);
1613 CMOS_WRITE(val, RTC_CONTROL);
1614 CMOS_READ(RTC_INTR_FLAGS);
1615 restore_flags(flags);
1620 ==============================================================================
1621 Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1623 static void rtc_dropped_irq(unsigned long data)
1625 struct comedi_device *dev = (void *)data;
1626 unsigned long flags, tmp;
1628 switch (devpriv->int818_mode) {
1629 case INT_TYPE_AI1_DMA_RTC:
1630 case INT_TYPE_AI3_DMA_RTC:
1631 mod_timer(&devpriv->rtc_irq_timer,
1632 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1635 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */
1636 restore_flags(flags);
1642 ==============================================================================
1643 Set frequency of interrupts from RTC
1645 static int rtc_setfreq_irq(int freq)
1650 unsigned long flags;
1657 while (freq > (1 << tmp))
1660 rtc_freq = 1 << tmp;
1664 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1666 CMOS_WRITE(val, RTC_FREQ_SELECT);
1667 restore_flags(flags);
1673 ==============================================================================
1674 Free any resources that we have claimed
1676 static void free_resources(struct comedi_device *dev)
1678 /* printk("free_resource()\n"); */
1680 pcl818_ai_cancel(dev, devpriv->sub_ai);
1683 free_dma(devpriv->dma);
1684 if (devpriv->dmabuf[0])
1685 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1686 if (devpriv->dmabuf[1])
1687 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1689 if (devpriv->rtc_irq)
1690 free_irq(devpriv->rtc_irq, dev);
1691 if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1692 if (devpriv->rtc_iobase)
1693 release_region(devpriv->rtc_iobase,
1694 devpriv->rtc_iosize);
1696 if (devpriv->dma_rtc)
1702 free_irq(dev->irq, dev);
1704 release_region(dev->iobase, devpriv->io_range);
1705 /* printk("free_resource() end\n"); */
1709 ==============================================================================
1714 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1717 unsigned long iobase;
1720 unsigned long pages;
1721 struct comedi_subdevice *s;
1723 ret = alloc_private(dev, sizeof(struct pcl818_private));
1725 return ret; /* Can't alloc mem */
1727 /* claim our I/O space */
1728 iobase = it->options[0];
1729 printk("comedi%d: pcl818: board=%s, ioport=0x%03lx",
1730 dev->minor, this_board->name, iobase);
1731 devpriv->io_range = this_board->io_range;
1732 if ((this_board->fifo) && (it->options[2] == -1)) { /* we've board with FIFO and we want to use FIFO */
1733 devpriv->io_range = PCLx1xFIFO_RANGE;
1734 devpriv->usefifo = 1;
1736 if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1737 printk("I/O port conflict\n");
1741 dev->iobase = iobase;
1743 if (pcl818_check(iobase)) {
1744 printk(", I can't detect board. FAIL!\n");
1748 /* set up some name stuff */
1749 dev->board_name = this_board->name;
1752 if (this_board->IRQbits != 0) { /* board support IRQ */
1753 irq = it->options[1];
1754 if (irq) { /* we want to use IRQ */
1755 if (((1 << irq) & this_board->IRQbits) == 0) {
1757 (", IRQ %u is out of allowed range, DISABLING IT",
1759 irq = 0; /* Bad IRQ */
1762 (irq, interrupt_pcl818, 0, "pcl818", dev)) {
1764 (", unable to allocate IRQ %u, DISABLING IT",
1766 irq = 0; /* Can't use IRQ */
1768 printk(", irq=%u", irq);
1776 devpriv->irq_free = 1;
1777 } /* 1=we have allocated irq */
1779 devpriv->irq_free = 0;
1781 devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */
1782 devpriv->ai_mode = 0; /* mode of irq */
1785 /* grab RTC for DMA operations */
1786 devpriv->dma_rtc = 0;
1787 if (it->options[2] > 0) { /* we want to use DMA */
1788 if (RTC_lock == 0) {
1789 if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1793 devpriv->rtc_iobase = RTC_PORT(0);
1794 devpriv->rtc_iosize = RTC_IO_EXTENT;
1796 if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0,
1797 "pcl818 DMA (RTC)", dev)) {
1798 devpriv->dma_rtc = 1;
1799 devpriv->rtc_irq = RTC_IRQ;
1800 printk(", dma_irq=%u", devpriv->rtc_irq);
1803 if (RTC_lock == 0) {
1804 if (devpriv->rtc_iobase)
1805 release_region(devpriv->rtc_iobase,
1806 devpriv->rtc_iosize);
1808 devpriv->rtc_iobase = 0;
1809 devpriv->rtc_iosize = 0;
1818 if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1819 goto no_dma; /* if we haven't IRQ, we can't use DMA */
1820 if (this_board->DMAbits != 0) { /* board support DMA */
1821 dma = it->options[2];
1823 goto no_dma; /* DMA disabled */
1824 if (((1 << dma) & this_board->DMAbits) == 0) {
1825 printk(", DMA is out of allowed range, FAIL!\n");
1826 return -EINVAL; /* Bad DMA */
1828 ret = request_dma(dma, "pcl818");
1830 printk(", unable to allocate DMA %u, FAIL!\n", dma);
1831 return -EBUSY; /* DMA isn't free */
1834 printk(", dma=%u", dma);
1835 pages = 2; /* we need 16KB */
1836 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1837 if (!devpriv->dmabuf[0]) {
1838 printk(", unable to allocate DMA buffer, FAIL!\n");
1839 /* maybe experiment with try_to_free_pages() will help .... */
1840 return -EBUSY; /* no buffer :-( */
1842 devpriv->dmapages[0] = pages;
1843 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1844 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1845 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1846 if (devpriv->dma_rtc == 0) { /* we must do duble buff :-( */
1847 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1848 if (!devpriv->dmabuf[1]) {
1850 (", unable to allocate DMA buffer, FAIL!\n");
1853 devpriv->dmapages[1] = pages;
1854 devpriv->hwdmaptr[1] =
1855 virt_to_bus((void *)devpriv->dmabuf[1]);
1856 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1862 ret = alloc_subdevices(dev, 4);
1866 s = dev->subdevices + 0;
1867 if (!this_board->n_aichan_se) {
1868 s->type = COMEDI_SUBD_UNUSED;
1870 s->type = COMEDI_SUBD_AI;
1871 devpriv->sub_ai = s;
1872 s->subdev_flags = SDF_READABLE;
1873 if (check_single_ended(dev->iobase)) {
1874 s->n_chan = this_board->n_aichan_se;
1875 s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1876 printk(", %dchans S.E. DAC", s->n_chan);
1878 s->n_chan = this_board->n_aichan_diff;
1879 s->subdev_flags |= SDF_DIFF;
1880 printk(", %dchans DIFF DAC", s->n_chan);
1882 s->maxdata = this_board->ai_maxdata;
1883 s->len_chanlist = s->n_chan;
1884 s->range_table = this_board->ai_range_type;
1885 s->cancel = pcl818_ai_cancel;
1886 s->insn_read = pcl818_ai_insn_read;
1887 if ((irq) || (devpriv->dma_rtc)) {
1888 dev->read_subdev = s;
1889 s->subdev_flags |= SDF_CMD_READ;
1890 s->do_cmdtest = ai_cmdtest;
1893 if (this_board->is_818) {
1894 if ((it->options[4] == 1) || (it->options[4] == 10))
1895 s->range_table = &range_pcl818l_h_ai; /* secondary range list jumper selectable */
1897 switch (it->options[4]) {
1899 s->range_table = &range_bipolar10;
1902 s->range_table = &range_bipolar5;
1905 s->range_table = &range_bipolar2_5;
1908 s->range_table = &range718_bipolar1;
1911 s->range_table = &range718_bipolar0_5;
1914 s->range_table = &range_unipolar10;
1917 s->range_table = &range_unipolar5;
1920 s->range_table = &range718_unipolar2;
1923 s->range_table = &range718_unipolar1;
1926 s->range_table = &range_unknown;
1932 s = dev->subdevices + 1;
1933 if (!this_board->n_aochan) {
1934 s->type = COMEDI_SUBD_UNUSED;
1936 s->type = COMEDI_SUBD_AO;
1937 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1938 s->n_chan = this_board->n_aochan;
1939 s->maxdata = this_board->ao_maxdata;
1940 s->len_chanlist = this_board->n_aochan;
1941 s->range_table = this_board->ao_range_type;
1942 s->insn_read = pcl818_ao_insn_read;
1943 s->insn_write = pcl818_ao_insn_write;
1945 #ifdef PCL818_MODE13_AO
1947 s->trig[1] = pcl818_ao_mode1;
1948 s->trig[3] = pcl818_ao_mode3;
1952 if (this_board->is_818) {
1953 if ((it->options[4] == 1) || (it->options[4] == 10))
1954 s->range_table = &range_unipolar10;
1955 if (it->options[4] == 2)
1956 s->range_table = &range_unknown;
1958 if ((it->options[5] == 1) || (it->options[5] == 10))
1959 s->range_table = &range_unipolar10;
1960 if (it->options[5] == 2)
1961 s->range_table = &range_unknown;
1965 s = dev->subdevices + 2;
1966 if (!this_board->n_dichan) {
1967 s->type = COMEDI_SUBD_UNUSED;
1969 s->type = COMEDI_SUBD_DI;
1970 s->subdev_flags = SDF_READABLE;
1971 s->n_chan = this_board->n_dichan;
1973 s->len_chanlist = this_board->n_dichan;
1974 s->range_table = &range_digital;
1975 s->insn_bits = pcl818_di_insn_bits;
1978 s = dev->subdevices + 3;
1979 if (!this_board->n_dochan) {
1980 s->type = COMEDI_SUBD_UNUSED;
1982 s->type = COMEDI_SUBD_DO;
1983 s->subdev_flags = SDF_WRITABLE;
1984 s->n_chan = this_board->n_dochan;
1986 s->len_chanlist = this_board->n_dochan;
1987 s->range_table = &range_digital;
1988 s->insn_bits = pcl818_do_insn_bits;
1991 /* select 1/10MHz oscilator */
1992 if ((it->options[3] == 0) || (it->options[3] == 10)) {
1993 devpriv->i8253_osc_base = 100;
1995 devpriv->i8253_osc_base = 1000;
1998 /* max sampling speed */
1999 devpriv->ns_min = this_board->ns_min;
2001 if (!this_board->is_818) {
2002 if ((it->options[6] == 1) || (it->options[6] == 100))
2003 devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */
2014 ==============================================================================
2017 static int pcl818_detach(struct comedi_device *dev)
2019 /* printk("comedi%d: pcl818: remove\n", dev->minor); */
2020 free_resources(dev);