101 #include "../comedidev.h"
117 #define boardPCL818L 0
118 #define boardPCL818H 1
119 #define boardPCL818HD 2
120 #define boardPCL818HG 3
121 #define boardPCL818 4
122 #define boardPCL718 5
125 #define PCLx1x_RANGE 16
127 #define PCLx1xFIFO_RANGE 32
130 #define PCL818_CLRINT 8
132 #define PCL818_STATUS 8
134 #define PCL818_RANGE 1
138 #define PCL818_CONTROL 9
140 #define PCL818_CNTENABLE 10
143 #define PCL818_AD_LO 0
145 #define PCL818_AD_HI 1
147 #define PCL818_DA_LO 4
148 #define PCL818_DA_HI 5
150 #define PCL818_DI_LO 3
151 #define PCL818_DI_HI 11
153 #define PCL818_DO_LO 3
154 #define PCL818_DO_HI 11
156 #define PCL718_DA2_LO 6
157 #define PCL718_DA2_HI 7
159 #define PCL818_CTR0 12
160 #define PCL818_CTR1 13
161 #define PCL818_CTR2 14
163 #define PCL818_CTRCTL 15
166 #define PCL818_FI_ENABLE 6
168 #define PCL818_FI_INTCLR 20
170 #define PCL818_FI_FLUSH 25
172 #define PCL818_FI_STATUS 25
174 #define PCL818_FI_DATALO 23
175 #define PCL818_FI_DATAHI 23
178 #define INT_TYPE_AI1_INT 1
179 #define INT_TYPE_AI1_DMA 2
180 #define INT_TYPE_AI1_FIFO 3
181 #define INT_TYPE_AI3_INT 4
182 #define INT_TYPE_AI3_DMA 5
183 #define INT_TYPE_AI3_FIFO 6
184 #ifdef PCL818_MODE13_AO
185 #define INT_TYPE_AO1_INT 7
186 #define INT_TYPE_AO3_INT 8
191 #define INT_TYPE_AI1_DMA_RTC 9
192 #define INT_TYPE_AI3_DMA_RTC 10
195 #define RTC_IO_EXTENT 0x10
198 #define MAGIC_DMA_WORD 0x5a5a
213 static const struct comedi_lrange range_pcl818hg_ai = { 10, {
229 static const struct comedi_lrange range_pcl818l_l_ai = { 4, {
237 static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
253 static int RTC_timer_lock;
283 unsigned long rtc_iobase;
284 unsigned int rtc_iosize;
285 unsigned int rtc_irq;
287 unsigned long rtc_freq;
325 static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
326 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
329 #define devpriv ((struct pcl818_private *)dev->private)
337 unsigned int seglen);
345 unsigned int divisor1,
unsigned int divisor2);
348 static int set_rtc_irq_bit(
unsigned char bit);
349 static void rtc_dropped_irq(
unsigned long data);
350 static int rtc_setfreq_irq(
int freq);
373 for (n = 0; n < insn->
n; n++) {
412 for (n = 0; n < insn->
n; n++)
413 data[n] =
devpriv->ao_readback[chan];
425 for (n = 0; n < insn->
n; n++) {
426 devpriv->ao_readback[chan] = data[
n];
462 s->
state &= ~data[0];
463 s->
state |= (data[0] & data[1]);
478 static irqreturn_t interrupt_pcl818_ai_mode13_int(
int irq,
void *
d)
492 pcl818_ai_cancel(dev, s);
502 if ((low & 0xf) !=
devpriv->act_chanlist[
devpriv->act_chanlist_pos]) {
504 (
"comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
507 pcl818_ai_cancel(dev, s);
516 s->
async->cur_chan++;
519 s->
async->cur_chan = 0;
523 if (!
devpriv->neverending_ai) {
524 if (
devpriv->ai_act_scan == 0) {
525 pcl818_ai_cancel(dev, s);
537 static irqreturn_t interrupt_pcl818_ai_mode13_dma(
int irq,
void *d)
562 printk(
"comedi: A/D mode1/3 IRQ \n");
568 len =
devpriv->hwdmasize[0] >> 1;
571 for (i = 0; i < len; i++) {
572 if ((ptr[bufptr] & 0xf) !=
devpriv->act_chanlist[
devpriv->act_chanlist_pos]) {
574 (
"comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
578 pcl818_ai_cancel(dev, s);
590 s->
async->cur_chan++;
592 s->
async->cur_chan = 0;
597 if (
devpriv->ai_act_scan == 0) {
598 pcl818_ai_cancel(dev, s);
616 static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(
int irq,
void *d)
621 unsigned int top1, top2,
i,
bufptr;
623 short *dmabuf = (
short *)
devpriv->dmabuf[0];
627 case INT_TYPE_AI1_DMA_RTC:
628 case INT_TYPE_AI3_DMA_RTC:
633 for (i = 0; i < 10; i++) {
642 top1 =
devpriv->hwdmasize[0] - top1;
644 ofs_dats = top1 -
devpriv->last_top_dma;
646 ofs_dats = (
devpriv->dmasamplsize) + ofs_dats;
651 i &= (
devpriv->dmasamplsize - 1);
656 pcl818_ai_cancel(dev, s);
663 bufptr =
devpriv->last_top_dma;
665 for (i = 0; i < ofs_dats; i++) {
666 if ((dmabuf[bufptr] & 0xf) !=
devpriv->act_chanlist[
devpriv->act_chanlist_pos]) {
668 (
"comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
669 (dmabuf[bufptr] & 0xf),
671 act_chanlist[
devpriv->act_chanlist_pos]);
672 pcl818_ai_cancel(dev, s);
680 bufptr &= (
devpriv->dmasamplsize - 1);
683 if (
devpriv->act_chanlist_pos >=
687 s->
async->cur_chan++;
689 s->
async->cur_chan = 0;
694 if (
devpriv->ai_act_scan == 0) {
695 pcl818_ai_cancel(dev, s);
705 bufptr &= (
devpriv->dmasamplsize - 1);
721 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(
int irq,
void *d)
733 pcl818_ai_cancel(dev, s);
740 comedi_error(dev,
"A/D mode1/3 FIFO interrupt without data!");
741 pcl818_ai_cancel(dev, s);
752 for (i = 0; i < len; i++) {
754 if ((lo & 0xf) !=
devpriv->act_chanlist[
devpriv->act_chanlist_pos]) {
756 (
"comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
759 pcl818_ai_cancel(dev, s);
771 s->
async->cur_chan++;
773 s->
async->cur_chan = 0;
778 if (
devpriv->ai_act_scan == 0) {
779 pcl818_ai_cancel(dev, s);
795 static irqreturn_t interrupt_pcl818(
int irq,
void *d)
818 pcl818_ai_cancel(dev, s);
829 return interrupt_pcl818_ai_mode13_dma(irq, d);
832 return interrupt_pcl818_ai_mode13_int(irq, d);
835 return interrupt_pcl818_ai_mode13_fifo(irq, d);
836 #ifdef PCL818_MODE13_AO
837 case INT_TYPE_AO1_INT:
838 case INT_TYPE_AO3_INT:
839 return interrupt_pcl818_ao_mode13_int(irq, d);
867 printk(
"mode13dma_int, mode: %d\n", mode);
870 if (!
devpriv->neverending_ai) {
875 if (
devpriv->dma_runs_to_end >= 0)
902 static void pcl818_ai_mode13dma_rtc(
int mode,
struct comedi_device *dev,
916 pole = (
short *)
devpriv->dmabuf[0];
920 devpriv->rtc_freq = rtc_setfreq_irq(2048);
921 devpriv->rtc_irq_timer.expires =
924 devpriv->rtc_irq_timer.function = rtc_dropped_irq;
930 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
933 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
943 static int pcl818_ai_cmd_mode(
int mode,
struct comedi_device *dev,
947 int divisor1 = 0, divisor2 = 0;
959 start_pacer(dev, -1, 0, 0);
961 seglen = check_channel_list(dev, s,
devpriv->ai_chanlist,
965 setup_channel_list(dev, s,
devpriv->ai_chanlist,
973 devpriv->irq_was_now_closed = 0;
1001 pcl818_ai_mode13dma_int(mode, dev, s);
1005 pcl818_ai_mode13dma_rtc(mode, dev, s);
1043 start_pacer(dev, mode, divisor1, divisor2);
1047 case INT_TYPE_AI1_DMA_RTC:
1048 case INT_TYPE_AI3_DMA_RTC:
1062 #ifdef PCL818_MODE13_AO
1063 static int pcl818_ao_mode13(
int mode,
struct comedi_device *dev,
1066 int divisor1 = 0, divisor2 = 0;
1076 start_pacer(dev, -1, 0, 0);
1081 devpriv->irq_was_now_closed = 0;
1083 devpriv->act_chanlist_pos = 0;
1089 if (divisor1 == 1) {
1093 if (divisor2 == 1) {
1101 devpriv->int818_mode = INT_TYPE_AO1_INT;
1104 devpriv->int818_mode = INT_TYPE_AO3_INT;
1108 start_pacer(dev, mode, divisor1, divisor2);
1120 return pcl818_ao_mode13(1, dev, s, it);
1130 return pcl818_ao_mode13(3, dev, s, it);
1139 static void start_pacer(
struct comedi_device *dev,
int mode,
1140 unsigned int divisor1,
unsigned int divisor2)
1161 unsigned int *
chanlist,
unsigned int n_chan)
1163 unsigned int chansegment[16];
1164 unsigned int i, nowmustbechan, seglen, segpos;
1174 chansegment[0] = chanlist[0];
1176 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1183 if (chanlist[0] == chanlist[i])
1187 if (nowmustbechan !=
CR_CHAN(chanlist[i])) {
1189 (
"comedi%d: pcl818: channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
1191 nowmustbechan,
CR_CHAN(chanlist[0]));
1195 chansegment[
i] = chanlist[
i];
1199 for (i = 0, segpos = 0; i < n_chan; i++) {
1201 if (chanlist[i] != chansegment[i % seglen]) {
1203 (
"comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1207 CR_CHAN(chanlist[i % seglen]),
1209 CR_AREF(chansegment[i % seglen]));
1216 printk(
"check_channel_list: seglen %d\n", seglen);
1222 unsigned int *chanlist,
unsigned int n_chan,
1223 unsigned int seglen)
1227 devpriv->act_chanlist_len = seglen;
1228 devpriv->act_chanlist_pos = 0;
1230 for (i = 0; i < seglen; i++) {
1248 static int check_single_ended(
unsigned int port)
1263 int tmp, divisor1 = 0, divisor2 = 0;
1278 err |= cfc_check_trigger_is_unique(cmd->
convert_src);
1279 err |= cfc_check_trigger_is_unique(cmd->
stop_src);
1348 if (!check_channel_list(dev, s, cmd->
chanlist,
1381 retval = pcl818_ai_cmd_mode(1, dev, s);
1386 return pcl818_ai_cmd_mode(3, dev, s);
1400 if (
devpriv->irq_blocked > 0) {
1402 devpriv->irq_was_now_closed = 1;
1406 case INT_TYPE_AI1_DMA_RTC:
1407 case INT_TYPE_AI3_DMA_RTC:
1413 if (
devpriv->neverending_ai ||
1424 #ifdef PCL818_MODE13_AO
1425 case INT_TYPE_AO1_INT:
1426 case INT_TYPE_AO3_INT:
1430 start_pacer(dev, -1, 0, 0);
1445 devpriv->irq_was_now_closed = 0;
1459 static int pcl818_check(
unsigned long iobase)
1517 static int set_rtc_irq_bit(
unsigned char bit)
1520 unsigned long flags;
1524 if (RTC_timer_lock > 1)
1528 if (RTC_timer_lock < 0)
1530 if (RTC_timer_lock > 0)
1544 restore_flags(flags);
1552 static void rtc_dropped_irq(
unsigned long data)
1557 switch (
devpriv->int818_mode) {
1558 case INT_TYPE_AI1_DMA_RTC:
1559 case INT_TYPE_AI3_DMA_RTC:
1565 restore_flags(flags);
1574 static int rtc_setfreq_irq(
int freq)
1579 unsigned long flags;
1586 while (freq > (1 << tmp))
1589 rtc_freq = 1 <<
tmp;
1596 restore_flags(flags);
1608 unsigned long pages;
1618 (
"comedi%d: pcl818: board=%s, ioport=0x%03lx",
1633 if (pcl818_check(iobase)) {
1645 if (((1 << irq) & board->
IRQbits) == 0) {
1647 (
", IRQ %u is out of allowed range, DISABLING IT",
1652 (irq, interrupt_pcl818, 0,
"pcl818", dev)) {
1654 (
", unable to allocate IRQ %u, DISABLING IT",
1677 if (RTC_lock == 0) {
1686 "pcl818 DMA (RTC)", dev)) {
1692 if (RTC_lock == 0) {
1713 if (((1 << dma) & board->
DMAbits) == 0) {
1754 if (check_single_ended(dev->
iobase)) {
1766 s->
cancel = pcl818_ai_cancel;
1768 if ((irq) || (
devpriv->dma_rtc)) {
1826 #ifdef PCL818_MODE13_AO
1828 s->trig[1] = pcl818_ao_mode1;
1829 s->trig[3] = pcl818_ao_mode3;
1874 devpriv->i8253_osc_base = 100;
1876 devpriv->i8253_osc_base = 1000;
1896 pcl818_ai_cancel(dev,
devpriv->sub_ai);
1907 if ((
devpriv->dma_rtc) && (RTC_lock == 1)) {
1923 {
"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
1925 0x0a, 0xfff, 0xfff, 0, 1},
1926 {
"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1928 0x0a, 0xfff, 0xfff, 0, 1},
1929 {
"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1931 0x0a, 0xfff, 0xfff, 1, 1},
1932 {
"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
1934 0x0a, 0xfff, 0xfff, 1, 1},
1935 {
"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
1937 0x0a, 0xfff, 0xfff, 0, 1},
1940 0x0a, 0xfff, 0xfff, 0, 0},
1942 {
"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
1944 0x0a, 0xfff, 0xfff, 0, 1 },
1948 .driver_name =
"pcl818",
1950 .attach = pcl818_attach,
1951 .detach = pcl818_detach,
1952 .board_name = &boardtypes[0].
name,