diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/pcmmio.c')
-rw-r--r-- | drivers/staging/comedi/drivers/pcmmio.c | 268 |
1 files changed, 82 insertions, 186 deletions
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 01e40f1b5628..cdf501afa14e 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -73,11 +73,11 @@ Configuration Options: [1] - IRQ (optional -- for edge-detect interrupt support only, leave out if you don't need this feature) */ +#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) ) - /* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */ #define CHANS_PER_PORT 8 #define PORTS_PER_ASIC 6 @@ -179,19 +179,19 @@ static const struct comedi_lrange ranges_ao = 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,14 +264,14 @@ 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_detach(struct comedi_device * dev); +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 = { - driver_name:"pcmmio", - module:THIS_MODULE, - attach:pcmmio_attach, - detach:pcmmio_detach, + .driver_name = "pcmmio", + .module = THIS_MODULE, + .attach = pcmmio_attach, + .detach = pcmmio_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 @@ -290,29 +290,29 @@ static struct comedi_driver driver = { * the type of board in software. ISA PnP, PCI, and PCMCIA * devices are such boards. */ - board_name:&pcmmio_boards[0].name, - offset:sizeof(struct pcmmio_board), - num_names:sizeof(pcmmio_boards) / sizeof(struct pcmmio_board), + .board_name = &pcmmio_boards[0].name, + .offset = sizeof(struct pcmmio_board), + .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 PT_REGS_ARG); +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); +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); /* 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 /* @@ -321,7 +321,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 pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * it) +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, @@ -364,7 +364,7 @@ static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * i dev->iobase + 16 + 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); } @@ -435,7 +435,7 @@ static int pcmmio_attach(struct comedi_device * dev, struct comedi_devconfig * i s->type = COMEDI_SUBD_DIO; s->insn_bits = pcmmio_dio_insn_bits; s->insn_config = pcmmio_dio_insn_config; - s->n_chan = MIN(chans_left, MAX_CHANS_PER_SUBDEV); + s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV); subpriv->dio.intr.asic = -1; subpriv->dio.intr.first_chan = -1; subpriv->dio.intr.asic_chan = -1; @@ -489,12 +489,12 @@ static int pcmmio_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_pcmmio, + && request_irq(irq[asic], interrupt_pcmmio, 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; @@ -526,7 +526,7 @@ static int pcmmio_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 pcmmio_detach(struct comedi_device * dev) +static int pcmmio_detach(struct comedi_device *dev) { int i; @@ -536,7 +536,7 @@ static int pcmmio_detach(struct comedi_device * dev) for (i = 0; i < MAX_ASICS; ++i) { if (devpriv && devpriv->asics[i].irq) - comedi_free_irq(devpriv->asics[i].irq, dev); + free_irq(devpriv->asics[i].irq, dev); } if (devpriv && devpriv->sprivs) @@ -550,8 +550,8 @@ 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) @@ -624,8 +624,8 @@ static int pcmmio_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 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; @@ -685,7 +685,7 @@ static int pcmmio_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; @@ -722,7 +722,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->dio_num_asics) return; /* paranoia */ @@ -738,7 +738,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->dio_num_asics) return; /* paranoia */ @@ -752,7 +752,7 @@ static void lock_port(struct comedi_device * dev, int asic, int port) return; } -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->dio_num_asics) return; /* paranoia */ @@ -765,7 +765,7 @@ static void unlock_port(struct comedi_device * dev, int asic, int port) } #endif /* notused */ -static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG) +static irqreturn_t interrupt_pcmmio(int irq, void *d) { int asic, got1 = 0; struct comedi_device *dev = (struct comedi_device *) d; @@ -778,8 +778,7 @@ static irqreturn_t interrupt_pcmmio(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; @@ -811,8 +810,7 @@ static irqreturn_t interrupt_pcmmio(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; @@ -825,9 +823,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG) unsigned long flags; unsigned oldevents; - comedi_spin_lock_irqsave - (&subpriv->dio.intr. - spinlock, flags); + spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); oldevents = s->async->events; @@ -859,10 +855,10 @@ static irqreturn_t interrupt_pcmmio(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!! */ @@ -896,9 +892,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG) } } - comedi_spin_unlock_irqrestore - (&subpriv->dio.intr. - spinlock, flags); + spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); if (oldevents != s->async->events) { @@ -917,11 +911,12 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d PT_REGS_ARG) 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; - if ((asic = subpriv->dio.intr.asic) < 0) + asic = subpriv->dio.intr.asic; + if (asic < 0) return; /* not an interrupt subdev */ subpriv->dio.intr.enabled_mask = 0; @@ -936,7 +931,7 @@ 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! */ @@ -948,7 +943,8 @@ static int pcmmio_start_intr(struct comedi_device * dev, struct comedi_subdevice int nports, firstport, asic, port; struct comedi_cmd *cmd = &s->async->cmd; - if ((asic = subpriv->dio.intr.asic) < 0) + asic = subpriv->dio.intr.asic; + if (asic < 0) return 1; /* not an interrupt subdev */ subpriv->dio.intr.enabled_mask = 0; @@ -995,14 +991,14 @@ static int pcmmio_start_intr(struct comedi_device * dev, struct comedi_subdevice return 0; } -static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s) +static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { unsigned long flags; - comedi_spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); + spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); if (subpriv->dio.intr.active) pcmmio_stop_intr(dev, s); - comedi_spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); + spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); return 0; } @@ -1011,7 +1007,7 @@ static int pcmmio_cancel(struct comedi_device * dev, struct comedi_subdevice * s * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. */ static int -pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * s, +pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { unsigned long flags; @@ -1020,12 +1016,12 @@ pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * if (trignum != 0) return -EINVAL; - comedi_spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); + spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); s->async->inttrig = 0; if (subpriv->dio.intr.active) { event = pcmmio_start_intr(dev, s); } - comedi_spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); + spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); if (event) { comedi_event(dev, s); @@ -1037,13 +1033,13 @@ pcmmio_inttrig_start_intr(struct comedi_device * dev, struct comedi_subdevice * /* * 'do_cmd' function for an 'INTERRUPT' subdevice. */ -static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) +static int pcmmio_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->dio.intr.spinlock, flags); + spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); subpriv->dio.intr.active = 1; /* Set up end of acquisition. */ @@ -1069,7 +1065,7 @@ static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) event = pcmmio_start_intr(dev, s); break; } - comedi_spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); + spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); if (event) { comedi_event(dev, s); @@ -1078,110 +1074,10 @@ static int pcmmio_cmd(struct comedi_device * dev, struct comedi_subdevice * s) return 0; } -/* - * 'do_cmdtest' function for an 'INTERRUPT' subdevice. - */ 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) { - 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); } static int adc_wait_ready(unsigned long iobase) @@ -1194,8 +1090,8 @@ 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) +static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; unsigned long iobase = subpriv->iobase; @@ -1258,8 +1154,8 @@ static int ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, return n; } -static int ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, - struct comedi_insn * insn, unsigned int * data) +static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; for (n = 0; n < insn->n; n++) { @@ -1288,8 +1184,8 @@ static int wait_dac_ready(unsigned long iobase) return 1; } -static int ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, - struct comedi_insn * insn, unsigned int * data) +static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, + struct comedi_insn *insn, unsigned int *data) { int n; unsigned iobase = subpriv->iobase, iooffset = 0; |