diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/pcmmio.c')
-rw-r--r-- | drivers/staging/comedi/drivers/pcmmio.c | 287 |
1 files changed, 153 insertions, 134 deletions
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index cdf501afa14e..d812c2c3af12 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -139,15 +139,16 @@ Configuration Options: #define PAGE_ENAB 2 #define PAGE_INT_ID 3 -typedef int (*comedi_insn_fn_t) (struct comedi_device *, struct comedi_subdevice *, - struct comedi_insn *, unsigned int *); +typedef int (*comedi_insn_fn_t) (struct comedi_device *, + struct comedi_subdevice *, + struct comedi_insn *, unsigned int *); -static int ai_rinsn(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, - unsigned int *); -static int ao_rinsn(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, - unsigned int *); -static int ao_winsn(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, - unsigned int *); +static int ai_rinsn(struct comedi_device *, struct comedi_subdevice *, + struct comedi_insn *, unsigned int *); +static int ao_rinsn(struct comedi_device *, struct comedi_subdevice *, + struct comedi_insn *, unsigned int *); +static int ao_winsn(struct comedi_device *, struct comedi_subdevice *, + struct comedi_insn *, unsigned int *); /* * Board descriptions for two imaginary boards. Describing the @@ -168,30 +169,30 @@ struct pcmmio_board { }; static const struct comedi_lrange ranges_ai = - { 4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0., - 10.)} + { 4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0., + 10.)} }; static const struct comedi_lrange ranges_ao = - { 6, {RANGE(0., 5.), RANGE(0., 10.), RANGE(-5., 5.), RANGE(-10., 10.), - RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)} + { 6, {RANGE(0., 5.), RANGE(0., 10.), RANGE(-5., 5.), RANGE(-10., 10.), + RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)} }; static const struct pcmmio_board pcmmio_boards[] = { { - .name = "pcmmio", - .dio_num_asics = 1, - .dio_num_ports = 6, - .total_iosize = 32, - .ai_bits = 16, - .ao_bits = 16, - .n_ai_chans = 16, - .n_ao_chans = 8, - .ai_range_table = &ranges_ai, - .ao_range_table = &ranges_ao, - .ai_rinsn = ai_rinsn, - .ao_rinsn = ao_rinsn, - .ao_winsn = ao_winsn}, + .name = "pcmmio", + .dio_num_asics = 1, + .dio_num_ports = 6, + .total_iosize = 32, + .ai_bits = 16, + .ao_bits = 16, + .n_ai_chans = 16, + .n_ao_chans = 8, + .ai_range_table = &ranges_ai, + .ao_range_table = &ranges_ao, + .ai_rinsn = ai_rinsn, + .ao_rinsn = ao_rinsn, + .ao_winsn = ao_winsn}, }; /* @@ -264,7 +265,8 @@ struct pcmmio_private { * the board, and also about the kernel module that contains * the device code. */ -static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int pcmmio_attach(struct comedi_device *dev, + struct comedi_devconfig *it); static int pcmmio_detach(struct comedi_device *dev); static struct comedi_driver driver = { @@ -295,17 +297,19 @@ static struct comedi_driver driver = { .num_names = ARRAY_SIZE(pcmmio_boards), }; -static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int pcmmio_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); +static int pcmmio_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int pcmmio_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); static irqreturn_t interrupt_pcmmio(int irq, void *d); static void pcmmio_stop_intr(struct comedi_device *, struct comedi_subdevice *); static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s); static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s); static int pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_cmd *cmd); + struct comedi_cmd *cmd); /* some helper functions to deal with specifics of this device's registers */ static void init_asics(struct comedi_device *dev); /* sets up/clears ASIC chips to defaults */ @@ -325,7 +329,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic, - thisasic_chanct = 0; + thisasic_chanct = 0; unsigned long iobase; unsigned int irq[MAX_ASICS]; @@ -333,12 +337,13 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq[0] = it->options[1]; printk("comedi%d: %s: io: %lx ", dev->minor, driver.driver_name, - iobase); + iobase); dev->iobase = iobase; if (!iobase || !request_region(iobase, - thisboard->total_iosize, driver.driver_name)) { + thisboard->total_iosize, + driver.driver_name)) { printk("I/O port conflict\n"); return -EIO; } @@ -361,7 +366,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) for (asic = 0; asic < MAX_ASICS; ++asic) { devpriv->asics[asic].num = asic; devpriv->asics[asic].iobase = - dev->iobase + 16 + asic * ASIC_IOSIZE; + dev->iobase + 16 + asic * ASIC_IOSIZE; devpriv->asics[asic].irq = 0; /* this gets actually set at the end of this function when we request_irqs */ @@ -372,7 +377,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left); n_subdevs = n_dio_subdevs + 2; devpriv->sprivs = - kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private), GFP_KERNEL); + kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private), + GFP_KERNEL); if (!devpriv->sprivs) { printk("cannot allocate subdevice private data structures\n"); return -ENOMEM; @@ -452,11 +458,11 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) thisasic_chanct = 0; } subpriv->iobases[byte_no] = - devpriv->asics[asic].iobase + port; + devpriv->asics[asic].iobase + port; if (thisasic_chanct < - CHANS_PER_PORT * INTR_PORTS_PER_ASIC - && subpriv->dio.intr.asic < 0) { + CHANS_PER_PORT * INTR_PORTS_PER_ASIC + && subpriv->dio.intr.asic < 0) { /* this is an interrupt subdevice, so setup the struct */ subpriv->dio.intr.asic = asic; subpriv->dio.intr.active = 0; @@ -464,13 +470,12 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) subpriv->dio.intr.first_chan = byte_no * 8; subpriv->dio.intr.asic_chan = thisasic_chanct; subpriv->dio.intr.num_asic_chans = - s->n_chan - - subpriv->dio.intr.first_chan; + s->n_chan - subpriv->dio.intr.first_chan; s->cancel = pcmmio_cancel; s->do_cmd = pcmmio_cmd; s->do_cmdtest = pcmmio_cmdtest; s->len_chanlist = - subpriv->dio.intr.num_asic_chans; + subpriv->dio.intr.num_asic_chans; } thisasic_chanct += CHANS_PER_PORT; } @@ -489,8 +494,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { if (irq[asic] - && request_irq(irq[asic], interrupt_pcmmio, - IRQF_SHARED, thisboard->name, dev)) { + && request_irq(irq[asic], interrupt_pcmmio, + IRQF_SHARED, thisboard->name, dev)) { int i; /* unroll the allocated irqs.. */ for (i = asic - 1; i >= 0; --i) { @@ -550,8 +555,9 @@ static int pcmmio_detach(struct comedi_device *dev) * useful to applications if you implement the insn_bits interface. * This allows packed reading/writing of the DIO channels. The * comedi core can convert between insn_bits and insn_read/write */ -static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pcmmio_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int byte_no; if (insn->n != 2) @@ -578,20 +584,23 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevi for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) { /* address of 8-bit port */ unsigned long ioaddr = subpriv->iobases[byte_no], - /* bit offset of port in 32-bit doubleword */ - offset = byte_no * 8; + /* bit offset of port in 32-bit doubleword */ + offset = byte_no * 8; /* this 8-bit port's data */ unsigned char byte = 0, - /* The write mask for this port (if any) */ - write_mask_byte = (data[0] >> offset) & 0xff, - /* The data byte for this port */ - data_byte = (data[1] >> offset) & 0xff; + /* The write mask for this port (if any) */ + write_mask_byte = (data[0] >> offset) & 0xff, + /* The data byte for this port */ + data_byte = (data[1] >> offset) & 0xff; byte = inb(ioaddr); /* read all 8-bits for this port */ #ifdef DAMMIT_ITS_BROKEN /* DEBUG */ - printk("byte %d wmb %02x db %02x offset %02d io %04x, data_in %02x ", byte_no, (unsigned)write_mask_byte, (unsigned)data_byte, offset, ioaddr, (unsigned)byte); + printk + ("byte %d wmb %02x db %02x offset %02d io %04x, data_in %02x ", + byte_no, (unsigned)write_mask_byte, (unsigned)data_byte, + offset, ioaddr, (unsigned)byte); #endif if (write_mask_byte) { @@ -624,11 +633,12 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevi * configured by a special insn_config instruction. chanspec * contains the channel to be changed, and data[0] contains the * value COMEDI_INPUT or COMEDI_OUTPUT. */ -static int pcmmio_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pcmmio_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no = - chan % 8; + chan % 8; unsigned long ioaddr; unsigned char byte; @@ -672,8 +682,7 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev, struct comedi_subde case INSN_CONFIG_DIO_QUERY: /* retreive from shadow register */ data[1] = - (s-> - io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; break; @@ -706,7 +715,7 @@ static void init_asics(struct comedi_device *dev) /* now clear all the paged registers */ switch_page(dev, asic, page); for (reg = FIRST_PAGED_REG; - reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg) + reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg) outb(0, baseaddr + reg); } @@ -734,7 +743,7 @@ static void switch_page(struct comedi_device *dev, int asic, int page) /* now write out the shadow register */ outb(devpriv->asics[asic].pagelock, - devpriv->asics[asic].iobase + REG_PAGELOCK); + devpriv->asics[asic].iobase + REG_PAGELOCK); } #ifdef notused @@ -748,7 +757,7 @@ static void lock_port(struct comedi_device *dev, int asic, int port) devpriv->asics[asic].pagelock |= 0x1 << port; /* now write out the shadow register */ outb(devpriv->asics[asic].pagelock, - devpriv->asics[asic].iobase + REG_PAGELOCK); + devpriv->asics[asic].iobase + REG_PAGELOCK); return; } @@ -761,14 +770,14 @@ static void unlock_port(struct comedi_device *dev, int asic, int port) devpriv->asics[asic].pagelock &= ~(0x1 << port) | REG_LOCK_MASK; /* now write out the shadow register */ outb(devpriv->asics[asic].pagelock, - devpriv->asics[asic].iobase + REG_PAGELOCK); + devpriv->asics[asic].iobase + REG_PAGELOCK); } #endif /* notused */ static irqreturn_t interrupt_pcmmio(int irq, void *d) { int asic, got1 = 0; - struct comedi_device *dev = (struct comedi_device *) d; + struct comedi_device *dev = (struct comedi_device *)d; for (asic = 0; asic < MAX_ASICS; ++asic) { if (irq == devpriv->asics[asic].irq) { @@ -778,124 +787,130 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) /* it is an interrupt for ASIC #asic */ unsigned char int_pend; - spin_lock_irqsave(&devpriv->asics[asic].spinlock, flags); + spin_lock_irqsave(&devpriv->asics[asic].spinlock, + flags); int_pend = inb(iobase + REG_INT_PENDING) & 0x07; if (int_pend) { int port; for (port = 0; port < INTR_PORTS_PER_ASIC; - ++port) { + ++port) { if (int_pend & (0x1 << port)) { unsigned char - io_lines_with_edges = 0; + io_lines_with_edges = 0; switch_page(dev, asic, - PAGE_INT_ID); + PAGE_INT_ID); io_lines_with_edges = - inb(iobase + + inb(iobase + REG_INT_ID0 + port); if (io_lines_with_edges) /* clear pending interrupt */ outb(0, iobase + - REG_INT_ID0 + - port); + REG_INT_ID0 + + port); triggered |= - io_lines_with_edges << - port * 8; + io_lines_with_edges << + port * 8; } } ++got1; } - spin_unlock_irqrestore(&devpriv->asics[asic]. spinlock, flags); + spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, + flags); if (triggered) { struct comedi_subdevice *s; /* TODO here: dispatch io lines to subdevs with commands.. */ - printk("PCMMIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", irq, asic, triggered); + printk + ("PCMMIO DEBUG: got edge detect interrupt %d asic %d which_chans: %06x\n", + irq, asic, triggered); for (s = dev->subdevices + 2; - s < dev->subdevices + dev->n_subdevices; - ++s) { + s < dev->subdevices + dev->n_subdevices; + ++s) { if (subpriv->dio.intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */ unsigned long flags; unsigned oldevents; - spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); + spin_lock_irqsave(&subpriv->dio. + intr.spinlock, + flags); oldevents = s->async->events; if (subpriv->dio.intr.active) { unsigned mytrig = - ((triggered >> - subpriv-> - dio. - intr. - asic_chan) - & ((0x1 << subpriv->dio.intr.num_asic_chans) - 1)) << subpriv->dio.intr.first_chan; - if (mytrig & subpriv-> - dio.intr. - enabled_mask) { - unsigned int val = - 0; + ((triggered >> + subpriv->dio.intr.asic_chan) + & + ((0x1 << subpriv-> + dio.intr. + num_asic_chans) - + 1)) << subpriv-> + dio.intr.first_chan; + if (mytrig & + subpriv->dio. + intr.enabled_mask) { + unsigned int val + = 0; unsigned int n, - ch, len; + ch, len; - len = s->async-> - cmd. - chanlist_len; + len = + s-> + async->cmd.chanlist_len; for (n = 0; - n < len; - n++) { + n < len; + n++) { ch = CR_CHAN(s->async->cmd.chanlist[n]); if (mytrig & (1U << ch)) { val |= (1U << n); } } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, ((short *) &val)[0]) - && - comedi_buf_put - (s->async, ((short *) &val)[1])) { + if (comedi_buf_put(s->async, ((short *)&val)[0]) + && + comedi_buf_put + (s->async, + ((short *) + &val)[1])) + { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ /* TODO: STOP_ACQUISITION_CALL_HERE!! */ pcmmio_stop_intr - (dev, - s); + (dev, + s); } /* Check for end of acquisition. */ - if (!subpriv-> - dio. - intr. - continuous) - { + if (!subpriv->dio.intr.continuous) { /* stop_src == TRIG_COUNT */ if (subpriv->dio.intr.stop_count > 0) { - subpriv-> - dio. - intr. - stop_count--; + subpriv->dio.intr.stop_count--; if (subpriv->dio.intr.stop_count == 0) { s->async->events |= COMEDI_CB_EOA; /* TODO: STOP_ACQUISITION_CALL_HERE!! */ pcmmio_stop_intr - (dev, - s); + (dev, + s); } } } } } - spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); + spin_unlock_irqrestore + (&subpriv->dio.intr. + spinlock, flags); if (oldevents != - s->async->events) { + s->async->events) { comedi_event(dev, s); } @@ -911,7 +926,8 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) return IRQ_HANDLED; } -static void pcmmio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s) +static void pcmmio_stop_intr(struct comedi_device *dev, + struct comedi_subdevice *s) { int nports, firstport, asic, port; @@ -931,7 +947,8 @@ static void pcmmio_stop_intr(struct comedi_device *dev, struct comedi_subdevice } } -static int pcmmio_start_intr(struct comedi_device *dev, struct comedi_subdevice *s) +static int pcmmio_start_intr(struct comedi_device *dev, + struct comedi_subdevice *s) { if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) { /* An empty acquisition! */ @@ -944,7 +961,7 @@ static int pcmmio_start_intr(struct comedi_device *dev, struct comedi_subdevice struct comedi_cmd *cmd = &s->async->cmd; asic = subpriv->dio.intr.asic; - if (asic < 0) + if (asic < 0) return 1; /* not an interrupt subdev */ subpriv->dio.intr.enabled_mask = 0; @@ -955,12 +972,13 @@ static int pcmmio_start_intr(struct comedi_device *dev, struct comedi_subdevice for (n = 0; n < cmd->chanlist_len; n++) { bits |= (1U << CR_CHAN(cmd->chanlist[n])); pol_bits |= (CR_AREF(cmd->chanlist[n]) - || CR_RANGE(cmd->chanlist[n]) ? 1U : 0U) - << CR_CHAN(cmd->chanlist[n]); + || CR_RANGE(cmd-> + chanlist[n]) ? 1U : 0U) + << CR_CHAN(cmd->chanlist[n]); } } bits &= ((0x1 << subpriv->dio.intr.num_asic_chans) - - 1) << subpriv->dio.intr.first_chan; + 1) << subpriv->dio.intr.first_chan; subpriv->dio.intr.enabled_mask = bits; { /* the below code configures the board to use a specific IRQ from 0-15. */ @@ -976,16 +994,17 @@ static int pcmmio_start_intr(struct comedi_device *dev, struct comedi_subdevice switch_page(dev, asic, PAGE_ENAB); for (port = firstport; port < firstport + nports; ++port) { unsigned enab = - bits >> (subpriv->dio.intr.first_chan + (port - - firstport) * 8) & 0xff, pol = - pol_bits >> (subpriv->dio.intr.first_chan + - (port - firstport) * 8) & 0xff; + bits >> (subpriv->dio.intr.first_chan + (port - + firstport) + * 8) & 0xff, pol = + pol_bits >> (subpriv->dio.intr.first_chan + + (port - firstport) * 8) & 0xff; /* set enab intrs for this subdev.. */ outb(enab, - devpriv->asics[asic].iobase + REG_ENAB0 + port); + devpriv->asics[asic].iobase + REG_ENAB0 + port); switch_page(dev, asic, PAGE_POL); outb(pol, - devpriv->asics[asic].iobase + REG_ENAB0 + port); + devpriv->asics[asic].iobase + REG_ENAB0 + port); } } return 0; @@ -1008,7 +1027,7 @@ static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) */ static int pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int trignum) + unsigned int trignum) { unsigned long flags; int event = 0; @@ -1075,7 +1094,8 @@ static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } static int -pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) +pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_cmd *cmd) { return comedi_pcm_cmdtest(dev, s, cmd); } @@ -1091,7 +1111,7 @@ static int adc_wait_ready(unsigned long iobase) /* All this is for AI and AO */ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, unsigned int *data) { int n; unsigned long iobase = subpriv->iobase; @@ -1110,8 +1130,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, /* convert n samples */ for (n = 0; n < insn->n; n++) { unsigned chan = CR_CHAN(insn->chanspec), range = - CR_RANGE(insn->chanspec), aref = - CR_AREF(insn->chanspec); + CR_RANGE(insn->chanspec), aref = CR_AREF(insn->chanspec); unsigned char command_byte = 0; unsigned iooffset = 0; short sample, adc_adjust = 0; @@ -1155,7 +1174,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, } static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, unsigned int *data) { int n; for (n = 0; n < insn->n; n++) { @@ -1185,17 +1204,17 @@ static int wait_dac_ready(unsigned long iobase) } static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, unsigned int *data) { int n; unsigned iobase = subpriv->iobase, iooffset = 0; for (n = 0; n < insn->n; n++) { unsigned chan = CR_CHAN(insn->chanspec), range = - CR_RANGE(insn->chanspec); + CR_RANGE(insn->chanspec); if (chan < s->n_chan) { unsigned char command_byte = 0, range_byte = - range & ((1 << 4) - 1); + range & ((1 << 4) - 1); if (chan >= 4) chan -= 4, iooffset += 4; /* set the range.. */ |