diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/pcmuio.c')
-rw-r--r-- | drivers/staging/comedi/drivers/pcmuio.c | 241 |
1 files changed, 69 insertions, 172 deletions
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 4e7d8b6327fd..81ee7cdc0caf 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -75,11 +75,12 @@ Configuration Options: [2] - IRQ for second ASIC (pcmuio96 only - IRQ for chans 48-72 .. can be the same as first irq!) */ +#include <linux/interrupt.h> #include "../comedidev.h" +#include "pcm_common.h" #include <linux/pci.h> /* for PCI devices */ -#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) ) #define CHANS_PER_PORT 8 #define PORTS_PER_ASIC 6 #define INTR_PORTS_PER_ASIC 3 @@ -155,14 +156,14 @@ struct pcmuio_board { static const struct pcmuio_board pcmuio_boards[] = { { - name: "pcmuio48", - num_asics:1, - num_ports:6, + .name = "pcmuio48", + .num_asics = 1, + .num_ports = 6, }, { - name: "pcmuio96", - num_asics:2, - num_ports:12, + .name = "pcmuio96", + .num_asics = 2, + .num_ports = 12, }, }; @@ -222,14 +223,14 @@ struct pcmuio_private { * the board, and also about the kernel module that contains * the device code. */ -static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it); -static int pcmuio_detach(struct comedi_device * dev); +static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it); +static int pcmuio_detach(struct comedi_device *dev); static struct comedi_driver driver = { - driver_name:"pcmuio", - module:THIS_MODULE, - attach:pcmuio_attach, - detach:pcmuio_detach, + .driver_name = "pcmuio", + .module = THIS_MODULE, + .attach = pcmuio_attach, + .detach = pcmuio_detach, /* It is not necessary to implement the following members if you are * writing a driver for a ISA PnP or PCI card */ /* Most drivers will support multiple types of boards by @@ -248,29 +249,29 @@ static struct comedi_driver driver = { * the type of board in software. ISA PnP, PCI, and PCMCIA * devices are such boards. */ - board_name:&pcmuio_boards[0].name, - offset:sizeof(struct pcmuio_board), - num_names:sizeof(pcmuio_boards) / sizeof(struct pcmuio_board), + .board_name = &pcmuio_boards[0].name, + .offset = sizeof(struct pcmuio_board), + .num_names = ARRAY_SIZE(pcmuio_boards), }; -static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, - struct comedi_insn * insn, unsigned int * data); -static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, - struct comedi_insn * insn, unsigned int * data); +static int pcmuio_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); +static int pcmuio_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data); -static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG); +static irqreturn_t interrupt_pcmuio(int irq, void *d); static void pcmuio_stop_intr(struct comedi_device *, struct comedi_subdevice *); -static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s); -static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s); -static int pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, - struct comedi_cmd * cmd); +static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s); +static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s); +static int pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, + 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 */ -static void switch_page(struct comedi_device * dev, int asic, int page); +static void init_asics(struct comedi_device *dev); /* sets up/clears ASIC chips to defaults */ +static void switch_page(struct comedi_device *dev, int asic, int page); #ifdef notused -static void lock_port(struct comedi_device * dev, int asic, int port); -static void unlock_port(struct comedi_device * dev, int asic, int port); +static void lock_port(struct comedi_device *dev, int asic, int port); +static void unlock_port(struct comedi_device *dev, int asic, int port); #endif /* @@ -279,7 +280,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port); * in the driver structure, dev->board_ptr contains that * address. */ -static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; int sdev_no, chans_left, n_subdevs, port, asic, thisasic_chanct = 0; @@ -322,7 +323,7 @@ static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * i devpriv->asics[asic].iobase = dev->iobase + asic * ASIC_IOSIZE; devpriv->asics[asic].irq = 0; /* this gets actually set at the end of this function when we - comedi_request_irqs */ + request_irqs */ spin_lock_init(&devpriv->asics[asic].spinlock); } @@ -359,7 +360,7 @@ static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * i s->type = COMEDI_SUBD_DIO; s->insn_bits = pcmuio_dio_insn_bits; s->insn_config = pcmuio_dio_insn_config; - s->n_chan = MIN(chans_left, MAX_CHANS_PER_SUBDEV); + s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV); subpriv->intr.asic = -1; subpriv->intr.first_chan = -1; subpriv->intr.asic_chan = -1; @@ -413,12 +414,12 @@ static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * i for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) { if (irq[asic] - && comedi_request_irq(irq[asic], interrupt_pcmuio, + && request_irq(irq[asic], interrupt_pcmuio, IRQF_SHARED, thisboard->name, dev)) { int i; /* unroll the allocated irqs.. */ for (i = asic - 1; i >= 0; --i) { - comedi_free_irq(irq[i], dev); + free_irq(irq[i], dev); devpriv->asics[i].irq = irq[i] = 0; } irq[asic] = 0; @@ -450,7 +451,7 @@ static int pcmuio_attach(struct comedi_device * dev, struct comedi_devconfig * i * allocated by _attach(). dev->private and dev->subdevices are * deallocated automatically by the core. */ -static int pcmuio_detach(struct comedi_device * dev) +static int pcmuio_detach(struct comedi_device *dev) { int i; @@ -460,7 +461,7 @@ static int pcmuio_detach(struct comedi_device * dev) for (i = 0; i < MAX_ASICS; ++i) { if (devpriv->asics[i].irq) - comedi_free_irq(devpriv->asics[i].irq, dev); + free_irq(devpriv->asics[i].irq, dev); } if (devpriv && devpriv->sprivs) @@ -474,8 +475,8 @@ static int pcmuio_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 pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, - struct comedi_insn * insn, unsigned int * data) +static int pcmuio_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) @@ -548,8 +549,8 @@ static int pcmuio_dio_insn_bits(struct comedi_device * dev, struct comedi_subdev * 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 pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, - struct comedi_insn * insn, unsigned int * data) +static int pcmuio_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; @@ -609,7 +610,7 @@ static int pcmuio_dio_insn_config(struct comedi_device * dev, struct comedi_subd return insn->n; } -static void init_asics(struct comedi_device * dev) +static void init_asics(struct comedi_device *dev) { /* sets up an ASIC chip to defaults */ int asic; @@ -646,7 +647,7 @@ static void init_asics(struct comedi_device * dev) } } -static void switch_page(struct comedi_device * dev, int asic, int page) +static void switch_page(struct comedi_device *dev, int asic, int page) { if (asic < 0 || asic >= thisboard->num_asics) return; /* paranoia */ @@ -662,7 +663,7 @@ static void switch_page(struct comedi_device * dev, int asic, int page) } #ifdef notused -static void lock_port(struct comedi_device * dev, int asic, int port) +static void lock_port(struct comedi_device *dev, int asic, int port) { if (asic < 0 || asic >= thisboard->num_asics) return; /* paranoia */ @@ -675,7 +676,7 @@ static void lock_port(struct comedi_device * dev, int asic, int port) dev->iobase + ASIC_IOSIZE * asic + REG_PAGELOCK); } -static void unlock_port(struct comedi_device * dev, int asic, int port) +static void unlock_port(struct comedi_device *dev, int asic, int port) { if (asic < 0 || asic >= thisboard->num_asics) return; /* paranoia */ @@ -688,7 +689,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port) } #endif /* notused */ -static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) +static irqreturn_t interrupt_pcmuio(int irq, void *d) { int asic, got1 = 0; struct comedi_device *dev = (struct comedi_device *) d; @@ -701,8 +702,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) /* it is an interrupt for ASIC #asic */ unsigned char int_pend; - comedi_spin_lock_irqsave(&devpriv->asics[asic].spinlock, - flags); + spin_lock_irqsave(&devpriv->asics[asic].spinlock, flags); int_pend = inb(iobase + REG_INT_PENDING) & 0x07; @@ -734,8 +734,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) ++got1; } - comedi_spin_unlock_irqrestore(&devpriv->asics[asic]. - spinlock, flags); + spin_unlock_irqrestore(&devpriv->asics[asic].spinlock, flags); if (triggered) { struct comedi_subdevice *s; @@ -748,9 +747,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) unsigned long flags; unsigned oldevents; - comedi_spin_lock_irqsave - (&subpriv->intr. - spinlock, flags); + spin_lock_irqsave (&subpriv->intr.spinlock, flags); oldevents = s->async->events; @@ -781,10 +778,10 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) } } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, ((short *) & val)[0]) + if (comedi_buf_put(s->async, ((short *) &val)[0]) && comedi_buf_put - (s->async, ((short *) & val)[1])) { + (s->async, ((short *) &val)[1])) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ @@ -816,9 +813,7 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) } } - comedi_spin_unlock_irqrestore - (&subpriv->intr. - spinlock, flags); + spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); if (oldevents != s->async->events) { @@ -837,11 +832,12 @@ static irqreturn_t interrupt_pcmuio(int irq, void *d PT_REGS_ARG) return IRQ_HANDLED; } -static void pcmuio_stop_intr(struct comedi_device * dev, struct comedi_subdevice * s) +static void pcmuio_stop_intr(struct comedi_device *dev, struct comedi_subdevice *s) { int nports, firstport, asic, port; - if ((asic = subpriv->intr.asic) < 0) + asic = subpriv->intr.asic; + if (asic < 0) return; /* not an interrupt subdev */ subpriv->intr.enabled_mask = 0; @@ -856,7 +852,7 @@ static void pcmuio_stop_intr(struct comedi_device * dev, struct comedi_subdevice } } -static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice * s) +static int pcmuio_start_intr(struct comedi_device *dev, struct comedi_subdevice *s) { if (!subpriv->intr.continuous && subpriv->intr.stop_count == 0) { /* An empty acquisition! */ @@ -868,7 +864,8 @@ static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice int nports, firstport, asic, port; struct comedi_cmd *cmd = &s->async->cmd; - if ((asic = subpriv->intr.asic) < 0) + asic = subpriv->intr.asic; + if (asic < 0) return 1; /* not an interrupt subdev */ subpriv->intr.enabled_mask = 0; @@ -905,14 +902,14 @@ static int pcmuio_start_intr(struct comedi_device * dev, struct comedi_subdevice return 0; } -static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +static int pcmuio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { unsigned long flags; - comedi_spin_lock_irqsave(&subpriv->intr.spinlock, flags); + spin_lock_irqsave(&subpriv->intr.spinlock, flags); if (subpriv->intr.active) pcmuio_stop_intr(dev, s); - comedi_spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); return 0; } @@ -921,7 +918,7 @@ static int pcmuio_cancel(struct comedi_device * dev, struct comedi_subdevice * s * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. */ static int -pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s, +pcmuio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { unsigned long flags; @@ -930,12 +927,12 @@ pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * if (trignum != 0) return -EINVAL; - comedi_spin_lock_irqsave(&subpriv->intr.spinlock, flags); + spin_lock_irqsave(&subpriv->intr.spinlock, flags); s->async->inttrig = 0; if (subpriv->intr.active) { event = pcmuio_start_intr(dev, s); } - comedi_spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); if (event) { comedi_event(dev, s); @@ -947,13 +944,13 @@ pcmuio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * /* * 'do_cmd' function for an 'INTERRUPT' subdevice. */ -static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +static int pcmuio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_cmd *cmd = &s->async->cmd; unsigned long flags; int event = 0; - comedi_spin_lock_irqsave(&subpriv->intr.spinlock, flags); + spin_lock_irqsave(&subpriv->intr.spinlock, flags); subpriv->intr.active = 1; /* Set up end of acquisition. */ @@ -979,7 +976,7 @@ static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) event = pcmuio_start_intr(dev, s); break; } - comedi_spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); + spin_unlock_irqrestore(&subpriv->intr.spinlock, flags); if (event) { comedi_event(dev, s); @@ -988,110 +985,10 @@ static int pcmuio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) return 0; } -/* - * 'do_cmdtest' function for an 'INTERRUPT' subdevice. - */ static int -pcmuio_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, struct comedi_cmd * cmd) +pcmuio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - int err = 0; - unsigned int tmp; - - /* step 1: make sure trigger sources are trivially valid */ - - tmp = cmd->start_src; - cmd->start_src &= (TRIG_NOW | TRIG_INT); - if (!cmd->start_src || tmp != cmd->start_src) - err++; - - tmp = cmd->scan_begin_src; - cmd->scan_begin_src &= TRIG_EXT; - if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) - err++; - - tmp = cmd->convert_src; - cmd->convert_src &= TRIG_NOW; - 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) - return 1; - - /* step 2: make sure trigger sources are unique and mutually compatible */ - - /* these tests are true if more than one _src bit is set */ - if ((cmd->start_src & (cmd->start_src - 1)) != 0) - err++; - if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) - err++; - if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) - err++; - if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) - err++; - if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) - err++; - - if (err) - return 2; - - /* step 3: make sure arguments are trivially compatible */ - - /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */ - if (cmd->start_arg != 0) { - cmd->start_arg = 0; - err++; - } - - /* cmd->scan_begin_src == TRIG_EXT */ - if (cmd->scan_begin_arg != 0) { - cmd->scan_begin_arg = 0; - err++; - } - - /* cmd->convert_src == TRIG_NOW */ - if (cmd->convert_arg != 0) { - cmd->convert_arg = 0; - err++; - } - - /* cmd->scan_end_src == TRIG_COUNT */ - if (cmd->scan_end_arg != cmd->chanlist_len) { - cmd->scan_end_arg = cmd->chanlist_len; - err++; - } - - switch (cmd->stop_src) { - case TRIG_COUNT: - /* any count allowed */ - break; - case TRIG_NONE: - if (cmd->stop_arg != 0) { - cmd->stop_arg = 0; - err++; - } - break; - default: - break; - } - - if (err) - return 3; - - /* step 4: fix up any arguments */ - - /* if (err) return 4; */ - - return 0; + return comedi_pcm_cmdtest(dev, s, cmd); } /* |