35 #include "../comedidev.h"
51 #define PCLx1x_RANGE 16
60 #define PCL816_CTRCTL 7
63 #define PCL816_RANGE 9
65 #define PCL816_CLRINT 10
69 #define PCL816_CONTROL 12
72 #define PCL816_STATUS 13
73 #define PCL816_STATUS_DRDY_MASK 0x80
76 #define PCL816_AD_LO 8
78 #define PCL816_AD_HI 9
81 #define INT_TYPE_AI1_INT 1
82 #define INT_TYPE_AI1_DMA 2
83 #define INT_TYPE_AI3_INT 4
84 #define INT_TYPE_AI3_DMA 5
86 #define INT_TYPE_AI1_DMA_RTC 9
87 #define INT_TYPE_AI3_DMA_RTC 10
91 #define RTC_IO_EXTENT 0x10
94 #define MAGIC_DMA_WORD 0x5a5a
129 #define devpriv ((struct pcl816_private *)dev->private)
133 static int RTC_timer_lock;
141 unsigned long rtc_iobase;
142 unsigned int rtc_iosize;
143 unsigned int rtc_irq;
174 unsigned long rtc_freq;
183 unsigned int *chanlist,
unsigned int chanlen);
186 unsigned int *chanlist,
unsigned int seglen);
190 unsigned int divisor1,
unsigned int divisor2);
192 static int set_rtc_irq_bit(
unsigned char bit);
211 DPRINTK(
"mode 0 analog input\n");
222 for (n = 0; n < insn->
n; n++) {
259 static irqreturn_t interrupt_pcl816_ai_mode13_int(
int irq,
void *
d)
268 PCL816_STATUS_DRDY_MASK))
275 pcl816_ai_cancel(dev, s);
290 if (++
devpriv->ai_act_chanlist_pos >=
devpriv->ai_act_chanlist_len)
291 devpriv->ai_act_chanlist_pos = 0;
293 s->
async->cur_chan++;
295 s->
async->cur_chan = 0;
303 pcl816_ai_cancel(dev, s);
316 unsigned int bufptr,
unsigned int len)
320 s->
async->events = 0;
322 for (i = 0; i < len; i++) {
326 if (++
devpriv->ai_act_chanlist_pos >=
327 devpriv->ai_act_chanlist_len) {
328 devpriv->ai_act_chanlist_pos = 0;
331 s->
async->cur_chan++;
333 s->
async->cur_chan = 0;
340 pcl816_ai_cancel(dev, s);
350 static irqreturn_t interrupt_pcl816_ai_mode13_dma(
int irq,
void *d)
354 int len,
bufptr, this_dma_buf;
355 unsigned long dma_flags;
359 this_dma_buf =
devpriv->next_dma_buf;
370 if (
devpriv->dma_runs_to_end) {
384 ptr = (
short *)
devpriv->dmabuf[this_dma_buf];
390 transfer_from_dma_buf(dev, s, ptr, bufptr, len);
398 static irqreturn_t interrupt_pcl816(
int irq,
void *d)
408 switch (
devpriv->int816_mode) {
411 return interrupt_pcl816_ai_mode13_dma(irq, d);
414 return interrupt_pcl816_ai_mode13_int(irq, d);
420 if (
devpriv->irq_was_now_closed) {
421 devpriv->irq_was_now_closed = 0;
444 printk(
KERN_INFO "pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",
456 int tmp, divisor1 = 0, divisor2 = 0;
459 pcl816_cmdtest_out(-1, cmd);
475 err |= cfc_check_trigger_is_unique(cmd->
convert_src);
476 err |= cfc_check_trigger_is_unique(cmd->
stop_src);
530 &divisor1, &divisor2,
546 if (!check_channel_list(dev, s, cmd->
chanlist,
557 unsigned int divisor1 = 0, divisor2 = 0, dma_flags,
bytes, dmairq;
592 start_pacer(dev, -1, 0, 0);
597 setup_channel_list(dev, s, cmd->
chanlist, seglen);
602 s->
async->cur_chan = 0;
605 devpriv->irq_was_now_closed = 0;
618 "pl816: You wankt WAKE_EOS but I dont want handle it");
626 if (!
devpriv->ai_neverending) {
628 bytes = s->
async->cmd.chanlist_len *
629 s->
async->cmd.chanlist_len *
633 devpriv->dma_runs_to_end = bytes /
639 if (
devpriv->dma_runs_to_end >= 0)
654 start_pacer(dev, 1, divisor1, divisor2);
655 dmairq = ((
devpriv->dma & 0x3) << 4) | (dev->
irq & 0x7);
679 DPRINTK(
"pcl816 END: pcl812_ai_cmd()\n");
686 unsigned int top1, top2,
i;
693 for (i = 0; i < 20; i++) {
700 spin_unlock_irqrestore(&dev->
spinlock, flags);
705 top1 =
devpriv->hwdmasize[0] - top1;
707 top2 = top1 -
devpriv->ai_poll_ptr;
709 spin_unlock_irqrestore(&dev->
spinlock, flags);
713 transfer_from_dma_buf(dev, s,
718 spin_unlock_irqrestore(&dev->
spinlock, flags);
720 return s->
async->buf_write_count - s->
async->buf_read_count;
732 if (
devpriv->irq_blocked > 0) {
733 switch (
devpriv->int816_mode) {
735 case INT_TYPE_AI1_DMA_RTC:
736 case INT_TYPE_AI3_DMA_RTC:
771 DEBUG(
printk(
"comedi: pcl816_ai_cancel() successful\n");)
779 static int pcl816_check(
unsigned long iobase)
825 unsigned int divisor2)
839 DPRINTK(
"mode %d, divisor1 %d, divisor2 %d\n", mode, divisor1,
859 unsigned int chanlen)
861 unsigned int chansegment[16];
862 unsigned int i, nowmustbechan, seglen, segpos;
872 chansegment[0] = chanlist[0];
873 for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
880 if (chanlist[0] == chanlist[i])
883 (
CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
884 if (nowmustbechan !=
CR_CHAN(chanlist[i])) {
887 "comedi%d: pcl816: channel list must "
888 "be continuous! chanlist[%i]=%d but "
889 "must be %d or %d!\n", dev->
minor,
890 i,
CR_CHAN(chanlist[i]), nowmustbechan,
895 chansegment[
i] = chanlist[
i];
899 for (i = 0, segpos = 0; i < chanlen; i++) {
901 CR_CHAN(chansegment[i % seglen]),
905 if (chanlist[i] != chansegment[i % seglen]) {
907 "comedi%d: pcl816: bad channel or range"
908 " number! chanlist[%i]=%d,%d,%d and not"
909 " %d,%d,%d!\n", dev->
minor, i,
915 CR_AREF(chansegment[i % seglen]));
937 devpriv->ai_act_chanlist_len = seglen;
938 devpriv->ai_act_chanlist_pos = 0;
940 for (i = 0; i < seglen; i++) {
950 (
devpriv->ai_act_chanlist[seglen - 1] << 4),
959 static int set_rtc_irq_bit(
unsigned char bit)
966 if (RTC_timer_lock > 1)
970 if (RTC_timer_lock < 0)
972 if (RTC_timer_lock > 0)
986 restore_flags(flags);
996 unsigned int irq,
dma;
1003 printk(
"comedi%d: pcl816: board=%s, ioport=0x%03lx", dev->
minor,
1004 board->
name, iobase);
1007 printk(
"I/O port conflict\n");
1013 if (pcl816_check(iobase)) {
1029 if (((1 << irq) & board->
IRQbits) == 0) {
1031 (
", IRQ %u is out of allowed range, "
1032 "DISABLING IT", irq);
1036 (irq, interrupt_pcl816, 0,
"pcl816", dev)) {
1038 (
", unable to allocate IRQ %u, "
1039 "DISABLING IT", irq);
1061 if (RTC_lock == 0) {
1069 #ifdef UNTESTED_CODE
1071 "pcl816 DMA (RTC)", dev)) {
1077 if (RTC_lock == 0) {
1086 printk(
"pcl816: RTC code missing");
1104 if (((1 << dma) & board->
DMAbits) == 0) {
1105 printk(
", DMA is out of allowed range, FAIL!\n");
1111 ", unable to allocate DMA %u, FAIL!\n", dma);
1121 printk(
", unable to allocate DMA buffer, FAIL!\n");
1137 ", unable to allocate DMA buffer, "
1174 s->
cancel = pcl816_ai_cancel;
1176 s->
do_cmd = pcl816_ai_cmd;
1177 s->
poll = pcl816_ai_poll;
1221 pcl816_ai_cancel(dev,
devpriv->sub_ai);
1232 if ((
devpriv->dma_rtc) && (RTC_lock == 1)) {
1250 {
"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
1259 {
"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
1271 .driver_name =
"pcl816",
1273 .attach = pcl816_attach,
1274 .detach = pcl816_detach,
1275 .board_name = &boardtypes[0].
name,