diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/pcmmio.c')
-rw-r--r-- | drivers/staging/comedi/drivers/pcmmio.c | 231 |
1 files changed, 159 insertions, 72 deletions
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index d812c2c3af12..35ba93989a36 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -32,8 +32,10 @@ Winsystems. This board is a PC-104 based I/O board. It contains four subdevices: subdevice 0 - 16 channels of 16-bit AI subdevice 1 - 8 channels of 16-bit AO - subdevice 2 - first 24 channels of the 48 channel of DIO (with edge-triggered interrupt support) - subdevice 3 - last 24 channels of the 48 channel DIO (no interrupt support for this bank of channels) + subdevice 2 - first 24 channels of the 48 channel of DIO + (with edge-triggered interrupt support) + subdevice 3 - last 24 channels of the 48 channel DIO + (no interrupt support for this bank of channels) Some notes: @@ -70,7 +72,8 @@ four subdevices: Configuration Options: [0] - I/O port base address - [1] - IRQ (optional -- for edge-detect interrupt support only, leave out if you don't need this feature) + [1] - IRQ (optional -- for edge-detect interrupt support only, + leave out if you don't need this feature) */ #include <linux/interrupt.h> @@ -115,9 +118,11 @@ Configuration Options: #define REG_PORT4 0x4 #define REG_PORT5 0x5 #define REG_INT_PENDING 0x6 -#define REG_PAGELOCK 0x7 /* page selector register, upper 2 bits select a page - and bits 0-5 are used to 'lock down' a particular - port above to make it readonly. */ +#define REG_PAGELOCK 0x7 /* + * page selector register, upper 2 bits select + * a page and bits 0-5 are used to 'lock down' + * a particular port above to make it readonly. + */ #define REG_POL0 0x8 #define REG_POL1 0x9 #define REG_POL2 0xA @@ -134,7 +139,7 @@ Configuration Options: #define REG_PAGE_BITOFFSET 6 #define REG_LOCK_BITOFFSET 0 #define REG_PAGE_MASK (~((0x1<<REG_PAGE_BITOFFSET)-1)) -#define REG_LOCK_MASK ~(REG_PAGE_MASK) +#define REG_LOCK_MASK (~(REG_PAGE_MASK)) #define PAGE_POL 1 #define PAGE_ENAB 2 #define PAGE_INT_ID 3 @@ -168,13 +173,12 @@ struct pcmmio_board { comedi_insn_fn_t ai_rinsn, ao_rinsn, ao_winsn; }; -static const struct comedi_lrange ranges_ai = - { 4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0., - 10.)} +static const struct comedi_lrange ranges_ai = { + 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.), +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)} }; @@ -204,7 +208,8 @@ static const struct pcmmio_board pcmmio_boards[] = { struct pcmmio_subdev_private { union { - /* for DIO: mapping of halfwords (bytes) in port/chanarray to iobase */ + /* for DIO: mapping of halfwords (bytes) + in port/chanarray to iobase */ unsigned long iobases[PORTS_PER_SUBDEV]; /* for AI/AO */ @@ -215,15 +220,31 @@ struct pcmmio_subdev_private { /* The below is only used for intr subdevices */ struct { - int asic; /* if non-negative, this subdev has an interrupt asic */ - int first_chan; /* if nonnegative, the first channel id for - interrupts. */ - int num_asic_chans; /* the number of asic channels in this subdev - that have interrutps */ - int asic_chan; /* if nonnegative, the first channel id with - respect to the asic that has interrupts */ - int enabled_mask; /* subdev-relative channel mask for channels - we are interested in */ + /* + * if non-negative, this subdev has an + * interrupt asic + */ + int asic; + /* + * if nonnegative, the first channel id for + * interrupts. + */ + int first_chan; + /* + * the number of asic channels in this subdev + * that have interrutps + */ + int num_asic_chans; + /* + * if nonnegative, the first channel id with + * respect to the asic that has interrupts + */ + int asic_chan; + /* + * subdev-relative channel mask for channels + * we are interested in + */ + int enabled_mask; int active; int stop_count; int continuous; @@ -231,20 +252,25 @@ struct pcmmio_subdev_private { } intr; } dio; struct { - unsigned int shadow_samples[8]; /* the last unsigned int data written */ + /* the last unsigned int data written */ + unsigned int shadow_samples[8]; } ao; }; }; -/* this structure is for data unique to this hardware driver. If - several hardware drivers keep similar information in this structure, - feel free to suggest moving the variable to the struct comedi_device struct. */ +/* + * this structure is for data unique to this hardware driver. If + * several hardware drivers keep similar information in this structure, + * feel free to suggest moving the variable to the struct comedi_device struct. + */ struct pcmmio_private { /* stuff for DIO */ struct { unsigned char pagelock; /* current page and lock */ - unsigned char pol[NUM_PAGED_REGS]; /* shadow of POLx registers */ - unsigned char enab[NUM_PAGED_REGS]; /* shadow of ENABx registers */ + /* shadow of POLx registers */ + unsigned char pol[NUM_PAGED_REGS]; + /* shadow of ENABx registers */ + unsigned char enab[NUM_PAGED_REGS]; int num; unsigned long iobase; unsigned int irq; @@ -312,7 +338,8 @@ 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 */ +/* sets up/clears ASIC chips to defaults */ +static void init_asics(struct comedi_device *dev); 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); @@ -367,9 +394,11 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->asics[asic].num = asic; devpriv->asics[asic].iobase = 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 */ + /* + * this gets actually set at the end of this function when we + * request_irqs + */ + devpriv->asics[asic].irq = 0; spin_lock_init(&devpriv->asics[asic].spinlock); } @@ -463,7 +492,10 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (thisasic_chanct < CHANS_PER_PORT * INTR_PORTS_PER_ASIC && subpriv->dio.intr.asic < 0) { - /* this is an interrupt subdevice, so setup the struct */ + /* + * this is an interrupt subdevice, + * so setup the struct + */ subpriv->dio.intr.asic = asic; subpriv->dio.intr.active = 0; subpriv->dio.intr.stop_count = 0; @@ -484,7 +516,11 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) chans_left -= s->n_chan; if (!chans_left) { - asic = 0; /* reset the asic to our first asic, to do intr subdevs */ + /* + * reset the asic to our first asic, + * to do intr subdevs + */ + asic = 0; port = 0; } @@ -507,8 +543,10 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->asics[asic].irq = irq[asic]; } - dev->irq = irq[0]; /* grr.. wish comedi dev struct supported multiple - irqs.. */ + dev->irq = irq[0]; /* + * grr.. wish comedi dev struct supported + * multiple irqs.. + */ if (irq[0]) { printk("irq: %u ", irq[0]); @@ -604,9 +642,14 @@ static int pcmmio_dio_insn_bits(struct comedi_device *dev, #endif if (write_mask_byte) { - /* this byte has some write_bits -- so set the output lines */ - byte &= ~write_mask_byte; /* clear bits for write mask */ - byte |= ~data_byte & write_mask_byte; /* set to inverted data_byte */ + /* + * this byte has some write_bits + * -- so set the output lines + */ + /* clear bits for write mask */ + byte &= ~write_mask_byte; + /* set to inverted data_byte */ + byte |= ~data_byte & write_mask_byte; /* Write out the new digital output state */ outb(byte, ioaddr); } @@ -670,9 +713,11 @@ static int pcmmio_dio_insn_config(struct comedi_device *dev, byte &= ~(1 << bit_no); /**< set input channel to '0' */ - /* write out byte -- this is the only time we actually affect the - hardware as all channels are implicitly output -- but input - channels are set to float-high */ + /* + * write out byte -- this is the only time we actually affect + * the hardware as all channels are implicitly output + * -- but input channels are set to float-high + */ outb(byte, ioaddr); /* save to io_bits */ @@ -726,8 +771,8 @@ static void init_asics(struct comedi_device *dev) outb(0xff, baseaddr + REG_ENAB0); */ /* END DEBUG */ - switch_page(dev, asic, 0); /* switch back to default page 0 */ - + /* switch back to default page 0 */ + switch_page(dev, asic, 0); } } @@ -806,7 +851,10 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) REG_INT_ID0 + port); if (io_lines_with_edges) - /* clear pending interrupt */ + /* + * clear pending + * interrupt + */ outb(0, iobase + REG_INT_ID0 + port); @@ -825,14 +873,21 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) if (triggered) { struct comedi_subdevice *s; - /* TODO here: dispatch io lines to subdevs with commands.. */ + /* + * 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); for (s = dev->subdevices + 2; s < dev->subdevices + dev->n_subdevices; ++s) { - if (subpriv->dio.intr.asic == asic) { /* this is an interrupt subdev, and it matches this asic! */ + /* + * this is an interrupt subdev, + * and it matches this asic! + */ + if (subpriv->dio.intr.asic == asic) { unsigned long flags; unsigned oldevents; @@ -867,9 +922,8 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) n < len; n++) { ch = CR_CHAN(s->async->cmd.chanlist[n]); - if (mytrig & (1U << ch)) { + if (mytrig & (1U << ch)) val |= (1U << n); - } } /* Write the scan to the buffer. */ if (comedi_buf_put(s->async, ((short *)&val)[0]) @@ -877,8 +931,7 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) comedi_buf_put (s->async, ((short *) - &val)[1])) - { + &val)[1])) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ @@ -981,9 +1034,16 @@ static int pcmmio_start_intr(struct comedi_device *dev, 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. */ + { + /* + * the below code configures the board + * to use a specific IRQ from 0-15. + */ unsigned char b; - /* set resource enable register to enable IRQ operation */ + /* + * set resource enable register + * to enable IRQ operation + */ outb(1 << 4, dev->iobase + 3); /* set bits 0-3 of b to the irq number from 0-15 */ b = dev->irq & ((1 << 4) - 1); @@ -1037,14 +1097,12 @@ pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags); s->async->inttrig = 0; - if (subpriv->dio.intr.active) { + if (subpriv->dio.intr.active) event = pcmmio_start_intr(dev, s); - } spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); - if (event) { + if (event) comedi_event(dev, s); - } return 1; } @@ -1086,9 +1144,8 @@ static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags); - if (event) { + if (event) comedi_event(dev, s); - } return 0; } @@ -1136,17 +1193,32 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, short sample, adc_adjust = 0; if (chan > 7) - chan -= 8, iooffset = 4; /* use the second dword for channels > 7 */ + chan -= 8, iooffset = 4; /* + * use the second dword + * for channels > 7 + */ if (aref != AREF_DIFF) { aref = AREF_GROUND; - command_byte |= 1 << 7; /* set bit 7 to indicate single-ended */ + command_byte |= 1 << 7; /* + * set bit 7 to indicate + * single-ended + */ } if (range < 2) - adc_adjust = 0x8000; /* bipolar ranges (-5,5 .. -10,10 need to be adjusted -- that is.. they need to wrap around by adding 0x8000 */ + adc_adjust = 0x8000; /* + * bipolar ranges + * (-5,5 .. -10,10 need to be + * adjusted -- that is.. they + * need to wrap around by + * adding 0x8000 + */ if (chan % 2) { - command_byte |= 1 << 6; /* odd-numbered channels have bit 6 set */ + command_byte |= 1 << 6; /* + * odd-numbered channels + * have bit 6 set + */ } /* select the channel, bits 4-5 == chan/2 */ @@ -1156,16 +1228,22 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, command_byte |= (range & 0x3) << 2; /* need to do this twice to make sure mux settled */ - outb(command_byte, iobase + iooffset + 2); /* chan/range/aref select */ + /* chan/range/aref select */ + outb(command_byte, iobase + iooffset + 2); - adc_wait_ready(iobase + iooffset); /* wait for the adc to say it finised the conversion */ + /* wait for the adc to say it finised the conversion */ + adc_wait_ready(iobase + iooffset); - outb(command_byte, iobase + iooffset + 2); /* select the chan/range/aref AGAIN */ + /* select the chan/range/aref AGAIN */ + outb(command_byte, iobase + iooffset + 2); adc_wait_ready(iobase + iooffset); - sample = inb(iobase + iooffset + 0); /* read data lo byte */ - sample |= inb(iobase + iooffset + 1) << 8; /* read data hi byte */ + /* read data lo byte */ + sample = inb(iobase + iooffset + 0); + + /* read data hi byte */ + sample |= inb(iobase + iooffset + 1) << 8; sample += adc_adjust; /* adjustment .. munge data */ data[n] = sample; } @@ -1227,15 +1305,24 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, wait_dac_ready(iobase + iooffset); - outb(data[n] & 0xff, iobase + iooffset + 0); /* low order byte */ - outb((data[n] >> 8) & 0xff, iobase + iooffset + 1); /* high order byte */ - command_byte = 0x70 | (chan << 1); /* set bit 4 of command byte to indicate data is loaded and trigger conversion */ + /* low order byte */ + outb(data[n] & 0xff, iobase + iooffset + 0); + + /* high order byte */ + outb((data[n] >> 8) & 0xff, iobase + iooffset + 1); + + /* + * set bit 4 of command byte to indicate + * data is loaded and trigger conversion + */ + command_byte = 0x70 | (chan << 1); /* trigger converion */ outb(command_byte, iobase + iooffset + 2); wait_dac_ready(iobase + iooffset); - subpriv->ao.shadow_samples[chan] = data[n]; /* save to shadow register for ao_rinsn */ + /* save to shadow register for ao_rinsn */ + subpriv->ao.shadow_samples[chan] = data[n]; } } return n; |