diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/adv_pci1710.c')
-rw-r--r-- | drivers/staging/comedi/drivers/adv_pci1710.c | 769 |
1 files changed, 316 insertions, 453 deletions
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 31986608eaf1..def37bcc2a66 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -45,6 +45,7 @@ Configuration options: #include "../comedidev.h" +#include "comedi_fc.h" #include "8253.h" #include "amcc_s5933.h" @@ -52,17 +53,6 @@ Configuration options: * correct channel number on every 12 bit * sample */ -#undef PCI171X_EXTDEBUG - -#define DRV_NAME "adv_pci1710" - -#undef DPRINTK -#ifdef PCI171X_EXTDEBUG -#define DPRINTK(fmt, args...) printk(fmt, ## args) -#else -#define DPRINTK(fmt, args...) -#endif - #define PCI_VENDOR_ID_ADVANTECH 0x13fe /* hardware types of the cards */ @@ -211,44 +201,101 @@ struct boardtype { }; static const struct boardtype boardtypes[] = { - {"pci1710", 0x1710, - IORANGE_171x, 1, TYPE_PCI171X, - 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, - &range_pci1710_3, range_codes_pci1710_3, - &range_pci171x_da, - 10000, 2048}, - {"pci1710hg", 0x1710, - IORANGE_171x, 1, TYPE_PCI171X, - 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff, - &range_pci1710hg, range_codes_pci1710hg, - &range_pci171x_da, - 10000, 2048}, - {"pci1711", 0x1711, - IORANGE_171x, 1, TYPE_PCI171X, - 16, 0, 2, 16, 16, 1, 0x0fff, 0x0fff, - &range_pci17x1, range_codes_pci17x1, &range_pci171x_da, - 10000, 512}, - {"pci1713", 0x1713, - IORANGE_171x, 1, TYPE_PCI1713, - 32, 16, 0, 0, 0, 0, 0x0fff, 0x0000, - &range_pci1710_3, range_codes_pci1710_3, NULL, - 10000, 2048}, - {"pci1720", 0x1720, - IORANGE_1720, 0, TYPE_PCI1720, - 0, 0, 4, 0, 0, 0, 0x0000, 0x0fff, - NULL, NULL, &range_pci1720, - 0, 0}, - {"pci1731", 0x1731, - IORANGE_171x, 1, TYPE_PCI171X, - 16, 0, 0, 16, 16, 0, 0x0fff, 0x0000, - &range_pci17x1, range_codes_pci17x1, NULL, - 10000, 512}, - /* dummy entry corresponding to driver name */ - {.name = DRV_NAME}, + { + .name = "pci1710", + .device_id = 0x1710, + .iorange = IORANGE_171x, + .have_irq = 1, + .cardtype = TYPE_PCI171X, + .n_aichan = 16, + .n_aichand = 8, + .n_aochan = 2, + .n_dichan = 16, + .n_dochan = 16, + .n_counter = 1, + .ai_maxdata = 0x0fff, + .ao_maxdata = 0x0fff, + .rangelist_ai = &range_pci1710_3, + .rangecode_ai = range_codes_pci1710_3, + .rangelist_ao = &range_pci171x_da, + .ai_ns_min = 10000, + .fifo_half_size = 2048, + }, { + .name = "pci1710hg", + .device_id = 0x1710, + .iorange = IORANGE_171x, + .have_irq = 1, + .cardtype = TYPE_PCI171X, + .n_aichan = 16, + .n_aichand = 8, + .n_aochan = 2, + .n_dichan = 16, + .n_dochan = 16, + .n_counter = 1, + .ai_maxdata = 0x0fff, + .ao_maxdata = 0x0fff, + .rangelist_ai = &range_pci1710hg, + .rangecode_ai = range_codes_pci1710hg, + .rangelist_ao = &range_pci171x_da, + .ai_ns_min = 10000, + .fifo_half_size = 2048, + }, { + .name = "pci1711", + .device_id = 0x1711, + .iorange = IORANGE_171x, + .have_irq = 1, + .cardtype = TYPE_PCI171X, + .n_aichan = 16, + .n_aochan = 2, + .n_dichan = 16, + .n_dochan = 16, + .n_counter = 1, + .ai_maxdata = 0x0fff, + .ao_maxdata = 0x0fff, + .rangelist_ai = &range_pci17x1, + .rangecode_ai = range_codes_pci17x1, + .rangelist_ao = &range_pci171x_da, + .ai_ns_min = 10000, + .fifo_half_size = 512, + }, { + .name = "pci1713", + .device_id = 0x1713, + .iorange = IORANGE_171x, + .have_irq = 1, + .cardtype = TYPE_PCI1713, + .n_aichan = 32, + .n_aichand = 16, + .ai_maxdata = 0x0fff, + .rangelist_ai = &range_pci1710_3, + .rangecode_ai = range_codes_pci1710_3, + .ai_ns_min = 10000, + .fifo_half_size = 2048, + }, { + .name = "pci1720", + .device_id = 0x1720, + .iorange = IORANGE_1720, + .cardtype = TYPE_PCI1720, + .n_aochan = 4, + .ao_maxdata = 0x0fff, + .rangelist_ao = &range_pci1720, + }, { + .name = "pci1731", + .device_id = 0x1731, + .iorange = IORANGE_171x, + .have_irq = 1, + .cardtype = TYPE_PCI171X, + .n_aichan = 16, + .n_dichan = 16, + .n_dochan = 16, + .ai_maxdata = 0x0fff, + .rangelist_ai = &range_pci17x1, + .rangecode_ai = range_codes_pci17x1, + .ai_ns_min = 10000, + .fifo_half_size = 512, + }, }; struct pci1710_private { - char valid; /* card is usable */ char neverending_ai; /* we do unlimited AI */ unsigned int CntrlReg; /* Control register */ unsigned int i8254_osc_base; /* frequence of onboard oscilator */ @@ -278,33 +325,108 @@ struct pci1710_private { * internal state */ }; -#define devpriv ((struct pci1710_private *)dev->private) -#define this_board ((const struct boardtype *)dev->board_ptr) +/* used for gain list programming */ +static const unsigned int muxonechan[] = { + 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, + 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, + 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, + 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f +}; /* ============================================================================== + Check if channel list from user is builded correctly + If it's ok, then program scan/gain logic. + This works for all cards. */ - static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan); + unsigned int *chanlist, unsigned int n_chan) +{ + unsigned int chansegment[32]; + unsigned int i, nowmustbechan, seglen, segpos; + + /* correct channel and range number check itself comedi/range.c */ + if (n_chan < 1) { + comedi_error(dev, "range/channel list is empty!"); + return 0; + } + + if (n_chan == 1) + return 1; /* seglen=1 */ + + chansegment[0] = chanlist[0]; /* first channel is every time ok */ + for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { + if (chanlist[0] == chanlist[i]) + break; /* we detected a loop, stop */ + if ((CR_CHAN(chanlist[i]) & 1) && + (CR_AREF(chanlist[i]) == AREF_DIFF)) { + comedi_error(dev, "Odd channel cannot be differential input!\n"); + return 0; + } + nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; + if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) + nowmustbechan = (nowmustbechan + 1) % s->n_chan; + if (nowmustbechan != CR_CHAN(chanlist[i])) { + printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", + i, CR_CHAN(chanlist[i]), nowmustbechan, + CR_CHAN(chanlist[0])); + return 0; + } + chansegment[i] = chanlist[i]; /* next correct channel in list */ + } + + for (i = 0, segpos = 0; i < n_chan; i++) { + if (chanlist[i] != chansegment[i % seglen]) { + printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", + i, CR_CHAN(chansegment[i]), + CR_RANGE(chansegment[i]), + CR_AREF(chansegment[i]), + CR_CHAN(chanlist[i % seglen]), + CR_RANGE(chanlist[i % seglen]), + CR_AREF(chansegment[i % seglen])); + return 0; + } + } + return seglen; +} + static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan, - unsigned int seglen); -static void start_pacer(struct comedi_device *dev, int mode, - unsigned int divisor1, unsigned int divisor2); -static int pci1710_reset(struct comedi_device *dev); -static int pci171x_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s); + unsigned int seglen) +{ + const struct boardtype *this_board = comedi_board(dev); + struct pci1710_private *devpriv = dev->private; + unsigned int i, range, chanprog; -/* used for gain list programming */ -static const unsigned int muxonechan[] = { - 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, - 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, - 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, - 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f -}; + devpriv->act_chanlist_len = seglen; + devpriv->act_chanlist_pos = 0; + + for (i = 0; i < seglen; i++) { /* store range list to card */ + chanprog = muxonechan[CR_CHAN(chanlist[i])]; + outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ + range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; + if (CR_AREF(chanlist[i]) == AREF_DIFF) + range |= 0x0020; + outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ +#ifdef PCI171x_PARANOIDCHECK + devpriv->act_chanlist[i] = + (CR_CHAN(chanlist[i]) << 12) & 0xf000; +#endif + } +#ifdef PCI171x_PARANOIDCHECK + for ( ; i < n_chan; i++) { /* store remainder of channel list */ + devpriv->act_chanlist[i] = + (CR_CHAN(chanlist[i]) << 12) & 0xf000; + } +#endif + + devpriv->ai_et_MuxVal = + CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); + /* select channel interval to scan */ + outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); +} /* ============================================================================== @@ -313,12 +435,13 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci1710_private *devpriv = dev->private; int n, timeout; #ifdef PCI171x_PARANOIDCHECK + const struct boardtype *this_board = comedi_board(dev); unsigned int idata; #endif - DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n"); devpriv->CntrlReg &= Control_CNT0; devpriv->CntrlReg |= Control_SW; /* set software trigger */ outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); @@ -327,32 +450,18 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, setup_channel_list(dev, s, &insn->chanspec, 1, 1); - DPRINTK("adv_pci1710 A ST=%4x IO=%x\n", - inw(dev->iobase + PCI171x_STATUS), - dev->iobase + PCI171x_STATUS); for (n = 0; n < insn->n; n++) { outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */ - DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n, - inw(dev->iobase + PCI171x_STATUS)); /* udelay(1); */ - DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n, - inw(dev->iobase + PCI171x_STATUS)); timeout = 100; while (timeout--) { if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE)) goto conv_finish; - if (!(timeout % 10)) - DPRINTK("adv_pci1710 D n=%d tm=%d ST=%4x\n", n, - timeout, - inw(dev->iobase + PCI171x_STATUS)); } comedi_error(dev, "A/D insn timeout"); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); data[n] = 0; - DPRINTK - ("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", - n); return -ETIME; conv_finish: @@ -373,7 +482,6 @@ conv_finish: outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); - DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n); return n; } @@ -384,6 +492,7 @@ static int pci171x_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci1710_private *devpriv = dev->private; int n, chan, range, ofs; chan = CR_CHAN(insn->chanspec); @@ -416,6 +525,7 @@ static int pci171x_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci1710_private *devpriv = dev->private; int n, chan; chan = CR_CHAN(insn->chanspec); @@ -457,6 +567,23 @@ static int pci171x_insn_bits_do(struct comedi_device *dev, /* ============================================================================== */ +static void start_pacer(struct comedi_device *dev, int mode, + unsigned int divisor1, unsigned int divisor2) +{ + outw(0xb4, dev->iobase + PCI171x_CNTCTRL); + outw(0x74, dev->iobase + PCI171x_CNTCTRL); + + if (mode == 1) { + outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2); + outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2); + outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1); + outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1); + } +} + +/* +============================================================================== +*/ static int pci171x_insn_counter_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -486,6 +613,7 @@ static int pci171x_insn_counter_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { + struct pci1710_private *devpriv = dev->private; uint msb, lsb, ccntrl, status; lsb = data[0] & 0x00FF; @@ -517,6 +645,7 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, { #ifdef unused /* This doesn't work like a normal Comedi counter config */ + struct pci1710_private *devpriv = dev->private; uint ccntrl = 0; devpriv->cnt0_write_wait = data[0] & 0x20; @@ -552,6 +681,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + struct pci1710_private *devpriv = dev->private; int n, rangereg, chan; chan = CR_CHAN(insn->chanspec); @@ -575,16 +705,47 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, /* ============================================================================== */ +static int pci171x_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + const struct boardtype *this_board = comedi_board(dev); + struct pci1710_private *devpriv = dev->private; + + switch (this_board->cardtype) { + default: + devpriv->CntrlReg &= Control_CNT0; + devpriv->CntrlReg |= Control_SW; + + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ + start_pacer(dev, -1, 0, 0); + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); + break; + } + + devpriv->ai_do = 0; + devpriv->ai_act_scan = 0; + s->async->cur_chan = 0; + devpriv->ai_buf_ptr = 0; + devpriv->neverending_ai = 0; + + return 0; +} + +/* +============================================================================== +*/ static void interrupt_pci1710_every_sample(void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = dev->subdevices + 0; + struct pci1710_private *devpriv = dev->private; + struct comedi_subdevice *s = &dev->subdevices[0]; int m; #ifdef PCI171x_PARANOIDCHECK + const struct boardtype *this_board = comedi_board(dev); short sampl; #endif - DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n"); m = inw(dev->iobase + PCI171x_STATUS); if (m & Status_FE) { printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m); @@ -605,11 +766,9 @@ static void interrupt_pci1710_every_sample(void *d) outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ - DPRINTK("FOR "); for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { #ifdef PCI171x_PARANOIDCHECK sampl = inw(dev->iobase + PCI171x_AD_DATA); - DPRINTK("%04x:", sampl); if (this_board->cardtype != TYPE_PCI1713) if ((sampl & 0xf000) != devpriv->act_chanlist[s->async->cur_chan]) { @@ -626,8 +785,6 @@ static void interrupt_pci1710_every_sample(void *d) comedi_event(dev, s); return; } - DPRINTK("%8d %2d %8d~", s->async->buf_int_ptr, - s->async->cur_chan, s->async->buf_int_count); comedi_buf_put(s->async, sampl & 0x0fff); #else comedi_buf_put(s->async, @@ -641,11 +798,6 @@ static void interrupt_pci1710_every_sample(void *d) if (s->async->cur_chan == 0) { /* one scan done */ devpriv->ai_act_scan++; - DPRINTK - ("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n", - s->async->buf_int_count, s->async->buf_int_ptr, - s->async->buf_user_count, s->async->buf_user_ptr); - DPRINTK("adv_pci1710 EDBG: EOS2\n"); if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) { /* all data sampled */ @@ -658,7 +810,6 @@ static void interrupt_pci1710_every_sample(void *d) } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ - DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n"); comedi_event(dev, s); } @@ -669,12 +820,13 @@ static void interrupt_pci1710_every_sample(void *d) static int move_block_from_fifo(struct comedi_device *dev, struct comedi_subdevice *s, int n, int turn) { + struct pci1710_private *devpriv = dev->private; int i, j; #ifdef PCI171x_PARANOIDCHECK + const struct boardtype *this_board = comedi_board(dev); int sampl; #endif - DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n", n, - turn); + j = s->async->cur_chan; for (i = 0; i < n; i++) { #ifdef PCI171x_PARANOIDCHECK @@ -705,7 +857,6 @@ static int move_block_from_fifo(struct comedi_device *dev, } } s->async->cur_chan = j; - DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n"); return 0; } @@ -715,10 +866,11 @@ static int move_block_from_fifo(struct comedi_device *dev, static void interrupt_pci1710_half_fifo(void *d) { struct comedi_device *dev = d; - struct comedi_subdevice *s = dev->subdevices + 0; + const struct boardtype *this_board = comedi_board(dev); + struct pci1710_private *devpriv = dev->private; + struct comedi_subdevice *s = &dev->subdevices[0]; int m, samplesinbuf; - DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n"); m = inw(dev->iobase + PCI171x_STATUS); if (!(m & Status_FH)) { printk("comedi%d: A/D FIFO not half full! (%4x)\n", @@ -760,7 +912,6 @@ static void interrupt_pci1710_half_fifo(void *d) return; } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ - DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n"); comedi_event(dev, s); } @@ -771,18 +922,14 @@ static void interrupt_pci1710_half_fifo(void *d) static irqreturn_t interrupt_service_pci1710(int irq, void *d) { struct comedi_device *dev = d; + struct pci1710_private *devpriv = dev->private; - DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n", - irq); if (!dev->attached) /* is device attached? */ return IRQ_NONE; /* no, exit */ /* is this interrupt from our board? */ if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) return IRQ_NONE; /* no, exit */ - DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n", - inw(dev->iobase + PCI171x_STATUS)); - if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */ devpriv->ai_et = 0; devpriv->CntrlReg &= Control_CNT0; @@ -802,7 +949,6 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) } else { interrupt_pci1710_half_fifo(d); } - DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n"); return IRQ_HANDLED; } @@ -812,11 +958,11 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, struct comedi_subdevice *s) { + const struct boardtype *this_board = comedi_board(dev); + struct pci1710_private *devpriv = dev->private; unsigned int divisor1 = 0, divisor2 = 0; unsigned int seglen; - DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n", - mode); start_pacer(dev, -1, 0, 0); /* stop pacer */ seglen = check_channel_list(dev, s, devpriv->ai_chanlist, @@ -869,10 +1015,6 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, &divisor2, &devpriv->ai_timer1, devpriv->ai_flags & TRIG_ROUND_MASK); - DPRINTK - ("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n", - devpriv->i8254_osc_base, divisor1, divisor2, - devpriv->ai_timer1); outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); if (mode != 2) { /* start pacer */ @@ -888,27 +1030,9 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, break; } - DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n"); return 0; } -#ifdef PCI171X_EXTDEBUG -/* -============================================================================== -*/ -static void pci171x_cmdtest_out(int e, struct comedi_cmd *cmd) -{ - printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e, - cmd->start_src, cmd->scan_begin_src, cmd->convert_src); - printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n", e, - cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg); - printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src, - cmd->scan_end_src); - printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", - e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len); -} -#endif - /* ============================================================================== */ @@ -916,83 +1040,33 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { + const struct boardtype *this_board = comedi_board(dev); + struct pci1710_private *devpriv = dev->private; int err = 0; int tmp; unsigned int divisor1 = 0, divisor2 = 0; - DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n"); -#ifdef PCI171X_EXTDEBUG - pci171x_cmdtest_out(-1, cmd); -#endif - /* step 1: make sure trigger sources are trivially valid */ + /* Step 1 : check if triggers are trivially valid */ - tmp = cmd->start_src; - cmd->start_src &= TRIG_NOW | TRIG_EXT; - if (!cmd->start_src || tmp != cmd->start_src) - err++; - - tmp = cmd->scan_begin_src; - cmd->scan_begin_src &= TRIG_FOLLOW; - if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) - err++; + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); - tmp = cmd->convert_src; - cmd->convert_src &= TRIG_TIMER | TRIG_EXT; - if (!cmd->convert_src || tmp != cmd->convert_src) - err++; - - tmp = cmd->scan_end_src; - cmd->scan_end_src &= TRIG_COUNT; - if (!cmd->scan_end_src || tmp != cmd->scan_end_src) - err++; - - tmp = cmd->stop_src; - cmd->stop_src &= TRIG_COUNT | TRIG_NONE; - if (!cmd->stop_src || tmp != cmd->stop_src) - err++; - - if (err) { -#ifdef PCI171X_EXTDEBUG - pci171x_cmdtest_out(1, cmd); -#endif - DPRINTK( - "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n", - err); + if (err) return 1; - } - - /* step2: make sure trigger srcs are unique and mutually compatible */ - - if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) { - cmd->start_src = TRIG_NOW; - err++; - } - if (cmd->scan_begin_src != TRIG_FOLLOW) { - cmd->scan_begin_src = TRIG_FOLLOW; - err++; - } + /* step 2a: make sure trigger sources are unique */ - if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) - err++; + err |= cfc_check_trigger_is_unique(cmd->start_src); + err |= cfc_check_trigger_is_unique(cmd->convert_src); + err |= cfc_check_trigger_is_unique(cmd->stop_src); - if (cmd->scan_end_src != TRIG_COUNT) { - cmd->scan_end_src = TRIG_COUNT; - err++; - } - - if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) - err++; + /* step 2b: and mutually compatible */ - if (err) { -#ifdef PCI171X_EXTDEBUG - pci171x_cmdtest_out(2, cmd); -#endif - DPRINTK( - "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n", - err); + if (err) return 2; - } /* step 3: make sure arguments are trivially compatible */ @@ -1034,15 +1108,8 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, } } - if (err) { -#ifdef PCI171X_EXTDEBUG - pci171x_cmdtest_out(3, cmd); -#endif - DPRINTK( - "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n", - err); + if (err) return 3; - } /* step 4: fix up any arguments */ @@ -1057,12 +1124,8 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, err++; } - if (err) { - DPRINTK - ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n", - err); + if (err) return 4; - } /* step 5: complain about special chanlist considerations */ @@ -1072,7 +1135,6 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, return 5; /* incorrect channels list */ } - DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n"); return 0; } @@ -1081,9 +1143,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, */ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct pci1710_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n"); devpriv->ai_n_chan = cmd->chanlist_len; devpriv->ai_chanlist = cmd->chanlist; devpriv->ai_flags = cmd->flags; @@ -1115,162 +1177,12 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* ============================================================================== - Check if channel list from user is builded correctly - If it's ok, then program scan/gain logic. - This works for all cards. -*/ -static int check_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan) -{ - unsigned int chansegment[32]; - unsigned int i, nowmustbechan, seglen, segpos; - - DPRINTK("adv_pci1710 EDBG: check_channel_list(...,%d)\n", n_chan); - /* correct channel and range number check itself comedi/range.c */ - if (n_chan < 1) { - comedi_error(dev, "range/channel list is empty!"); - return 0; - } - - if (n_chan == 1) - return 1; /* seglen=1 */ - - chansegment[0] = chanlist[0]; /* first channel is every time ok */ - for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { - if (chanlist[0] == chanlist[i]) - break; /* we detected a loop, stop */ - if ((CR_CHAN(chanlist[i]) & 1) && - (CR_AREF(chanlist[i]) == AREF_DIFF)) { - comedi_error(dev, "Odd channel cannot be differential input!\n"); - return 0; - } - nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; - if (CR_AREF(chansegment[i - 1]) == AREF_DIFF) - nowmustbechan = (nowmustbechan + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { - printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", - i, CR_CHAN(chanlist[i]), nowmustbechan, - CR_CHAN(chanlist[0])); - return 0; - } - chansegment[i] = chanlist[i]; /* next correct channel in list */ - } - - for (i = 0, segpos = 0; i < n_chan; i++) { - if (chanlist[i] != chansegment[i % seglen]) { - printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n", - i, CR_CHAN(chansegment[i]), - CR_RANGE(chansegment[i]), - CR_AREF(chansegment[i]), - CR_CHAN(chanlist[i % seglen]), - CR_RANGE(chanlist[i % seglen]), - CR_AREF(chansegment[i % seglen])); - return 0; - } - } - return seglen; -} - -static void setup_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan, - unsigned int seglen) -{ - unsigned int i, range, chanprog; - - DPRINTK("adv_pci1710 EDBG: setup_channel_list(...,%d,%d)\n", n_chan, - seglen); - devpriv->act_chanlist_len = seglen; - devpriv->act_chanlist_pos = 0; - - DPRINTK("SegLen: %d\n", seglen); - for (i = 0; i < seglen; i++) { /* store range list to card */ - chanprog = muxonechan[CR_CHAN(chanlist[i])]; - outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ - range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; - if (CR_AREF(chanlist[i]) == AREF_DIFF) - range |= 0x0020; - outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ -#ifdef PCI171x_PARANOIDCHECK - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; -#endif - DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, - devpriv->act_chanlist[i]); - } -#ifdef PCI171x_PARANOIDCHECK - for ( ; i < n_chan; i++) { /* store remainder of channel list */ - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; - } -#endif - - devpriv->ai_et_MuxVal = - CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); - /* select channel interval to scan */ - outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); - DPRINTK("MUX: %4x L%4x.H%4x\n", - CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8), - CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1])); -} - -/* -============================================================================== -*/ -static void start_pacer(struct comedi_device *dev, int mode, - unsigned int divisor1, unsigned int divisor2) -{ - DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, - divisor1, divisor2); - outw(0xb4, dev->iobase + PCI171x_CNTCTRL); - outw(0x74, dev->iobase + PCI171x_CNTCTRL); - - if (mode == 1) { - outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2); - outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2); - outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1); - outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1); - } - DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n"); -} - -/* -============================================================================== -*/ -static int pci171x_ai_cancel(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n"); - - switch (this_board->cardtype) { - default: - devpriv->CntrlReg &= Control_CNT0; - devpriv->CntrlReg |= Control_SW; - - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ - start_pacer(dev, -1, 0, 0); - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); - break; - } - - devpriv->ai_do = 0; - devpriv->ai_act_scan = 0; - s->async->cur_chan = 0; - devpriv->ai_buf_ptr = 0; - devpriv->neverending_ai = 0; - - DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n"); - return 0; -} - -/* -============================================================================== */ static int pci171x_reset(struct comedi_device *dev) { - DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n"); + const struct boardtype *this_board = comedi_board(dev); + struct pci1710_private *devpriv = dev->private; + outw(0x30, dev->iobase + PCI171x_CNTCTRL); devpriv->CntrlReg = Control_SW | Control_CNT0; /* Software trigger, CNT0=external */ outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */ @@ -1291,7 +1203,6 @@ static int pci171x_reset(struct comedi_device *dev) outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ - DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n"); return 0; } @@ -1300,7 +1211,8 @@ static int pci171x_reset(struct comedi_device *dev) */ static int pci1720_reset(struct comedi_device *dev) { - DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n"); + struct pci1710_private *devpriv = dev->private; + outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); /* set synchronous output mode */ devpriv->da_ranges = 0xAA; outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); /* set all ranges to +/-5V */ @@ -1313,7 +1225,6 @@ static int pci1720_reset(struct comedi_device *dev) devpriv->ao_data[1] = 0x0800; devpriv->ao_data[2] = 0x0800; devpriv->ao_data[3] = 0x0800; - DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n"); return 0; } @@ -1322,85 +1233,55 @@ static int pci1720_reset(struct comedi_device *dev) */ static int pci1710_reset(struct comedi_device *dev) { - DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n"); + const struct boardtype *this_board = comedi_board(dev); + switch (this_board->cardtype) { case TYPE_PCI1720: return pci1720_reset(dev); default: return pci171x_reset(dev); } - DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n"); } -static struct pci_dev *pci1710_find_pci_dev(struct comedi_device *dev, - struct comedi_devconfig *it) +static const void *pci1710_find_boardinfo(struct comedi_device *dev, + struct pci_dev *pcidev) { - struct pci_dev *pcidev = NULL; - int bus = it->options[0]; - int slot = it->options[1]; - int board_index = this_board - boardtypes; + const struct boardtype *this_board; int i; - for_each_pci_dev(pcidev) { - if (bus || slot) { - if (bus != pcidev->bus->number || - slot != PCI_SLOT(pcidev->devfn)) - continue; - } - if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH) - continue; - if (pci_is_enabled(pcidev)) - continue; - - if (strcmp(this_board->name, DRV_NAME) == 0) { - for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) { - if (pcidev->device == boardtypes[i].device_id) { - board_index = i; - break; - } - } - if (i == ARRAY_SIZE(boardtypes)) - continue; - } else { - if (pcidev->device != boardtypes[board_index].device_id) - continue; - } - dev->board_ptr = &boardtypes[board_index]; - return pcidev; + for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { + this_board = &boardtypes[i]; + if (pcidev->device == this_board->device_id) + return this_board; } - dev_err(dev->class_dev, - "No supported board found! (req. bus %d, slot %d)\n", - bus, slot); return NULL; } -static int pci1710_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static int pci1710_attach_pci(struct comedi_device *dev, + struct pci_dev *pcidev) { - struct pci_dev *pcidev; + const struct boardtype *this_board; + struct pci1710_private *devpriv; struct comedi_subdevice *s; int ret, subdev, n_subdevices; - unsigned int irq; - dev_info(dev->class_dev, DRV_NAME ": attach\n"); + comedi_set_hw_dev(dev, &pcidev->dev); - ret = alloc_private(dev, sizeof(struct pci1710_private)); - if (ret < 0) - return -ENOMEM; + this_board = pci1710_find_boardinfo(dev, pcidev); + if (!this_board) + return -ENODEV; + dev->board_ptr = this_board; + dev->board_name = this_board->name; - pcidev = pci1710_find_pci_dev(dev, it); - if (!pcidev) - return -EIO; - comedi_set_hw_dev(dev, &pcidev->dev); + ret = alloc_private(dev, sizeof(*devpriv)); + if (ret < 0) + return ret; + devpriv = dev->private; - ret = comedi_pci_enable(pcidev, DRV_NAME); + ret = comedi_pci_enable(pcidev, dev->board_name); if (ret) return ret; - dev->iobase = pci_resource_start(pcidev, 2); - irq = pcidev->irq; - - dev->board_name = this_board->name; n_subdevices = 0; if (this_board->n_aichan) @@ -1420,30 +1301,17 @@ static int pci1710_attach(struct comedi_device *dev, pci1710_reset(dev); - if (this_board->have_irq) { - if (irq) { - if (request_irq(irq, interrupt_service_pci1710, - IRQF_SHARED, "Advantech PCI-1710", - dev)) { - dev_dbg(dev->class_dev, - "unable to allocate IRQ %d, DISABLING IT", - irq); - irq = 0; /* Can't use IRQ */ - } else { - dev_dbg(dev->class_dev, "irq=%u", irq); - } - } else { - dev_dbg(dev->class_dev, "IRQ disabled"); - } - } else { - irq = 0; + if (this_board->have_irq && pcidev->irq) { + ret = request_irq(pcidev->irq, interrupt_service_pci1710, + IRQF_SHARED, dev->board_name, dev); + if (ret == 0) + dev->irq = pcidev->irq; } - dev->irq = irq; subdev = 0; if (this_board->n_aichan) { - s = dev->subdevices + subdev; + s = &dev->subdevices[subdev]; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; @@ -1455,7 +1323,7 @@ static int pci1710_attach(struct comedi_device *dev, s->range_table = this_board->rangelist_ai; s->cancel = pci171x_ai_cancel; s->insn_read = pci171x_insn_read_ai; - if (irq) { + if (dev->irq) { s->subdev_flags |= SDF_CMD_READ; s->do_cmdtest = pci171x_ai_cmdtest; s->do_cmd = pci171x_ai_cmd; @@ -1465,7 +1333,7 @@ static int pci1710_attach(struct comedi_device *dev, } if (this_board->n_aochan) { - s = dev->subdevices + subdev; + s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_aochan; @@ -1485,7 +1353,7 @@ static int pci1710_attach(struct comedi_device *dev, } if (this_board->n_dichan) { - s = dev->subdevices + subdev; + s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_dichan; @@ -1498,7 +1366,7 @@ static int pci1710_attach(struct comedi_device *dev, } if (this_board->n_dochan) { - s = dev->subdevices + subdev; + s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_dochan; @@ -1513,7 +1381,7 @@ static int pci1710_attach(struct comedi_device *dev, } if (this_board->n_counter) { - s = dev->subdevices + subdev; + s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = this_board->n_counter; @@ -1526,7 +1394,8 @@ static int pci1710_attach(struct comedi_device *dev, subdev++; } - devpriv->valid = 1; + dev_info(dev->class_dev, "%s attached, irq %sabled\n", + dev->board_name, dev->irq ? "en" : "dis"); return 0; } @@ -1535,27 +1404,21 @@ static void pci1710_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - if (dev->private) { - if (devpriv->valid) - pci1710_reset(dev); - if (dev->irq) - free_irq(dev->irq, dev); - } + if (dev->iobase) + pci1710_reset(dev); + if (dev->irq) + free_irq(dev->irq, dev); if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); - pci_dev_put(pcidev); } } static struct comedi_driver adv_pci1710_driver = { .driver_name = "adv_pci1710", .module = THIS_MODULE, - .attach = pci1710_attach, + .attach_pci = pci1710_attach_pci, .detach = pci1710_detach, - .num_names = ARRAY_SIZE(boardtypes), - .board_name = &boardtypes[0].name, - .offset = sizeof(struct boardtype), }; static int __devinit adv_pci1710_pci_probe(struct pci_dev *dev, |