diff options
Diffstat (limited to 'drivers/staging/comedi')
91 files changed, 4491 insertions, 4422 deletions
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index f73287eab373..bfa27e7fc016 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -485,6 +485,7 @@ config COMEDI_NI_ATMIO tristate "NI AT-MIO E series ISA-PNP card support" select COMEDI_8255 select COMEDI_NI_TIO + select COMEDI_FC ---help--- Enable support for National Instruments AT-MIO E series cards National Instruments AT-MIO-16E-1 (ni_atmio), @@ -990,8 +991,6 @@ config COMEDI_ME_DAQ config COMEDI_NI_6527 tristate "NI 6527 support" - depends on HAS_DMA - select COMEDI_MITE ---help--- Enable support for the National Instruments 6527 PCI card diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 94b2385fb0af..4e26bd7fc84f 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -344,7 +344,7 @@ unsigned int comedi_buf_read_free(struct comedi_async *async, } EXPORT_SYMBOL_GPL(comedi_buf_read_free); -int comedi_buf_put(struct comedi_async *async, short x) +int comedi_buf_put(struct comedi_async *async, unsigned short x) { unsigned int n = __comedi_buf_write_alloc(async, sizeof(short), 1); @@ -352,20 +352,20 @@ int comedi_buf_put(struct comedi_async *async, short x) async->events |= COMEDI_CB_ERROR; return 0; } - *(short *)(async->prealloc_buf + async->buf_write_ptr) = x; + *(unsigned short *)(async->prealloc_buf + async->buf_write_ptr) = x; comedi_buf_write_free(async, sizeof(short)); return 1; } EXPORT_SYMBOL_GPL(comedi_buf_put); -int comedi_buf_get(struct comedi_async *async, short *x) +int comedi_buf_get(struct comedi_async *async, unsigned short *x) { unsigned int n = comedi_buf_read_n_available(async); if (n < sizeof(short)) return 0; comedi_buf_read_alloc(async, sizeof(short)); - *x = *(short *)(async->prealloc_buf + async->buf_read_ptr); + *x = *(unsigned short *)(async->prealloc_buf + async->buf_read_ptr); comedi_buf_read_free(async, sizeof(short)); return 1; } diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 2dfb06aedb15..1e9da405d833 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -86,9 +86,6 @@ struct comedi32_insnlist_struct { static int translated_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - if (!file->f_op) - return -ENOTTY; - if (file->f_op->unlocked_ioctl) return file->f_op->unlocked_ioctl(file, cmd, arg); diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 1636c7ca57e2..f3d59e2a1152 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -543,7 +543,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) { s->private = kzalloc(size, GFP_KERNEL); if (s->private) - comedi_set_subdevice_runflags(s, ~0, SRF_FREE_SPRIV); + s->runflags |= SRF_FREE_SPRIV; return s->private; } EXPORT_SYMBOL_GPL(comedi_alloc_spriv); @@ -806,7 +806,6 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, } else { us->range_type = 0; /* XXX */ } - us->flags = s->flags; if (s->busy) us->subd_flags |= SDF_BUSY; @@ -818,8 +817,6 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, us->subd_flags |= SDF_LOCK_OWNER; if (!s->maxdata && s->maxdata_list) us->subd_flags |= SDF_MAXDATA; - if (s->flaglist) - us->subd_flags |= SDF_FLAGS; if (s->range_table_list) us->subd_flags |= SDF_RANGETYPE; if (s->do_cmd) @@ -829,8 +826,6 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, us->insn_bits_support = COMEDI_SUPPORTED; else us->insn_bits_support = COMEDI_UNSUPPORTED; - - us->settling_time_0 = s->settling_time_0; } ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp)); @@ -875,13 +870,8 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, return -EFAULT; } - if (it.flaglist) { - if (!s->flaglist) - return -EINVAL; - if (copy_to_user(it.flaglist, s->flaglist, - s->n_chan * sizeof(unsigned int))) - return -EFAULT; - } + if (it.flaglist) + return -EINVAL; /* flaglist not supported */ if (it.rangelist) { int i; @@ -1431,17 +1421,11 @@ static int do_cmd_ioctl(struct comedi_device *dev, async->cmd = cmd; async->cmd.data = NULL; /* load channel/gain list */ - async->cmd.chanlist = - kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL); - if (!async->cmd.chanlist) { - DPRINTK("allocation failed\n"); - return -ENOMEM; - } - - if (copy_from_user(async->cmd.chanlist, user_chanlist, - async->cmd.chanlist_len * sizeof(int))) { - DPRINTK("fault reading chanlist\n"); - ret = -EFAULT; + async->cmd.chanlist = memdup_user(user_chanlist, + async->cmd.chanlist_len * sizeof(int)); + if (IS_ERR(async->cmd.chanlist)) { + ret = PTR_ERR(async->cmd.chanlist); + DPRINTK("memdup_user failed with code %d\n", ret); goto cleanup; } @@ -1485,7 +1469,8 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (async->cmd.flags & TRIG_WAKE_EOS) async->cb_mask |= COMEDI_CB_EOS; - comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING); + comedi_set_subdevice_runflags(s, SRF_USER | SRF_ERROR | SRF_RUNNING, + SRF_USER | SRF_RUNNING); /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with * comedi_read() or comedi_write() */ @@ -1558,18 +1543,11 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, /* load channel/gain list */ if (cmd.chanlist) { - chanlist = - kmalloc(cmd.chanlist_len * sizeof(int), GFP_KERNEL); - if (!chanlist) { - DPRINTK("allocation failed\n"); - ret = -ENOMEM; - goto cleanup; - } - - if (copy_from_user(chanlist, user_chanlist, - cmd.chanlist_len * sizeof(int))) { - DPRINTK("fault reading chanlist\n"); - ret = -EFAULT; + chanlist = memdup_user(user_chanlist, + cmd.chanlist_len * sizeof(int)); + if (IS_ERR(chanlist)) { + ret = PTR_ERR(chanlist); + DPRINTK("memdup_user exited with code %d", ret); goto cleanup; } diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 2e19f659cd22..143be8076a2e 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -57,11 +57,6 @@ struct comedi_subdevice { unsigned int maxdata; /* if maxdata==0, use list */ const unsigned int *maxdata_list; /* list is channel specific */ - unsigned int flags; - const unsigned int *flaglist; - - unsigned int settling_time_0; - const struct comedi_lrange *range_table; const struct comedi_lrange *const *range_table_list; @@ -307,7 +302,26 @@ static inline bool comedi_range_is_unipolar(struct comedi_subdevice *s, return s->range_table->range[range].min >= 0; } -/* some silly little inline functions */ +static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s, + unsigned int chan, + unsigned int range) +{ + return s->range_table_list[chan]->range[range].min < 0; +} + +static inline bool comedi_chan_range_is_unipolar(struct comedi_subdevice *s, + unsigned int chan, + unsigned int range) +{ + return s->range_table_list[chan]->range[range].min >= 0; +} + +/* munge between offset binary and two's complement values */ +static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s, + unsigned int val) +{ + return val ^ s->maxdata ^ (s->maxdata >> 1); +} static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) { @@ -332,8 +346,8 @@ unsigned int comedi_buf_read_n_available(struct comedi_async *); unsigned int comedi_buf_read_alloc(struct comedi_async *, unsigned int); unsigned int comedi_buf_read_free(struct comedi_async *, unsigned int); -int comedi_buf_put(struct comedi_async *, short); -int comedi_buf_get(struct comedi_async *, short *); +int comedi_buf_put(struct comedi_async *, unsigned short); +int comedi_buf_get(struct comedi_async *, unsigned short *); void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, const void *source, unsigned int num_bytes); @@ -345,6 +359,8 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, int comedi_dio_insn_config(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, unsigned int *data, unsigned int mask); +unsigned int comedi_dio_update_state(struct comedi_subdevice *, + unsigned int *data); void *comedi_alloc_devpriv(struct comedi_device *, size_t); int comedi_alloc_subdevices(struct comedi_device *, int); diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 317a821b7906..8f02bf66e20b 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -190,6 +190,28 @@ int comedi_dio_insn_config(struct comedi_device *dev, } EXPORT_SYMBOL_GPL(comedi_dio_insn_config); +/** + * comedi_dio_update_state() - update the internal state of DIO subdevices. + * @s: comedi_subdevice struct + * @data: the channel mask and bits to update + */ +unsigned int comedi_dio_update_state(struct comedi_subdevice *s, + unsigned int *data) +{ + unsigned int chanmask = (s->n_chan < 32) ? ((1 << s->n_chan) - 1) + : 0xffffffff; + unsigned int mask = data[0] & chanmask; + unsigned int bits = data[1]; + + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); + } + + return mask; +} +EXPORT_SYMBOL_GPL(comedi_dio_update_state); + static int insn_rw_emulate_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -285,6 +307,13 @@ static int __comedi_device_postconfig(struct comedi_device *dev) if (s->type == COMEDI_SUBD_UNUSED) continue; + if (s->type == COMEDI_SUBD_DO) { + if (s->n_chan < 32) + s->io_bits = (1 << s->n_chan) - 1; + else + s->io_bits = 0xffffffff; + } + if (s->len_chanlist == 0) s->len_chanlist = 1; diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index 3abedcd2527b..e3d737cf7302 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -21,6 +21,15 @@ #include "../comedi.h" +/* + * Common oscillator base values in nanoseconds + */ +#define I8254_OSC_BASE_10MHZ 100 +#define I8254_OSC_BASE_5MHZ 200 +#define I8254_OSC_BASE_4MHZ 250 +#define I8254_OSC_BASE_2MHZ 500 +#define I8254_OSC_BASE_1MHZ 1000 + #define i8253_cascade_ns_to_timer i8253_cascade_ns_to_timer_2div static inline void i8253_cascade_ns_to_timer_2div_old(int i8253_osc_base, diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 2f070fdbbb1d..b4009e863414 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -112,7 +112,7 @@ void subdev_8255_interrupt(struct comedi_device *dev, { struct subdev_8255_private *spriv = s->private; unsigned long iobase = spriv->iobase; - short d; + unsigned short d; d = spriv->io(0, _8255_DATA, 0, iobase); d |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8); @@ -126,30 +126,24 @@ EXPORT_SYMBOL_GPL(subdev_8255_interrupt); static int subdev_8255_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct subdev_8255_private *spriv = s->private; unsigned long iobase = spriv->iobase; unsigned int mask; - unsigned int bits; unsigned int v; - mask = data[0]; - bits = data[1]; - + mask = comedi_dio_update_state(s, data); if (mask) { - v = s->state; - v &= ~mask; - v |= (bits & mask); - if (mask & 0xff) - spriv->io(1, _8255_DATA, v & 0xff, iobase); + spriv->io(1, _8255_DATA, s->state & 0xff, iobase); if (mask & 0xff00) - spriv->io(1, _8255_DATA + 1, (v >> 8) & 0xff, iobase); + spriv->io(1, _8255_DATA + 1, (s->state >> 8) & 0xff, + iobase); if (mask & 0xff0000) - spriv->io(1, _8255_DATA + 2, (v >> 16) & 0xff, iobase); - - s->state = v; + spriv->io(1, _8255_DATA + 2, (s->state >> 16) & 0xff, + iobase); } v = spriv->io(0, _8255_DATA, 0, iobase); @@ -288,9 +282,6 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, s->insn_bits = subdev_8255_insn; s->insn_config = subdev_8255_insn_config; - s->state = 0; - s->io_bits = 0; - subdev_8255_do_config(dev, s); return 0; diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index 63dff7729ea8..dc87df032203 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -204,7 +204,6 @@ static int addi_auto_attach(struct comedi_device *dev, s->len_chanlist = devpriv->s_EeParameters.i_NbrDiChannel; s->range_table = &range_digital; - s->io_bits = 0; /* all bits input */ s->insn_config = this_board->di_config; s->insn_read = this_board->di_read; s->insn_write = this_board->di_write; @@ -223,7 +222,6 @@ static int addi_auto_attach(struct comedi_device *dev, s->len_chanlist = devpriv->s_EeParameters.i_NbrDoChannel; s->range_table = &range_digital; - s->io_bits = 0xf; /* all bits output */ /* insn_config - for digital output memory */ s->insn_config = this_board->do_config; diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h index dfd1e666cc18..2ed2da3499f4 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -133,7 +133,7 @@ struct addi_private { unsigned short us_UseDma; /* To use Dma or not */ unsigned char b_DmaDoubleBuffer; /* we can use double buffering */ unsigned int ui_DmaActualBuffer; /* which buffer is used now */ - short *ul_DmaBufferVirtual[2]; /* pointers to begin of DMA buffer */ + unsigned short *ul_DmaBufferVirtual[2]; /* pointers to DMA buffer */ unsigned int ul_DmaBufferHw[2]; /* hw address of DMA buff */ unsigned int ui_DmaBufferSize[2]; /* size of dma buffer in bytes */ unsigned int ui_DmaBufferUsesize[2]; /* which size we may now used for transfer */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c index e3cc429403c0..84668544f52d 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -260,18 +260,13 @@ static int apci1564_do_insn_bits(struct comedi_device *dev, unsigned int *data) { struct addi_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_RW); - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP + APCI1564_DIGITAL_OP_RW); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index 1449b92403e2..3c9eec84f0eb 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -1391,7 +1391,7 @@ static int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, */ static void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev, struct comedi_subdevice *s, - short *dma_buffer, + unsigned short *dma_buffer, unsigned int num_samples) { struct addi_private *devpriv = dev->private; @@ -2175,21 +2175,16 @@ static int apci3120_do_insn_bits(struct comedi_device *dev, unsigned int *data) { struct addi_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; - unsigned int val; - /* The do channels are bits 7:4 of the do register */ - val = devpriv->b_DigitalOutputRegister >> 4; - if (mask) { - val &= ~mask; - val |= (bits & mask); - devpriv->b_DigitalOutputRegister = val << 4; + if (comedi_dio_update_state(s, data)) { + /* The do channels are bits 7:4 of the do register */ + devpriv->b_DigitalOutputRegister = s->state << 4; - outb(val << 4, devpriv->iobase + APCI3120_DIGITAL_OUTPUT); + outb(devpriv->b_DigitalOutputRegister, + devpriv->iobase + APCI3120_DIGITAL_OUTPUT); } - data[1] = val; + data[1] = s->state; return insn->n; } diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index 32dce0329fd5..dc73d4d348ed 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -623,16 +623,11 @@ static int apci3200_do_insn_bits(struct comedi_device *dev, unsigned int *data) { struct addi_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; s->state = inl(devpriv->i_IobaseAddon) & 0xf; - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outl(s->state, devpriv->i_IobaseAddon); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index 08674c18cf42..9d1b1425c60b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -90,16 +90,10 @@ static int apci1516_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - s->state = inw(dev->iobase + APCI1516_DO_REG); - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + APCI1516_DO_REG); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index 96523744b8de..5ee204bcbeef 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -87,17 +87,8 @@ static int apci16xx_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - /* Only update the channels configured as outputs */ - mask &= s->io_bits; - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) outl(s->state, dev->iobase + APCI16XX_OUT_REG(s->index)); - } data[1] = inl(dev->iobase + APCI16XX_IN_REG(s->index)); diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index 6b0ea16ff546..c77ee8732d38 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -57,16 +57,10 @@ static int apci2032_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - s->state = inl(dev->iobase + APCI2032_DO_REG); - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outl(s->state, dev->iobase + APCI2032_DO_REG); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index 92ac8ece8494..7fb32e778d8b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -50,16 +50,10 @@ static int apci2200_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - s->state = inw(dev->iobase + APCI2200_DO_REG); - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + APCI2200_DO_REG); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index d804957018ab..67d09e8afb2e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -164,7 +164,6 @@ static int apci3120_auto_attach(struct comedi_device *dev, s->maxdata = 1; s->len_chanlist = this_board->i_NbrDiChannel; s->range_table = &range_digital; - s->io_bits = 0; /* all bits input */ s->insn_bits = apci3120_di_insn_bits; /* Allocate and Initialise DO Subdevice Structures */ @@ -176,7 +175,6 @@ static int apci3120_auto_attach(struct comedi_device *dev, s->maxdata = this_board->i_DoMaxdata; s->len_chanlist = this_board->i_NbrDoChannel; s->range_table = &range_digital; - s->io_bits = 0xf; /* all bits output */ s->insn_bits = apci3120_do_insn_bits; /* Allocate and Initialise Timer Subdevice Structures */ diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index d9650ffb7d2f..6138440b919e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -161,16 +161,10 @@ static int apci3501_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - s->state = inl(dev->iobase + APCI3501_DO_REG); - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outl(s->state, dev->iobase + APCI3501_DO_REG); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index cf5dd10eaf91..761cbf8f964b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -664,16 +664,10 @@ static int apci3xxx_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - s->state = inl(dev->iobase + 48) & 0xf; - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outl(s->state, dev->iobase + 48); - } data[1] = s->state; @@ -717,16 +711,11 @@ static int apci3xxx_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; + unsigned int mask; unsigned int val; - /* only update output channels */ - mask &= s->io_bits; + mask = comedi_dio_update_state(s, data); if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - if (mask & 0xff) outl(s->state & 0xff, dev->iobase + 80); if (mask & 0xff0000) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index a67ad57cefcb..dd092c7954a9 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -1,44 +1,35 @@ /* - comedi/drivers/adl_pci6208.c - - Hardware driver for ADLink 6208 series cards: - card | voltage output | current output - -------------+-------------------+--------------- - PCI-6208V | 8 channels | - - PCI-6216V | 16 channels | - - PCI-6208A | 8 channels | 8 channels - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * adl_pci6208.c + * Comedi driver for ADLink 6208 series cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + /* -Driver: adl_pci6208 -Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards -Devices: (ADLink) PCI-6208 [adl_pci6208] - (ADLink) PCI-6216 [adl_pci6216] -Author: nsyeow <nsyeow@pd.jaring.my> -Updated: Fri, 30 Jan 2004 14:44:27 +0800 -Status: untested - -Configuration Options: not applicable, uses PCI auto config - -References: - - ni_660x.c - - adl_pci9111.c copied the entire pci setup section - - adl_pci9118.c -*/ + * Driver: adl_pci6208 + * Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards + * Devices: (ADLink) PCI-6208 [adl_pci6208] + * (ADLink) PCI-6216 [adl_pci6216] + * Author: nsyeow <nsyeow@pd.jaring.my> + * Updated: Fri, 30 Jan 2004 14:44:27 +0800 + * Status: untested + * + * Configuration Options: not applicable, uses PCI auto config + */ #include <linux/module.h> +#include <linux/delay.h> #include <linux/pci.h> #include "../comedidev.h" @@ -82,37 +73,56 @@ struct pci6208_private { unsigned int ao_readback[PCI6208_MAX_AO_CHANNELS]; }; -static int pci6208_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pci6208_ao_wait_for_data_send(struct comedi_device *dev, + unsigned int timeout) +{ + unsigned int status; + + while (timeout--) { + status = inw(dev->iobase + PCI6208_AO_STATUS); + if ((status & PCI6208_AO_STATUS_DATA_SEND) == 0) + return 0; + udelay(1); + } + + return -ETIME; +} + +static int pci6208_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct pci6208_private *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); - unsigned long invert = 1 << (16 - 1); - unsigned long value = 0; - unsigned short status; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val = devpriv->ao_readback[chan]; + int ret; int i; for (i = 0; i < insn->n; i++) { - value = data[i] ^ invert; + val = data[i]; - do { - status = inw(dev->iobase + PCI6208_AO_STATUS); - } while (status & PCI6208_AO_STATUS_DATA_SEND); + /* D/A transfer rate is 2.2us, wait up to 10us */ + ret = pci6208_ao_wait_for_data_send(dev, 10); + if (ret) + return ret; - outw(value, dev->iobase + PCI6208_AO_CONTROL(chan)); + /* the hardware expects two's complement values */ + outw(comedi_offset_munge(s, val), + dev->iobase + PCI6208_AO_CONTROL(chan)); } - devpriv->ao_readback[chan] = value; + devpriv->ao_readback[chan] = val; return insn->n; } -static int pci6208_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pci6208_ao_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct pci6208_private *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); int i; for (i = 0; i < insn->n; i++) @@ -141,15 +151,8 @@ static int pci6208_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + PCI6208_DIO); - } data[1] = s->state; @@ -193,8 +196,8 @@ static int pci6208_auto_attach(struct comedi_device *dev, s->n_chan = boardinfo->ao_chans; s->maxdata = 0xffff; s->range_table = &range_bipolar10; - s->insn_write = pci6208_ao_winsn; - s->insn_read = pci6208_ao_rinsn; + s->insn_write = pci6208_ao_insn_write; + s->insn_read = pci6208_ao_insn_read; s = &dev->subdevices[1]; /* digital input subdevice */ @@ -221,10 +224,6 @@ static int pci6208_auto_attach(struct comedi_device *dev, val = inw(dev->iobase + PCI6208_DIO); val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT; s->state = val; - s->io_bits = 0x0f; - - dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n", - dev->driver->driver_name, dev->board_name, dev->iobase); return 0; } @@ -259,5 +258,5 @@ static struct pci_driver adl_pci6208_pci_driver = { module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for ADLink 6208 series cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index 81b7203f824f..5617f5ca384a 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -112,21 +112,10 @@ static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev, unsigned int *data) { unsigned long reg = (unsigned long)s->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) outl(s->state, dev->iobase + reg); - } - /* - * NOTE: The output register is not readable. - * This returned state will not be correct until all the - * outputs have been updated. - */ data[1] = s->state; return insn->n; diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 78cea193504f..eab8da2c3d66 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -86,8 +86,6 @@ TODO: #define PCI9111_AI_INSTANT_READ_UDELAY_US 2 #define PCI9111_AI_INSTANT_READ_TIMEOUT 100 -#define PCI9111_8254_CLOCK_PERIOD_NS 500 - /* * IO address map and bit defines */ @@ -153,7 +151,7 @@ struct pci9111_private_data { unsigned int div1; unsigned int div2; - short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; + unsigned short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; }; static void plx9050_interrupt_control(unsigned long io_base, @@ -393,11 +391,10 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, - &dev_private->div1, - &dev_private->div2, - &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, + &dev_private->div1, + &dev_private->div2, + &cmd->convert_arg, cmd->flags); if (tmp != cmd->convert_arg) error++; } @@ -570,7 +567,7 @@ static void pci9111_ai_munge(struct comedi_device *dev, unsigned int num_bytes, unsigned int start_chan_index) { - short *array = data; + unsigned short *array = data; unsigned int maxdata = s->maxdata; unsigned int invert = (maxdata + 1) >> 1; unsigned int shift = (maxdata == 0xffff) ? 0 : 4; @@ -813,15 +810,8 @@ static int pci9111_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + PCI9111_DIO_REG); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 22196ada0362..986489641ed7 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -352,12 +352,11 @@ struct pci9118_private { * on external start */ unsigned int ai_data_len; - short *ai_data; - short ao_data[2]; /* data output buffer */ + unsigned short ao_data[2]; /* data output buffer */ unsigned int ai_scans; /* number of scans to do */ char dma_doublebuf; /* we can use double buffering */ unsigned int dma_actbuf; /* which buffer is used now */ - short *dmabuf_virt[2]; /* + unsigned short *dmabuf_virt[2]; /* * pointers to begin of * DMA buffer */ @@ -671,13 +670,12 @@ static int pci9118_insn_bits_di(struct comedi_device *dev, static int pci9118_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) outl(s->state & 0x0f, dev->iobase + PCI9118_DO); - } + data[1] = s->state; return insn->n; @@ -701,7 +699,7 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev) static unsigned int defragment_dma_buffer(struct comedi_device *dev, struct comedi_subdevice *s, - short *dma_buffer, + unsigned short *dma_buffer, unsigned int num_samples) { struct pci9118_private *devpriv = dev->private; @@ -725,7 +723,7 @@ static unsigned int defragment_dma_buffer(struct comedi_device *dev, static int move_block_from_dma(struct comedi_device *dev, struct comedi_subdevice *s, - short *dma_buffer, + unsigned short *dma_buffer, unsigned int num_samples) { struct pci9118_private *devpriv = dev->private; @@ -793,7 +791,8 @@ static void pci9118_calc_divisors(char mode, struct comedi_device *dev, case 4: if (*tim2 < this_board->ai_ns_min) *tim2 = this_board->ai_ns_min; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2, + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + div1, div2, tim2, flags & TRIG_ROUND_NEAREST); break; case 2: @@ -925,7 +924,7 @@ static void pci9118_ai_munge(struct comedi_device *dev, { struct pci9118_private *devpriv = dev->private; unsigned int i, num_samples = num_bytes / sizeof(short); - short *array = data; + unsigned short *array = data; for (i = 0; i < num_samples; i++) { if (devpriv->usedma) @@ -945,7 +944,7 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, unsigned short int_daq) { struct pci9118_private *devpriv = dev->private; - register short sampl; + unsigned short sampl; s->async->events = 0; @@ -1278,9 +1277,9 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, - &divisor2, &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + &divisor1, &divisor2, + &cmd->scan_begin_arg, cmd->flags); if (cmd->scan_begin_arg < this_board->ai_ns_min) cmd->scan_begin_arg = this_board->ai_ns_min; if (tmp != cmd->scan_begin_arg) @@ -1289,9 +1288,9 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev, if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, - &divisor2, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + &divisor1, &divisor2, + &cmd->convert_arg, cmd->flags); if (cmd->convert_arg < this_board->ai_ns_min) cmd->convert_arg = this_board->ai_ns_min; if (tmp != cmd->convert_arg) @@ -1613,7 +1612,6 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_n_chan = cmd->chanlist_len; devpriv->ai_n_scanlen = cmd->scan_end_arg; devpriv->ai_chanlist = cmd->chanlist; - devpriv->ai_data = s->async->prealloc_buf; devpriv->ai_data_len = s->async->prealloc_bufsz; devpriv->ai_timer1 = 0; devpriv->ai_timer2 = 0; @@ -1987,8 +1985,8 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, for (i = 0; i < 2; i++) { for (pages = 4; pages >= 0; pages--) { devpriv->dmabuf_virt[i] = - (short *)__get_free_pages(GFP_KERNEL, - pages); + (unsigned short *) + __get_free_pages(GFP_KERNEL, pages); if (devpriv->dmabuf_virt[i]) break; } @@ -2075,7 +2073,6 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, s->maxdata = 1; s->len_chanlist = 4; s->range_table = &range_digital; - s->io_bits = 0; /* all bits input */ s->insn_bits = pci9118_insn_bits_di; s = &dev->subdevices[3]; @@ -2085,11 +2082,10 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, s->maxdata = 1; s->len_chanlist = 4; s->range_table = &range_digital; - s->io_bits = 0xf; /* all bits output */ s->insn_bits = pci9118_insn_bits_do; devpriv->valid = 1; - devpriv->i8254_osc_base = 250; /* 250ns=4MHz */ + devpriv->i8254_osc_base = I8254_OSC_BASE_4MHZ; devpriv->ai_maskharderr = 0x10a; /* default measure crash condition */ if (hw_err_mask) /* disable some requested */ diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index cdf5ba26c590..8150a67cd1fb 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -119,7 +119,6 @@ struct adq12b_private { int differential; /* option 3 of comedi_config */ int last_channel; int last_range; - unsigned int digital_state; }; /* @@ -186,23 +185,25 @@ static int adq12b_di_insn_bits(struct comedi_device *dev, static int adq12b_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct adq12b_private *devpriv = dev->private; - int channel; - - for (channel = 0; channel < 8; channel++) - if (((data[0] >> channel) & 0x01) != 0) - outb((((data[1] >> channel) & 0x01) << 3) | channel, - dev->iobase + ADQ12B_OUTBR); - - /* store information to retrieve when asked for reading */ - if (data[0]) { - devpriv->digital_state &= ~data[0]; - devpriv->digital_state |= (data[0] & data[1]); + unsigned int mask; + unsigned int chan; + unsigned int val; + + mask = comedi_dio_update_state(s, data); + if (mask) { + for (chan = 0; chan < 8; chan++) { + if ((mask >> chan) & 0x01) { + val = (s->state >> chan) & 0x01; + outb((val << 3) | chan, + dev->iobase + ADQ12B_OUTBR); + } + } } - data[1] = devpriv->digital_state; + data[1] = s->state; return insn->n; } @@ -223,7 +224,6 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->unipolar = it->options[1]; devpriv->differential = it->options[2]; - devpriv->digital_state = 0; /* * initialize channel and range to -1 so we make sure we * always write at least once to the CTREG in the instruction diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index f84df46d326a..c3fdcabe9aec 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -314,10 +314,9 @@ struct pci1710_private { unsigned int *ai_chanlist; /* actaul chanlist */ unsigned int ai_flags; /* flaglist */ unsigned int ai_data_len; /* len of data buffer */ - short *ai_data; /* data buffer */ unsigned int ai_timer1; /* timers */ unsigned int ai_timer2; - short ao_data[4]; /* data output buffer */ + unsigned short ao_data[4]; /* data output buffer */ unsigned int cnt0_write_wait; /* after a write, wait for update of the * internal state */ }; @@ -544,18 +543,14 @@ static int pci171x_insn_bits_di(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ static int pci171x_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + PCI171x_DO); - } + data[1] = s->state; return insn->n; @@ -740,7 +735,7 @@ static void interrupt_pci1710_every_sample(void *d) int m; #ifdef PCI171x_PARANOIDCHECK const struct boardtype *this_board = comedi_board(dev); - short sampl; + unsigned short sampl; #endif m = inw(dev->iobase + PCI171x_STATUS); @@ -821,7 +816,7 @@ static int move_block_from_fifo(struct comedi_device *dev, int i, j; #ifdef PCI171x_PARANOIDCHECK const struct boardtype *this_board = comedi_board(dev); - int sampl; + unsigned short sampl; #endif j = s->async->cur_chan; @@ -1009,9 +1004,10 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev, } else { devpriv->ai_et = 0; } - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, - &divisor2, &devpriv->ai_timer1, - devpriv->ai_flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + &divisor1, &divisor2, + &devpriv->ai_timer1, + devpriv->ai_flags); outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); if (mode != 2) { /* start pacer */ @@ -1090,9 +1086,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1, - &divisor2, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, + &divisor1, &divisor2, + &cmd->convert_arg, cmd->flags); if (cmd->convert_arg < this_board->ai_ns_min) cmd->convert_arg = this_board->ai_ns_min; if (tmp != cmd->convert_arg) @@ -1125,7 +1121,6 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_chanlist = cmd->chanlist; devpriv->ai_flags = cmd->flags; devpriv->ai_data_len = s->async->prealloc_bufsz; - devpriv->ai_data = s->async->prealloc_buf; devpriv->ai_timer1 = 0; devpriv->ai_timer2 = 0; @@ -1288,7 +1283,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->do_cmdtest = pci171x_ai_cmdtest; s->do_cmd = pci171x_ai_cmd; } - devpriv->i8254_osc_base = 100; /* 100ns=10MHz */ + devpriv->i8254_osc_base = I8254_OSC_BASE_10MHZ; subdev++; } @@ -1320,7 +1315,6 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->maxdata = 1; s->len_chanlist = this_board->n_dichan; s->range_table = &range_digital; - s->io_bits = 0; /* all bits input */ s->insn_bits = pci171x_insn_bits_di; subdev++; } @@ -1333,9 +1327,6 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->maxdata = 1; s->len_chanlist = this_board->n_dochan; s->range_table = &range_digital; - /* all bits output */ - s->io_bits = (1 << this_board->n_dochan) - 1; - s->state = 0; s->insn_bits = pci171x_insn_bits_do; subdev++; } diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index b793d6987b84..bd4f781b4b24 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -105,7 +105,7 @@ TODO: struct pci1723_private { unsigned char da_range[8]; /* D/A output range for each channel */ - short ao_data[8]; /* data output buffer */ + unsigned short ao_data[8]; /* data output buffer */ }; /* @@ -205,19 +205,16 @@ static int pci1723_dio_insn_config(struct comedi_device *dev, return insn->n; } -/* - digital i/o bits read/write -*/ static int pci1723_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + PCI1723_WRITE_DIGITAL_OUTPUT_CMD); - } + data[1] = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA); + return insn->n; } diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index f091fa0d304d..6bac665261f8 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -448,45 +448,39 @@ static int pci_dio_insn_bits_di_w(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ static int pci_dio_insn_bits_do_b(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { const struct diosubd_data *d = (const struct diosubd_data *)s->private; int i; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) { for (i = 0; i < d->regs; i++) outb((s->state >> (8 * i)) & 0xff, dev->iobase + d->addr + i); } + data[1] = s->state; return insn->n; } -/* -============================================================================== -*/ static int pci_dio_insn_bits_do_w(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { const struct diosubd_data *d = (const struct diosubd_data *)s->private; int i; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) { for (i = 0; i < d->regs; i++) outw((s->state >> (16 * i)) & 0xffff, dev->iobase + d->addr + 2 * i); } + data[1] = s->state; return insn->n; @@ -641,12 +635,10 @@ static int pci1760_insn_bits_di(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ static int pci1760_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { int ret; unsigned char omb[4] = { @@ -657,14 +649,13 @@ static int pci1760_insn_bits_do(struct comedi_device *dev, }; unsigned char imb[4]; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) { omb[0] = s->state; ret = pci1760_mbxrequest(dev, omb, imb); if (!ret) return ret; } + data[1] = s->state; return insn->n; diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index afe87cc89761..22b3dda135ff 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -45,9 +45,7 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + if (comedi_dio_update_state(s, data)) { outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7); outb((s->state >> 8) & 0xff, dev->iobase + AIO_IIRO_16_RELAY_8_15); diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index c1f723e86146..2e4bf284d52c 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -941,31 +941,34 @@ static void dio200_subdev_8255_set_dir(struct comedi_device *dev, dio200_write8(dev, subpriv->ofs + 3, config); } -/* - * Handle 'insn_bits' for an '8255' DIO subdevice. - */ static int dio200_subdev_8255_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct dio200_subdev_8255 *subpriv = s->private; + unsigned int mask; + unsigned int val; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - if (data[0] & 0xff) + mask = comedi_dio_update_state(s, data); + if (mask) { + if (mask & 0xff) dio200_write8(dev, subpriv->ofs, s->state & 0xff); - if (data[0] & 0xff00) + if (mask & 0xff00) dio200_write8(dev, subpriv->ofs + 1, (s->state >> 8) & 0xff); - if (data[0] & 0xff0000) + if (mask & 0xff0000) dio200_write8(dev, subpriv->ofs + 2, (s->state >> 16) & 0xff); } - data[1] = dio200_read8(dev, subpriv->ofs); - data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8; - data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16; - return 2; + + val = dio200_read8(dev, subpriv->ofs); + val |= dio200_read8(dev, subpriv->ofs + 1) << 8; + val |= dio200_read8(dev, subpriv->ofs + 2) << 16; + + data[1] = val; + + return insn->n; } /* @@ -1022,8 +1025,6 @@ static int dio200_subdev_8255_init(struct comedi_device *dev, s->maxdata = 1; s->insn_bits = dio200_subdev_8255_bits; s->insn_config = dio200_subdev_8255_config; - s->state = 0; - s->io_bits = 0; dio200_subdev_8255_set_dir(dev, s); return 0; } diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index e7108045f553..5b4b5ab34e2e 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -57,17 +57,16 @@ static const struct pc263_board pc263_boards[] = { static int pc263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - /* Write out the new digital output lines */ - outb(s->state & 0xFF, dev->iobase); - outb(s->state >> 8, dev->iobase + 1); + if (comedi_dio_update_state(s, data)) { + outb(s->state & 0xff, dev->iobase); + outb((s->state >> 8) & 0xff, dev->iobase + 1); } + + data[1] = s->state; + return insn->n; } diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 179de53a86f0..810e397d8fd7 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -215,12 +215,6 @@ Caveats: #define CLK_EXT 7 /* external clock */ /* Macro to construct clock input configuration register value. */ #define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7)) -/* Timebases in ns. */ -#define TIMEBASE_10MHZ 100 -#define TIMEBASE_1MHZ 1000 -#define TIMEBASE_100KHZ 10000 -#define TIMEBASE_10KHZ 100000 -#define TIMEBASE_1KHZ 1000000 /* * Counter/timer gate input configuration sources. @@ -379,7 +373,7 @@ struct pci224_private { unsigned long state; spinlock_t ao_spinlock; unsigned int *ao_readback; - short *ao_scan_vals; + unsigned short *ao_scan_vals; unsigned char *ao_scan_order; int intr_cpuid; short intr_running; @@ -843,26 +837,26 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, switch (round_mode) { case TRIG_ROUND_NEAREST: default: - round = TIMEBASE_10MHZ / 2; + round = I8254_OSC_BASE_10MHZ / 2; break; case TRIG_ROUND_DOWN: round = 0; break; case TRIG_ROUND_UP: - round = TIMEBASE_10MHZ - 1; + round = I8254_OSC_BASE_10MHZ - 1; break; } /* Be careful to avoid overflow! */ - div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ; - div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) / - TIMEBASE_10MHZ; + div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ; + div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) / + I8254_OSC_BASE_10MHZ; if (div2 <= 0x10000) { /* A single timer will suffice. */ if (div2 < 2) div2 = 2; - cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ; + cmd->scan_begin_arg = div2 * I8254_OSC_BASE_10MHZ; if (cmd->scan_begin_arg < div2 || - cmd->scan_begin_arg < TIMEBASE_10MHZ) { + cmd->scan_begin_arg < I8254_OSC_BASE_10MHZ) { /* Overflow! */ cmd->scan_begin_arg = MAX_SCAN_PERIOD; } @@ -870,7 +864,8 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* Use two timers. */ div1 = devpriv->cached_div1; div2 = devpriv->cached_div2; - pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2, + pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &div1, &div2, &cmd->scan_begin_arg, round_mode); devpriv->cached_div1 = div1; @@ -1002,19 +997,19 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) switch (round_mode) { case TRIG_ROUND_NEAREST: default: - round = TIMEBASE_10MHZ / 2; + round = I8254_OSC_BASE_10MHZ / 2; break; case TRIG_ROUND_DOWN: round = 0; break; case TRIG_ROUND_UP: - round = TIMEBASE_10MHZ - 1; + round = I8254_OSC_BASE_10MHZ - 1; break; } /* Be careful to avoid overflow! */ - div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ; - div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) / - TIMEBASE_10MHZ; + div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ; + div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) / + I8254_OSC_BASE_10MHZ; if (div2 <= 0x10000) { /* A single timer will suffice. */ if (div2 < 2) @@ -1025,7 +1020,8 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* Use two timers. */ div1 = devpriv->cached_div1; div2 = devpriv->cached_div2; - pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2, + pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &div1, &div2, &ns, round_mode); } @@ -1116,7 +1112,7 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, const struct pci224_board *thisboard = comedi_board(dev); struct pci224_private *devpriv = dev->private; struct comedi_async *async = s->async; - short *array = data; + unsigned short *array = data; unsigned int length = num_bytes / sizeof(*array); unsigned int offset; unsigned int shift; diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 43059c25d5ea..a97bbd6ca3db 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -573,14 +573,14 @@ static const struct comedi_lrange pci230_ao_range = { 2, { /* PCI230 daccon bipolar flag for each analogue output range. */ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 }; -static short pci230_ai_read(struct comedi_device *dev) +static unsigned short pci230_ai_read(struct comedi_device *dev) { const struct pci230_board *thisboard = comedi_board(dev); struct pci230_private *devpriv = dev->private; - short data; + unsigned short data; /* Read sample. */ - data = (short)inw(dev->iobase + PCI230_ADCDATA); + data = inw(dev->iobase + PCI230_ADCDATA); /* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower * four bits reserved for expansion). */ /* PCI230+ is 16 bit AI. */ @@ -595,7 +595,7 @@ static short pci230_ai_read(struct comedi_device *dev) } static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, - short datum) + unsigned short datum) { const struct pci230_board *thisboard = comedi_board(dev); struct pci230_private *devpriv = dev->private; @@ -609,11 +609,12 @@ static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, * four bits reserved for expansion). */ /* PCI230+ is also 12 bit AO. */ datum <<= (16 - thisboard->ao_bits); - return (unsigned short)datum; + return datum; } static inline void pci230_ao_write_nofifo(struct comedi_device *dev, - short datum, unsigned int chan) + unsigned short datum, + unsigned int chan) { struct pci230_private *devpriv = dev->private; @@ -627,8 +628,8 @@ static inline void pci230_ao_write_nofifo(struct comedi_device *dev, PCI230_DACOUT2)); } -static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum, - unsigned int chan) +static inline void pci230_ao_write_fifo(struct comedi_device *dev, + unsigned short datum, unsigned int chan) { struct pci230_private *devpriv = dev->private; @@ -1165,7 +1166,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci230_private *devpriv = dev->private; - short data; + unsigned short data; int i, ret; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; @@ -1258,7 +1259,7 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev, /* Process scans. */ for (n = 0; n < num_scans; n++) { for (i = 0; i < cmd->chanlist_len; i++) { - short datum; + unsigned short datum; comedi_buf_get(async, &datum); pci230_ao_write_fifo(dev, datum, diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index 145bb48f618e..4bd4ef8e88cd 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -44,17 +44,16 @@ The state of the outputs can be read. static int pci263_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - /* Write out the new digital output lines */ - outb(s->state & 0xFF, dev->iobase); - outb(s->state >> 8, dev->iobase + 1); + if (comedi_dio_update_state(s, data)) { + outb(s->state & 0xff, dev->iobase); + outb((s->state >> 8) & 0xff, dev->iobase + 1); } + + data[1] = s->state; + return insn->n; } diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 0ce93da70847..64d5f291553f 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -234,9 +234,9 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev, unsigned int div1 = 0, div2 = 0; tmp = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer(100, &div1, &div2, - &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &div1, &div2, + &cmd->scan_begin_arg, cmd->flags); if (tmp != cmd->scan_begin_arg) err++; } @@ -244,9 +244,9 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev, unsigned int div1 = 0, div2 = 0; tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(100, &div1, &div2, - &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &div1, &div2, + &cmd->scan_begin_arg, cmd->flags); if (tmp != cmd->convert_arg) err++; if (cmd->scan_begin_src == TRIG_TIMER && @@ -325,14 +325,11 @@ static int das16cs_ao_rinsn(struct comedi_device *dev, static int das16cs_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + DAS16CS_DIO); - } data[1] = inw(dev->iobase + DAS16CS_DIO); diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 41d89ee7fa33..e72a403db17c 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -73,7 +73,6 @@ analog triggering on 1602 series #include "amcc_s5933.h" #include "comedi_fc.h" -#define TIMER_BASE 100 /* 10MHz master clock */ #define AI_BUFFER_SIZE 1024 /* max ai fifo size */ #define AO_BUFFER_SIZE 1024 /* max ao fifo size */ #define NUM_CHANNELS_8800 8 @@ -358,15 +357,15 @@ struct cb_pcidas_private { unsigned int s5933_intcsr_bits; unsigned int ao_control_bits; /* fifo buffers */ - short ai_buffer[AI_BUFFER_SIZE]; - short ao_buffer[AO_BUFFER_SIZE]; + unsigned short ai_buffer[AI_BUFFER_SIZE]; + unsigned short ao_buffer[AO_BUFFER_SIZE]; /* divisors of master clock for analog output pacing */ unsigned int ao_divisor1; unsigned int ao_divisor2; /* number of analog output samples remaining */ unsigned int ao_count; /* cached values for readback */ - int ao_value[2]; + unsigned short ao_value[2]; unsigned int caldac_value[NUM_CHANNELS_8800]; unsigned int trimpot_value[NUM_CHANNELS_8402]; unsigned int dac08_value; @@ -880,21 +879,19 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd->scan_begin_arg), - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->scan_begin_arg, cmd->flags); if (tmp != cmd->scan_begin_arg) err++; } if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd->convert_arg), - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, cmd->flags); if (tmp != cmd->convert_arg) err++; } @@ -932,9 +929,9 @@ static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns, { struct cb_pcidas_private *devpriv = dev->private; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), - &(devpriv->divisor2), ns, - rounding_flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->divisor1, &devpriv->divisor2, + ns, rounding_flags); /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1, @@ -1084,11 +1081,10 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &(devpriv->ao_divisor1), - &(devpriv->ao_divisor2), - &(cmd->scan_begin_arg), - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->ao_divisor1, + &devpriv->ao_divisor2, + &cmd->scan_begin_arg, cmd->flags); if (tmp != cmd->scan_begin_arg) err++; } @@ -1209,11 +1205,10 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, /* load counters */ if (cmd->scan_begin_src == TRIG_TIMER) { - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &(devpriv->ao_divisor1), - &(devpriv->ao_divisor2), - &(cmd->scan_begin_arg), - cmd->flags); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->ao_divisor1, + &devpriv->ao_divisor2, + &cmd->scan_begin_arg, cmd->flags); /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1, diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 388dbd7a5d27..ff5206536be3 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1137,7 +1137,7 @@ struct pcidas64_private { volatile short ai_cmd_running; unsigned int ai_fifo_segment_length; struct ext_clock_info ext_clock; - short ao_bounce_buffer[DAC_FIFO_SIZE]; + unsigned short ao_bounce_buffer[DAC_FIFO_SIZE]; }; static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, @@ -3490,18 +3490,15 @@ static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, return insn->n; } -static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int do_wbits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct pcidas64_private *devpriv = dev->private; - data[0] &= 0xf; - /* zero bits we are going to change */ - s->state &= ~data[0]; - /* set new bits */ - s->state |= data[0] & data[1]; - - writeb(s->state, devpriv->dio_counter_iobase + DO_REG); + if (comedi_dio_update_state(s, data)) + writeb(s->state, devpriv->dio_counter_iobase + DO_REG); data[1] = s->state; @@ -3526,14 +3523,14 @@ static int dio_60xx_config_insn(struct comedi_device *dev, return insn->n; } -static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int dio_60xx_wbits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct pcidas64_private *devpriv = dev->private; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) { writeb(s->state, devpriv->dio_counter_iobase + DIO_DATA_60XX_REG); } diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h index a4dea7cb86be..8558b07f8df3 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.h +++ b/drivers/staging/comedi/drivers/comedi_fc.h @@ -30,7 +30,7 @@ extern unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, unsigned int num_bytes); static inline unsigned int cfc_write_to_buffer(struct comedi_subdevice *subd, - short data) + unsigned short data) { return cfc_write_array_to_buffer(subd, &data, sizeof(data)); }; diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index f28a15f0274e..9de81c7712fb 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -1,168 +1,153 @@ /* - comedi/drivers/comedi_parport.c - hardware driver for standard parallel port - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: comedi_parport -Description: Standard PC parallel port -Author: ds -Status: works in immediate mode -Devices: [standard] parallel port (comedi_parport) -Updated: Tue, 30 Apr 2002 21:11:45 -0700 - -A cheap and easy way to get a few more digital I/O lines. Steal -additional parallel ports from old computers or your neighbors' -computers. - -Option list: - 0: I/O port base for the parallel port. - 1: IRQ - -Parallel Port Lines: - -pin subdev chan aka ---- ------ ---- --- -1 2 0 strobe -2 0 0 data 0 -3 0 1 data 1 -4 0 2 data 2 -5 0 3 data 3 -6 0 4 data 4 -7 0 5 data 5 -8 0 6 data 6 -9 0 7 data 7 -10 1 3 acknowledge -11 1 4 busy -12 1 2 output -13 1 1 printer selected -14 2 1 auto LF -15 1 0 error -16 2 2 init -17 2 3 select printer -18-25 ground - -Notes: - -Subdevices 0 is digital I/O, subdevice 1 is digital input, and -subdevice 2 is digital output. Unlike other Comedi devices, -subdevice 0 defaults to output. - -Pins 13 and 14 are inverted once by Comedi and once by the -hardware, thus cancelling the effect. - -Pin 1 is a strobe, thus acts like one. There's no way in software -to change this, at least on a standard parallel port. - -Subdevice 3 pretends to be a digital input subdevice, but it always -returns 0 when read. However, if you run a command with -scan_begin_src=TRIG_EXT, it uses pin 10 as a external triggering -pin, which can be used to wake up tasks. -*/ + * comedi_parport.c + * Comedi driver for standard parallel port + * + * For more information see: + * http://retired.beyondlogic.org/spp/parallel.htm + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + /* - see http://www.beyondlogic.org/ for information. - or http://www.linux-magazin.de/ausgabe/1999/10/IO/io.html + * Driver: comedi_parport + * Description: Standard PC parallel port + * Author: ds + * Status: works in immediate mode + * Devices: (standard) parallel port [comedi_parport] + * Updated: Tue, 30 Apr 2002 21:11:45 -0700 + * + * A cheap and easy way to get a few more digital I/O lines. Steal + * additional parallel ports from old computers or your neighbors' + * computers. + * + * Option list: + * 0: I/O port base for the parallel port. + * 1: IRQ (optional) + * + * Parallel Port Lines: + * + * pin subdev chan type name + * ----- ------ ---- ---- -------------- + * 1 2 0 DO strobe + * 2 0 0 DIO data 0 + * 3 0 1 DIO data 1 + * 4 0 2 DIO data 2 + * 5 0 3 DIO data 3 + * 6 0 4 DIO data 4 + * 7 0 5 DIO data 5 + * 8 0 6 DIO data 6 + * 9 0 7 DIO data 7 + * 10 1 3 DI ack + * 11 1 4 DI busy + * 12 1 2 DI paper out + * 13 1 1 DI select in + * 14 2 1 DO auto LF + * 15 1 0 DI error + * 16 2 2 DO init + * 17 2 3 DO select printer + * 18-25 ground + * + * When an IRQ is configured subdevice 3 pretends to be a digital + * input subdevice, but it always returns 0 when read. However, if + * you run a command with scan_begin_src=TRIG_EXT, it uses pin 10 + * as a external trigger, which can be used to wake up tasks. */ #include <linux/module.h> -#include "../comedidev.h" #include <linux/interrupt.h> -#include "comedi_fc.h" - -#define PARPORT_SIZE 3 - -#define PARPORT_A 0 -#define PARPORT_B 1 -#define PARPORT_C 2 +#include "../comedidev.h" -struct parport_private { - unsigned int a_data; - unsigned int c_data; - int enable_irq; -}; +#include "comedi_fc.h" -static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +/* + * Register map + */ +#define PARPORT_DATA_REG 0x00 +#define PARPORT_STATUS_REG 0x01 +#define PARPORT_CTRL_REG 0x02 +#define PARPORT_CTRL_IRQ_ENA (1 << 4) +#define PARPORT_CTRL_BIDIR_ENA (1 << 5) + +static int parport_data_reg_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct parport_private *devpriv = dev->private; - - if (data[0]) { - devpriv->a_data &= ~data[0]; - devpriv->a_data |= (data[0] & data[1]); - - outb(devpriv->a_data, dev->iobase + PARPORT_A); - } + if (comedi_dio_update_state(s, data)) + outb(s->state, dev->iobase + PARPORT_DATA_REG); - data[1] = inb(dev->iobase + PARPORT_A); + data[1] = inb(dev->iobase + PARPORT_DATA_REG); return insn->n; } -static int parport_insn_config_a(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int parport_data_reg_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct parport_private *devpriv = dev->private; - - if (data[0]) { - s->io_bits = 0xff; - devpriv->c_data &= ~(1 << 5); - } else { - s->io_bits = 0; - devpriv->c_data |= (1 << 5); - } - outb(devpriv->c_data, dev->iobase + PARPORT_C); + unsigned int ctrl; + int ret; + + ret = comedi_dio_insn_config(dev, s, insn, data, 0xff); + if (ret) + return ret; + + ctrl = inb(dev->iobase + PARPORT_CTRL_REG); + if (s->io_bits) + ctrl &= ~PARPORT_CTRL_BIDIR_ENA; + else + ctrl |= PARPORT_CTRL_BIDIR_ENA; + outb(ctrl, dev->iobase + PARPORT_CTRL_REG); - return 1; + return insn->n; } -static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int parport_status_reg_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - /* should writes be ignored? */ - /* anyone??? */ - } - - data[1] = (inb(dev->iobase + PARPORT_B) >> 3); + data[1] = inb(dev->iobase + PARPORT_STATUS_REG) >> 3; return insn->n; } -static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int parport_ctrl_reg_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct parport_private *devpriv = dev->private; - - data[0] &= 0x0f; - if (data[0]) { - devpriv->c_data &= ~data[0]; - devpriv->c_data |= (data[0] & data[1]); + unsigned int ctrl; - outb(devpriv->c_data, dev->iobase + PARPORT_C); + if (comedi_dio_update_state(s, data)) { + ctrl = inb(dev->iobase + PARPORT_CTRL_REG); + ctrl &= (PARPORT_CTRL_IRQ_ENA | PARPORT_CTRL_BIDIR_ENA); + ctrl |= s->state; + outb(ctrl, dev->iobase + PARPORT_CTRL_REG); } - data[1] = devpriv->c_data & 0xf; + data[1] = s->state; return insn->n; } -static int parport_intr_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int parport_intr_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { data[1] = 0; return insn->n; @@ -213,12 +198,11 @@ static int parport_intr_cmdtest(struct comedi_device *dev, static int parport_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - struct parport_private *devpriv = dev->private; + unsigned int ctrl; - devpriv->c_data |= 0x10; - outb(devpriv->c_data, dev->iobase + PARPORT_C); - - devpriv->enable_irq = 1; + ctrl = inb(dev->iobase + PARPORT_CTRL_REG); + ctrl |= PARPORT_CTRL_IRQ_ENA; + outb(ctrl, dev->iobase + PARPORT_CTRL_REG); return 0; } @@ -226,12 +210,11 @@ static int parport_intr_cmd(struct comedi_device *dev, static int parport_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct parport_private *devpriv = dev->private; - - devpriv->c_data &= ~0x10; - outb(devpriv->c_data, dev->iobase + PARPORT_C); + unsigned int ctrl; - devpriv->enable_irq = 0; + ctrl = inb(dev->iobase + PARPORT_CTRL_REG); + ctrl &= ~PARPORT_CTRL_IRQ_ENA; + outb(ctrl, dev->iobase + PARPORT_CTRL_REG); return 0; } @@ -239,10 +222,11 @@ static int parport_intr_cancel(struct comedi_device *dev, static irqreturn_t parport_interrupt(int irq, void *d) { struct comedi_device *dev = d; - struct parport_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[3]; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int ctrl; - if (!devpriv->enable_irq) + ctrl = inb(dev->iobase + PARPORT_CTRL_REG); + if (!(ctrl & PARPORT_CTRL_IRQ_ENA)) return IRQ_NONE; comedi_buf_put(s->async, 0); @@ -255,79 +239,69 @@ static irqreturn_t parport_interrupt(int irq, void *d) static int parport_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct parport_private *devpriv; struct comedi_subdevice *s; - unsigned int irq; int ret; - ret = comedi_request_region(dev, it->options[0], PARPORT_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x03); if (ret) return ret; - irq = it->options[1]; - if (irq) { - ret = request_irq(irq, parport_interrupt, 0, dev->board_name, - dev); - if (ret < 0) { - dev_err(dev->class_dev, "irq not available\n"); - return -EINVAL; - } - dev->irq = irq; + if (it->options[1]) { + ret = request_irq(it->options[1], parport_interrupt, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; } - ret = comedi_alloc_subdevices(dev, 4); + ret = comedi_alloc_subdevices(dev, dev->irq ? 4 : 3); if (ret) return ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - + /* Digial I/O subdevice - Parallel port DATA register */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = parport_insn_a; - s->insn_config = parport_insn_config_a; - + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = parport_data_reg_insn_bits; + s->insn_config = parport_data_reg_insn_config; + + /* Digial Input subdevice - Parallel port STATUS register */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 5; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = parport_insn_b; - + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 5; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = parport_status_reg_insn_bits; + + /* Digial Output subdevice - Parallel port CONTROL register */ s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = parport_insn_c; - - s = &dev->subdevices[3]; - if (irq) { + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = parport_ctrl_reg_insn_bits; + + if (dev->irq) { + /* Digial Input subdevice - Interrupt support */ + s = &dev->subdevices[3]; dev->read_subdev = s; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - s->n_chan = 1; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = parport_intr_insn; - s->do_cmdtest = parport_intr_cmdtest; - s->do_cmd = parport_intr_cmd; - s->cancel = parport_intr_cancel; - } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = parport_intr_insn_bits; + s->do_cmdtest = parport_intr_cmdtest; + s->do_cmd = parport_intr_cmd; + s->cancel = parport_intr_cancel; } - devpriv->a_data = 0; - outb(devpriv->a_data, dev->iobase + PARPORT_A); - devpriv->c_data = 0; - outb(devpriv->c_data, dev->iobase + PARPORT_C); + outb(0, dev->iobase + PARPORT_DATA_REG); + outb(0, dev->iobase + PARPORT_CTRL_REG); return 0; } @@ -341,5 +315,5 @@ static struct comedi_driver parport_driver = { module_comedi_driver(parport_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi: Standard parallel port driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index e781716bf355..89836c0828d9 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -40,17 +40,11 @@ Configuration Options: not applicable, uses comedi PCI auto config static int contec_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + PIO1616L_DO_REG); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 5f669709501f..15dd33e3e1c7 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -279,27 +279,23 @@ static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, return insn->n; } -static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das08_do_wbits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct das08_private_struct *devpriv = dev->private; - int wbits; - - /* get current settings of digital output lines */ - wbits = (devpriv->do_mux_bits >> 4) & 0xf; - /* null bits we are going to set */ - wbits &= ~data[0]; - /* set new bit values */ - wbits |= data[0] & data[1]; - /* remember digital output bits */ - /* prevent race with setting of analog input mux */ - spin_lock(&dev->spinlock); - devpriv->do_mux_bits &= ~DAS08_DO_MASK; - devpriv->do_mux_bits |= DAS08_OP(wbits); - outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); - spin_unlock(&dev->spinlock); - data[1] = wbits; + if (comedi_dio_update_state(s, data)) { + /* prevent race with setting of analog input mux */ + spin_lock(&dev->spinlock); + devpriv->do_mux_bits &= ~DAS08_DO_MASK; + devpriv->do_mux_bits |= DAS08_OP(s->state); + outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); + spin_unlock(&dev->spinlock); + } + + data[1] = s->state; return insn->n; } @@ -316,17 +312,13 @@ static int das08jr_di_rbits(struct comedi_device *dev, static int das08jr_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct das08_private_struct *devpriv = dev->private; - - /* null bits we are going to set */ - devpriv->do_bits &= ~data[0]; - /* set new bit values */ - devpriv->do_bits |= data[0] & data[1]; - outb(devpriv->do_bits, dev->iobase + DAS08JR_DIO); + if (comedi_dio_update_state(s, data)) + outb(s->state, dev->iobase + DAS08JR_DIO); - data[1] = devpriv->do_bits; + data[1] = s->state; return insn->n; } diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h index cce1b584200a..46a314c5113e 100644 --- a/drivers/staging/comedi/drivers/das08.h +++ b/drivers/staging/comedi/drivers/das08.h @@ -41,7 +41,6 @@ struct das08_board_struct { struct das08_private_struct { unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */ - unsigned int do_bits; /* bits for do register on boards with register dedicated to digital out only */ const unsigned int *pg_gainlist; unsigned int ao_readback[2]; /* assume 2 AO channels */ }; diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 1b0793f33b9f..a8446ca04110 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -675,21 +675,19 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, if (cmd->scan_begin_src == TRIG_TIMER) { unsigned int tmp = cmd->scan_begin_arg; /* set divisors, correct timing arguments */ - i8253_cascade_ns_to_timer_2div(devpriv->clockbase, - &devpriv->divisor1, - &devpriv->divisor2, - &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->clockbase, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->scan_begin_arg, cmd->flags); err += (tmp != cmd->scan_begin_arg); } if (cmd->convert_src == TRIG_TIMER) { unsigned int tmp = cmd->convert_arg; /* set divisors, correct timing arguments */ - i8253_cascade_ns_to_timer_2div(devpriv->clockbase, - &devpriv->divisor1, - &devpriv->divisor2, - &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->clockbase, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, cmd->flags); err += (tmp != cmd->convert_arg); } if (err) @@ -725,11 +723,9 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, struct das16_private_struct *devpriv = dev->private; unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG; - i8253_cascade_ns_to_timer_2div(devpriv->clockbase, - &devpriv->divisor1, - &devpriv->divisor2, - &ns, - rounding_flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->clockbase, + &devpriv->divisor1, &devpriv->divisor2, + &ns, rounding_flags); /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ i8254_load(timer_base, 0, 1, devpriv->divisor1, 2); @@ -850,7 +846,7 @@ static void das16_ai_munge(struct comedi_device *dev, unsigned int start_chan_index) { unsigned int i, num_samples = num_bytes / sizeof(short); - short *data = array; + unsigned short *data = array; for (i = 0; i < num_samples; i++) { data[i] = le16_to_cpu(data[i]); @@ -952,15 +948,8 @@ static int das16_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) outb(s->state, dev->iobase + DAS16_DIO_REG); - } data[1] = s->state; @@ -1043,14 +1032,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) status = inb(dev->iobase + DAS1600_STATUS_REG); if (status & DAS1600_STATUS_CLK_10MHZ) - devpriv->clockbase = 100; + devpriv->clockbase = I8254_OSC_BASE_10MHZ; else - devpriv->clockbase = 1000; + devpriv->clockbase = I8254_OSC_BASE_1MHZ; } else { if (it->options[3]) - devpriv->clockbase = 1000 / it->options[3]; + devpriv->clockbase = I8254_OSC_BASE_1MHZ / + it->options[3]; else - devpriv->clockbase = 1000; /* 1 MHz default */ + devpriv->clockbase = I8254_OSC_BASE_1MHZ; } /* initialize dma */ diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index b943c449b691..fce9acfe8084 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -63,8 +63,6 @@ irq can be omitted, although the cmd interface will not work without it. #define DAS16M1_SIZE 16 #define DAS16M1_SIZE2 8 -#define DAS16M1_XTAL 100 /* 10 MHz master clock */ - #define FIFO_SIZE 1024 /* 1024 sample fifo */ /* @@ -133,19 +131,18 @@ struct das16m1_private_struct { * needed to keep track of whether new count has been loaded into * counter yet (loaded by first sample conversion) */ u16 initial_hw_count; - short ai_buffer[FIFO_SIZE]; - unsigned int do_bits; /* saves status of digital output bits */ + unsigned short ai_buffer[FIFO_SIZE]; unsigned int divisor1; /* divides master clock to obtain conversion speed */ unsigned int divisor2; /* divides master clock to obtain conversion speed */ unsigned long extra_iobase; }; -static inline short munge_sample(short data) +static inline unsigned short munge_sample(unsigned short data) { return (data >> 4) & 0xfff; } -static void munge_sample_array(short *array, unsigned int num_elements) +static void munge_sample_array(unsigned short *array, unsigned int num_elements) { unsigned int i; @@ -208,11 +205,10 @@ static int das16m1_cmd_test(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; /* calculate counter values that give desired timing */ - i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, - &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd->convert_arg), - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, cmd->flags); if (tmp != cmd->convert_arg) err++; } @@ -251,9 +247,10 @@ static unsigned int das16m1_set_pacer(struct comedi_device *dev, { struct das16m1_private_struct *devpriv = dev->private; - i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1), - &(devpriv->divisor2), &ns, - rounding_flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer_2div(I8254_OSC_BASE_10MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &ns, rounding_flags); /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 1, devpriv->divisor1, @@ -393,22 +390,13 @@ static int das16m1_di_rbits(struct comedi_device *dev, static int das16m1_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct das16m1_private_struct *devpriv = dev->private; - unsigned int wbits; - - /* only set bits that have been masked */ - data[0] &= 0xf; - wbits = devpriv->do_bits; - /* zero bits that have been masked */ - wbits &= ~data[0]; - /* set masked bits */ - wbits |= data[0] & data[1]; - devpriv->do_bits = wbits; - data[1] = wbits; + if (comedi_dio_update_state(s, data)) + outb(s->state, dev->iobase + DAS16M1_DIO); - outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO); + data[1] = s->state; return insn->n; } @@ -649,7 +637,7 @@ static int das16m1_attach(struct comedi_device *dev, outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL); /* initialize digital output lines */ - outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO); + outb(0, dev->iobase + DAS16M1_DIO); /* set the interrupt level */ if (dev->irq) diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 5b300294d322..1880038956d0 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -108,7 +108,6 @@ TODO: /* misc. defines */ #define DAS1800_SIZE 16 /* uses 16 io addresses */ #define FIFO_SIZE 1024 /* 1024 sample fifo */ -#define TIMER_BASE 200 /* 5 Mhz master clock */ #define UNIPOLAR 0x4 /* bit that determines whether input range is uni/bipolar */ #define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */ @@ -427,7 +426,6 @@ struct das1800_private { volatile unsigned int count; /* number of data points left to be taken */ unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ - int do_bits; /* digital output bits */ int irq_dma_bits; /* bits for control register b */ /* dma bits for control register b, stored so that dma can be * turned on and off */ @@ -440,7 +438,8 @@ struct das1800_private { uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ - short ao_update_bits; /* remembers the last write to the 'update' dac */ + unsigned short ao_update_bits; /* remembers the last write to the + * 'update' dac */ }; /* analog out range for 'ao' boards */ @@ -503,7 +502,7 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - short dpnt; + unsigned short dpnt; int unipolar; struct comedi_cmd *cmd = &s->async->cmd; @@ -840,12 +839,11 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_FOLLOW) { tmp_arg = cmd->convert_arg; /* calculate counter values that give desired timing */ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd->convert_arg), - cmd-> - flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, + cmd->flags); if (tmp_arg != cmd->convert_arg) err++; } @@ -870,16 +868,11 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, } tmp_arg = cmd->scan_begin_arg; /* calculate counter values that give desired timing */ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &(devpriv-> - divisor1), - &(devpriv-> - divisor2), - &(cmd-> - scan_begin_arg), - cmd-> - flags & - TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->scan_begin_arg, + cmd->flags); if (tmp_arg != cmd->scan_begin_arg) err++; } @@ -1011,12 +1004,10 @@ static int setup_counters(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { /* set conversion frequency */ period = cmd->convert_arg; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &devpriv->divisor1, - &devpriv->divisor2, - &period, - cmd->flags & - TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &period, cmd->flags); if (das1800_set_frequency(dev) < 0) return -1; } @@ -1024,9 +1015,10 @@ static int setup_counters(struct comedi_device *dev, case TRIG_TIMER: /* in burst mode */ /* set scan frequency */ period = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, &devpriv->divisor1, - &devpriv->divisor2, &period, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &period, cmd->flags); if (das1800_set_frequency(dev) < 0) return -1; break; @@ -1220,7 +1212,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, int i, n; int chan, range, aref, chan_range; int timeout = 1000; - short dpnt; + unsigned short dpnt; int conv_flags = 0; unsigned long irq_flags; @@ -1285,7 +1277,7 @@ static int das1800_ao_winsn(struct comedi_device *dev, int chan = CR_CHAN(insn->chanspec); /* int range = CR_RANGE(insn->chanspec); */ int update_chan = thisboard->ao_n_chan - 1; - short output; + unsigned short output; unsigned long irq_flags; /* card expects two's complement data */ @@ -1319,24 +1311,15 @@ static int das1800_di_rbits(struct comedi_device *dev, return insn->n; } -/* writes to digital output channels */ static int das1800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct das1800_private *devpriv = dev->private; - unsigned int wbits; - - /* only set bits that have been masked */ - data[0] &= (1 << s->n_chan) - 1; - wbits = devpriv->do_bits; - wbits &= ~data[0]; - wbits |= data[0] & data[1]; - devpriv->do_bits = wbits; - - outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); + if (comedi_dio_update_state(s, data)) + outb(s->state, dev->iobase + DAS1800_DIGITAL); - data[1] = devpriv->do_bits; + data[1] = s->state; return insn->n; } @@ -1644,7 +1627,7 @@ static int das1800_attach(struct comedi_device *dev, das1800_cancel(dev, dev->read_subdev); /* initialize digital out channels */ - outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); + outb(0, dev->iobase + DAS1800_DIGITAL); /* initialize analog out channels */ if (thisboard->ao_ability == 1) { diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 11e16114e4e3..5af0a5764a8c 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -66,7 +66,6 @@ cmd triggers supported: #include "comedi_fc.h" #define DAS800_SIZE 8 -#define TIMER_BASE 1000 #define N_CHAN_AI 8 /* number of analog input channels */ /* Registers for the das800 */ @@ -356,11 +355,10 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, int tmp = cmd->convert_arg; /* calculate counter values that give desired timing */ - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &devpriv->divisor1, - &devpriv->divisor2, - &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_1MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, cmd->flags); if (tmp != cmd->convert_arg) err++; } @@ -630,13 +628,9 @@ static int das800_do_insn_bits(struct comedi_device *dev, unsigned int *data) { struct das800_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; unsigned long irq_flags; - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) { devpriv->do_bits = s->state << 4; spin_lock_irqsave(&dev->spinlock, irq_flags); diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 118a4fd129f9..b04a5633f754 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -596,52 +596,40 @@ static int dmm32at_ao_rinsn(struct comedi_device *dev, static int dmm32at_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct dmm32at_private *devpriv = dev->private; - unsigned char diobits; - - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - /* Write out the new digital output lines */ - /* outw(s->state,dev->iobase + DMM32AT_DIO); */ + unsigned int mask; + unsigned int val; + + mask = comedi_dio_update_state(s, data); + if (mask) { + /* get access to the DIO regs */ + outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); + + /* if either part of dio is set for output */ + if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) || + ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) { + val = (s->state & 0x00ff0000) >> 16; + outb(val, dev->iobase + DMM32AT_DIOC); + } + if ((devpriv->dio_config & DMM32AT_DIRB) == 0) { + val = (s->state & 0x0000ff00) >> 8; + outb(val, dev->iobase + DMM32AT_DIOB); + } + if ((devpriv->dio_config & DMM32AT_DIRA) == 0) { + val = (s->state & 0x000000ff); + outb(val, dev->iobase + DMM32AT_DIOA); + } } - /* get access to the DIO regs */ - outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL); - - /* if either part of dio is set for output */ - if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) || - ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) { - diobits = (s->state & 0x00ff0000) >> 16; - outb(diobits, dev->iobase + DMM32AT_DIOC); - } - if ((devpriv->dio_config & DMM32AT_DIRB) == 0) { - diobits = (s->state & 0x0000ff00) >> 8; - outb(diobits, dev->iobase + DMM32AT_DIOB); - } - if ((devpriv->dio_config & DMM32AT_DIRA) == 0) { - diobits = (s->state & 0x000000ff); - outb(diobits, dev->iobase + DMM32AT_DIOA); - } + val = inb(dev->iobase + DMM32AT_DIOA); + val |= inb(dev->iobase + DMM32AT_DIOB) << 8; + val |= inb(dev->iobase + DMM32AT_DIOC) << 16; + s->state = val; - /* now read the state back in */ - s->state = inb(dev->iobase + DMM32AT_DIOC); - s->state <<= 8; - s->state |= inb(dev->iobase + DMM32AT_DIOB); - s->state <<= 8; - s->state |= inb(dev->iobase + DMM32AT_DIOA); - data[1] = s->state; - - /* on return, data[1] contains the value of the digital - * input and output lines. */ - /* data[1]=inw(dev->iobase + DMM32AT_DIO); */ - /* or we could just return the software copy of the output values if - * it was a purely digital output subdevice */ - /* data[1]=s->state; */ + data[1] = val; return insn->n; } diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 38918a1198aa..811c8c59c017 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -260,7 +260,8 @@ static int dt2801_readdata(struct comedi_device *dev, int *data) static int dt2801_readdata2(struct comedi_device *dev, int *data) { - int lb, hb; + int lb = 0; + int hb = 0; int ret; ret = dt2801_readdata(dev, &lb); @@ -528,23 +529,23 @@ static int dt2801_ao_insn_write(struct comedi_device *dev, static int dt2801_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - int which = 0; - - if (s == &dev->subdevices[3]) - which = 1; + int which = (s == &dev->subdevices[3]) ? 1 : 0; + unsigned int val = 0; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) { dt2801_writecmd(dev, DT_C_WRITE_DIG); dt2801_writedata(dev, which); dt2801_writedata(dev, s->state); } + dt2801_writecmd(dev, DT_C_READ_DIG); dt2801_writedata(dev, which); - dt2801_readdata(dev, data + 1); + dt2801_readdata(dev, &val); + + data[1] = val; return insn->n; } diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index a41a5716f358..0ca02fa7ba1b 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -353,11 +353,11 @@ static int dt2811_di_insn_bits(struct comedi_device *dev, static int dt2811_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - outb(s->state, dev->iobase + DT2811_DIO); + if (comedi_dio_update_state(s, data)) + outb(s->state, dev->iobase + DT2811_DIO); data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index f4a8529239b5..bf589936e546 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -80,36 +80,31 @@ static int dt2817_dio_insn_config(struct comedi_device *dev, static int dt2817_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - unsigned int changed; - - /* It's questionable whether it is more important in - * a driver like this to be deterministic or fast. - * We choose fast. */ - - if (data[0]) { - changed = s->state; - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - changed ^= s->state; - changed &= s->io_bits; - if (changed & 0x000000ff) - outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0); - if (changed & 0x0000ff00) - outb((s->state >> 8) & 0xff, - dev->iobase + DT2817_DATA + 1); - if (changed & 0x00ff0000) - outb((s->state >> 16) & 0xff, - dev->iobase + DT2817_DATA + 2); - if (changed & 0xff000000) - outb((s->state >> 24) & 0xff, - dev->iobase + DT2817_DATA + 3); + unsigned long iobase = dev->iobase + DT2817_DATA; + unsigned int mask; + unsigned int val; + + mask = comedi_dio_update_state(s, data); + if (mask) { + if (mask & 0x000000ff) + outb(s->state & 0xff, iobase + 0); + if (mask & 0x0000ff00) + outb((s->state >> 8) & 0xff, iobase + 1); + if (mask & 0x00ff0000) + outb((s->state >> 16) & 0xff, iobase + 2); + if (mask & 0xff000000) + outb((s->state >> 24) & 0xff, iobase + 3); } - data[1] = inb(dev->iobase + DT2817_DATA + 0); - data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8); - data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16); - data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24); + + val = inb(iobase + 0); + val |= (inb(iobase + 1) << 8); + val |= (inb(iobase + 2) << 16); + val |= (inb(iobase + 3) << 24); + + data[1] = val; return insn->n; } diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index da3ee859bdbc..a01e6b553887 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -226,7 +226,7 @@ struct dt282x_private { const struct comedi_lrange *darangelist[2]; - short ao[2]; + unsigned short ao[2]; volatile int dacsr; /* software copies of registers */ volatile int adcsr; @@ -237,7 +237,7 @@ struct dt282x_private { struct { int chan; - short *buf; /* DMA buffer */ + unsigned short *buf; /* DMA buffer */ volatile int size; /* size of current transfer */ } dma[2]; int dma_maxsize; /* max size of DMA transfer (in bytes) */ @@ -283,7 +283,7 @@ static void dt282x_disable_dma(struct comedi_device *dev); static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2); -static void dt282x_munge(struct comedi_device *dev, short *buf, +static void dt282x_munge(struct comedi_device *dev, unsigned short *buf, unsigned int nbytes) { const struct dt282x_board *board = comedi_board(dev); @@ -496,9 +496,9 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) #if 0 if (adcsr & DT2821_ADDONE) { int ret; - short data; + unsigned short data; - data = (short)inw(dev->iobase + DT2821_ADDAT); + data = inw(dev->iobase + DT2821_ADDAT); data &= (1 << board->adbits) - 1; if (devpriv->ad_2scomp) @@ -796,7 +796,7 @@ static int dt282x_ao_insn_write(struct comedi_device *dev, { const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; - short d; + unsigned short d; unsigned int chan; chan = CR_CHAN(insn->chanspec); @@ -967,14 +967,12 @@ static int dt282x_ao_cancel(struct comedi_device *dev, static int dt282x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + DT2821_DIODAT); - } + data[1] = inw(dev->iobase + DT2821_DIODAT); return insn->n; diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 64ef87598b60..292226eeff92 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -331,7 +331,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, int rear; int count; int i; - short data; + unsigned short data; front = readw(devpriv->io_addr + DPR_AD_Buf_Front); count = front - devpriv->ai_front; @@ -665,13 +665,12 @@ static int dt3k_dio_insn_config(struct comedi_device *dev, static int dt3k_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[1] & data[0]; + if (comedi_dio_update_state(s, data)) dt3k_writesingle(dev, SUBS_DOUT, 0, s->state); - } + data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0); return insn->n; diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index b5e6f33dc217..73af600c1725 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -85,13 +85,9 @@ for my needs. #define F020_MASK_DACxCN_DACxEN 0x80 enum { - /* A/D D/A DI DO CT */ - DT9812_DEVID_DT9812_10, /* 8 2 8 8 1 +/- 10V */ - DT9812_DEVID_DT9812_2PT5, /* 8 2 8 8 1 0-2.44V */ -#if 0 - DT9812_DEVID_DT9813, /* 16 2 4 4 1 +/- 10V */ - DT9812_DEVID_DT9814 /* 24 2 0 0 1 +/- 10V */ -#endif + /* A/D D/A DI DO CT */ + DT9812_DEVID_DT9812_10, /* 8 2 8 8 1 +/- 10V */ + DT9812_DEVID_DT9812_2PT5, /* 8 2 8 8 1 0-2.44V */ }; enum dt9812_gain { @@ -580,15 +576,8 @@ static int dt9812_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) dt9812_digital_out(dev, s->state); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index fd525f499f2a..f2a9f1c2f3b6 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -147,33 +147,23 @@ static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev, return insn->n; } -/* digital output bit interface */ static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct dyna_pci10xx_private *devpriv = dev->private; - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. - * s->state contains the previous write data - */ mutex_lock(&devpriv->mutex); - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) { smp_mb(); outw_p(s->state, devpriv->BADR3); udelay(10); } - /* - * On return, data[1] contains the value of the digital - * input and output lines. We just return the software copy of the - * output values if it was a purely digital output subdevice. - */ data[1] = s->state; mutex_unlock(&devpriv->mutex); + return insn->n; } diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 8d70f64b1574..e3ff4c438979 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -25,8 +25,7 @@ Configuration options: #define FL512_SIZE 16 /* the size of the used memory */ struct fl512_private { - - short ao_readback[2]; + unsigned short ao_readback[2]; }; static const struct comedi_lrange range_fl512 = { 4, { diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 3889d23292d0..1e16641ec52d 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -118,9 +118,7 @@ struct icp_multi_private { unsigned char act_chanlist_len; /* len of scanlist */ unsigned char act_chanlist_pos; /* actual position in MUX list */ unsigned int *ai_chanlist; /* actaul chanlist */ - short *ai_data; /* data buffer */ - short ao_data[4]; /* data output buffer */ - short di_data; /* Digital input data */ + unsigned short ao_data[4]; /* data output buffer */ unsigned int do_data; /* Remember digital output data */ }; @@ -348,18 +346,13 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev, static int icp_multi_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct icp_multi_private *devpriv = dev->private; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - - printk(KERN_DEBUG "Digital outputs = %4x \n", s->state); - + if (comedi_dio_update_state(s, data)) writew(s->state, devpriv->io_addr + ICP_MULTI_DO); - } data[1] = readw(devpriv->io_addr + ICP_MULTI_DI); @@ -548,7 +541,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev, s->maxdata = 1; s->len_chanlist = 16; s->range_table = &range_digital; - s->io_bits = 0; s->insn_bits = icp_multi_insn_bits_di; s = &dev->subdevices[3]; @@ -558,8 +550,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev, s->maxdata = 1; s->len_chanlist = 8; s->range_table = &range_digital; - s->io_bits = 0xff; - s->state = 0; s->insn_bits = icp_multi_insn_bits_do; s = &dev->subdevices[4]; diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 5c3a318b4640..8577778441fa 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -378,13 +378,10 @@ static int ii20k_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { struct ii20k_private *devpriv = dev->private; - unsigned int mask = data[0] & s->io_bits; /* outputs only */ - unsigned int bits = data[1]; + unsigned int mask; + mask = comedi_dio_update_state(s, data); if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - if (mask & 0x000000ff) writeb((s->state >> 0) & 0xff, devpriv->ioaddr + II20K_DIO0_REG); diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 8f4afadab76a..3d12e9135926 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -427,7 +427,7 @@ static int xilinx_download(struct comedi_device *dev) static void me4000_reset(struct comedi_device *dev) { struct me4000_info *info = dev->private; - unsigned long val; + unsigned int val; int chan; /* Make a hardware reset */ @@ -480,9 +480,9 @@ static int me4000_ai_insn_read(struct comedi_device *dev, int rang = CR_RANGE(insn->chanspec); int aref = CR_AREF(insn->chanspec); - unsigned long entry = 0; - unsigned long tmp; - long lval; + unsigned int entry = 0; + unsigned int tmp; + unsigned int lval; if (insn->n == 0) { return 0; @@ -586,7 +586,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - unsigned long tmp; + unsigned int tmp; /* Stop any running conversion */ tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); @@ -783,7 +783,7 @@ static int ai_prepare(struct comedi_device *dev, unsigned int scan_ticks, unsigned int chan_ticks) { - unsigned long tmp = 0; + unsigned int tmp = 0; /* Write timer arguments */ ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks); @@ -1108,7 +1108,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) struct comedi_subdevice *s = &dev->subdevices[0]; int i; int c = 0; - long lval; + unsigned int lval; if (!dev->attached) return IRQ_NONE; @@ -1252,7 +1252,7 @@ static int me4000_ao_insn_write(struct comedi_device *dev, int chan = CR_CHAN(insn->chanspec); int rang = CR_RANGE(insn->chanspec); int aref = CR_AREF(insn->chanspec); - unsigned long tmp; + unsigned int tmp; if (insn->n == 0) { return 0; @@ -1313,29 +1313,12 @@ static int me4000_ao_insn_read(struct comedi_device *dev, return 1; } -/*============================================================================= - Digital I/O section - ===========================================================================*/ - static int me4000_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - /* - * The insn data consists of a mask in data[0] and the new data - * in data[1]. The mask defines which bits we are concerning about. - * The new data must be anded with the mask. - * Each channel corresponds to a bit. - */ - if (data[0]) { - /* Check if requested ports are configured for output */ - if ((s->io_bits & data[0]) != data[0]) - return -EIO; - - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - - /* Write out the new digital output lines */ + if (comedi_dio_update_state(s, data)) { outl((s->state >> 0) & 0xFF, dev->iobase + ME4000_DIO_PORT_0_REG); outl((s->state >> 8) & 0xFF, @@ -1346,8 +1329,6 @@ static int me4000_dio_insn_bits(struct comedi_device *dev, dev->iobase + ME4000_DIO_PORT_3_REG); } - /* On return, data[1] contains the value of - the digital input and output lines. */ data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) | ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) | ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) | diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index a6f6d4a46587..24ec9ef9b1a0 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -222,15 +222,11 @@ static int me_dio_insn_bits(struct comedi_device *dev, struct me_private_data *dev_private = dev->private; void __iomem *mmio_porta = dev_private->me_regbase + ME_DIO_PORT_A; void __iomem *mmio_portb = dev_private->me_regbase + ME_DIO_PORT_B; - unsigned int mask = data[0]; - unsigned int bits = data[1]; + unsigned int mask; unsigned int val; - mask &= s->io_bits; /* only update the COMEDI_OUTPUT channels */ + mask = comedi_dio_update_state(s, data); if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - if (mask & 0x0000ffff) writew((s->state & 0xffff), mmio_porta); if (mask & 0xffff0000) @@ -545,7 +541,6 @@ static int me_auto_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = me_dio_insn_bits; s->insn_config = me_dio_insn_config; - s->io_bits = 0; dev_info(dev->class_dev, "%s: %s attached\n", dev->driver->driver_name, dev->board_name); diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 9d75ea4e201b..3ca755eca285 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -163,11 +163,11 @@ static int multiq3_di_insn_bits(struct comedi_device *dev, static int multiq3_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT); + if (comedi_dio_update_state(s, data)) + outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT); data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index c2745f201f2c..85aa9609d6a2 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -1,41 +1,33 @@ /* - comedi/drivers/ni_6527.c - driver for National Instruments PCI-6527 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_6527 -Description: National Instruments 6527 -Author: ds -Status: works -Devices: [National Instruments] PCI-6527 (ni6527), PXI-6527 -Updated: Sat, 25 Jan 2003 13:24:40 -0800 - - -*/ + * ni_6527.c + * Comedi driver for National Instruments PCI-6527 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - Manuals (available from ftp://ftp.natinst.com/support/manuals) - - 370106b.pdf 6527 Register Level Programmer Manual - + * Driver: ni_6527 + * Description: National Instruments 6527 + * Devices: (National Instruments) PCI-6527 [pci-6527] + * (National Instruments) PXI-6527 [pxi-6527] + * Author: David A. Schleef <ds@schleef.org> + * Updated: Sat, 25 Jan 2003 13:24:40 -0800 + * Status: works + * + * Configuration Options: not applicable, uses PCI auto config */ -#define DEBUG 1 -#define DEBUG_FLAGS - #include <linux/module.h> #include <linux/pci.h> #include <linux/interrupt.h> @@ -43,39 +35,41 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800 #include "../comedidev.h" #include "comedi_fc.h" -#include "mite.h" - -#define DRIVER_NAME "ni_6527" - -#define NI6527_DIO_SIZE 4096 -#define NI6527_MITE_SIZE 4096 - -#define Port_Register(x) (0x00+(x)) -#define ID_Register 0x06 - -#define Clear_Register 0x07 -#define ClrEdge 0x08 -#define ClrOverflow 0x04 -#define ClrFilter 0x02 -#define ClrInterval 0x01 -#define Filter_Interval(x) (0x08+(x)) -#define Filter_Enable(x) (0x0c+(x)) - -#define Change_Status 0x14 -#define MasterInterruptStatus 0x04 -#define Overflow 0x02 -#define EdgeStatus 0x01 - -#define Master_Interrupt_Control 0x15 -#define FallingEdgeIntEnable 0x10 -#define RisingEdgeIntEnable 0x08 -#define MasterInterruptEnable 0x04 -#define OverflowIntEnable 0x02 -#define EdgeIntEnable 0x01 - -#define Rising_Edge_Detection_Enable(x) (0x018+(x)) -#define Falling_Edge_Detection_Enable(x) (0x020+(x)) +/* + * PCI BAR1 - Register memory map + * + * Manuals (available from ftp://ftp.natinst.com/support/manuals) + * 370106b.pdf 6527 Register Level Programmer Manual + */ +#define NI6527_DI_REG(x) (0x00 + (x)) +#define NI6527_DO_REG(x) (0x03 + (x)) +#define NI6527_ID_REG 0x06 +#define NI6527_CLR_REG 0x07 +#define NI6527_CLR_EDGE (1 << 3) +#define NI6527_CLR_OVERFLOW (1 << 2) +#define NI6527_CLR_FILT (1 << 1) +#define NI6527_CLR_INTERVAL (1 << 0) +#define NI6527_CLR_IRQS (NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW) +#define NI6527_CLR_RESET_FILT (NI6527_CLR_FILT | NI6527_CLR_INTERVAL) +#define NI6527_FILT_INTERVAL_REG(x) (0x08 + (x)) +#define NI6527_FILT_ENA_REG(x) (0x0c + (x)) +#define NI6527_STATUS_REG 0x14 +#define NI6527_STATUS_IRQ (1 << 2) +#define NI6527_STATUS_OVERFLOW (1 << 1) +#define NI6527_STATUS_EDGE (1 << 0) +#define NI6527_CTRL_REG 0x15 +#define NI6527_CTRL_FALLING (1 << 4) +#define NI6527_CTRL_RISING (1 << 3) +#define NI6527_CTRL_IRQ (1 << 2) +#define NI6527_CTRL_OVERFLOW (1 << 1) +#define NI6527_CTRL_EDGE (1 << 0) +#define NI6527_CTRL_DISABLE_IRQS 0 +#define NI6527_CTRL_ENABLE_IRQS (NI6527_CTRL_FALLING | \ + NI6527_CTRL_RISING | \ + NI6527_CTRL_IRQ | NI6527_CTRL_EDGE) +#define NI6527_RISING_EDGE_REG(x) (0x18 + (x)) +#define NI6527_FALLING_EDGE_REG(x) (0x20 + (x)) enum ni6527_boardid { BOARD_PCI6527, @@ -96,96 +90,113 @@ static const struct ni6527_board ni6527_boards[] = { }; struct ni6527_private { - struct mite_struct *mite; + void __iomem *mmio_base; unsigned int filter_interval; unsigned int filter_enable; }; +static void ni6527_set_filter_interval(struct comedi_device *dev, + unsigned int val) +{ + struct ni6527_private *devpriv = dev->private; + void __iomem *mmio = devpriv->mmio_base; + + if (val != devpriv->filter_interval) { + writeb(val & 0xff, mmio + NI6527_FILT_INTERVAL_REG(0)); + writeb((val >> 8) & 0xff, mmio + NI6527_FILT_INTERVAL_REG(1)); + writeb((val >> 16) & 0x0f, mmio + NI6527_FILT_INTERVAL_REG(2)); + + writeb(NI6527_CLR_INTERVAL, mmio + NI6527_CLR_REG); + + devpriv->filter_interval = val; + } +} + +static void ni6527_set_filter_enable(struct comedi_device *dev, + unsigned int val) +{ + struct ni6527_private *devpriv = dev->private; + void __iomem *mmio = devpriv->mmio_base; + + writeb(val & 0xff, mmio + NI6527_FILT_ENA_REG(0)); + writeb((val >> 8) & 0xff, mmio + NI6527_FILT_ENA_REG(1)); + writeb((val >> 16) & 0xff, mmio + NI6527_FILT_ENA_REG(2)); +} + static int ni6527_di_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni6527_private *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); unsigned int interval; - if (insn->n != 2) - return -EINVAL; - - if (data[0] != INSN_CONFIG_FILTER) - return -EINVAL; - - if (data[1]) { + switch (data[0]) { + case INSN_CONFIG_FILTER: + /* + * The deglitch filter interval is specified in nanoseconds. + * The hardware supports intervals in 200ns increments. Round + * the user values up and return the actual interval. + */ interval = (data[1] + 100) / 200; data[1] = interval * 200; - if (interval != devpriv->filter_interval) { - writeb(interval & 0xff, - devpriv->mite->daq_io_addr + Filter_Interval(0)); - writeb((interval >> 8) & 0xff, - devpriv->mite->daq_io_addr + Filter_Interval(1)); - writeb((interval >> 16) & 0x0f, - devpriv->mite->daq_io_addr + Filter_Interval(2)); - - writeb(ClrInterval, - devpriv->mite->daq_io_addr + Clear_Register); - - devpriv->filter_interval = interval; + if (interval) { + ni6527_set_filter_interval(dev, interval); + devpriv->filter_enable |= 1 << chan; + } else { + devpriv->filter_enable &= ~(1 << chan); } - - devpriv->filter_enable |= 1 << chan; - } else { - devpriv->filter_enable &= ~(1 << chan); + ni6527_set_filter_enable(dev, devpriv->filter_enable); + break; + default: + return -EINVAL; } - writeb(devpriv->filter_enable, - devpriv->mite->daq_io_addr + Filter_Enable(0)); - writeb(devpriv->filter_enable >> 8, - devpriv->mite->daq_io_addr + Filter_Enable(1)); - writeb(devpriv->filter_enable >> 16, - devpriv->mite->daq_io_addr + Filter_Enable(2)); - - return 2; + return insn->n; } static int ni6527_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni6527_private *devpriv = dev->private; + void __iomem *mmio = devpriv->mmio_base; + unsigned int val; - data[1] = readb(devpriv->mite->daq_io_addr + Port_Register(0)); - data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8; - data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16; + val = readb(mmio + NI6527_DI_REG(0)); + val |= (readb(mmio + NI6527_DI_REG(1)) << 8); + val |= (readb(mmio + NI6527_DI_REG(2)) << 16); + + data[1] = val; return insn->n; } static int ni6527_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni6527_private *devpriv = dev->private; - - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - - /* The open relay state on the board cooresponds to 1, - * but in Comedi, it is represented by 0. */ - if (data[0] & 0x0000ff) { - writeb((s->state ^ 0xff), - devpriv->mite->daq_io_addr + Port_Register(3)); - } - if (data[0] & 0x00ff00) { - writeb((s->state >> 8) ^ 0xff, - devpriv->mite->daq_io_addr + Port_Register(4)); - } - if (data[0] & 0xff0000) { - writeb((s->state >> 16) ^ 0xff, - devpriv->mite->daq_io_addr + Port_Register(5)); - } + void __iomem *mmio = devpriv->mmio_base; + unsigned int mask; + + mask = comedi_dio_update_state(s, data); + if (mask) { + /* Outputs are inverted */ + unsigned int val = s->state ^ 0xffffff; + + if (mask & 0x0000ff) + writeb(val & 0xff, mmio + NI6527_DO_REG(0)); + if (mask & 0x00ff00) + writeb((val >> 8) & 0xff, mmio + NI6527_DO_REG(1)); + if (mask & 0xff0000) + writeb((val >> 16) & 0xff, mmio + NI6527_DO_REG(2)); } + data[1] = s->state; return insn->n; @@ -195,21 +206,22 @@ static irqreturn_t ni6527_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct ni6527_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[2]; + struct comedi_subdevice *s = dev->read_subdev; + void __iomem *mmio = devpriv->mmio_base; unsigned int status; - status = readb(devpriv->mite->daq_io_addr + Change_Status); - if ((status & MasterInterruptStatus) == 0) - return IRQ_NONE; - if ((status & EdgeStatus) == 0) + status = readb(mmio + NI6527_STATUS_REG); + if (!(status & NI6527_STATUS_IRQ)) return IRQ_NONE; - writeb(ClrEdge | ClrOverflow, - devpriv->mite->daq_io_addr + Clear_Register); + if (status & NI6527_STATUS_EDGE) { + comedi_buf_put(s->async, 0); + s->async->events |= COMEDI_CB_EOS; + comedi_event(dev, s); + } + + writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG); - comedi_buf_put(s->async, 0); - s->async->events |= COMEDI_CB_EOS; - comedi_event(dev, s); return IRQ_HANDLED; } @@ -259,13 +271,10 @@ static int ni6527_intr_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct ni6527_private *devpriv = dev->private; - /* struct comedi_cmd *cmd = &s->async->cmd; */ + void __iomem *mmio = devpriv->mmio_base; - writeb(ClrEdge | ClrOverflow, - devpriv->mite->daq_io_addr + Clear_Register); - writeb(FallingEdgeIntEnable | RisingEdgeIntEnable | - MasterInterruptEnable | EdgeIntEnable, - devpriv->mite->daq_io_addr + Master_Interrupt_Control); + writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG); + writeb(NI6527_CTRL_ENABLE_IRQS, mmio + NI6527_CTRL_REG); return 0; } @@ -274,8 +283,9 @@ static int ni6527_intr_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct ni6527_private *devpriv = dev->private; + void __iomem *mmio = devpriv->mmio_base; - writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control); + writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG); return 0; } @@ -288,32 +298,54 @@ static int ni6527_intr_insn_bits(struct comedi_device *dev, return insn->n; } +static void ni6527_set_edge_detection(struct comedi_device *dev, + unsigned int rising, + unsigned int falling) +{ + struct ni6527_private *devpriv = dev->private; + void __iomem *mmio = devpriv->mmio_base; + + /* enable rising-edge detection channels */ + writeb(rising & 0xff, mmio + NI6527_RISING_EDGE_REG(0)); + writeb((rising >> 8) & 0xff, mmio + NI6527_RISING_EDGE_REG(1)); + writeb((rising >> 16) & 0xff, mmio + NI6527_RISING_EDGE_REG(2)); + + /* enable falling-edge detection channels */ + writeb(falling & 0xff, mmio + NI6527_FALLING_EDGE_REG(0)); + writeb((falling >> 8) & 0xff, mmio + NI6527_FALLING_EDGE_REG(1)); + writeb((falling >> 16) & 0xff, mmio + NI6527_FALLING_EDGE_REG(2)); +} + static int ni6527_intr_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) +{ + switch (data[0]) { + case INSN_CONFIG_CHANGE_NOTIFY: + /* check_insn_config_length() does not check this instruction */ + if (insn->n != 3) + return -EINVAL; + ni6527_set_edge_detection(dev, data[1], data[2]); + break; + default: + return -EINVAL; + } + + return insn->n; +} + +static void ni6527_reset(struct comedi_device *dev) { struct ni6527_private *devpriv = dev->private; + void __iomem *mmio = devpriv->mmio_base; - if (insn->n < 1) - return -EINVAL; - if (data[0] != INSN_CONFIG_CHANGE_NOTIFY) - return -EINVAL; + /* disable deglitch filters on all channels */ + ni6527_set_filter_enable(dev, 0); - writeb(data[1], - devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0)); - writeb(data[1] >> 8, - devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(1)); - writeb(data[1] >> 16, - devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(2)); - - writeb(data[2], - devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0)); - writeb(data[2] >> 8, - devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(1)); - writeb(data[2] >> 16, - devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(2)); - - return 2; + writeb(NI6527_CLR_IRQS | NI6527_CLR_RESET_FILT, + mmio + NI6527_CLR_REG); + writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG); } static int ni6527_auto_attach(struct comedi_device *dev, @@ -332,75 +364,69 @@ static int ni6527_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; + ret = comedi_pci_enable(dev); if (ret) return ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) + devpriv->mmio_base = pci_ioremap_bar(pcidev, 1); + if (!devpriv->mmio_base) return -ENOMEM; - devpriv->mite = mite_alloc(pcidev); - if (!devpriv->mite) - return -ENOMEM; + /* make sure this is actually a 6527 device */ + if (readb(devpriv->mmio_base + NI6527_ID_REG) != 0x27) + return -ENODEV; - ret = mite_setup(devpriv->mite); - if (ret < 0) { - dev_err(dev->class_dev, "error setting up mite\n"); - return ret; - } + ni6527_reset(dev); - dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name, - readb(devpriv->mite->daq_io_addr + ID_Register)); + ret = request_irq(pcidev->irq, ni6527_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (ret == 0) + dev->irq = pcidev->irq; ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; + /* Digital Input subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 24; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_config = ni6527_di_insn_config; - s->insn_bits = ni6527_di_insn_bits; - + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 24; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_config = ni6527_di_insn_config; + s->insn_bits = ni6527_di_insn_bits; + + /* Digital Output subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 24; - s->range_table = &range_unknown; /* FIXME: actually conductance */ - s->maxdata = 1; - s->insn_bits = ni6527_do_insn_bits; - + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 24; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ni6527_do_insn_bits; + + /* Edge detection interrupt subdevice */ s = &dev->subdevices[2]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; - s->n_chan = 1; - s->range_table = &range_unknown; - s->maxdata = 1; - s->do_cmdtest = ni6527_intr_cmdtest; - s->do_cmd = ni6527_intr_cmd; - s->cancel = ni6527_intr_cancel; - s->insn_bits = ni6527_intr_insn_bits; - s->insn_config = ni6527_intr_insn_config; - - writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0)); - writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(1)); - writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(2)); - - writeb(ClrEdge | ClrOverflow | ClrFilter | ClrInterval, - devpriv->mite->daq_io_addr + Clear_Register); - writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control); - - ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt, - IRQF_SHARED, DRIVER_NAME, dev); - if (ret < 0) - dev_warn(dev->class_dev, "irq not available\n"); - else - dev->irq = mite_irq(devpriv->mite); + if (dev->irq) { + dev->read_subdev = s; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_config = ni6527_intr_insn_config; + s->insn_bits = ni6527_intr_insn_bits; + s->do_cmdtest = ni6527_intr_cmdtest; + s->do_cmd = ni6527_intr_cmd; + s->cancel = ni6527_intr_cancel; + } else { + s->type = COMEDI_SUBD_UNUSED; + } return 0; } @@ -409,23 +435,18 @@ static void ni6527_detach(struct comedi_device *dev) { struct ni6527_private *devpriv = dev->private; - if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr) - writeb(0x00, - devpriv->mite->daq_io_addr + Master_Interrupt_Control); + if (devpriv && devpriv->mmio_base) + ni6527_reset(dev); if (dev->irq) free_irq(dev->irq, dev); - if (devpriv && devpriv->mite) { - mite_unsetup(devpriv->mite); - mite_free(devpriv->mite); - } comedi_pci_disable(dev); } static struct comedi_driver ni6527_driver = { - .driver_name = DRIVER_NAME, - .module = THIS_MODULE, - .auto_attach = ni6527_auto_attach, - .detach = ni6527_detach, + .driver_name = "ni_6527", + .module = THIS_MODULE, + .auto_attach = ni6527_auto_attach, + .detach = ni6527_detach, }; static int ni6527_pci_probe(struct pci_dev *dev, @@ -442,7 +463,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = { MODULE_DEVICE_TABLE(pci, ni6527_pci_table); static struct pci_driver ni6527_pci_driver = { - .name = DRIVER_NAME, + .name = "ni_6527", .id_table = ni6527_pci_table, .probe = ni6527_pci_probe, .remove = comedi_pci_auto_unconfig, @@ -450,5 +471,5 @@ static struct pci_driver ni6527_pci_driver = { module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for National Instruments PCI-6527"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index 3607336dafe2..8a991dcab24a 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -1213,7 +1213,6 @@ static int ni_660x_auto_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = ni_660x_dio_insn_bits; s->insn_config = ni_660x_dio_insn_config; - s->io_bits = 0; /* all bits default to input */ /* we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg */ ni_660x_write_register(dev, 0, 0, STCDIOControl); diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index e2926ce3fb24..e4414cf110e7 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -136,20 +136,15 @@ static int ni_670x_ao_rinsn(struct comedi_device *dev, static int ni_670x_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni_670x_private *devpriv = dev->private; void __iomem *io_addr = devpriv->mite->daq_io_addr + DIO_PORT0_DATA_OFFSET; - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) writel(s->state, io_addr); - } data[1] = readl(io_addr); diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 2512ce8dfcaa..63c847932eb8 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -154,7 +154,7 @@ struct a2150_private { volatile unsigned int count; /* number of data points left to be taken */ unsigned int dma; /* dma channel */ - s16 *dma_buffer; /* dma buffer */ + uint16_t *dma_buffer; /* dma buffer */ unsigned int dma_transfer_size; /* size in bytes of dma transfers */ int irq_dma_bits; /* irq/dma register bits */ int config_bits; /* config register bits */ @@ -192,7 +192,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) struct comedi_async *async; struct comedi_cmd *cmd; unsigned int max_points, num_points, residue, leftover; - short dpnt; + unsigned short dpnt; static const int sample_size = sizeof(devpriv->dma_buffer[0]); if (!dev->attached) { @@ -684,13 +684,12 @@ static int a2150_set_chanlist(struct comedi_device *dev, devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel); break; case 2: - if (start_channel == 0) { + if (start_channel == 0) devpriv->config_bits |= CHANNEL_BITS(0x2); - } else if (start_channel == 2) { + else if (start_channel == 2) devpriv->config_bits |= CHANNEL_BITS(0x3); - } else { + else return -1; - } break; case 4: devpriv->config_bits |= CHANNEL_BITS(0x1); diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index b9122fd835e1..10e3e9475ee2 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -1,247 +1,193 @@ /* - comedi/drivers/ni_at_ao.c - Driver for NI AT-AO-6/10 boards - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000,2002 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: ni_at_ao -Description: National Instruments AT-AO-6/10 -Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10) -Status: should work -Author: ds -Updated: Sun Dec 26 12:26:28 EST 2004 - -Configuration options: - [0] - I/O port base address - [1] - IRQ (unused) - [2] - DMA (unused) - [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V - bipolar, 1 for 0V to 10V unipolar) - -*/ + * ni_at_ao.c + * Driver for NI AT-AO-6/10 boards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000,2002 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + /* - * Register-level programming information can be found in NI - * document 320379.pdf. + * Driver: ni_at_ao + * Description: National Instruments AT-AO-6/10 + * Devices: (National Instruments) AT-AO-6 [at-ao-6] + * (National Instruments) AT-AO-10 [at-ao-10] + * Status: should work + * Author: David A. Schleef <ds@schleef.org> + * Updated: Sun Dec 26 12:26:28 EST 2004 + * + * Configuration options: + * [0] - I/O port base address + * [1] - IRQ (unused) + * [2] - DMA (unused) + * [3] - analog output range, set by jumpers on hardware + * 0 for -10 to 10V bipolar + * 1 for 0V to 10V unipolar */ #include <linux/module.h> -#include "../comedidev.h" -/* board egisters */ -/* registers with _2_ are accessed when GRP2WR is set in CFG1 */ +#include "../comedidev.h" -#define ATAO_SIZE 0x20 - -#define ATAO_2_DMATCCLR 0x00 /* W 16 */ -#define ATAO_DIN 0x00 /* R 16 */ -#define ATAO_DOUT 0x00 /* W 16 */ - -#define ATAO_CFG2 0x02 /* W 16 */ -#define CALLD1 0x8000 -#define CALLD0 0x4000 -#define FFRTEN 0x2000 -#define DAC2S8 0x1000 -#define DAC2S6 0x0800 -#define DAC2S4 0x0400 -#define DAC2S2 0x0200 -#define DAC2S0 0x0100 -#define LDAC8 0x0080 -#define LDAC6 0x0040 -#define LDAC4 0x0020 -#define LDAC2 0x0010 -#define LDAC0 0x0008 -#define PROMEN 0x0004 -#define SCLK 0x0002 -#define SDATA 0x0001 - -#define ATAO_2_INT1CLR 0x02 /* W 16 */ - -#define ATAO_CFG3 0x04 /* W 16 */ -#define DMAMODE 0x0040 -#define CLKOUT 0x0020 -#define RCLKEN 0x0010 -#define DOUTEN2 0x0008 -#define DOUTEN1 0x0004 -#define EN2_5V 0x0002 -#define SCANEN 0x0001 - -#define ATAO_2_INT2CLR 0x04 /* W 16 */ - -#define ATAO_82C53_BASE 0x06 /* RW 8 */ - -#define ATAO_82C53_CNTR1 0x06 /* RW 8 */ -#define ATAO_82C53_CNTR2 0x07 /* RW 8 */ -#define ATAO_82C53_CNTR3 0x08 /* RW 8 */ -#define ATAO_82C53_CNTRCMD 0x09 /* W 8 */ -#define CNTRSEL1 0x80 -#define CNTRSEL0 0x40 -#define RWSEL1 0x20 -#define RWSEL0 0x10 -#define MODESEL2 0x08 -#define MODESEL1 0x04 -#define MODESEL0 0x02 -#define BCDSEL 0x01 - /* read-back command */ -#define COUNT 0x20 -#define STATUS 0x10 -#define CNTR3 0x08 -#define CNTR2 0x04 -#define CNTR1 0x02 - /* status */ -#define OUT 0x80 -#define _NULL 0x40 -#define RW1 0x20 -#define RW0 0x10 -#define MODE2 0x08 -#define MODE1 0x04 -#define MODE0 0x02 -#define BCD 0x01 - -#define ATAO_2_RTSISHFT 0x06 /* W 8 */ -#define RSI 0x01 - -#define ATAO_2_RTSISTRB 0x07 /* W 8 */ - -#define ATAO_CFG1 0x0a /* W 16 */ -#define EXTINT2EN 0x8000 -#define EXTINT1EN 0x4000 -#define CNTINT2EN 0x2000 -#define CNTINT1EN 0x1000 -#define TCINTEN 0x0800 -#define CNT1SRC 0x0400 -#define CNT2SRC 0x0200 -#define FIFOEN 0x0100 -#define GRP2WR 0x0080 -#define EXTUPDEN 0x0040 -#define DMARQ 0x0020 -#define DMAEN 0x0010 -#define CH_mask 0x000f -#define ATAO_STATUS 0x0a /* R 16 */ -#define FH 0x0040 -#define FE 0x0020 -#define FF 0x0010 -#define INT2 0x0008 -#define INT1 0x0004 -#define TCINT 0x0002 -#define PROMOUT 0x0001 - -#define ATAO_FIFO_WRITE 0x0c /* W 16 */ -#define ATAO_FIFO_CLEAR 0x0c /* R 16 */ -#define ATAO_DACn(x) (0x0c + 2*(x)) /* W */ +#include "8253.h" /* - * Board descriptions for two imaginary boards. Describing the - * boards in this way is optional, and completely driver-dependent. - * Some drivers use arrays such as this, other do not. + * Register map + * + * Register-level programming information can be found in NI + * document 320379.pdf. */ +#define ATAO_DIO_REG 0x00 +#define ATAO_CFG2_REG 0x02 +#define ATAO_CFG2_CALLD_NOP (0 << 14) +#define ATAO_CFG2_CALLD(x) ((((x) >> 3) + 1) << 14) +#define ATAO_CFG2_FFRTEN (1 << 13) +#define ATAO_CFG2_DACS(x) (1 << (((x) / 2) + 8)) +#define ATAO_CFG2_LDAC(x) (1 << (((x) / 2) + 3)) +#define ATAO_CFG2_PROMEN (1 << 2) +#define ATAO_CFG2_SCLK (1 << 1) +#define ATAO_CFG2_SDATA (1 << 0) +#define ATAO_CFG3_REG 0x04 +#define ATAO_CFG3_DMAMODE (1 << 6) +#define ATAO_CFG3_CLKOUT (1 << 5) +#define ATAO_CFG3_RCLKEN (1 << 4) +#define ATAO_CFG3_DOUTEN2 (1 << 3) +#define ATAO_CFG3_DOUTEN1 (1 << 2) +#define ATAO_CFG3_EN2_5V (1 << 1) +#define ATAO_CFG3_SCANEN (1 << 0) +#define ATAO_82C53_BASE 0x06 +#define ATAO_CFG1_REG 0x0a +#define ATAO_CFG1_EXTINT2EN (1 << 15) +#define ATAO_CFG1_EXTINT1EN (1 << 14) +#define ATAO_CFG1_CNTINT2EN (1 << 13) +#define ATAO_CFG1_CNTINT1EN (1 << 12) +#define ATAO_CFG1_TCINTEN (1 << 11) +#define ATAO_CFG1_CNT1SRC (1 << 10) +#define ATAO_CFG1_CNT2SRC (1 << 9) +#define ATAO_CFG1_FIFOEN (1 << 8) +#define ATAO_CFG1_GRP2WR (1 << 7) +#define ATAO_CFG1_EXTUPDEN (1 << 6) +#define ATAO_CFG1_DMARQ (1 << 5) +#define ATAO_CFG1_DMAEN (1 << 4) +#define ATAO_CFG1_CH(x) (((x) & 0xf) << 0) +#define ATAO_STATUS_REG 0x0a +#define ATAO_STATUS_FH (1 << 6) +#define ATAO_STATUS_FE (1 << 5) +#define ATAO_STATUS_FF (1 << 4) +#define ATAO_STATUS_INT2 (1 << 3) +#define ATAO_STATUS_INT1 (1 << 2) +#define ATAO_STATUS_TCINT (1 << 1) +#define ATAO_STATUS_PROMOUT (1 << 0) +#define ATAO_FIFO_WRITE_REG 0x0c +#define ATAO_FIFO_CLEAR_REG 0x0c +#define ATAO_AO_REG(x) (0x0c + ((x) * 2)) + +/* registers with _2_ are accessed when GRP2WR is set in CFG1 */ +#define ATAO_2_DMATCCLR_REG 0x00 +#define ATAO_2_INT1CLR_REG 0x02 +#define ATAO_2_INT2CLR_REG 0x04 +#define ATAO_2_RTSISHFT_REG 0x06 +#define ATAO_2_RTSISHFT_RSI (1 << 0) +#define ATAO_2_RTSISTRB_REG 0x07 + struct atao_board { const char *name; int n_ao_chans; }; -struct atao_private { +static const struct atao_board atao_boards[] = { + { + .name = "at-ao-6", + .n_ao_chans = 6, + }, { + .name = "at-ao-10", + .n_ao_chans = 10, + }, +}; +struct atao_private { unsigned short cfg1; - unsigned short cfg2; unsigned short cfg3; /* Used for AO readback */ unsigned int ao_readback[10]; + + /* Used for caldac readback */ + unsigned char caldac[21]; }; -static void atao_reset(struct comedi_device *dev) +static void atao_select_reg_group(struct comedi_device *dev, int group) { struct atao_private *devpriv = dev->private; - /* This is the reset sequence described in the manual */ - - devpriv->cfg1 = 0; - outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); - - outb(RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); - outb(0x03, dev->iobase + ATAO_82C53_CNTR1); - outb(CNTRSEL0 | RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); - - devpriv->cfg2 = 0; - outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); - - devpriv->cfg3 = 0; - outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); - - inw(dev->iobase + ATAO_FIFO_CLEAR); - - devpriv->cfg1 |= GRP2WR; - outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); - - outw(0, dev->iobase + ATAO_2_INT1CLR); - outw(0, dev->iobase + ATAO_2_INT2CLR); - outw(0, dev->iobase + ATAO_2_DMATCCLR); - - devpriv->cfg1 &= ~GRP2WR; - outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); + if (group) + devpriv->cfg1 |= ATAO_CFG1_GRP2WR; + else + devpriv->cfg1 &= ~ATAO_CFG1_GRP2WR; + outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG); } -static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int atao_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct atao_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val; int i; - int chan = CR_CHAN(insn->chanspec); - short bits; + + if (chan == 0) + atao_select_reg_group(dev, 1); for (i = 0; i < insn->n; i++) { - bits = data[i] - 0x800; - if (chan == 0) { - devpriv->cfg1 |= GRP2WR; - outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); - } - outw(bits, dev->iobase + ATAO_DACn(chan)); - if (chan == 0) { - devpriv->cfg1 &= ~GRP2WR; - outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); - } - devpriv->ao_readback[chan] = data[i]; + val = data[i]; + devpriv->ao_readback[chan] = val; + + /* munge offset binary (unsigned) to two's complement */ + val = comedi_offset_munge(s, val); + outw(val, dev->iobase + ATAO_AO_REG(chan)); } - return i; + if (chan == 0) + atao_select_reg_group(dev, 0); + + return insn->n; } -static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int atao_ao_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct atao_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); int i; - int chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; - return i; + return insn->n; } static int atao_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - outw(s->state, dev->iobase + ATAO_DOUT); - } + if (comedi_dio_update_state(s, data)) + outw(s->state, dev->iobase + ATAO_DIO_REG); - data[1] = inw(dev->iobase + ATAO_DIN); + data[1] = inw(dev->iobase + ATAO_DIO_REG); return insn->n; } @@ -266,57 +212,128 @@ static int atao_dio_insn_config(struct comedi_device *dev, return ret; if (s->io_bits & 0x0f) - devpriv->cfg3 |= DOUTEN1; + devpriv->cfg3 |= ATAO_CFG3_DOUTEN1; else - devpriv->cfg3 &= ~DOUTEN1; + devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN1; if (s->io_bits & 0xf0) - devpriv->cfg3 |= DOUTEN2; + devpriv->cfg3 |= ATAO_CFG3_DOUTEN2; else - devpriv->cfg3 &= ~DOUTEN2; + devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN2; - outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); + outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG); return insn->n; } /* - * Figure 2-1 in the manual shows 3 chips labeled DAC8800, which - * are 8-channel 8-bit DACs. These are most likely the calibration - * DACs. It is not explicitly stated in the manual how to access - * the caldacs, but we can guess. + * There are three DAC8800 TrimDACs on the board. These are 8-channel, + * 8-bit DACs that are used to calibrate the Analog Output channels. + * The factory default calibration values are stored in the EEPROM. + * The TrimDACs, and EEPROM addresses, are mapped as: + * + * Channel EEPROM Description + * ----------------- ------ ----------------------------------- + * 0 - DAC0 Chan 0 0x30 AO Channel 0 Offset + * 1 - DAC0 Chan 1 0x31 AO Channel 0 Gain + * 2 - DAC0 Chan 2 0x32 AO Channel 1 Offset + * 3 - DAC0 Chan 3 0x33 AO Channel 1 Gain + * 4 - DAC0 Chan 4 0x34 AO Channel 2 Offset + * 5 - DAC0 Chan 5 0x35 AO Channel 2 Gain + * 6 - DAC0 Chan 6 0x36 AO Channel 3 Offset + * 7 - DAC0 Chan 7 0x37 AO Channel 3 Gain + * 8 - DAC1 Chan 0 0x38 AO Channel 4 Offset + * 9 - DAC1 Chan 1 0x39 AO Channel 4 Gain + * 10 - DAC1 Chan 2 0x3a AO Channel 5 Offset + * 11 - DAC1 Chan 3 0x3b AO Channel 5 Gain + * 12 - DAC1 Chan 4 0x3c 2.5V Offset + * 13 - DAC1 Chan 5 0x3d AO Channel 6 Offset (at-ao-10 only) + * 14 - DAC1 Chan 6 0x3e AO Channel 6 Gain (at-ao-10 only) + * 15 - DAC1 Chan 7 0x3f AO Channel 7 Offset (at-ao-10 only) + * 16 - DAC2 Chan 0 0x40 AO Channel 7 Gain (at-ao-10 only) + * 17 - DAC2 Chan 1 0x41 AO Channel 8 Offset (at-ao-10 only) + * 18 - DAC2 Chan 2 0x42 AO Channel 8 Gain (at-ao-10 only) + * 19 - DAC2 Chan 3 0x43 AO Channel 9 Offset (at-ao-10 only) + * 20 - DAC2 Chan 4 0x44 AO Channel 9 Gain (at-ao-10 only) + * DAC2 Chan 5 0x45 Reserved + * DAC2 Chan 6 0x46 Reserved + * DAC2 Chan 7 0x47 Reserved */ +static int atao_calib_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct atao_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int bitstring; + unsigned int val; + int bit; + + if (insn->n == 0) + return 0; + + devpriv->caldac[chan] = data[insn->n - 1] & s->maxdata; + + /* write the channel and last data value to the caldac */ + bitstring = ((chan & 0x7) << 8) | devpriv->caldac[chan]; + + /* clock the bitstring to the caldac; MSB -> LSB */ + for (bit = 1 << 10; bit; bit >>= 1) { + val = (bit & bitstring) ? ATAO_CFG2_SDATA : 0; + + outw(val, dev->iobase + ATAO_CFG2_REG); + outw(val | ATAO_CFG2_SCLK, dev->iobase + ATAO_CFG2_REG); + } + + /* strobe the caldac to load the value */ + outw(ATAO_CFG2_CALLD(chan), dev->iobase + ATAO_CFG2_REG); + outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG); + + return insn->n; +} + static int atao_calib_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { + struct atao_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); int i; + for (i = 0; i < insn->n; i++) - data[i] = 0; /* XXX */ + data[i] = devpriv->caldac[chan]; + return insn->n; } -static int atao_calib_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static void atao_reset(struct comedi_device *dev) { struct atao_private *devpriv = dev->private; - unsigned int bitstring, bit; - unsigned int chan = CR_CHAN(insn->chanspec); - bitstring = ((chan & 0x7) << 8) | (data[insn->n - 1] & 0xff); + /* This is the reset sequence described in the manual */ - for (bit = 1 << (11 - 1); bit; bit >>= 1) { - outw(devpriv->cfg2 | ((bit & bitstring) ? SDATA : 0), - dev->iobase + ATAO_CFG2); - outw(devpriv->cfg2 | SCLK | ((bit & bitstring) ? SDATA : 0), - dev->iobase + ATAO_CFG2); - } - /* strobe the appropriate caldac */ - outw(devpriv->cfg2 | (((chan >> 3) + 1) << 14), - dev->iobase + ATAO_CFG2); - outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); + devpriv->cfg1 = 0; + outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG); - return insn->n; + /* Put outputs of counter 1 and counter 2 in a high state */ + i8254_load(dev->iobase + ATAO_82C53_BASE, 0, + 0, 0x0003, I8254_MODE4 | I8254_BINARY); + i8254_set_mode(dev->iobase + ATAO_82C53_BASE, 0, + 1, I8254_MODE4 | I8254_BINARY); + + outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG); + + devpriv->cfg3 = 0; + outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG); + + inw(dev->iobase + ATAO_FIFO_CLEAR_REG); + + atao_select_reg_group(dev, 1); + outw(0, dev->iobase + ATAO_2_INT1CLR_REG); + outw(0, dev->iobase + ATAO_2_INT2CLR_REG); + outw(0, dev->iobase + ATAO_2_DMATCCLR_REG); + atao_select_reg_group(dev, 0); } static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -324,12 +341,9 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct atao_board *board = comedi_board(dev); struct atao_private *devpriv; struct comedi_subdevice *s; - int ao_unipolar; int ret; - ao_unipolar = it->options[3]; - - ret = comedi_request_region(dev, it->options[0], ATAO_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x20); if (ret) return ret; @@ -341,60 +355,44 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; + /* Analog Output subdevice */ s = &dev->subdevices[0]; - /* analog output subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = board->n_ao_chans; - s->maxdata = (1 << 12) - 1; - if (ao_unipolar) - s->range_table = &range_unipolar10; - else - s->range_table = &range_bipolar10; - s->insn_write = &atao_ao_winsn; - s->insn_read = &atao_ao_rinsn; - + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = board->n_ao_chans; + s->maxdata = 0x0fff; + s->range_table = it->options[3] ? &range_unipolar10 : &range_bipolar10; + s->insn_write = atao_ao_insn_write; + s->insn_read = atao_ao_insn_read; + + /* Digital I/O subdevice */ s = &dev->subdevices[1]; - /* digital i/o subdevice */ - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = atao_dio_insn_bits; - s->insn_config = atao_dio_insn_config; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = atao_dio_insn_bits; + s->insn_config = atao_dio_insn_config; - s = &dev->subdevices[2]; /* caldac subdevice */ - s->type = COMEDI_SUBD_CALIB; - s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; - s->n_chan = 21; - s->maxdata = 0xff; - s->insn_read = atao_calib_insn_read; - s->insn_write = atao_calib_insn_write; - + s = &dev->subdevices[2]; + s->type = COMEDI_SUBD_CALIB; + s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; + s->n_chan = (board->n_ao_chans * 2) + 1; + s->maxdata = 0xff; + s->insn_read = atao_calib_insn_read; + s->insn_write = atao_calib_insn_write; + + /* EEPROM subdevice */ s = &dev->subdevices[3]; - /* eeprom subdevice */ - /* s->type=COMEDI_SUBD_EEPROM; */ - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; atao_reset(dev); - printk(KERN_INFO "\n"); - return 0; } -static const struct atao_board atao_boards[] = { - { - .name = "ai-ao-6", - .n_ao_chans = 6, - }, { - .name = "ai-ao-10", - .n_ao_chans = 10, - }, -}; - static struct comedi_driver ni_at_ao_driver = { .driver_name = "ni_at_ao", .module = THIS_MODULE, @@ -407,5 +405,5 @@ static struct comedi_driver ni_at_ao_driver = { module_comedi_driver(ni_at_ao_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for NI AT-AO-6/10 boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index bb3491f5ad21..a9f7d40d6db2 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -558,13 +558,12 @@ static int atmio16d_ao_insn_write(struct comedi_device *dev, static int atmio16d_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] | data[1]); + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + MIO_16_DIG_OUT_REG); - } + data[1] = inw(dev->iobase + MIO_16_DIG_IN_REG); return insn->n; diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 404f83de276d..e4cdca349157 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -72,18 +72,22 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf static int daq700_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + unsigned int mask; + unsigned int val; - if (data[0] & 0xff) + mask = comedi_dio_update_state(s, data); + if (mask) { + if (mask & 0xff) outb(s->state & 0xff, dev->iobase + DIO_W); } - data[1] = s->state & 0xff; - data[1] |= inb(dev->iobase + DIO_R) << 8; + val = s->state & 0xff; + val |= inb(dev->iobase + DIO_R) << 8; + + data[1] = val; return insn->n; } @@ -212,7 +216,6 @@ static int daq700_auto_attach(struct comedi_device *dev, s->maxdata = 1; s->insn_bits = daq700_dio_insn_bits; s->insn_config = daq700_dio_insn_config; - s->state = 0; s->io_bits = 0x00ff; /* DAQCard-700 ai */ diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 1add114dc0bc..0512445df08e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -73,7 +73,6 @@ #include "ni_labpc_isadma.h" #define LABPC_SIZE 0x20 /* size of ISA io region */ -#define LABPC_TIMER_BASE 500 /* 2 MHz master clock */ #define LABPC_ADC_TIMEOUT 1000 enum scan_mode { @@ -201,12 +200,6 @@ static int labpc_counter_set_mode(struct comedi_device *dev, return i8254_set_mode(base_address, 0, counter_number, mode); } -static bool labpc_range_is_unipolar(struct comedi_subdevice *s, - unsigned int range) -{ - return s->range_table->range[range].min >= 0; -} - static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct labpc_private *devpriv = dev->private; @@ -272,7 +265,7 @@ static void labpc_setup_cmd6_reg(struct comedi_device *dev, devpriv->cmd6 &= ~CMD6_NRSE; /* bipolar or unipolar range? */ - if (labpc_range_is_unipolar(s, range)) + if (comedi_range_is_unipolar(s, range)) devpriv->cmd6 |= CMD6_ADCUNI; else devpriv->cmd6 &= ~CMD6_ADCUNI; @@ -465,13 +458,13 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, * clock speed on convert and scan counters) */ devpriv->divisor_b0 = (scan_period - 1) / - (LABPC_TIMER_BASE * max_counter_value) + 1; + (I8254_OSC_BASE_2MHZ * max_counter_value) + 1; if (devpriv->divisor_b0 < min_counter_value) devpriv->divisor_b0 = min_counter_value; if (devpriv->divisor_b0 > max_counter_value) devpriv->divisor_b0 = max_counter_value; - base_period = LABPC_TIMER_BASE * devpriv->divisor_b0; + base_period = I8254_OSC_BASE_2MHZ * devpriv->divisor_b0; /* set a0 for conversion frequency and b1 for scan frequency */ switch (cmd->flags & TRIG_ROUND_MASK) { @@ -516,22 +509,20 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, * calculate cascaded counter values * that give desired scan timing */ - i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, - &(devpriv->divisor_b1), - &(devpriv->divisor_b0), - &scan_period, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, + &devpriv->divisor_b1, + &devpriv->divisor_b0, + &scan_period, cmd->flags); labpc_set_ai_scan_period(cmd, mode, scan_period); } else if (convert_period) { /* * calculate cascaded counter values * that give desired conversion timing */ - i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE, - &(devpriv->divisor_a0), - &(devpriv->divisor_b0), - &convert_period, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, + &devpriv->divisor_a0, + &devpriv->divisor_b0, + &convert_period, cmd->flags); labpc_set_ai_convert_period(cmd, mode, convert_period); } } @@ -902,7 +893,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int labpc_drain_fifo(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - short data; + unsigned short data; struct comedi_async *async = dev->read_subdev->async; const int timeout = 10000; unsigned int i; @@ -1046,7 +1037,7 @@ static int labpc_ao_insn_write(struct comedi_device *dev, /* set range */ if (board->is_labpc1200) { range = CR_RANGE(insn->chanspec); - if (labpc_range_is_unipolar(s, range)) + if (comedi_range_is_unipolar(s, range)) devpriv->cmd6 |= CMD6_DACUNI(channel); else devpriv->cmd6 &= ~CMD6_DACUNI(channel); diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 4e02770e834b..5113397bfecf 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1292,7 +1292,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev, struct comedi_cmd *cmd = &async->cmd; int chan; int i; - short d; + unsigned short d; u32 packed_data; int range; int err = 1; @@ -1403,7 +1403,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, int i; if (board->reg_type == ni_reg_611x) { - short data[2]; + unsigned short data[2]; u32 dl; for (i = 0; i < n / 2; i++) { @@ -1420,7 +1420,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, cfc_write_to_buffer(s, data[0]); } } else if (board->reg_type == ni_reg_6143) { - short data[2]; + unsigned short data[2]; u32 dl; /* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */ @@ -1511,9 +1511,9 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - short data[2]; + unsigned short data[2]; u32 dl; - short fifo_empty; + unsigned short fifo_empty; int i; if (board->reg_type == ni_reg_611x) { @@ -1577,7 +1577,7 @@ static void get_last_sample_611x(struct comedi_device *dev) const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv __maybe_unused = dev->private; struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - short data; + unsigned short data; u32 dl; if (board->reg_type != ni_reg_611x) @@ -1596,7 +1596,7 @@ static void get_last_sample_6143(struct comedi_device *dev) const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv __maybe_unused = dev->private; struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - short data; + unsigned short data; u32 dl; if (board->reg_type != ni_reg_6143) @@ -1621,7 +1621,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_async *async = s->async; unsigned int i; unsigned int length = num_bytes / bytes_per_sample(s); - short *array = data; + unsigned short *array = data; unsigned int *larray = data; for (i = 0; i < length; i++) { @@ -2873,7 +2873,7 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int i; unsigned int offset; unsigned int length = num_bytes / sizeof(short); - short *array = data; + unsigned short *array = data; offset = 1 << (board->aobits - 1); for (i = 0; i < length; i++) { @@ -3547,28 +3547,22 @@ static int ni_dio_insn_config(struct comedi_device *dev, static int ni_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct ni_private *devpriv = dev->private; -#ifdef DEBUG_DIO - printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]); -#endif - - if (data[0]) { - /* Perform check to make sure we're not using the - serial part of the dio */ - if ((data[0] & (DIO_SDIN | DIO_SDOUT)) - && devpriv->serial_interval_ns) - return -EBUSY; + /* Make sure we're not using the serial part of the dio */ + if ((data[0] & (DIO_SDIN | DIO_SDOUT)) && devpriv->serial_interval_ns) + return -EBUSY; - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) { devpriv->dio_output &= ~DIO_Parallel_Data_Mask; devpriv->dio_output |= DIO_Parallel_Data_Out(s->state); devpriv->stc_writew(dev, devpriv->dio_output, DIO_Output_Register); } + data[1] = devpriv->stc_readw(dev, DIO_Parallel_Input_Register); return insn->n; @@ -3598,16 +3592,9 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev, { struct ni_private *devpriv __maybe_unused = dev->private; -#ifdef DEBUG_DIO - printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], - data[1]); -#endif - - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) ni_writel(s->state, M_Offset_Static_Digital_Output); - } + data[1] = ni_readl(M_Offset_Static_Digital_Input); return insn->n; @@ -5355,20 +5342,20 @@ static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel, static int ni_pfi_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv __maybe_unused = dev->private; - if ((board->reg_type & ni_reg_m_series_mask) == 0) { + if (!(board->reg_type & ni_reg_m_series_mask)) return -ENOTSUPP; - } - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + + if (comedi_dio_update_state(s, data)) ni_writew(s->state, M_Offset_PFI_DO); - } + data[1] = ni_readw(M_Offset_PFI_DI); + return insn->n; } diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index fad81bc97b6e..e3a8fa96d9b3 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -406,9 +406,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d) struct mite_struct *mite = devpriv->mite; /* int i, j; */ - long int AuxData = 0; - short data1 = 0; - short data2 = 0; + unsigned int auxdata = 0; + unsigned short data1 = 0; + unsigned short data2 = 0; int flags; int status; int work = 0; @@ -481,11 +481,11 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ); goto out; } - AuxData = + auxdata = readl(devpriv->mite->daq_io_addr + Group_1_FIFO); - data1 = AuxData & 0xffff; - data2 = (AuxData & 0xffff0000) >> 16; + data1 = auxdata & 0xffff; + data2 = (auxdata & 0xffff0000) >> 16; comedi_buf_put(async, data1); comedi_buf_put(async, data2); /* DPRINTK("read:%d, %d\n",data1,data2); */ @@ -657,15 +657,14 @@ static int ni_pcidio_insn_config(struct comedi_device *dev, static int ni_pcidio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct nidio96_private *devpriv = dev->private; - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); + if (comedi_dio_update_state(s, data)) writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0)); - } + data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0)); return insn->n; diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index 11bf0aab82ea..f0630b7897b5 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -1491,7 +1491,7 @@ struct ni_board_struct { unsigned short pwm_up_count; \ unsigned short pwm_down_count; \ \ - short ai_fifo_buffer[0x2000]; \ + unsigned short ai_fifo_buffer[0x2000]; \ uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; \ uint32_t serial_number; \ \ diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index e859f85a8e17..f0fc123ef566 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -1,258 +1,295 @@ /* - comedi/drivers/pcl711.c - hardware driver for PC-LabCard PCL-711 and AdSys ACL-8112 - and compatibles - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef <ds@schleef.org> - Janne Jalkanen <jalkanen@cs.hut.fi> - Eric Bunn <ebu@cs.hut.fi> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + * pcl711.c + * Comedi driver for PC-LabCard PCL-711 and AdSys ACL-8112 and compatibles + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * Janne Jalkanen <jalkanen@cs.hut.fi> + * Eric Bunn <ebu@cs.hut.fi> + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ -/* -Driver: pcl711 -Description: Advantech PCL-711 and 711b, ADLink ACL-8112 -Author: ds, Janne Jalkanen <jalkanen@cs.hut.fi>, Eric Bunn <ebu@cs.hut.fi> -Status: mostly complete -Devices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b), - [AdLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg) - -Since these boards do not have DMA or FIFOs, only immediate mode is -supported. - -*/ /* - Dave Andruczyk <dave@tech.buffalostate.edu> also wrote a - driver for the PCL-711. I used a few ideas from his driver - here. His driver also has more comments, if you are - interested in understanding how this driver works. - http://tech.buffalostate.edu/~dave/driver/ - - The ACL-8112 driver was hacked from the sources of the PCL-711 - driver (the 744 chip used on the 8112 is almost the same as - the 711b chip, but it has more I/O channels) by - Janne Jalkanen (jalkanen@cs.hut.fi) and - Erik Bunn (ebu@cs.hut.fi). Remerged with the PCL-711 driver - by ds. - - [acl-8112] - This driver supports both TRIGNOW and TRIGCLK, - but does not yet support DMA transfers. It also supports - both high (HG) and low (DG) versions of the card, though - the HG version has been untested. - + * Driver: pcl711 + * Description: Advantech PCL-711 and 711b, ADLink ACL-8112 + * Devices: (Advantech) PCL-711 [pcl711] + * (Advantech) PCL-711B [pcl711b] + * (AdLink) ACL-8112HG [acl8112hg] + * (AdLink) ACL-8112DG [acl8112dg] + * Author: David A. Schleef <ds@schleef.org> + * Janne Jalkanen <jalkanen@cs.hut.fi> + * Eric Bunn <ebu@cs.hut.fi> + * Updated: + * Status: mostly complete + * + * Configuration Options: + * [0] - I/O port base + * [1] - IRQ, optional */ #include <linux/module.h> +#include <linux/delay.h> #include <linux/interrupt.h> -#include "../comedidev.h" -#include <linux/delay.h> +#include "../comedidev.h" #include "comedi_fc.h" #include "8253.h" -#define PCL711_SIZE 16 - -#define PCL711_CTR0 0 -#define PCL711_CTR1 1 -#define PCL711_CTR2 2 -#define PCL711_CTRCTL 3 -#define PCL711_AD_LO 4 -#define PCL711_DA0_LO 4 -#define PCL711_AD_HI 5 -#define PCL711_DA0_HI 5 -#define PCL711_DI_LO 6 -#define PCL711_DA1_LO 6 -#define PCL711_DI_HI 7 -#define PCL711_DA1_HI 7 -#define PCL711_CLRINTR 8 -#define PCL711_GAIN 9 -#define PCL711_MUX 10 -#define PCL711_MODE 11 -#define PCL711_SOFTTRIG 12 -#define PCL711_DO_LO 13 -#define PCL711_DO_HI 14 - -static const struct comedi_lrange range_pcl711b_ai = { 5, { - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - BIP_RANGE(0.625), - BIP_RANGE(0.3125) - } +/* + * I/O port register map + */ +#define PCL711_TIMER_BASE 0x00 +#define PCL711_AI_LSB_REG 0x04 +#define PCL711_AI_MSB_REG 0x05 +#define PCL711_AI_MSB_DRDY (1 << 4) +#define PCL711_AO_LSB_REG(x) (0x04 + ((x) * 2)) +#define PCL711_AO_MSB_REG(x) (0x05 + ((x) * 2)) +#define PCL711_DI_LSB_REG 0x06 +#define PCL711_DI_MSB_REG 0x07 +#define PCL711_INT_STAT_REG 0x08 +#define PCL711_INT_STAT_CLR (0 << 0) /* any value will work */ +#define PCL711_AI_GAIN_REG 0x09 +#define PCL711_AI_GAIN(x) (((x) & 0xf) << 0) +#define PCL711_MUX_REG 0x0a +#define PCL711_MUX_CHAN(x) (((x) & 0xf) << 0) +#define PCL711_MUX_CS0 (1 << 4) +#define PCL711_MUX_CS1 (1 << 5) +#define PCL711_MUX_DIFF (PCL711_MUX_CS0 | PCL711_MUX_CS1) +#define PCL711_MODE_REG 0x0b +#define PCL711_MODE_DEFAULT (0 << 0) +#define PCL711_MODE_SOFTTRIG (1 << 0) +#define PCL711_MODE_EXT (2 << 0) +#define PCL711_MODE_EXT_IRQ (3 << 0) +#define PCL711_MODE_PACER (4 << 0) +#define PCL711_MODE_PACER_IRQ (6 << 0) +#define PCL711_MODE_IRQ(x) (((x) & 0x7) << 4) +#define PCL711_SOFTTRIG_REG 0x0c +#define PCL711_SOFTTRIG (0 << 0) /* any value will work */ +#define PCL711_DO_LSB_REG 0x0d +#define PCL711_DO_MSB_REG 0x0e + +static const struct comedi_lrange range_pcl711b_ai = { + 5, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + BIP_RANGE(0.3125) + } }; -static const struct comedi_lrange range_acl8112hg_ai = { 12, { - BIP_RANGE(5), - BIP_RANGE(0.5), - BIP_RANGE(0.05), - BIP_RANGE(0.005), - UNI_RANGE(10), - UNI_RANGE(1), - UNI_RANGE(0.1), - UNI_RANGE(0.01), - BIP_RANGE(10), - BIP_RANGE(1), - BIP_RANGE(0.1), - BIP_RANGE(0.01) - } +static const struct comedi_lrange range_acl8112hg_ai = { + 12, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.005), + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01), + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01) + } }; -static const struct comedi_lrange range_acl8112dg_ai = { 9, { - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - BIP_RANGE(0.625), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2.5), - UNI_RANGE(1.25), - BIP_RANGE(10) - } +static const struct comedi_lrange range_acl8112dg_ai = { + 9, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + BIP_RANGE(10) + } }; -/* - * flags - */ - -#define PCL711_TIMEOUT 100 -#define PCL711_DRDY 0x10 - -static const int i8253_osc_base = 500; /* 2 Mhz */ - struct pcl711_board { - const char *name; - int is_pcl711b; - int is_8112; - int is_dg; - int n_ranges; int n_aichan; int n_aochan; int maxirq; const struct comedi_lrange *ai_range_type; }; -struct pcl711_private { +static const struct pcl711_board boardtypes[] = { + { + .name = "pcl711", + .n_aichan = 8, + .n_aochan = 1, + .ai_range_type = &range_bipolar5, + }, { + .name = "pcl711b", + .n_aichan = 8, + .n_aochan = 1, + .maxirq = 7, + .ai_range_type = &range_pcl711b_ai, + }, { + .name = "acl8112hg", + .n_aichan = 16, + .n_aochan = 2, + .maxirq = 15, + .ai_range_type = &range_acl8112hg_ai, + }, { + .name = "acl8112dg", + .n_aichan = 16, + .n_aochan = 2, + .maxirq = 15, + .ai_range_type = &range_acl8112dg_ai, + }, +}; - int board; - int adchan; - int ntrig; - int aip[8]; - int mode; +struct pcl711_private { + unsigned int ntrig; unsigned int ao_readback[2]; unsigned int divisor1; unsigned int divisor2; }; +static void pcl711_ai_set_mode(struct comedi_device *dev, unsigned int mode) +{ + /* + * The pcl711b board uses bits in the mode register to select the + * interrupt. The other boards supported by this driver all use + * jumpers on the board. + * + * Enables the interrupt when needed on the pcl711b board. These + * bits do nothing on the other boards. + */ + if (mode == PCL711_MODE_EXT_IRQ || mode == PCL711_MODE_PACER_IRQ) + mode |= PCL711_MODE_IRQ(dev->irq); + + outb(mode, dev->iobase + PCL711_MODE_REG); +} + +static unsigned int pcl711_ai_get_sample(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + unsigned int val; + + val = inb(dev->iobase + PCL711_AI_MSB_REG) << 8; + val |= inb(dev->iobase + PCL711_AI_LSB_REG); + + return val & s->maxdata; +} + +static int pcl711_ai_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG); + pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG); + return 0; +} + static irqreturn_t pcl711_interrupt(int irq, void *d) { - int lo, hi; - int data; struct comedi_device *dev = d; - const struct pcl711_board *board = comedi_board(dev); struct pcl711_private *devpriv = dev->private; - struct comedi_subdevice *s = &dev->subdevices[0]; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int data; if (!dev->attached) { comedi_error(dev, "spurious interrupt"); return IRQ_HANDLED; } - hi = inb(dev->iobase + PCL711_AD_HI); - lo = inb(dev->iobase + PCL711_AD_LO); - outb(0, dev->iobase + PCL711_CLRINTR); - - data = (hi << 8) | lo; + data = pcl711_ai_get_sample(dev, s); - /* FIXME! Nothing else sets ntrig! */ - if (!(--devpriv->ntrig)) { - if (board->is_8112) - outb(1, dev->iobase + PCL711_MODE); - else - outb(0, dev->iobase + PCL711_MODE); + outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG); - s->async->events |= COMEDI_CB_EOA; + if (comedi_buf_put(s->async, data) == 0) { + s->async->events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; + } else { + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + if (s->async->cmd.stop_src == TRIG_COUNT && + !(--devpriv->ntrig)) { + pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG); + s->async->events |= COMEDI_CB_EOA; + } } comedi_event(dev, s); return IRQ_HANDLED; } -static void pcl711_set_changain(struct comedi_device *dev, int chan) +static void pcl711_set_changain(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int chanspec) { - const struct pcl711_board *board = comedi_board(dev); - int chan_register; - - outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN); - - chan_register = CR_CHAN(chan); - - if (board->is_8112) { + unsigned int chan = CR_CHAN(chanspec); + unsigned int range = CR_RANGE(chanspec); + unsigned int aref = CR_AREF(chanspec); + unsigned int mux = 0; + + outb(PCL711_AI_GAIN(range), dev->iobase + PCL711_AI_GAIN_REG); + + if (s->n_chan > 8) { + /* Select the correct MPC508A chip */ + if (aref == AREF_DIFF) { + chan &= 0x7; + mux |= PCL711_MUX_DIFF; + } else { + if (chan < 8) + mux |= PCL711_MUX_CS0; + else + mux |= PCL711_MUX_CS1; + } + } + outb(mux | PCL711_MUX_CHAN(chan), dev->iobase + PCL711_MUX_REG); +} - /* - * Set the correct channel. The two channel banks are switched - * using the mask value. - * NB: To use differential channels, you should use - * mask = 0x30, but I haven't written the support for this - * yet. /JJ - */ +static int pcl711_ai_wait_for_eoc(struct comedi_device *dev, + unsigned int timeout) +{ + unsigned int msb; - if (chan_register >= 8) - chan_register = 0x20 | (chan_register & 0x7); - else - chan_register |= 0x10; - } else { - outb(chan_register, dev->iobase + PCL711_MUX); + while (timeout--) { + msb = inb(dev->iobase + PCL711_AI_MSB_REG); + if ((msb & PCL711_AI_MSB_DRDY) == 0) + return 0; + udelay(1); } + return -ETIME; } -static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pcl711_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - const struct pcl711_board *board = comedi_board(dev); - int i, n; - int hi, lo; - - pcl711_set_changain(dev, insn->chanspec); - - for (n = 0; n < insn->n; n++) { - /* - * Write the correct mode (software polling) and start polling - * by writing to the trigger register - */ - outb(1, dev->iobase + PCL711_MODE); - - if (!board->is_8112) - outb(0, dev->iobase + PCL711_SOFTTRIG); - - i = PCL711_TIMEOUT; - while (--i) { - hi = inb(dev->iobase + PCL711_AD_HI); - if (!(hi & PCL711_DRDY)) - goto ok; - udelay(1); - } - printk(KERN_ERR "comedi%d: pcl711: A/D timeout\n", dev->minor); - return -ETIME; + int ret; + int i; + + pcl711_set_changain(dev, s, insn->chanspec); -ok: - lo = inb(dev->iobase + PCL711_AD_LO); + pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG); - data[n] = ((hi & 0xf) << 8) | lo; + for (i = 0; i < insn->n; i++) { + outb(PCL711_SOFTTRIG, dev->iobase + PCL711_SOFTTRIG_REG); + + ret = pcl711_ai_wait_for_eoc(dev, 100); + if (ret) + return ret; + + data[i] = pcl711_ai_get_sample(dev, s); } - return n; + return insn->n; } static int pcl711_ai_cmdtest(struct comedi_device *dev, @@ -292,7 +329,6 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); } else { #define MAX_SPEED 1000 -#define TIMER_BASE 100 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, MAX_SPEED); } @@ -313,11 +349,11 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) { tmp = cmd->scan_begin_arg; - i8253_cascade_ns_to_timer_2div(TIMER_BASE, - &devpriv->divisor1, - &devpriv->divisor2, - &cmd->scan_begin_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ, + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->scan_begin_arg, + cmd->flags); if (tmp != cmd->scan_begin_arg) err++; } @@ -331,110 +367,106 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev, static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl711_private *devpriv = dev->private; - int timer1, timer2; struct comedi_cmd *cmd = &s->async->cmd; - pcl711_set_changain(dev, cmd->chanlist[0]); + pcl711_set_changain(dev, s, cmd->chanlist[0]); + + if (cmd->stop_src == TRIG_COUNT) { + if (cmd->stop_arg == 0) { + /* an empty acquisition */ + s->async->events |= COMEDI_CB_EOA; + comedi_event(dev, s); + return 0; + } + devpriv->ntrig = cmd->stop_arg; + } if (cmd->scan_begin_src == TRIG_TIMER) { - /* - * Set timers - * timer chip is an 8253, with timers 1 and 2 - * cascaded - * 0x74 = Select Counter 1 | LSB/MSB | Mode=2 | Binary - * Mode 2 = Rate generator - * - * 0xb4 = Select Counter 2 | LSB/MSB | Mode=2 | Binary - */ - - timer1 = timer2 = 0; - i8253_cascade_ns_to_timer(i8253_osc_base, &timer1, &timer2, - &cmd->scan_begin_arg, - TRIG_ROUND_NEAREST); - - outb(0x74, dev->iobase + PCL711_CTRCTL); - outb(timer1 & 0xff, dev->iobase + PCL711_CTR1); - outb((timer1 >> 8) & 0xff, dev->iobase + PCL711_CTR1); - outb(0xb4, dev->iobase + PCL711_CTRCTL); - outb(timer2 & 0xff, dev->iobase + PCL711_CTR2); - outb((timer2 >> 8) & 0xff, dev->iobase + PCL711_CTR2); - - /* clear pending interrupts (just in case) */ - outb(0, dev->iobase + PCL711_CLRINTR); - - /* - * Set mode to IRQ transfer - */ - outb(devpriv->mode | 6, dev->iobase + PCL711_MODE); + i8254_load(dev->iobase + PCL711_TIMER_BASE, 0, + 1, devpriv->divisor1, I8254_MODE2 | I8254_BINARY); + i8254_load(dev->iobase + PCL711_TIMER_BASE, 0, + 2, devpriv->divisor2, I8254_MODE2 | I8254_BINARY); + + outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG); + + pcl711_ai_set_mode(dev, PCL711_MODE_PACER_IRQ); } else { - /* external trigger */ - outb(devpriv->mode | 3, dev->iobase + PCL711_MODE); + pcl711_ai_set_mode(dev, PCL711_MODE_EXT_IRQ); } return 0; } -/* - analog output -*/ -static int pcl711_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static void pcl711_ao_write(struct comedi_device *dev, + unsigned int chan, unsigned int val) { - struct pcl711_private *devpriv = dev->private; - int n; - int chan = CR_CHAN(insn->chanspec); + outb(val & 0xff, dev->iobase + PCL711_AO_LSB_REG(chan)); + outb((val >> 8) & 0xff, dev->iobase + PCL711_AO_MSB_REG(chan)); +} - for (n = 0; n < insn->n; n++) { - outb((data[n] & 0xff), - dev->iobase + (chan ? PCL711_DA1_LO : PCL711_DA0_LO)); - outb((data[n] >> 8), - dev->iobase + (chan ? PCL711_DA1_HI : PCL711_DA0_HI)); +static int pcl711_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct pcl711_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val = devpriv->ao_readback[chan]; + int i; - devpriv->ao_readback[chan] = data[n]; + for (i = 0; i < insn->n; i++) { + val = data[i]; + pcl711_ao_write(dev, chan, val); } + devpriv->ao_readback[chan] = val; - return n; + return insn->n; } static int pcl711_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pcl711_private *devpriv = dev->private; - int n; - int chan = CR_CHAN(insn->chanspec); - - for (n = 0; n < insn->n; n++) - data[n] = devpriv->ao_readback[chan]; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; - return n; + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; + return insn->n; } -/* Digital port read - Untested on 8112 */ static int pcl711_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - data[1] = inb(dev->iobase + PCL711_DI_LO) | - (inb(dev->iobase + PCL711_DI_HI) << 8); + unsigned int val; + + val = inb(dev->iobase + PCL711_DI_LSB_REG); + val |= (inb(dev->iobase + PCL711_DI_MSB_REG) << 8); + + data[1] = val; return insn->n; } -/* Digital port write - Untested on 8112 */ static int pcl711_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + unsigned int mask; + + mask = comedi_dio_update_state(s, data); + if (mask) { + if (mask & 0x00ff) + outb(s->state & 0xff, dev->iobase + PCL711_DO_LSB_REG); + if (mask & 0xff00) + outb((s->state >> 8), dev->iobase + PCL711_DO_MSB_REG); } - if (data[0] & 0x00ff) - outb(s->state & 0xff, dev->iobase + PCL711_DO_LO); - if (data[0] & 0xff00) - outb((s->state >> 8), dev->iobase + PCL711_DO_HI); data[1] = s->state; @@ -445,112 +477,82 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl711_board *board = comedi_board(dev); struct pcl711_private *devpriv; - int ret; - unsigned int irq; struct comedi_subdevice *s; + int ret; + + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], PCL711_SIZE); + ret = comedi_request_region(dev, it->options[0], 0x10); if (ret) return ret; - /* grab our IRQ */ - irq = it->options[1]; - if (irq > board->maxirq) { - printk(KERN_ERR "irq out of range\n"); - return -EINVAL; - } - if (irq) { - if (request_irq(irq, pcl711_interrupt, 0, dev->board_name, - dev)) { - printk(KERN_ERR "unable to allocate irq %u\n", irq); - return -EINVAL; - } else { - printk(KERN_INFO "( irq = %u )\n", irq); - } + if (it->options[1] && it->options[1] <= board->maxirq) { + ret = request_irq(it->options[1], pcl711_interrupt, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; } - dev->irq = irq; ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - + /* Analog Input subdevice */ s = &dev->subdevices[0]; - /* AI subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = board->n_aichan; - s->maxdata = 0xfff; - s->len_chanlist = 1; - s->range_table = board->ai_range_type; - s->insn_read = pcl711_ai_insn; - if (irq) { + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + if (board->n_aichan > 8) + s->subdev_flags |= SDF_DIFF; + s->n_chan = board->n_aichan; + s->maxdata = 0xfff; + s->range_table = board->ai_range_type; + s->insn_read = pcl711_ai_insn_read; + if (dev->irq) { dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->do_cmdtest = pcl711_ai_cmdtest; - s->do_cmd = pcl711_ai_cmd; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 1; + s->do_cmdtest = pcl711_ai_cmdtest; + s->do_cmd = pcl711_ai_cmd; + s->cancel = pcl711_ai_cancel; } + /* Analog Output subdevice */ s = &dev->subdevices[1]; - /* AO subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = board->n_aochan; - s->maxdata = 0xfff; - s->len_chanlist = 1; - s->range_table = &range_bipolar5; - s->insn_write = pcl711_ao_insn; - s->insn_read = pcl711_ao_insn_read; - + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = board->n_aochan; + s->maxdata = 0xfff; + s->range_table = &range_bipolar5; + s->insn_write = pcl711_ao_insn_write; + s->insn_read = pcl711_ao_insn_read; + + /* Digital Input subdevice */ s = &dev->subdevices[2]; - /* 16-bit digital input */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->len_chanlist = 16; - s->range_table = &range_digital; - s->insn_bits = pcl711_di_insn_bits; - + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pcl711_di_insn_bits; + + /* Digital Output subdevice */ s = &dev->subdevices[3]; - /* 16-bit digital out */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->len_chanlist = 16; - s->range_table = &range_digital; - s->state = 0; - s->insn_bits = pcl711_do_insn_bits; - - /* - this is the "base value" for the mode register, which is - used for the irq on the PCL711 - */ - if (board->is_pcl711b) - devpriv->mode = (dev->irq << 4); + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pcl711_do_insn_bits; /* clear DAC */ - outb(0, dev->iobase + PCL711_DA0_LO); - outb(0, dev->iobase + PCL711_DA0_HI); - outb(0, dev->iobase + PCL711_DA1_LO); - outb(0, dev->iobase + PCL711_DA1_HI); - - printk(KERN_INFO "\n"); + pcl711_ao_write(dev, 0, 0x0); + pcl711_ao_write(dev, 1, 0x0); return 0; } -static const struct pcl711_board boardtypes[] = { - { "pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5 }, - { "pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai }, - { "acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai }, - { "acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai }, -}; - static struct comedi_driver pcl711_driver = { .driver_name = "pcl711", .module = THIS_MODULE, @@ -563,5 +565,5 @@ static struct comedi_driver pcl711_driver = { module_comedi_driver(pcl711_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for PCL-711 compatible boards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index a4d0bcc31e52..cf9568ee46e4 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -1,230 +1,356 @@ /* - comedi/drivers/pcl726.c - - hardware driver for Advantech cards: - card: PCL-726, PCL-727, PCL-728 - driver: pcl726, pcl727, pcl728 - and for ADLink cards: - card: ACL-6126, ACL-6128 - driver: acl6126, acl6128 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef <ds@schleef.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ -/* -Driver: pcl726 -Description: Advantech PCL-726 & compatibles -Author: ds -Status: untested -Devices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728), - [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128) - -Interrupts are not supported. - - Options for PCL-726: - [0] - IO Base - [2]...[7] - D/A output range for channel 1-6: - 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, - 4: 4-20mA, 5: unknown (external reference) - - Options for PCL-727: - [0] - IO Base - [2]...[13] - D/A output range for channel 1-12: - 0: 0-5V, 1: 0-10V, 2: +/-5V, - 3: 4-20mA - - Options for PCL-728 and ACL-6128: - [0] - IO Base - [2], [3] - D/A output range for channel 1 and 2: - 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, - 4: 4-20mA, 5: 0-20mA - - Options for ACL-6126: - [0] - IO Base - [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored) - [2]...[7] - D/A output range for channel 1-6: - 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, - 4: 4-20mA -*/ + * pcl726.c + * Comedi driver for 6/12-Channel D/A Output and DIO cards + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - Thanks to Circuit Specialists for having programming info (!) on - their web page. (http://www.cir.com/) -*/ + * Driver: pcl726 + * Description: Advantech PCL-726 & compatibles + * Author: David A. Schleef <ds@schleef.org> + * Status: untested + * Devices: (Advantech) PCL-726 [pcl726] + * (Advantech) PCL-727 [pcl727] + * (Advantech) PCL-728 [pcl728] + * (ADLink) ACL-6126 [acl6126] + * (ADLink) ACL-6128 [acl6128] + * + * Configuration Options: + * [0] - IO Base + * [1] - IRQ (ACL-6126 only) + * [2] - D/A output range for channel 0 + * [3] - D/A output range for channel 1 + * + * Boards with > 2 analog output channels: + * [4] - D/A output range for channel 2 + * [5] - D/A output range for channel 3 + * [6] - D/A output range for channel 4 + * [7] - D/A output range for channel 5 + * + * Boards with > 6 analog output channels: + * [8] - D/A output range for channel 6 + * [9] - D/A output range for channel 7 + * [10] - D/A output range for channel 8 + * [11] - D/A output range for channel 9 + * [12] - D/A output range for channel 10 + * [13] - D/A output range for channel 11 + * + * For PCL-726 the D/A output ranges are: + * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA, 5: unknown + * + * For PCL-727: + * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: 4-20mA + * + * For PCL-728 and ACL-6128: + * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA, 5: 0-20mA + * + * For ACL-6126: + * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA + */ #include <linux/module.h> -#include "../comedidev.h" - -#undef ACL6126_IRQ /* no interrupt support (yet) */ +#include <linux/interrupt.h> -#define PCL726_SIZE 16 -#define PCL727_SIZE 32 -#define PCL728_SIZE 8 +#include "../comedidev.h" -#define PCL726_DAC0_HI 0 -#define PCL726_DAC0_LO 1 +#include "comedi_fc.h" -#define PCL726_DO_HI 12 -#define PCL726_DO_LO 13 -#define PCL726_DI_HI 14 -#define PCL726_DI_LO 15 +#define PCL726_AO_MSB_REG(x) (0x00 + ((x) * 2)) +#define PCL726_AO_LSB_REG(x) (0x01 + ((x) * 2)) +#define PCL726_DO_MSB_REG 0x0c +#define PCL726_DO_LSB_REG 0x0d +#define PCL726_DI_MSB_REG 0x0e +#define PCL726_DI_LSB_REG 0x0f -#define PCL727_DO_HI 24 -#define PCL727_DO_LO 25 -#define PCL727_DI_HI 0 -#define PCL727_DI_LO 1 +#define PCL727_DI_MSB_REG 0x00 +#define PCL727_DI_LSB_REG 0x01 +#define PCL727_DO_MSB_REG 0x18 +#define PCL727_DO_LSB_REG 0x19 static const struct comedi_lrange *const rangelist_726[] = { - &range_unipolar5, &range_unipolar10, - &range_bipolar5, &range_bipolar10, - &range_4_20mA, &range_unknown + &range_unipolar5, + &range_unipolar10, + &range_bipolar5, + &range_bipolar10, + &range_4_20mA, + &range_unknown }; static const struct comedi_lrange *const rangelist_727[] = { - &range_unipolar5, &range_unipolar10, + &range_unipolar5, + &range_unipolar10, &range_bipolar5, &range_4_20mA }; static const struct comedi_lrange *const rangelist_728[] = { - &range_unipolar5, &range_unipolar10, - &range_bipolar5, &range_bipolar10, - &range_4_20mA, &range_0_20mA + &range_unipolar5, + &range_unipolar10, + &range_bipolar5, + &range_bipolar10, + &range_4_20mA, + &range_0_20mA }; struct pcl726_board { - - const char *name; /* driver name */ - int n_aochan; /* num of D/A chans */ - int num_of_ranges; /* num of ranges */ - unsigned int IRQbits; /* allowed interrupts */ - unsigned int io_range; /* len of IO space */ - char have_dio; /* 1=card have DI/DO ports */ - int di_hi; /* ports for DI/DO operations */ - int di_lo; - int do_hi; - int do_lo; - const struct comedi_lrange *const *range_type_list; - /* list of supported ranges */ + const char *name; + unsigned long io_len; + unsigned int irq_mask; + const struct comedi_lrange *const *ao_ranges; + int ao_num_ranges; + int ao_nchan; + unsigned int have_dio:1; + unsigned int is_pcl727:1; }; -static const struct pcl726_board boardtypes[] = { - {"pcl726", 6, 6, 0x0000, PCL726_SIZE, 1, - PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, - &rangelist_726[0],}, - {"pcl727", 12, 4, 0x0000, PCL727_SIZE, 1, - PCL727_DI_HI, PCL727_DI_LO, PCL727_DO_HI, PCL727_DO_LO, - &rangelist_727[0],}, - {"pcl728", 2, 6, 0x0000, PCL728_SIZE, 0, - 0, 0, 0, 0, - &rangelist_728[0],}, - {"acl6126", 6, 5, 0x96e8, PCL726_SIZE, 1, - PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, - &rangelist_726[0],}, - {"acl6128", 2, 6, 0x0000, PCL728_SIZE, 0, - 0, 0, 0, 0, - &rangelist_728[0],}, +static const struct pcl726_board pcl726_boards[] = { + { + .name = "pcl726", + .io_len = 0x10, + .ao_ranges = &rangelist_726[0], + .ao_num_ranges = ARRAY_SIZE(rangelist_726), + .ao_nchan = 6, + .have_dio = 1, + }, { + .name = "pcl727", + .io_len = 0x20, + .ao_ranges = &rangelist_727[0], + .ao_num_ranges = ARRAY_SIZE(rangelist_727), + .ao_nchan = 12, + .have_dio = 1, + .is_pcl727 = 1, + }, { + .name = "pcl728", + .io_len = 0x08, + .ao_num_ranges = ARRAY_SIZE(rangelist_728), + .ao_ranges = &rangelist_728[0], + .ao_nchan = 2, + }, { + .name = "acl6126", + .io_len = 0x10, + .irq_mask = 0x96e8, + .ao_num_ranges = ARRAY_SIZE(rangelist_726), + .ao_ranges = &rangelist_726[0], + .ao_nchan = 6, + .have_dio = 1, + }, { + .name = "acl6128", + .io_len = 0x08, + .ao_num_ranges = ARRAY_SIZE(rangelist_728), + .ao_ranges = &rangelist_728[0], + .ao_nchan = 2, + }, }; struct pcl726_private { - - int bipolar[12]; const struct comedi_lrange *rangelist[12]; unsigned int ao_readback[12]; + unsigned int cmd_running:1; }; -static int pcl726_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pcl726_intr_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + data[1] = 0; + return insn->n; +} + +static int pcl726_intr_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + + /* Step 1 : check if triggers are trivially valid */ + + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + /* Step 2b : and mutually compatible */ + + if (err) + return 2; + + /* Step 3: check if arguments are trivially valid */ + + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* step 4: ignored */ + + if (err) + return 4; + + return 0; +} + +static int pcl726_intr_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pcl726_private *devpriv = dev->private; + + devpriv->cmd_running = 1; + + return 0; +} + +static int pcl726_intr_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) { struct pcl726_private *devpriv = dev->private; - int hi, lo; - int n; - int chan = CR_CHAN(insn->chanspec); - - for (n = 0; n < insn->n; n++) { - lo = data[n] & 0xff; - hi = (data[n] >> 8) & 0xf; - if (devpriv->bipolar[chan]) - hi ^= 0x8; - /* - * the programming info did not say which order - * to write bytes. switch the order of the next - * two lines if you get glitches. - */ - outb(hi, dev->iobase + PCL726_DAC0_HI + 2 * chan); - outb(lo, dev->iobase + PCL726_DAC0_LO + 2 * chan); - devpriv->ao_readback[chan] = data[n]; + + devpriv->cmd_running = 0; + + return 0; +} + +static irqreturn_t pcl726_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; + struct pcl726_private *devpriv = dev->private; + + if (devpriv->cmd_running) { + pcl726_intr_cancel(dev, s); + + comedi_buf_put(s->async, 0); + s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); + comedi_event(dev, s); } - return n; + return IRQ_HANDLED; +} + +static int pcl726_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct pcl726_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val; + int i; + + for (i = 0; i < insn->n; i++) { + val = data[i]; + devpriv->ao_readback[chan] = val; + + /* bipolar data to the DAC is two's complement */ + if (comedi_chan_range_is_bipolar(s, chan, range)) + val = comedi_offset_munge(s, val); + + /* order is important, MSB then LSB */ + outb((val >> 8) & 0xff, dev->iobase + PCL726_AO_MSB_REG(chan)); + outb(val & 0xff, dev->iobase + PCL726_AO_LSB_REG(chan)); + } + + return insn->n; } static int pcl726_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pcl726_private *devpriv = dev->private; - int chan = CR_CHAN(insn->chanspec); - int n; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[chan]; - for (n = 0; n < insn->n; n++) - data[n] = devpriv->ao_readback[chan]; - return n; + return insn->n; } static int pcl726_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { const struct pcl726_board *board = comedi_board(dev); + unsigned int val; - data[1] = inb(dev->iobase + board->di_lo) | - (inb(dev->iobase + board->di_hi) << 8); + if (board->is_pcl727) { + val = inb(dev->iobase + PCL727_DI_LSB_REG); + val |= (inb(dev->iobase + PCL727_DI_MSB_REG) << 8); + } else { + val = inb(dev->iobase + PCL726_DI_LSB_REG); + val |= (inb(dev->iobase + PCL726_DI_MSB_REG) << 8); + } + + data[1] = val; return insn->n; } static int pcl726_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { const struct pcl726_board *board = comedi_board(dev); - - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + unsigned long io = dev->iobase; + unsigned int mask; + + mask = comedi_dio_update_state(s, data); + if (mask) { + if (board->is_pcl727) { + if (mask & 0x00ff) + outb(s->state & 0xff, io + PCL727_DO_LSB_REG); + if (mask & 0xff00) + outb((s->state >> 8), io + PCL727_DO_MSB_REG); + } else { + if (mask & 0x00ff) + outb(s->state & 0xff, io + PCL726_DO_LSB_REG); + if (mask & 0xff00) + outb((s->state >> 8), io + PCL726_DO_MSB_REG); + } } - if (data[1] & 0x00ff) - outb(s->state & 0xff, dev->iobase + board->do_lo); - if (data[1] & 0xff00) - outb((s->state >> 8), dev->iobase + board->do_hi); data[1] = s->state; return insn->n; } -static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) +static int pcl726_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { const struct pcl726_board *board = comedi_board(dev); struct pcl726_private *devpriv; struct comedi_subdevice *s; - int ret, i; -#ifdef ACL6126_IRQ - unsigned int irq; -#endif + int subdev; + int ret; + int i; - ret = comedi_request_region(dev, it->options[0], board->io_range); + ret = comedi_request_region(dev, it->options[0], board->io_len); if (ret) return ret; @@ -232,97 +358,81 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (!devpriv) return -ENOMEM; - for (i = 0; i < 12; i++) { - devpriv->bipolar[i] = 0; - devpriv->rangelist[i] = &range_unknown; - } - -#ifdef ACL6126_IRQ - irq = 0; - if (boardtypes[board].IRQbits != 0) { /* board support IRQ */ - irq = it->options[1]; - devpriv->first_chan = 2; - if (irq) { /* we want to use IRQ */ - if (((1 << irq) & boardtypes[board].IRQbits) == 0) { - printk(KERN_WARNING - ", IRQ %d is out of allowed range," - " DISABLING IT", irq); - irq = 0; /* Bad IRQ */ - } else { - if (request_irq(irq, interrupt_pcl818, 0, - dev->board_name, dev)) { - printk(KERN_WARNING - ", unable to allocate IRQ %d," - " DISABLING IT", irq); - irq = 0; /* Can't use IRQ */ - } else { - printk(", irq=%d", irq); - } - } + /* + * Hook up the external trigger source interrupt only if the + * user config option is valid and the board supports interrupts. + */ + if (it->options[1] && (board->irq_mask & (1 << it->options[1]))) { + ret = request_irq(it->options[1], pcl726_interrupt, 0, + dev->board_name, dev); + if (ret == 0) { + /* External trigger source is from Pin-17 of CN3 */ + dev->irq = it->options[1]; } } - dev->irq = irq; -#endif + /* setup the per-channel analog output range_table_list */ + for (i = 0; i < 12; i++) { + unsigned int opt = it->options[2 + i]; - printk("\n"); + if (opt < board->ao_num_ranges && i < board->ao_nchan) + devpriv->rangelist[i] = board->ao_ranges[opt]; + else + devpriv->rangelist[i] = &range_unknown; + } - ret = comedi_alloc_subdevices(dev, 3); + subdev = board->have_dio ? 3 : 1; + if (dev->irq) + subdev++; + ret = comedi_alloc_subdevices(dev, subdev); if (ret) return ret; - s = &dev->subdevices[0]; - /* ao */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = board->n_aochan; - s->maxdata = 0xfff; - s->len_chanlist = 1; - s->insn_write = pcl726_ao_insn; - s->insn_read = pcl726_ao_insn_read; - s->range_table_list = devpriv->rangelist; - for (i = 0; i < board->n_aochan; i++) { - int j; - - j = it->options[2 + 1]; - if ((j < 0) || (j >= board->num_of_ranges)) { - printk - ("Invalid range for channel %d! Must be 0<=%d<%d\n", - i, j, board->num_of_ranges - 1); - j = 0; - } - devpriv->rangelist[i] = board->range_type_list[j]; - if (devpriv->rangelist[i]->range[0].min == - -devpriv->rangelist[i]->range[0].max) - devpriv->bipolar[i] = 1; /* bipolar range */ - } + subdev = 0; - s = &dev->subdevices[1]; - /* di */ - if (!board->have_dio) { - s->type = COMEDI_SUBD_UNUSED; - } else { - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 16; - s->maxdata = 1; - s->len_chanlist = 1; - s->insn_bits = pcl726_di_insn_bits; - s->range_table = &range_digital; + /* Analog Output subdevice */ + s = &dev->subdevices[subdev++]; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = board->ao_nchan; + s->maxdata = 0x0fff; + s->range_table_list = devpriv->rangelist; + s->insn_write = pcl726_ao_insn_write; + s->insn_read = pcl726_ao_insn_read; + + if (board->have_dio) { + /* Digital Input subdevice */ + s = &dev->subdevices[subdev++]; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->insn_bits = pcl726_di_insn_bits; + s->range_table = &range_digital; + + /* Digital Output subdevice */ + s = &dev->subdevices[subdev++]; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->insn_bits = pcl726_do_insn_bits; + s->range_table = &range_digital; } - s = &dev->subdevices[2]; - /* do */ - if (!board->have_dio) { - s->type = COMEDI_SUBD_UNUSED; - } else { - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND; - s->n_chan = 16; - s->maxdata = 1; - s->len_chanlist = 1; - s->insn_bits = pcl726_do_insn_bits; - s->range_table = &range_digital; + if (dev->irq) { + /* Digial Input subdevice - Interrupt support */ + s = &dev->subdevices[subdev++]; + dev->read_subdev = s; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->n_chan = 1; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pcl726_intr_insn_bits; + s->do_cmdtest = pcl726_intr_cmdtest; + s->do_cmd = pcl726_intr_cmd; + s->cancel = pcl726_intr_cancel; } return 0; @@ -333,12 +443,12 @@ static struct comedi_driver pcl726_driver = { .module = THIS_MODULE, .attach = pcl726_attach, .detach = comedi_legacy_detach, - .board_name = &boardtypes[0].name, - .num_names = ARRAY_SIZE(boardtypes), + .board_name = &pcl726_boards[0].name, + .num_names = ARRAY_SIZE(pcl726_boards), .offset = sizeof(struct pcl726_board), }; module_comedi_driver(pcl726_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Advantech PCL-726 & compatibles"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 2a659f23ecda..d041b714db29 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -167,20 +167,17 @@ static int pcl730_do_insn_bits(struct comedi_device *dev, unsigned int *data) { unsigned long reg = (unsigned long)s->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; + unsigned int mask; + mask = comedi_dio_update_state(s, data); if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - if (mask & 0x00ff) outb(s->state & 0xff, dev->iobase + reg); - if ((mask & 0xff00) && (s->n_chan > 8)) + if ((mask & 0xff00) & (s->n_chan > 8)) outb((s->state >> 8) & 0xff, dev->iobase + reg + 1); - if ((mask & 0xff0000) && (s->n_chan > 16)) + if ((mask & 0xff0000) & (s->n_chan > 16)) outb((s->state >> 16) & 0xff, dev->iobase + reg + 2); - if ((mask & 0xff000000) && (s->n_chan > 24)) + if ((mask & 0xff000000) & (s->n_chan > 24)) outb((s->state >> 24) & 0xff, dev->iobase + reg + 3); } diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 03a098900d34..03315abcca19 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -355,7 +355,6 @@ struct pcl812_private { unsigned int ai_n_chan; /* how many channels is measured */ unsigned int ai_flags; /* flaglist */ unsigned int ai_data_len; /* len of data buffer */ - short *ai_data; /* data buffer */ unsigned int ai_is16b; /* =1 we have 16 bit card */ unsigned long dmabuf[2]; /* PTR to DMA buf */ unsigned int dmapages[2]; /* how many pages we have allocated */ @@ -509,19 +508,16 @@ static int pcl812_di_insn_bits(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ static int pcl812_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + if (comedi_dio_update_state(s, data)) { outb(s->state & 0xff, dev->iobase + PCL812_DO_LO); outb((s->state >> 8), dev->iobase + PCL812_DO_HI); } + data[1] = s->state; return insn->n; @@ -592,9 +588,9 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, - &divisor2, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(board->i8254_osc_base, + &divisor1, &divisor2, + &cmd->convert_arg, cmd->flags); if (cmd->convert_arg < board->ai_ns_min) cmd->convert_arg = board->ai_ns_min; if (tmp != cmd->convert_arg) @@ -640,8 +636,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) cmd->convert_arg = board->ai_ns_min; i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, &divisor2, - &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + &cmd->convert_arg, cmd->flags); } start_pacer(dev, -1, 0, 0); /* stop pacer */ @@ -665,7 +660,6 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_flags = cmd->flags; devpriv->ai_data_len = s->async->prealloc_bufsz; - devpriv->ai_data = s->async->prealloc_buf; if (cmd->stop_src == TRIG_COUNT) { devpriv->ai_scans = cmd->stop_arg; devpriv->ai_neverending = 0; @@ -835,7 +829,8 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) ============================================================================== */ static void transfer_from_dma_buf(struct comedi_device *dev, - struct comedi_subdevice *s, short *ptr, + struct comedi_subdevice *s, + unsigned short *ptr, unsigned int bufptr, unsigned int len) { struct pcl812_private *devpriv = dev->private; @@ -873,9 +868,9 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) struct comedi_subdevice *s = &dev->subdevices[0]; unsigned long dma_flags; int len, bufptr; - short *ptr; + unsigned short *ptr; - ptr = (short *)devpriv->dmabuf[devpriv->next_dma_buf]; + ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf]; len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - devpriv->ai_poll_ptr; @@ -1443,40 +1438,40 @@ static void pcl812_detach(struct comedi_device *dev) static const struct pcl812_board boardtypes[] = { {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff, - 33000, 500, &range_bipolar10, &range_unipolar5, + 33000, I8254_OSC_BASE_2MHZ, &range_bipolar10, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff, - 33000, 500, &range_pcl812pg_ai, &range_unipolar5, + 33000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff, - 10000, 500, &range_pcl812pg_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, - 10000, 500, &range_acl8112dg_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, - 10000, 500, &range_acl8112hg_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff, - 10000, 500, &range_pcl813b_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, &range_unipolar5, 0x000c, 0x00, PCLx1x_IORANGE, 0}, {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff, - 10000, 500, &range_pcl813b_ai, NULL, + 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, NULL, 0x000c, 0x00, PCLx1x_IORANGE, 0}, {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff, - 10000, 500, &range_a821pgh_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_a821pgh_ai, &range_unipolar5, 0x000c, 0x00, PCLx1x_IORANGE, 0}, {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, - 10000, 500, &range_acl8112dg_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, - 10000, 500, &range_acl8112hg_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, - 8000, 500, &range_acl8112dg_ai, &range_unipolar5, + 8000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff, - 8000, 500, &range_acl8112hg_ai, &range_unipolar5, + 8000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff, 0, 0, &range_pcl813b_ai, NULL, @@ -1491,10 +1486,10 @@ static const struct pcl812_board boardtypes[] = { 0, 0, &range_iso813_1_ai, NULL, 0x0000, 0x00, PCLx1x_IORANGE, 0}, {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff, - 10000, 500, &range_pcl813b2_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 1}, {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff, - 10000, 500, &range_pcl813b2_ai, &range_unipolar5, + 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5, 0xdcfc, 0x0a, PCLx1x_IORANGE, 0}, }; diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index f03134962596..ab9d2bd26a20 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -229,7 +229,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) struct comedi_device *dev = d; struct pcl816_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[0]; - int low, hi; + unsigned char low, hi; int timeout = 50; /* wait max 50us */ while (timeout--) { @@ -281,7 +281,8 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) analog input dma mode 1 & 3, 816 cards */ static void transfer_from_dma_buf(struct comedi_device *dev, - struct comedi_subdevice *s, short *ptr, + struct comedi_subdevice *s, + unsigned short *ptr, unsigned int bufptr, unsigned int len) { struct pcl816_private *devpriv = dev->private; @@ -324,7 +325,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) struct comedi_subdevice *s = &dev->subdevices[0]; int len, bufptr, this_dma_buf; unsigned long dma_flags; - short *ptr; + unsigned short *ptr; disable_dma(devpriv->dma); this_dma_buf = devpriv->next_dma_buf; @@ -352,7 +353,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) devpriv->dma_runs_to_end--; outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ - ptr = (short *)devpriv->dmabuf[this_dma_buf]; + ptr = (unsigned short *)devpriv->dmabuf[this_dma_buf]; len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; @@ -481,8 +482,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, tmp = cmd->convert_arg; i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, &divisor2, - &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + &cmd->convert_arg, cmd->flags); if (cmd->convert_arg < board->ai_ns_min) cmd->convert_arg = board->ai_ns_min; if (tmp != cmd->convert_arg) @@ -528,9 +528,9 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->convert_arg < board->ai_ns_min) cmd->convert_arg = board->ai_ns_min; - i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1, - &divisor2, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(board->i8254_osc_base, + &divisor1, &divisor2, + &cmd->convert_arg, cmd->flags); /* PCL816 crash if any divisor is set to 1 */ if (divisor1 == 1) { @@ -666,7 +666,8 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) } transfer_from_dma_buf(dev, s, - (short *)devpriv->dmabuf[devpriv->next_dma_buf], + (unsigned short *)devpriv->dmabuf[devpriv-> + next_dma_buf], devpriv->ai_poll_ptr, top2); devpriv->ai_poll_ptr = top1; /* new buffer position */ @@ -1105,7 +1106,7 @@ static const struct pcl816_board boardtypes[] = { 0xffff, /* D/A maxdata */ 1024, 1, /* ao chan list */ - 100}, + I8254_OSC_BASE_10MHZ}, {"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816, &range_pcl816, PCLx1x_RANGE, 0x00fc, @@ -1114,7 +1115,7 @@ static const struct pcl816_board boardtypes[] = { 0x3fff, 1024, 1, - 100}, + I8254_OSC_BASE_10MHZ}, }; static struct comedi_driver pcl816_driver = { diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index a52ba82ff0e4..9e4d7e860509 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -289,7 +289,6 @@ struct pcl818_private { unsigned int *ai_chanlist; /* actaul chanlist */ unsigned int ai_flags; /* flaglist */ unsigned int ai_data_len; /* len of data buffer */ - short *ai_data; /* data buffer */ unsigned int ai_timer1; /* timers */ unsigned int ai_timer2; struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */ @@ -418,21 +417,15 @@ static int pcl818_di_insn_bits(struct comedi_device *dev, return insn->n; } -/* -============================================================================== - DIGITAL OUTPUT MODE0, 818 cards - - only one sample per call is supported -*/ static int pcl818_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - - outb(s->state & 0xff, dev->iobase + PCL818_DO_LO); - outb((s->state >> 8), dev->iobase + PCL818_DO_HI); + if (comedi_dio_update_state(s, data)) { + outb(s->state & 0xff, dev->iobase + PCL818_DO_LO); + outb((s->state >> 8), dev->iobase + PCL818_DO_HI); + } data[1] = s->state; @@ -449,7 +442,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[0]; - int low; + unsigned char low; int timeout = 50; /* wait max 50us */ while (timeout--) { @@ -511,7 +504,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) struct comedi_subdevice *s = &dev->subdevices[0]; int i, len, bufptr; unsigned long flags; - short *ptr; + unsigned short *ptr; disable_dma(devpriv->dma); devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; @@ -534,7 +527,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) devpriv->dma_runs_to_end--; outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ - ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf]; + ptr = (unsigned short *)devpriv->dmabuf[1 - devpriv->next_dma_buf]; len = devpriv->hwdmasize[0] >> 1; bufptr = 0; @@ -588,7 +581,8 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[0]; - int i, len, lo; + int i, len; + unsigned char lo; outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */ @@ -806,8 +800,9 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev, devpriv->neverending_ai = 1; /* well, user want neverending */ if (mode == 1) { - i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, - &divisor2, &cmd->convert_arg, + i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, + &divisor1, &divisor2, + &cmd->convert_arg, TRIG_ROUND_NEAREST); if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */ divisor1 = 2; @@ -1040,9 +1035,9 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (cmd->convert_src == TRIG_TIMER) { tmp = cmd->convert_arg; - i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1, - &divisor2, &cmd->convert_arg, - cmd->flags & TRIG_ROUND_MASK); + i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, + &divisor1, &divisor2, + &cmd->convert_arg, cmd->flags); if (cmd->convert_arg < board->ns_min) cmd->convert_arg = board->ns_min; if (tmp != cmd->convert_arg) @@ -1077,7 +1072,6 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_chanlist = cmd->chanlist; devpriv->ai_flags = cmd->flags; devpriv->ai_data_len = s->async->prealloc_bufsz; - devpriv->ai_data = s->async->prealloc_buf; devpriv->ai_timer1 = 0; devpriv->ai_timer2 = 0; @@ -1438,9 +1432,9 @@ no_dma: /* select 1/10MHz oscilator */ if ((it->options[3] == 0) || (it->options[3] == 10)) - devpriv->i8253_osc_base = 100; + devpriv->i8253_osc_base = I8254_OSC_BASE_10MHZ; else - devpriv->i8253_osc_base = 1000; + devpriv->i8253_osc_base = I8254_OSC_BASE_1MHZ; /* max sampling speed */ devpriv->ns_min = board->ns_min; diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index 423f23676d26..fe482fdd512e 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -75,12 +75,6 @@ static int pcmad_ai_wait_for_eoc(struct comedi_device *dev, return -ETIME; } -static bool pcmad_range_is_bipolar(struct comedi_subdevice *s, - unsigned int range) -{ - return s->range_table->range[range].min < 0; -} - static int pcmad_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -106,7 +100,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev, if (s->maxdata == 0x0fff) val >>= 4; - if (pcmad_range_is_bipolar(s, range)) { + if (comedi_range_is_bipolar(s, range)) { /* munge the two's complement value */ val ^= ((s->maxdata + 1) >> 1); } diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 574443df42da..14cee3ac92c5 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -553,12 +553,11 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) val |= (1U << n); } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, ((short *)&val)[0]) + if (comedi_buf_put(s->async, val) && comedi_buf_put (s->async, - ((short *) - &val)[1])) { + val >> 16)) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ @@ -846,7 +845,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, CR_RANGE(insn->chanspec), aref = CR_AREF(insn->chanspec); unsigned char command_byte = 0; unsigned iooffset = 0; - short sample, adc_adjust = 0; + unsigned short sample, adc_adjust = 0; if (chan > 7) chan -= 8, iooffset = 4; /* diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 67e2bb1d66f0..954fa96a50ac 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -315,8 +315,8 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, } /* 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, val) && + comedi_buf_put(s->async, val >> 16)) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 9775d3622a62..96a46954b3c0 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -208,8 +208,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) case buffer: while (!((status = inb(dev->iobase + DAQP_STATUS)) & DAQP_STATUS_FIFO_EMPTY)) { - - short data; + unsigned short data; if (status & DAQP_STATUS_DATA_LOST) { s->async->events |= @@ -690,18 +689,12 @@ static int daqp_do_insn_bits(struct comedi_device *dev, unsigned int *data) { struct daqp_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; if (devpriv->stop) return -EIO; - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) outb(s->state, dev->iobase + DAQP_DIGITAL_IO); - } data[1] = s->state; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 93c980c62a23..44c8712ed9e0 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -394,11 +394,8 @@ struct rtd_private { long ai_count; /* total transfer size (samples) */ int xfer_count; /* # to transfer data. 0->1/2FIFO */ int flags; /* flag event modes */ - - unsigned char chan_is_bipolar[RTD_MAX_CHANLIST / 8]; /* bit array */ - + DECLARE_BITMAP(chan_is_bipolar, RTD_MAX_CHANLIST); unsigned int ao_readback[2]; - unsigned fifosz; }; @@ -407,14 +404,6 @@ struct rtd_private { #define DMA0_ACTIVE 0x02 /* DMA0 is active */ #define DMA1_ACTIVE 0x04 /* DMA1 is active */ -/* Macros for accessing channel list bit array */ -#define CHAN_ARRAY_TEST(array, index) \ - (((array)[(index)/8] >> ((index) & 0x7)) & 0x1) -#define CHAN_ARRAY_SET(array, index) \ - (((array)[(index)/8] |= 1 << ((index) & 0x7))) -#define CHAN_ARRAY_CLEAR(array, index) \ - (((array)[(index)/8] &= ~(1 << ((index) & 0x7)))) - /* Given a desired period and the clock period (both in ns), return the proper counter value (divider-1). @@ -478,17 +467,17 @@ static unsigned short rtd_convert_chan_gain(struct comedi_device *dev, /* +-5 range */ r |= 0x000; r |= (range & 0x7) << 4; - CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index); + __set_bit(index, devpriv->chan_is_bipolar); } else if (range < board->range_uni10) { /* +-10 range */ r |= 0x100; r |= ((range - board->range_bip10) & 0x7) << 4; - CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index); + __set_bit(index, devpriv->chan_is_bipolar); } else { /* +10 range */ r |= 0x200; r |= ((range - board->range_uni10) & 0x7) << 4; - CHAN_ARRAY_CLEAR(devpriv->chan_is_bipolar, index); + __clear_bit(index, devpriv->chan_is_bipolar); } switch (aref) { @@ -602,7 +591,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev, /* convert n samples */ for (n = 0; n < insn->n; n++) { - s16 d; + unsigned short d; /* trigger conversion */ writew(0, devpriv->las0 + LAS0_ADC); @@ -619,11 +608,10 @@ static int rtd_ai_rinsn(struct comedi_device *dev, d = readw(devpriv->las1 + LAS1_ADC_FIFO); /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */ d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, 0)) + if (test_bit(0, devpriv->chan_is_bipolar)) /* convert to comedi unsigned data */ - data[n] = d + 2048; - else - data[n] = d; + d = comedi_offset_munge(s, d); + data[n] = d & s->maxdata; } /* return the number of samples read/written */ @@ -643,8 +631,7 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, int ii; for (ii = 0; ii < count; ii++) { - short sample; - s16 d; + unsigned short d; if (0 == devpriv->ai_count) { /* done */ d = readw(devpriv->las1 + LAS1_ADC_FIFO); @@ -653,14 +640,12 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, d = readw(devpriv->las1 + LAS1_ADC_FIFO); d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, - s->async->cur_chan)) { + if (test_bit(s->async->cur_chan, devpriv->chan_is_bipolar)) /* convert to comedi unsigned data */ - sample = d + 2048; - } else - sample = d; + d = comedi_offset_munge(s, d); + d &= s->maxdata; - if (!comedi_buf_put(s->async, sample)) + if (!comedi_buf_put(s->async, d)) return -1; if (devpriv->ai_count > 0) /* < 0, means read forever */ @@ -677,22 +662,19 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) struct rtd_private *devpriv = dev->private; while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) { - short sample; - s16 d = readw(devpriv->las1 + LAS1_ADC_FIFO); + unsigned short d = readw(devpriv->las1 + LAS1_ADC_FIFO); if (0 == devpriv->ai_count) { /* done */ continue; /* read rest */ } d = d >> 3; /* low 3 bits are marker lines */ - if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, - s->async->cur_chan)) { + if (test_bit(s->async->cur_chan, devpriv->chan_is_bipolar)) /* convert to comedi unsigned data */ - sample = d + 2048; - } else - sample = d; + d = comedi_offset_munge(s, d); + d &= s->maxdata; - if (!comedi_buf_put(s->async, sample)) + if (!comedi_buf_put(s->async, d)) return -1; if (devpriv->ai_count > 0) /* < 0, means read forever */ @@ -1217,15 +1199,9 @@ static int rtd_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { struct rtd_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); + if (comedi_dio_update_state(s, data)) writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0); - } data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff; diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index cbb4ba5b852a..e1f3671ac056 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -267,13 +267,7 @@ static int rti800_do_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - unsigned int mask = data[0]; - unsigned int bits = data[1]; - - if (mask) { - s->state &= ~mask; - s->state |= (bits & mask); - + if (comedi_dio_update_state(s, data)) { /* Outputs are inverted... */ outb(s->state ^ 0xff, dev->iobase + RTI800_DO); } diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index d629463b85a2..9950f59b1192 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -499,14 +499,11 @@ static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, static int s526_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - + if (comedi_dio_update_state(s, data)) outw(s->state, dev->iobase + REG_DIO); - } data[1] = inw(dev->iobase + REG_DIO) & 0xff; diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index d22b95dcb9bd..6815cfe2664e 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1,63 +1,63 @@ /* - comedi/drivers/s626.c - Sensoray s626 Comedi driver - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - Based on Sensoray Model 626 Linux driver Version 0.2 - Copyright (C) 2002-2004 Sensoray Co., Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/s626.c + * Sensoray s626 Comedi driver + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * Based on Sensoray Model 626 Linux driver Version 0.2 + * Copyright (C) 2002-2004 Sensoray Co., Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* -Driver: s626 -Description: Sensoray 626 driver -Devices: [Sensoray] 626 (s626) -Authors: Gianluca Palli <gpalli@deis.unibo.it>, -Updated: Fri, 15 Feb 2008 10:28:42 +0000 -Status: experimental - -Configuration options: not applicable, uses PCI auto config - -INSN_CONFIG instructions: - analog input: - none - - analog output: - none - - digital channel: - s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels - supported configuration options: - INSN_CONFIG_DIO_QUERY - COMEDI_INPUT - COMEDI_OUTPUT - - encoder: - Every channel must be configured before reading. - - Example code - - insn.insn=INSN_CONFIG; //configuration instruction - insn.n=1; //number of operation (must be 1) - insn.data=&initialvalue; //initial value loaded into encoder - //during configuration - insn.subdev=5; //encoder subdevice - insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel - //to configure - - comedi_do_insn(cf,&insn); //executing configuration -*/ + * Driver: s626 + * Description: Sensoray 626 driver + * Devices: [Sensoray] 626 (s626) + * Authors: Gianluca Palli <gpalli@deis.unibo.it>, + * Updated: Fri, 15 Feb 2008 10:28:42 +0000 + * Status: experimental + + * Configuration options: not applicable, uses PCI auto config + + * INSN_CONFIG instructions: + * analog input: + * none + * + * analog output: + * none + * + * digital channel: + * s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels + * supported configuration options: + * INSN_CONFIG_DIO_QUERY + * COMEDI_INPUT + * COMEDI_OUTPUT + * + * encoder: + * Every channel must be configured before reading. + * + * Example code + * + * insn.insn=INSN_CONFIG; //configuration instruction + * insn.n=1; //number of operation (must be 1) + * insn.data=&initialvalue; //initial value loaded into encoder + * //during configuration + * insn.subdev=5; //encoder subdevice + * insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel + * //to configure + * + * comedi_do_insn(cf,&insn); //executing configuration + */ #include <linux/module.h> #include <linux/delay.h> @@ -71,68 +71,91 @@ INSN_CONFIG instructions: #include "comedi_fc.h" #include "s626.h" -#define PCI_VENDOR_ID_S626 0x1131 -#define PCI_DEVICE_ID_S626 0x7146 -#define PCI_SUBVENDOR_ID_S626 0x6000 -#define PCI_SUBDEVICE_ID_S626 0x0272 +struct s626_buffer_dma { + dma_addr_t physical_base; + void *logical_base; +}; struct s626_private { void __iomem *mmio; - uint8_t ai_cmd_running; /* ai_cmd is running */ - uint8_t ai_continous; /* continous acquisition */ - int ai_sample_count; /* number of samples to acquire */ - unsigned int ai_sample_timer; - /* time between samples in units of the timer */ - int ai_convert_count; /* conversion counter */ - unsigned int ai_convert_timer; - /* time between conversion in units of the timer */ - uint16_t CounterIntEnabs; - /* Counter interrupt enable mask for MISC2 register. */ - uint8_t AdcItems; /* Number of items in ADC poll list. */ - struct bufferDMA RPSBuf; /* DMA buffer used to hold ADC (RPS1) program. */ - struct bufferDMA ANABuf; - /* DMA buffer used to receive ADC data and hold DAC data. */ - uint32_t *pDacWBuf; - /* Pointer to logical adrs of DMA buffer used to hold DAC data. */ - uint16_t Dacpol; /* Image of DAC polarity register. */ - uint8_t TrimSetpoint[12]; /* Images of TrimDAC setpoints */ - /* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */ - uint32_t I2CAdrs; - /* I2C device address for onboard EEPROM (board rev dependent). */ - /* short I2Cards; */ + uint8_t ai_cmd_running; /* ai_cmd is running */ + uint8_t ai_continuous; /* continuous acquisition */ + int ai_sample_count; /* number of samples to acquire */ + unsigned int ai_sample_timer; /* time between samples in + * units of the timer */ + int ai_convert_count; /* conversion counter */ + unsigned int ai_convert_timer; /* time between conversion in + * units of the timer */ + uint16_t counter_int_enabs; /* counter interrupt enable mask + * for MISC2 register */ + uint8_t adc_items; /* number of items in ADC poll list */ + struct s626_buffer_dma rps_buf; /* DMA buffer used to hold ADC (RPS1) + * program */ + struct s626_buffer_dma ana_buf; /* DMA buffer used to receive ADC data + * and hold DAC data */ + uint32_t *dac_wbuf; /* pointer to logical adrs of DMA buffer + * used to hold DAC data */ + uint16_t dacpol; /* image of DAC polarity register */ + uint8_t trim_setpoint[12]; /* images of TrimDAC setpoints */ + uint32_t i2c_adrs; /* I2C device address for onboard EEPROM + * (board rev dependent) */ unsigned int ao_readback[S626_DAC_CHANNELS]; }; -/* COUNTER OBJECT ------------------------------------------------ */ -struct enc_private { - /* Pointers to functions that differ for A and B counters: */ - uint16_t(*GetEnable) (struct comedi_device *dev, struct enc_private *); /* Return clock enable. */ - uint16_t(*GetIntSrc) (struct comedi_device *dev, struct enc_private *); /* Return interrupt source. */ - uint16_t(*GetLoadTrig) (struct comedi_device *dev, struct enc_private *); /* Return preload trigger source. */ - uint16_t(*GetMode) (struct comedi_device *dev, struct enc_private *); /* Return standardized operating mode. */ - void (*PulseIndex) (struct comedi_device *dev, struct enc_private *); /* Generate soft index strobe. */ - void (*SetEnable) (struct comedi_device *dev, struct enc_private *, uint16_t enab); /* Program clock enable. */ - void (*SetIntSrc) (struct comedi_device *dev, struct enc_private *, uint16_t IntSource); /* Program interrupt source. */ - void (*SetLoadTrig) (struct comedi_device *dev, struct enc_private *, uint16_t Trig); /* Program preload trigger source. */ - void (*SetMode) (struct comedi_device *dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc); /* Program standardized operating mode. */ - void (*ResetCapFlags) (struct comedi_device *dev, struct enc_private *); /* Reset event capture flags. */ - - uint16_t MyCRA; /* Address of CRA register. */ - uint16_t MyCRB; /* Address of CRB register. */ - uint16_t MyLatchLsw; /* Address of Latch least-significant-word */ - /* register. */ - uint16_t MyEventBits[4]; /* Bit translations for IntSrc -->RDMISC2. */ +/* COUNTER OBJECT ------------------------------------------------ */ +struct s626_enc_info { + /* Pointers to functions that differ for A and B counters: */ + /* Return clock enable. */ + uint16_t(*get_enable)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Return interrupt source. */ + uint16_t(*get_int_src)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Return preload trigger source. */ + uint16_t(*get_load_trig)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Return standardized operating mode. */ + uint16_t(*get_mode)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Generate soft index strobe. */ + void (*pulse_index)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Program clock enable. */ + void (*set_enable)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t enab); + /* Program interrupt source. */ + void (*set_int_src)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t int_source); + /* Program preload trigger source. */ + void (*set_load_trig)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t trig); + /* Program standardized operating mode. */ + void (*set_mode)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t setup, + uint16_t disable_int_src); + /* Reset event capture flags. */ + void (*reset_cap_flags)(struct comedi_device *dev, + const struct s626_enc_info *k); + + uint16_t my_cra; /* address of CRA register */ + uint16_t my_crb; /* address of CRB register */ + uint16_t my_latch_lsw; /* address of Latch least-significant-word + * register */ + uint16_t my_event_bits[4]; /* bit translations for IntSrc -->RDMISC2 */ }; -#define encpriv ((struct enc_private *)(dev->subdevices+5)->private) - -/* Counter overflow/index event flag masks for RDMISC2. */ -#define INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 + 4))) -#define OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10))) -#define EVBITS(C) { 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) } +/* Counter overflow/index event flag masks for RDMISC2. */ +#define S626_INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 + 4))) +#define S626_OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10))) +#define S626_EVBITS(C) { 0, S626_OVERMASK(C), S626_INDXMASK(C), \ + S626_OVERMASK(C) | S626_INDXMASK(C) } -/* Translation table to map IntSrc into equivalent RDMISC2 event flag bits. */ -/* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */ +/* + * Translation table to map IntSrc into equivalent RDMISC2 event flag bits. + * static const uint16_t s626_event_bits[][4] = + * { S626_EVBITS(0), S626_EVBITS(1), S626_EVBITS(2), S626_EVBITS(3), + * S626_EVBITS(4), S626_EVBITS(5) }; + */ /* * Enable/disable a function or test status bit(s) that are accessed @@ -144,6 +167,7 @@ static void s626_mc_enable(struct comedi_device *dev, struct s626_private *devpriv = dev->private; unsigned int val = (cmd << 16) | cmd; + mmiowb(); writel(val, devpriv->mmio + reg); } @@ -153,6 +177,7 @@ static void s626_mc_disable(struct comedi_device *dev, struct s626_private *devpriv = dev->private; writel(cmd << 16 , devpriv->mmio + reg); + mmiowb(); } static bool s626_mc_test(struct comedi_device *dev, @@ -166,15 +191,10 @@ static bool s626_mc_test(struct comedi_device *dev, return (val & cmd) ? true : false; } -#define BUGFIX_STREG(REGADRS) (REGADRS - 4) +#define S626_BUGFIX_STREG(REGADRS) ((REGADRS) - 4) -/* Write a time slot control record to TSL2. */ -#define VECTPORT(VECTNUM) (P_TSL2 + ((VECTNUM) << 2)) - -/* Code macros used for constructing I2C command bytes. */ -#define I2C_B2(ATTR, VAL) (((ATTR) << 6) | ((VAL) << 24)) -#define I2C_B1(ATTR, VAL) (((ATTR) << 4) | ((VAL) << 16)) -#define I2C_B0(ATTR, VAL) (((ATTR) << 2) | ((VAL) << 8)) +/* Write a time slot control record to TSL2. */ +#define S626_VECTPORT(VECTNUM) (S626_P_TSL2 + ((VECTNUM) << 2)) static const struct comedi_lrange s626_range_table = { 2, { @@ -183,178 +203,182 @@ static const struct comedi_lrange s626_range_table = { } }; -/* Execute a DEBI transfer. This must be called from within a */ -/* critical section. */ -static void DEBItransfer(struct comedi_device *dev) +/* + * Execute a DEBI transfer. This must be called from within a critical section. + */ +static void s626_debi_transfer(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; /* Initiate upload of shadow RAM to DEBI control register */ - s626_mc_enable(dev, MC2_UPLD_DEBI, P_MC2); + s626_mc_enable(dev, S626_MC2_UPLD_DEBI, S626_P_MC2); /* * Wait for completion of upload from shadow RAM to * DEBI control register. */ - while (!s626_mc_test(dev, MC2_UPLD_DEBI, P_MC2)) + while (!s626_mc_test(dev, S626_MC2_UPLD_DEBI, S626_P_MC2)) ; /* Wait until DEBI transfer is done */ - while (readl(devpriv->mmio + P_PSR) & PSR_DEBI_S) + while (readl(devpriv->mmio + S626_P_PSR) & S626_PSR_DEBI_S) ; } -/* Initialize the DEBI interface for all transfers. */ - -static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr) +/* + * Read a value from a gate array register. + */ +static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr) { struct s626_private *devpriv = dev->private; /* Set up DEBI control register value in shadow RAM */ - writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD); + writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD); /* Execute the DEBI transfer. */ - DEBItransfer(dev); + s626_debi_transfer(dev); - return readl(devpriv->mmio + P_DEBIAD); + return readl(devpriv->mmio + S626_P_DEBIAD); } -/* Write a value to a gate array register. */ -static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata) +/* + * Write a value to a gate array register. + */ +static void s626_debi_write(struct comedi_device *dev, uint16_t addr, + uint16_t wdata) { struct s626_private *devpriv = dev->private; /* Set up DEBI control register value in shadow RAM */ - writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD); - writel(wdata, devpriv->mmio + P_DEBIAD); + writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD); + writel(wdata, devpriv->mmio + S626_P_DEBIAD); /* Execute the DEBI transfer. */ - DEBItransfer(dev); + s626_debi_transfer(dev); } -/* Replace the specified bits in a gate array register. Imports: mask +/* + * Replace the specified bits in a gate array register. Imports: mask * specifies bits that are to be preserved, wdata is new value to be * or'd with the masked original. */ -static void DEBIreplace(struct comedi_device *dev, unsigned int addr, - unsigned int mask, unsigned int wdata) +static void s626_debi_replace(struct comedi_device *dev, unsigned int addr, + unsigned int mask, unsigned int wdata) { struct s626_private *devpriv = dev->private; unsigned int val; addr &= 0xffff; - writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD); - DEBItransfer(dev); + writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD); + s626_debi_transfer(dev); - writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD); - val = readl(devpriv->mmio + P_DEBIAD); + writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD); + val = readl(devpriv->mmio + S626_P_DEBIAD); val &= mask; val |= wdata; - writel(val & 0xffff, devpriv->mmio + P_DEBIAD); - DEBItransfer(dev); + writel(val & 0xffff, devpriv->mmio + S626_P_DEBIAD); + s626_debi_transfer(dev); } /* ************** EEPROM ACCESS FUNCTIONS ************** */ -static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val) +static uint32_t s626_i2c_handshake(struct comedi_device *dev, uint32_t val) { struct s626_private *devpriv = dev->private; unsigned int ctrl; /* Write I2C command to I2C Transfer Control shadow register */ - writel(val, devpriv->mmio + P_I2CCTRL); + writel(val, devpriv->mmio + S626_P_I2CCTRL); /* * Upload I2C shadow registers into working registers and * wait for upload confirmation. */ - s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); - while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2)) + s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); + while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2)) ; /* Wait until I2C bus transfer is finished or an error occurs */ do { - ctrl = readl(devpriv->mmio + P_I2CCTRL); - } while ((ctrl & (I2C_BUSY | I2C_ERR)) == I2C_BUSY); + ctrl = readl(devpriv->mmio + S626_P_I2CCTRL); + } while ((ctrl & (S626_I2C_BUSY | S626_I2C_ERR)) == S626_I2C_BUSY); /* Return non-zero if I2C error occurred */ - return ctrl & I2C_ERR; + return ctrl & S626_I2C_ERR; } -/* Read uint8_t from EEPROM. */ -static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr) +/* Read uint8_t from EEPROM. */ +static uint8_t s626_i2c_read(struct comedi_device *dev, uint8_t addr) { struct s626_private *devpriv = dev->private; - /* Send EEPROM target address. */ - if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW) - /* Byte2 = I2C command: write to I2C EEPROM device. */ - | I2C_B1(I2C_ATTRSTOP, addr) - /* Byte1 = EEPROM internal target address. */ - | I2C_B0(I2C_ATTRNOP, 0))) { /* Byte0 = Not sent. */ - /* Abort function and declare error if handshake failed. */ + /* + * Send EEPROM target address: + * Byte2 = I2C command: write to I2C EEPROM device. + * Byte1 = EEPROM internal target address. + * Byte0 = Not sent. + */ + if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART, + devpriv->i2c_adrs) | + S626_I2C_B1(S626_I2C_ATTRSTOP, addr) | + S626_I2C_B0(S626_I2C_ATTRNOP, 0))) + /* Abort function and declare error if handshake failed. */ return 0; - } - /* Execute EEPROM read. */ - if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR) - - /* Byte2 = I2C */ - /* command: read */ - /* from I2C EEPROM */ - /* device. */ - |I2C_B1(I2C_ATTRSTOP, 0) - /* Byte1 receives */ - /* uint8_t from */ - /* EEPROM. */ - |I2C_B0(I2C_ATTRNOP, 0))) { /* Byte0 = Not sent. */ - - /* Abort function and declare error if handshake failed. */ + /* + * Execute EEPROM read: + * Byte2 = I2C command: read from I2C EEPROM device. + * Byte1 receives uint8_t from EEPROM. + * Byte0 = Not sent. + */ + if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART, + (devpriv->i2c_adrs | 1)) | + S626_I2C_B1(S626_I2C_ATTRSTOP, 0) | + S626_I2C_B0(S626_I2C_ATTRNOP, 0))) + /* Abort function and declare error if handshake failed. */ return 0; - } - return (readl(devpriv->mmio + P_I2CCTRL) >> 16) & 0xff; + return (readl(devpriv->mmio + S626_P_I2CCTRL) >> 16) & 0xff; } /* *********** DAC FUNCTIONS *********** */ -/* Slot 0 base settings. */ -#define VECT0 (XSD2 | RSD3 | SIB_A2) -/* Slot 0 always shifts in 0xFF and store it to FB_BUFFER2. */ +/* TrimDac LogicalChan-to-PhysicalChan mapping table. */ +static const uint8_t s626_trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 }; -/* TrimDac LogicalChan-to-PhysicalChan mapping table. */ -static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 }; - -/* TrimDac LogicalChan-to-EepromAdrs mapping table. */ -static uint8_t trimadrs[] = { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 }; +/* TrimDac LogicalChan-to-EepromAdrs mapping table. */ +static const uint8_t s626_trimadrs[] = { + 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 +}; -/* Private helper function: Transmit serial data to DAC via Audio +/* + * Private helper function: Transmit serial data to DAC via Audio * channel 2. Assumes: (1) TSL2 slot records initialized, and (2) - * Dacpol contains valid target image. + * dacpol contains valid target image. */ -static void SendDAC(struct comedi_device *dev, uint32_t val) +static void s626_send_dac(struct comedi_device *dev, uint32_t val) { struct s626_private *devpriv = dev->private; /* START THE SERIAL CLOCK RUNNING ------------- */ - /* Assert DAC polarity control and enable gating of DAC serial clock + /* + * Assert DAC polarity control and enable gating of DAC serial clock * and audio bit stream signals. At this point in time we must be * assured of being in time slot 0. If we are not in slot 0, the * serial clock and audio stream signals will be disabled; this is - * because the following DEBIwrite statement (which enables signals - * to be passed through the gate array) would execute before the - * trailing edge of WS1/WS3 (which turns off the signals), thus + * because the following s626_debi_write statement (which enables + * signals to be passed through the gate array) would execute before + * the trailing edge of WS1/WS3 (which turns off the signals), thus * causing the signals to be inactive during the DAC write. */ - DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol); + s626_debi_write(dev, S626_LP_DACPOL, devpriv->dacpol); /* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */ /* Copy DAC setpoint value to DAC's output DMA buffer. */ - - /* writel(val, devpriv->mmio + (uint32_t)devpriv->pDacWBuf); */ - *devpriv->pDacWBuf = val; + /* writel(val, devpriv->mmio + (uint32_t)devpriv->dac_wbuf); */ + *devpriv->dac_wbuf = val; /* * Enable the output DMA transfer. This will cause the DMAC to copy @@ -362,56 +386,62 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * then immediately terminate because the protection address is * reached upon transfer of the first DWORD value. */ - s626_mc_enable(dev, MC1_A2OUT, P_MC1); + s626_mc_enable(dev, S626_MC1_A2OUT, S626_P_MC1); - /* While the DMA transfer is executing ... */ + /* While the DMA transfer is executing ... */ /* * Reset Audio2 output FIFO's underflow flag (along with any * other FIFO underflow/overflow flags). When set, this flag * will indicate that we have emerged from slot 0. */ - writel(ISR_AFOU, devpriv->mmio + P_ISR); + writel(S626_ISR_AFOU, devpriv->mmio + S626_P_ISR); - /* Wait for the DMA transfer to finish so that there will be data + /* + * Wait for the DMA transfer to finish so that there will be data * available in the FIFO when time slot 1 tries to transfer a DWORD * from the FIFO to the output buffer register. We test for DMA * Done by polling the DMAC enable flag; this flag is automatically * cleared when the transfer has finished. */ - while (readl(devpriv->mmio + P_MC1) & MC1_A2OUT) + while (readl(devpriv->mmio + S626_P_MC1) & S626_MC1_A2OUT) ; /* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */ - /* FIFO data is now available, so we enable execution of time slots + /* + * FIFO data is now available, so we enable execution of time slots * 1 and higher by clearing the EOS flag in slot 0. Note that SD3 * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list * detection. */ - writel(XSD2 | RSD3 | SIB_A2, devpriv->mmio + VECTPORT(0)); + writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2, + devpriv->mmio + S626_VECTPORT(0)); - /* Wait for slot 1 to execute to ensure that the Packet will be + /* + * Wait for slot 1 to execute to ensure that the Packet will be * transmitted. This is detected by polling the Audio2 output FIFO * underflow flag, which will be set when slot 1 execution has * finished transferring the DAC's data DWORD from the output FIFO * to the output buffer register. */ - while (!(readl(devpriv->mmio + P_SSR) & SSR_AF2_OUT)) + while (!(readl(devpriv->mmio + S626_P_SSR) & S626_SSR_AF2_OUT)) ; - /* Set up to trap execution at slot 0 when the TSL sequencer cycles + /* + * Set up to trap execution at slot 0 when the TSL sequencer cycles * back to slot 0 after executing the EOS in slot 5. Also, * simultaneously shift out and in the 0x00 that is ALWAYS the value * stored in the last byte to be shifted out of the FIFO's DWORD * buffer register. */ - writel(XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS, - devpriv->mmio + VECTPORT(0)); + writel(S626_XSD2 | S626_XFIFO_2 | S626_RSD2 | S626_SIB_A2 | S626_EOS, + devpriv->mmio + S626_VECTPORT(0)); /* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */ - /* Wait for the TSL to finish executing all time slots before + /* + * Wait for the TSL to finish executing all time slots before * exiting this function. We must do this so that the next DAC * write doesn't start, thereby enabling clock/chip select signals: * @@ -428,17 +458,19 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If * the TSL has not yet finished executing slot 5 ... */ - if (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000) { - /* The trap was set on time and we are still executing somewhere + if (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000) { + /* + * The trap was set on time and we are still executing somewhere * in slots 2-5, so we now wait for slot 0 to execute and trap * TSL execution. This is detected when FB_BUFFER2 MSB changes * from 0xFF to 0x00, which slot 0 causes to happen by shifting * out/in on SD2 the 0x00 that is always referenced by slot 5. */ - while (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000) + while (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000) ; } - /* Either (1) we were too late setting the slot 0 trap; the TSL + /* + * Either (1) we were too late setting the slot 0 trap; the TSL * sequencer restarted slot 0 before we could set the EOS trap flag, * or (2) we were not late and execution is now trapped at slot 0. * In either case, we must now change slot 0 so that it will store @@ -446,37 +478,46 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * In order to do this, we reprogram slot 0 so that it will shift in * SD3, which is driven only by a pull-up resistor. */ - writel(RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0)); + writel(S626_RSD3 | S626_SIB_A2 | S626_EOS, + devpriv->mmio + S626_VECTPORT(0)); - /* Wait for slot 0 to execute, at which time the TSL is setup for + /* + * Wait for slot 0 to execute, at which time the TSL is setup for * the next DAC write. This is detected when FB_BUFFER2 MSB changes * from 0x00 to 0xFF. */ - while (!(readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000)) + while (!(readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000)) ; } -/* Private helper function: Write setpoint to an application DAC channel. */ -static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata) +/* + * Private helper function: Write setpoint to an application DAC channel. + */ +static void s626_set_dac(struct comedi_device *dev, uint16_t chan, + unsigned short dacdata) { struct s626_private *devpriv = dev->private; - register uint16_t signmask; - register uint32_t WSImage; + uint16_t signmask; + uint32_t ws_image; + uint32_t val; - /* Adjust DAC data polarity and set up Polarity Control Register */ - /* image. */ + /* + * Adjust DAC data polarity and set up Polarity Control Register image. + */ signmask = 1 << chan; if (dacdata < 0) { dacdata = -dacdata; - devpriv->Dacpol |= signmask; - } else - devpriv->Dacpol &= ~signmask; + devpriv->dacpol |= signmask; + } else { + devpriv->dacpol &= ~signmask; + } - /* Limit DAC setpoint value to valid range. */ - if ((uint16_t) dacdata > 0x1FFF) + /* Limit DAC setpoint value to valid range. */ + if ((uint16_t)dacdata > 0x1FFF) dacdata = 0x1FFF; - /* Set up TSL2 records (aka "vectors") for DAC update. Vectors V2 + /* + * Set up TSL2 records (aka "vectors") for DAC update. Vectors V2 * and V3 transmit the setpoint to the target DAC. V4 and V5 send * data to a non-existent TrimDac channel just to keep the clock * running after sending data to the target DAC. This is necessary @@ -487,140 +528,792 @@ static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata) */ /* Choose DAC chip select to be asserted */ - WSImage = (chan & 2) ? WS1 : WS2; + ws_image = (chan & 2) ? S626_WS1 : S626_WS2; /* Slot 2: Transmit high data byte to target DAC */ - writel(XSD2 | XFIFO_1 | WSImage, devpriv->mmio + VECTPORT(2)); + writel(S626_XSD2 | S626_XFIFO_1 | ws_image, + devpriv->mmio + S626_VECTPORT(2)); /* Slot 3: Transmit low data byte to target DAC */ - writel(XSD2 | XFIFO_0 | WSImage, devpriv->mmio + VECTPORT(3)); + writel(S626_XSD2 | S626_XFIFO_0 | ws_image, + devpriv->mmio + S626_VECTPORT(3)); /* Slot 4: Transmit to non-existent TrimDac channel to keep clock */ - writel(XSD2 | XFIFO_3 | WS3, devpriv->mmio + VECTPORT(4)); + writel(S626_XSD2 | S626_XFIFO_3 | S626_WS3, + devpriv->mmio + S626_VECTPORT(4)); /* Slot 5: running after writing target DAC's low data byte */ - writel(XSD2 | XFIFO_2 | WS3 | EOS, devpriv->mmio + VECTPORT(5)); + writel(S626_XSD2 | S626_XFIFO_2 | S626_WS3 | S626_EOS, + devpriv->mmio + S626_VECTPORT(5)); - /* Construct and transmit target DAC's serial packet: - * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, + /* + * Construct and transmit target DAC's serial packet: + * (A10D DDDD), (DDDD DDDD), (0x0F), (0x00) where A is chan<0>, * and D<12:0> is the DAC setpoint. Append a WORD value (that writes * to a non-existent TrimDac channel) that serves to keep the clock * running after the packet has been sent to the target DAC. */ - SendDAC(dev, 0x0F000000 - /* Continue clock after target DAC data (write to non-existent trimdac). */ - | 0x00004000 - /* Address the two main dual-DAC devices (TSL's chip select enables - * target device). */ - | ((uint32_t) (chan & 1) << 15) - /* Address the DAC channel within the device. */ - | (uint32_t) dacdata); /* Include DAC setpoint data. */ - + val = 0x0F000000; /* Continue clock after target DAC data + * (write to non-existent trimdac). */ + val |= 0x00004000; /* Address the two main dual-DAC devices + * (TSL's chip select enables target device). */ + val |= ((uint32_t)(chan & 1) << 15); /* Address the DAC channel + * within the device. */ + val |= (uint32_t)dacdata; /* Include DAC setpoint data. */ + s626_send_dac(dev, val); } -static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan, - uint8_t DacData) +static void s626_write_trim_dac(struct comedi_device *dev, uint8_t logical_chan, + uint8_t dac_data) { struct s626_private *devpriv = dev->private; uint32_t chan; - /* Save the new setpoint in case the application needs to read it back later. */ - devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData; + /* + * Save the new setpoint in case the application needs to read it back + * later. + */ + devpriv->trim_setpoint[logical_chan] = (uint8_t)dac_data; - /* Map logical channel number to physical channel number. */ - chan = (uint32_t) trimchan[LogicalChan]; + /* Map logical channel number to physical channel number. */ + chan = s626_trimchan[logical_chan]; - /* Set up TSL2 records for TrimDac write operation. All slots shift + /* + * Set up TSL2 records for TrimDac write operation. All slots shift * 0xFF in from pulled-up SD3 so that the end of the slot sequence * can be detected. */ /* Slot 2: Send high uint8_t to target TrimDac */ - writel(XSD2 | XFIFO_1 | WS3, devpriv->mmio + VECTPORT(2)); + writel(S626_XSD2 | S626_XFIFO_1 | S626_WS3, + devpriv->mmio + S626_VECTPORT(2)); /* Slot 3: Send low uint8_t to target TrimDac */ - writel(XSD2 | XFIFO_0 | WS3, devpriv->mmio + VECTPORT(3)); + writel(S626_XSD2 | S626_XFIFO_0 | S626_WS3, + devpriv->mmio + S626_VECTPORT(3)); /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */ - writel(XSD2 | XFIFO_3 | WS1, devpriv->mmio + VECTPORT(4)); + writel(S626_XSD2 | S626_XFIFO_3 | S626_WS1, + devpriv->mmio + S626_VECTPORT(4)); /* Slot 5: Send NOP low uint8_t to DAC0 */ - writel(XSD2 | XFIFO_2 | WS1 | EOS, devpriv->mmio + VECTPORT(5)); + writel(S626_XSD2 | S626_XFIFO_2 | S626_WS1 | S626_EOS, + devpriv->mmio + S626_VECTPORT(5)); - /* Construct and transmit target DAC's serial packet: - * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the + /* + * Construct and transmit target DAC's serial packet: + * (0000 AAAA), (DDDD DDDD), (0x00), (0x00) where A<3:0> is the * DAC channel's address, and D<7:0> is the DAC setpoint. Append a * WORD value (that writes a channel 0 NOP command to a non-existent * main DAC channel) that serves to keep the clock running after the * packet has been sent to the target DAC. */ - /* Address the DAC channel within the trimdac device. */ - SendDAC(dev, ((uint32_t) chan << 8) - | (uint32_t) DacData); /* Include DAC setpoint data. */ + /* + * Address the DAC channel within the trimdac device. + * Include DAC setpoint data. + */ + s626_send_dac(dev, (chan << 8) | dac_data); } -static void LoadTrimDACs(struct comedi_device *dev) +static void s626_load_trim_dacs(struct comedi_device *dev) { - register uint8_t i; + uint8_t i; - /* Copy TrimDac setpoint values from EEPROM to TrimDacs. */ - for (i = 0; i < ARRAY_SIZE(trimchan); i++) - WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i])); + /* Copy TrimDac setpoint values from EEPROM to TrimDacs. */ + for (i = 0; i < ARRAY_SIZE(s626_trimchan); i++) + s626_write_trim_dac(dev, i, + s626_i2c_read(dev, s626_trimadrs[i])); } /* ****** COUNTER FUNCTIONS ******* */ -/* All counter functions address a specific counter by means of the + +/* + * All counter functions address a specific counter by means of the * "Counter" argument, which is a logical counter number. The Counter * argument may have any of the following legal values: 0=0A, 1=1A, * 2=2A, 3=0B, 4=1B, 5=2B. */ -/* Read a counter's output latch. */ -static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k) +/* + * Read a counter's output latch. + */ +static uint32_t s626_read_latch(struct comedi_device *dev, + const struct s626_enc_info *k) { - register uint32_t value; + uint32_t value; - /* Latch counts and fetch LSW of latched counts value. */ - value = (uint32_t) DEBIread(dev, k->MyLatchLsw); + /* Latch counts and fetch LSW of latched counts value. */ + value = s626_debi_read(dev, k->my_latch_lsw); - /* Fetch MSW of latched counts and combine with LSW. */ - value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16); + /* Fetch MSW of latched counts and combine with LSW. */ + value |= ((uint32_t)s626_debi_read(dev, k->my_latch_lsw + 2) << 16); - /* Return latched counts. */ + /* Return latched counts. */ return value; } -/* Return/set a counter pair's latch trigger source. 0: On read +/* + * Return/set a counter pair's latch trigger source. 0: On read * access, 1: A index latches A, 2: B index latches B, 3: A overflow * latches B. */ -static void SetLatchSource(struct comedi_device *dev, struct enc_private *k, - uint16_t value) +static void s626_set_latch_source(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) { - DEBIreplace(dev, k->MyCRB, - ~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC), - value << CRBBIT_LATCHSRC); + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_LATCHSRC), + S626_SET_CRB_LATCHSRC(value)); } -/* Write value into counter preload register. */ -static void Preload(struct comedi_device *dev, struct enc_private *k, - uint32_t value) +/* + * Write value into counter preload register. + */ +static void s626_preload(struct comedi_device *dev, + const struct s626_enc_info *k, uint32_t value) { - DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value); - DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2), - (uint16_t) (value >> 16)); + s626_debi_write(dev, k->my_latch_lsw, value); + s626_debi_write(dev, k->my_latch_lsw + 2, value >> 16); } -static unsigned int s626_ai_reg_to_uint(int data) +/* ****** PRIVATE COUNTER FUNCTIONS ****** */ + +/* + * Reset a counter's index and overflow event capture flags. + */ +static void s626_reset_cap_flags_a(struct comedi_device *dev, + const struct s626_enc_info *k) { - unsigned int tempdata; + s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, + (S626_SET_CRB_INTRESETCMD(1) | + S626_SET_CRB_INTRESET_A(1))); +} - tempdata = (data >> 18); - if (tempdata & 0x2000) - tempdata &= 0x1fff; - else - tempdata += (1 << 13); +static void s626_reset_cap_flags_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, + (S626_SET_CRB_INTRESETCMD(1) | + S626_SET_CRB_INTRESET_B(1))); +} + +/* + * Return counter setup in a format (COUNTER_SETUP) that is consistent + * for both A and B counters. + */ +static uint16_t s626_get_mode_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t cra; + uint16_t crb; + uint16_t setup; + unsigned cntsrc, clkmult, clkpol, encmode; + + /* Fetch CRA and CRB register images. */ + cra = s626_debi_read(dev, k->my_cra); + crb = s626_debi_read(dev, k->my_crb); + + /* + * Populate the standardized counter setup bit fields. + */ + setup = + /* LoadSrc = LoadSrcA. */ + S626_SET_STD_LOADSRC(S626_GET_CRA_LOADSRC_A(cra)) | + /* LatchSrc = LatchSrcA. */ + S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) | + /* IntSrc = IntSrcA. */ + S626_SET_STD_INTSRC(S626_GET_CRA_INTSRC_A(cra)) | + /* IndxSrc = IndxSrcA. */ + S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_A(cra)) | + /* IndxPol = IndxPolA. */ + S626_SET_STD_INDXPOL(S626_GET_CRA_INDXPOL_A(cra)) | + /* ClkEnab = ClkEnabA. */ + S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_A(crb)); + + /* Adjust mode-dependent parameters. */ + cntsrc = S626_GET_CRA_CNTSRC_A(cra); + if (cntsrc & S626_CNTSRC_SYSCLK) { + /* Timer mode (CntSrcA<1> == 1): */ + encmode = S626_ENCMODE_TIMER; + /* Set ClkPol to indicate count direction (CntSrcA<0>). */ + clkpol = cntsrc & 1; + /* ClkMult must be 1x in Timer mode. */ + clkmult = S626_CLKMULT_1X; + } else { + /* Counter mode (CntSrcA<1> == 0): */ + encmode = S626_ENCMODE_COUNTER; + /* Pass through ClkPol. */ + clkpol = S626_GET_CRA_CLKPOL_A(cra); + /* Force ClkMult to 1x if not legal, else pass through. */ + clkmult = S626_GET_CRA_CLKMULT_A(cra); + if (clkmult == S626_CLKMULT_SPECIAL) + clkmult = S626_CLKMULT_1X; + } + setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) | + S626_SET_STD_CLKPOL(clkpol); + + /* Return adjusted counter setup. */ + return setup; +} + +static uint16_t s626_get_mode_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t cra; + uint16_t crb; + uint16_t setup; + unsigned cntsrc, clkmult, clkpol, encmode; - return tempdata; + /* Fetch CRA and CRB register images. */ + cra = s626_debi_read(dev, k->my_cra); + crb = s626_debi_read(dev, k->my_crb); + + /* + * Populate the standardized counter setup bit fields. + */ + setup = + /* IntSrc = IntSrcB. */ + S626_SET_STD_INTSRC(S626_GET_CRB_INTSRC_B(crb)) | + /* LatchSrc = LatchSrcB. */ + S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) | + /* LoadSrc = LoadSrcB. */ + S626_SET_STD_LOADSRC(S626_GET_CRB_LOADSRC_B(crb)) | + /* IndxPol = IndxPolB. */ + S626_SET_STD_INDXPOL(S626_GET_CRB_INDXPOL_B(crb)) | + /* ClkEnab = ClkEnabB. */ + S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_B(crb)) | + /* IndxSrc = IndxSrcB. */ + S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_B(cra)); + + /* Adjust mode-dependent parameters. */ + cntsrc = S626_GET_CRA_CNTSRC_B(cra); + clkmult = S626_GET_CRB_CLKMULT_B(crb); + if (clkmult == S626_CLKMULT_SPECIAL) { + /* Extender mode (ClkMultB == S626_CLKMULT_SPECIAL): */ + encmode = S626_ENCMODE_EXTENDER; + /* Indicate multiplier is 1x. */ + clkmult = S626_CLKMULT_1X; + /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */ + clkpol = cntsrc & 1; + } else if (cntsrc & S626_CNTSRC_SYSCLK) { + /* Timer mode (CntSrcB<1> == 1): */ + encmode = S626_ENCMODE_TIMER; + /* Indicate multiplier is 1x. */ + clkmult = S626_CLKMULT_1X; + /* Set ClkPol equal to Timer count direction (CntSrcB<0>). */ + clkpol = cntsrc & 1; + } else { + /* If Counter mode (CntSrcB<1> == 0): */ + encmode = S626_ENCMODE_COUNTER; + /* Clock multiplier is passed through. */ + /* Clock polarity is passed through. */ + clkpol = S626_GET_CRB_CLKPOL_B(crb); + } + setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) | + S626_SET_STD_CLKPOL(clkpol); + + /* Return adjusted counter setup. */ + return setup; } -/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data){ */ -/* return 0; */ -/* } */ +/* + * Set the operating mode for the specified counter. The setup + * parameter is treated as a COUNTER_SETUP data type. The following + * parameters are programmable (all other parms are ignored): ClkMult, + * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc. + */ +static void s626_set_mode_a(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t setup, + uint16_t disable_int_src) +{ + struct s626_private *devpriv = dev->private; + uint16_t cra; + uint16_t crb; + unsigned cntsrc, clkmult, clkpol; + + /* Initialize CRA and CRB images. */ + /* Preload trigger is passed through. */ + cra = S626_SET_CRA_LOADSRC_A(S626_GET_STD_LOADSRC(setup)); + /* IndexSrc is passed through. */ + cra |= S626_SET_CRA_INDXSRC_A(S626_GET_STD_INDXSRC(setup)); + + /* Reset any pending CounterA event captures. */ + crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_A(1); + /* Clock enable is passed through. */ + crb |= S626_SET_CRB_CLKENAB_A(S626_GET_STD_CLKENAB(setup)); + + /* Force IntSrc to Disabled if disable_int_src is asserted. */ + if (!disable_int_src) + cra |= S626_SET_CRA_INTSRC_A(S626_GET_STD_INTSRC(setup)); + + /* Populate all mode-dependent attributes of CRA & CRB images. */ + clkpol = S626_GET_STD_CLKPOL(setup); + switch (S626_GET_STD_ENCMODE(setup)) { + case S626_ENCMODE_EXTENDER: /* Extender Mode: */ + /* Force to Timer mode (Extender valid only for B counters). */ + /* Fall through to case S626_ENCMODE_TIMER: */ + case S626_ENCMODE_TIMER: /* Timer Mode: */ + /* CntSrcA<1> selects system clock */ + cntsrc = S626_CNTSRC_SYSCLK; + /* Count direction (CntSrcA<0>) obtained from ClkPol. */ + cntsrc |= clkpol; + /* ClkPolA behaves as always-on clock enable. */ + clkpol = 1; + /* ClkMult must be 1x. */ + clkmult = S626_CLKMULT_1X; + break; + default: /* Counter Mode: */ + /* Select ENC_C and ENC_D as clock/direction inputs. */ + cntsrc = S626_CNTSRC_ENCODER; + /* Clock polarity is passed through. */ + /* Force multiplier to x1 if not legal, else pass through. */ + clkmult = S626_GET_STD_CLKMULT(setup); + if (clkmult == S626_CLKMULT_SPECIAL) + clkmult = S626_CLKMULT_1X; + break; + } + cra |= S626_SET_CRA_CNTSRC_A(cntsrc) | S626_SET_CRA_CLKPOL_A(clkpol) | + S626_SET_CRA_CLKMULT_A(clkmult); + + /* + * Force positive index polarity if IndxSrc is software-driven only, + * otherwise pass it through. + */ + if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT) + cra |= S626_SET_CRA_INDXPOL_A(S626_GET_STD_INDXPOL(setup)); + + /* + * If IntSrc has been forced to Disabled, update the MISC2 interrupt + * enable mask to indicate the counter interrupt is disabled. + */ + if (disable_int_src) + devpriv->counter_int_enabs &= ~k->my_event_bits[3]; + + /* + * While retaining CounterB and LatchSrc configurations, program the + * new counter operating mode. + */ + s626_debi_replace(dev, k->my_cra, + S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B, cra); + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), crb); +} + +static void s626_set_mode_b(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t setup, + uint16_t disable_int_src) +{ + struct s626_private *devpriv = dev->private; + uint16_t cra; + uint16_t crb; + unsigned cntsrc, clkmult, clkpol; + + /* Initialize CRA and CRB images. */ + /* IndexSrc is passed through. */ + cra = S626_SET_CRA_INDXSRC_B(S626_GET_STD_INDXSRC(setup)); + + /* Reset event captures and disable interrupts. */ + crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_B(1); + /* Clock enable is passed through. */ + crb |= S626_SET_CRB_CLKENAB_B(S626_GET_STD_CLKENAB(setup)); + /* Preload trigger source is passed through. */ + crb |= S626_SET_CRB_LOADSRC_B(S626_GET_STD_LOADSRC(setup)); + + /* Force IntSrc to Disabled if disable_int_src is asserted. */ + if (!disable_int_src) + crb |= S626_SET_CRB_INTSRC_B(S626_GET_STD_INTSRC(setup)); + + /* Populate all mode-dependent attributes of CRA & CRB images. */ + clkpol = S626_GET_STD_CLKPOL(setup); + switch (S626_GET_STD_ENCMODE(setup)) { + case S626_ENCMODE_TIMER: /* Timer Mode: */ + /* CntSrcB<1> selects system clock */ + cntsrc = S626_CNTSRC_SYSCLK; + /* with direction (CntSrcB<0>) obtained from ClkPol. */ + cntsrc |= clkpol; + /* ClkPolB behaves as always-on clock enable. */ + clkpol = 1; + /* ClkMultB must be 1x. */ + clkmult = S626_CLKMULT_1X; + break; + case S626_ENCMODE_EXTENDER: /* Extender Mode: */ + /* CntSrcB source is OverflowA (same as "timer") */ + cntsrc = S626_CNTSRC_SYSCLK; + /* with direction obtained from ClkPol. */ + cntsrc |= clkpol; + /* ClkPolB controls IndexB -- always set to active. */ + clkpol = 1; + /* ClkMultB selects OverflowA as the clock source. */ + clkmult = S626_CLKMULT_SPECIAL; + break; + default: /* Counter Mode: */ + /* Select ENC_C and ENC_D as clock/direction inputs. */ + cntsrc = S626_CNTSRC_ENCODER; + /* ClkPol is passed through. */ + /* Force ClkMult to x1 if not legal, otherwise pass through. */ + clkmult = S626_GET_STD_CLKMULT(setup); + if (clkmult == S626_CLKMULT_SPECIAL) + clkmult = S626_CLKMULT_1X; + break; + } + cra |= S626_SET_CRA_CNTSRC_B(cntsrc); + crb |= S626_SET_CRB_CLKPOL_B(clkpol) | S626_SET_CRB_CLKMULT_B(clkmult); + + /* + * Force positive index polarity if IndxSrc is software-driven only, + * otherwise pass it through. + */ + if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT) + crb |= S626_SET_CRB_INDXPOL_B(S626_GET_STD_INDXPOL(setup)); + + /* + * If IntSrc has been forced to Disabled, update the MISC2 interrupt + * enable mask to indicate the counter interrupt is disabled. + */ + if (disable_int_src) + devpriv->counter_int_enabs &= ~k->my_event_bits[3]; + + /* + * While retaining CounterA and LatchSrc configurations, program the + * new counter operating mode. + */ + s626_debi_replace(dev, k->my_cra, + ~(S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B), cra); + s626_debi_replace(dev, k->my_crb, + S626_CRBMSK_CLKENAB_A | S626_CRBMSK_LATCHSRC, crb); +} + +/* + * Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index. + */ +static void s626_set_enable_a(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t enab) +{ + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), + S626_SET_CRB_CLKENAB_A(enab)); +} + +static void s626_set_enable_b(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t enab) +{ + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_B), + S626_SET_CRB_CLKENAB_B(enab)); +} + +static uint16_t s626_get_enable_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_CRB_CLKENAB_A(s626_debi_read(dev, k->my_crb)); +} + +static uint16_t s626_get_enable_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_CRB_CLKENAB_B(s626_debi_read(dev, k->my_crb)); +} + +#ifdef unused +static uint16_t s626_get_latch_source(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, k->my_crb)); +} +#endif + +/* + * Return/set the event that will trigger transfer of the preload + * register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, + * 2=OverflowA (B counters only), 3=disabled. + */ +static void s626_set_load_trig_a(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t trig) +{ + s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_LOADSRC_A, + S626_SET_CRA_LOADSRC_A(trig)); +} + +static void s626_set_load_trig_b(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t trig) +{ + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL), + S626_SET_CRB_LOADSRC_B(trig)); +} + +static uint16_t s626_get_load_trig_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev, k->my_cra)); +} + +static uint16_t s626_get_load_trig_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev, k->my_crb)); +} + +/* + * Return/set counter interrupt source and clear any captured + * index/overflow events. int_source: 0=Disabled, 1=OverflowOnly, + * 2=IndexOnly, 3=IndexAndOverflow. + */ +static void s626_set_int_src_a(struct comedi_device *dev, + const struct s626_enc_info *k, + uint16_t int_source) +{ + struct s626_private *devpriv = dev->private; + + /* Reset any pending counter overflow or index captures. */ + s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, + (S626_SET_CRB_INTRESETCMD(1) | + S626_SET_CRB_INTRESET_A(1))); + + /* Program counter interrupt source. */ + s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_INTSRC_A, + S626_SET_CRA_INTSRC_A(int_source)); + + /* Update MISC2 interrupt enable mask. */ + devpriv->counter_int_enabs = + (devpriv->counter_int_enabs & ~k->my_event_bits[3]) | + k->my_event_bits[int_source]; +} + +static void s626_set_int_src_b(struct comedi_device *dev, + const struct s626_enc_info *k, + uint16_t int_source) +{ + struct s626_private *devpriv = dev->private; + uint16_t crb; + + /* Cache writeable CRB register image. */ + crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL; + + /* Reset any pending counter overflow or index captures. */ + s626_debi_write(dev, k->my_crb, (crb | S626_SET_CRB_INTRESETCMD(1) | + S626_SET_CRB_INTRESET_B(1))); + + /* Program counter interrupt source. */ + s626_debi_write(dev, k->my_crb, ((crb & ~S626_CRBMSK_INTSRC_B) | + S626_SET_CRB_INTSRC_B(int_source))); + + /* Update MISC2 interrupt enable mask. */ + devpriv->counter_int_enabs = + (devpriv->counter_int_enabs & ~k->my_event_bits[3]) | + k->my_event_bits[int_source]; +} + +static uint16_t s626_get_int_src_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_CRA_INTSRC_A(s626_debi_read(dev, k->my_cra)); +} + +static uint16_t s626_get_int_src_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_CRB_INTSRC_B(s626_debi_read(dev, k->my_crb)); +} + +#ifdef unused +/* + * Return/set the clock multiplier. + */ +static void s626_set_clk_mult(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKMULT) | + S626_SET_STD_CLKMULT(value)), false); +} + +static uint16_t s626_get_clk_mult(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_STD_CLKMULT(k->get_mode(dev, k)); +} + +/* + * Return/set the clock polarity. + */ +static void s626_set_clk_pol(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKPOL) | + S626_SET_STD_CLKPOL(value)), false); +} + +static uint16_t s626_get_clk_pol(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_STD_CLKPOL(k->get_mode(dev, k)); +} + +/* + * Return/set the encoder mode. + */ +static void s626_set_enc_mode(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_ENCMODE) | + S626_SET_STD_ENCMODE(value)), false); +} + +static uint16_t s626_get_enc_mode(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_STD_ENCMODE(k->get_mode(dev, k)); +} + +/* + * Return/set the index polarity. + */ +static void s626_set_index_pol(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXPOL) | + S626_SET_STD_INDXPOL(value != 0)), false); +} + +static uint16_t s626_get_index_pol(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_STD_INDXPOL(k->get_mode(dev, k)); +} + +/* + * Return/set the index source. + */ +static void s626_set_index_src(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXSRC) | + S626_SET_STD_INDXSRC(value != 0)), false); +} + +static uint16_t s626_get_index_src(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return S626_GET_STD_INDXSRC(k->get_mode(dev, k)); +} +#endif + +/* + * Generate an index pulse. + */ +static void s626_pulse_index_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t cra; + + cra = s626_debi_read(dev, k->my_cra); + /* Pulse index. */ + s626_debi_write(dev, k->my_cra, (cra ^ S626_CRAMSK_INDXPOL_A)); + s626_debi_write(dev, k->my_cra, cra); +} + +static void s626_pulse_index_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t crb; + + crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL; + /* Pulse index. */ + s626_debi_write(dev, k->my_crb, (crb ^ S626_CRBMSK_INDXPOL_B)); + s626_debi_write(dev, k->my_crb, crb); +} + +static const struct s626_enc_info s626_enc_chan_info[] = { + { + .get_enable = s626_get_enable_a, + .get_int_src = s626_get_int_src_a, + .get_load_trig = s626_get_load_trig_a, + .get_mode = s626_get_mode_a, + .pulse_index = s626_pulse_index_a, + .set_enable = s626_set_enable_a, + .set_int_src = s626_set_int_src_a, + .set_load_trig = s626_set_load_trig_a, + .set_mode = s626_set_mode_a, + .reset_cap_flags = s626_reset_cap_flags_a, + .my_cra = S626_LP_CR0A, + .my_crb = S626_LP_CR0B, + .my_latch_lsw = S626_LP_CNTR0ALSW, + .my_event_bits = S626_EVBITS(0), + }, { + .get_enable = s626_get_enable_a, + .get_int_src = s626_get_int_src_a, + .get_load_trig = s626_get_load_trig_a, + .get_mode = s626_get_mode_a, + .pulse_index = s626_pulse_index_a, + .set_enable = s626_set_enable_a, + .set_int_src = s626_set_int_src_a, + .set_load_trig = s626_set_load_trig_a, + .set_mode = s626_set_mode_a, + .reset_cap_flags = s626_reset_cap_flags_a, + .my_cra = S626_LP_CR1A, + .my_crb = S626_LP_CR1B, + .my_latch_lsw = S626_LP_CNTR1ALSW, + .my_event_bits = S626_EVBITS(1), + }, { + .get_enable = s626_get_enable_a, + .get_int_src = s626_get_int_src_a, + .get_load_trig = s626_get_load_trig_a, + .get_mode = s626_get_mode_a, + .pulse_index = s626_pulse_index_a, + .set_enable = s626_set_enable_a, + .set_int_src = s626_set_int_src_a, + .set_load_trig = s626_set_load_trig_a, + .set_mode = s626_set_mode_a, + .reset_cap_flags = s626_reset_cap_flags_a, + .my_cra = S626_LP_CR2A, + .my_crb = S626_LP_CR2B, + .my_latch_lsw = S626_LP_CNTR2ALSW, + .my_event_bits = S626_EVBITS(2), + }, { + .get_enable = s626_get_enable_b, + .get_int_src = s626_get_int_src_b, + .get_load_trig = s626_get_load_trig_b, + .get_mode = s626_get_mode_b, + .pulse_index = s626_pulse_index_b, + .set_enable = s626_set_enable_b, + .set_int_src = s626_set_int_src_b, + .set_load_trig = s626_set_load_trig_b, + .set_mode = s626_set_mode_b, + .reset_cap_flags = s626_reset_cap_flags_b, + .my_cra = S626_LP_CR0A, + .my_crb = S626_LP_CR0B, + .my_latch_lsw = S626_LP_CNTR0BLSW, + .my_event_bits = S626_EVBITS(3), + }, { + .get_enable = s626_get_enable_b, + .get_int_src = s626_get_int_src_b, + .get_load_trig = s626_get_load_trig_b, + .get_mode = s626_get_mode_b, + .pulse_index = s626_pulse_index_b, + .set_enable = s626_set_enable_b, + .set_int_src = s626_set_int_src_b, + .set_load_trig = s626_set_load_trig_b, + .set_mode = s626_set_mode_b, + .reset_cap_flags = s626_reset_cap_flags_b, + .my_cra = S626_LP_CR1A, + .my_crb = S626_LP_CR1B, + .my_latch_lsw = S626_LP_CNTR1BLSW, + .my_event_bits = S626_EVBITS(4), + }, { + .get_enable = s626_get_enable_b, + .get_int_src = s626_get_int_src_b, + .get_load_trig = s626_get_load_trig_b, + .get_mode = s626_get_mode_b, + .pulse_index = s626_pulse_index_b, + .set_enable = s626_set_enable_b, + .set_int_src = s626_set_int_src_b, + .set_load_trig = s626_set_load_trig_b, + .set_mode = s626_set_mode_b, + .reset_cap_flags = s626_reset_cap_flags_b, + .my_cra = S626_LP_CR2A, + .my_crb = S626_LP_CR2B, + .my_latch_lsw = S626_LP_CNTR2BLSW, + .my_event_bits = S626_EVBITS(5), + }, +}; + +static unsigned int s626_ai_reg_to_uint(unsigned int data) +{ + return ((data >> 18) & 0x3fff) ^ 0x2000; +} static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan) { @@ -629,19 +1322,19 @@ static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan) unsigned int status; /* set channel to capture positive edge */ - status = DEBIread(dev, LP_RDEDGSEL(group)); - DEBIwrite(dev, LP_WREDGSEL(group), mask | status); + status = s626_debi_read(dev, S626_LP_RDEDGSEL(group)); + s626_debi_write(dev, S626_LP_WREDGSEL(group), mask | status); /* enable interrupt on selected channel */ - status = DEBIread(dev, LP_RDINTSEL(group)); - DEBIwrite(dev, LP_WRINTSEL(group), mask | status); + status = s626_debi_read(dev, S626_LP_RDINTSEL(group)); + s626_debi_write(dev, S626_LP_WRINTSEL(group), mask | status); /* enable edge capture write command */ - DEBIwrite(dev, LP_MISC1, MISC1_EDCAP); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_EDCAP); /* enable edge capture on selected channel */ - status = DEBIread(dev, LP_RDCAPSEL(group)); - DEBIwrite(dev, LP_WRCAPSEL(group), mask | status); + status = s626_debi_read(dev, S626_LP_RDCAPSEL(group)); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask | status); return 0; } @@ -650,10 +1343,10 @@ static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group, unsigned int mask) { /* disable edge capture write command */ - DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP); /* enable edge capture on selected channel */ - DEBIwrite(dev, LP_WRCAPSEL(group), mask); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask); return 0; } @@ -663,17 +1356,17 @@ static int s626_dio_clear_irq(struct comedi_device *dev) unsigned int group; /* disable edge capture write command */ - DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP); /* clear all dio pending events and interrupt */ for (group = 0; group < S626_DIO_BANKS; group++) - DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff); return 0; } -static void handle_dio_interrupt(struct comedi_device *dev, - uint16_t irqbit, uint8_t group) +static void s626_handle_dio_interrupt(struct comedi_device *dev, + uint16_t irqbit, uint8_t group) { struct s626_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; @@ -686,7 +1379,7 @@ static void handle_dio_interrupt(struct comedi_device *dev, if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 && cmd->start_src == TRIG_EXT) { /* Start executing the RPS program */ - s626_mc_enable(dev, MC1_ERPS1, P_MC1); + s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1); if (cmd->scan_begin_src == TRIG_EXT) s626_dio_set_irq(dev, cmd->scan_begin_arg); @@ -694,7 +1387,7 @@ static void handle_dio_interrupt(struct comedi_device *dev, if ((irqbit >> (cmd->scan_begin_arg - (16 * group))) == 1 && cmd->scan_begin_src == TRIG_EXT) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); if (cmd->convert_src == TRIG_EXT) { devpriv->ai_convert_count = cmd->chanlist_len; @@ -703,16 +1396,17 @@ static void handle_dio_interrupt(struct comedi_device *dev, } if (cmd->convert_src == TRIG_TIMER) { - struct enc_private *k = &encpriv[5]; + const struct s626_enc_info *k = + &s626_enc_chan_info[5]; devpriv->ai_convert_count = cmd->chanlist_len; - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); } } if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 && cmd->convert_src == TRIG_EXT) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); devpriv->ai_convert_count--; if (devpriv->ai_convert_count > 0) @@ -721,7 +1415,7 @@ static void handle_dio_interrupt(struct comedi_device *dev, } } -static void check_dio_interrupts(struct comedi_device *dev) +static void s626_check_dio_interrupts(struct comedi_device *dev) { uint16_t irqbit; uint8_t group; @@ -729,90 +1423,91 @@ static void check_dio_interrupts(struct comedi_device *dev) for (group = 0; group < S626_DIO_BANKS; group++) { irqbit = 0; /* read interrupt type */ - irqbit = DEBIread(dev, LP_RDCAPFLG(group)); + irqbit = s626_debi_read(dev, S626_LP_RDCAPFLG(group)); /* check if interrupt is generated from dio channels */ if (irqbit) { - handle_dio_interrupt(dev, irqbit, group); + s626_handle_dio_interrupt(dev, irqbit, group); return; } } } -static void check_counter_interrupts(struct comedi_device *dev) +static void s626_check_counter_interrupts(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - struct enc_private *k; + const struct s626_enc_info *k; uint16_t irqbit; /* read interrupt type */ - irqbit = DEBIread(dev, LP_RDMISC2); + irqbit = s626_debi_read(dev, S626_LP_RDMISC2); /* check interrupt on counters */ - if (irqbit & IRQ_COINT1A) { - k = &encpriv[0]; + if (irqbit & S626_IRQ_COINT1A) { + k = &s626_enc_chan_info[0]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT2A) { - k = &encpriv[1]; + if (irqbit & S626_IRQ_COINT2A) { + k = &s626_enc_chan_info[1]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT3A) { - k = &encpriv[2]; + if (irqbit & S626_IRQ_COINT3A) { + k = &s626_enc_chan_info[2]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT1B) { - k = &encpriv[3]; + if (irqbit & S626_IRQ_COINT1B) { + k = &s626_enc_chan_info[3]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT2B) { - k = &encpriv[4]; + if (irqbit & S626_IRQ_COINT2B) { + k = &s626_enc_chan_info[4]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); if (devpriv->ai_convert_count > 0) { devpriv->ai_convert_count--; if (devpriv->ai_convert_count == 0) - k->SetEnable(dev, k, CLKENAB_INDEX); + k->set_enable(dev, k, S626_CLKENAB_INDEX); if (cmd->convert_src == TRIG_TIMER) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, + S626_P_MC2); } } } - if (irqbit & IRQ_COINT3B) { - k = &encpriv[5]; + if (irqbit & S626_IRQ_COINT3B) { + k = &s626_enc_chan_info[5]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); if (cmd->scan_begin_src == TRIG_TIMER) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); } if (cmd->convert_src == TRIG_TIMER) { - k = &encpriv[4]; + k = &s626_enc_chan_info[4]; devpriv->ai_convert_count = cmd->chanlist_len; - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); } } } -static bool handle_eos_interrupt(struct comedi_device *dev) +static bool s626_handle_eos_interrupt(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; @@ -823,19 +1518,19 @@ static bool handle_eos_interrupt(struct comedi_device *dev) * first uint16_t in the buffer because it contains junk data * from the final ADC of the previous poll list scan. */ - int32_t *readaddr = (int32_t *)devpriv->ANABuf.LogicalBase + 1; + uint32_t *readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1; bool finished = false; int i; /* get the data and hand it over to comedi */ for (i = 0; i < cmd->chanlist_len; i++) { - short tempdata; + unsigned short tempdata; /* * Convert ADC data to 16-bit integer values and copy * to application buffer. */ - tempdata = s626_ai_reg_to_uint((int)*readaddr); + tempdata = s626_ai_reg_to_uint(*readaddr); readaddr++; /* put data into read buffer */ @@ -846,13 +1541,13 @@ static bool handle_eos_interrupt(struct comedi_device *dev) /* end of scan occurs */ async->events |= COMEDI_CB_EOS; - if (!devpriv->ai_continous) + if (!devpriv->ai_continuous) devpriv->ai_sample_count--; if (devpriv->ai_sample_count <= 0) { devpriv->ai_cmd_running = 0; /* Stop RPS program */ - s626_mc_disable(dev, MC1_ERPS1, P_MC1); + s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); /* send end of acquisition */ async->events |= COMEDI_CB_EOA; @@ -879,229 +1574,238 @@ static irqreturn_t s626_irq_handler(int irq, void *d) if (!dev->attached) return IRQ_NONE; - /* lock to avoid race with comedi_poll */ + /* lock to avoid race with comedi_poll */ spin_lock_irqsave(&dev->spinlock, flags); /* save interrupt enable register state */ - irqstatus = readl(devpriv->mmio + P_IER); + irqstatus = readl(devpriv->mmio + S626_P_IER); /* read interrupt type */ - irqtype = readl(devpriv->mmio + P_ISR); + irqtype = readl(devpriv->mmio + S626_P_ISR); /* disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* clear interrupt */ - writel(irqtype, devpriv->mmio + P_ISR); + writel(irqtype, devpriv->mmio + S626_P_ISR); switch (irqtype) { - case IRQ_RPS1: /* end_of_scan occurs */ - if (handle_eos_interrupt(dev)) + case S626_IRQ_RPS1: /* end_of_scan occurs */ + if (s626_handle_eos_interrupt(dev)) irqstatus = 0; break; - case IRQ_GPIO3: /* check dio and conter interrupt */ + case S626_IRQ_GPIO3: /* check dio and counter interrupt */ /* s626_dio_clear_irq(dev); */ - check_dio_interrupts(dev); - check_counter_interrupts(dev); + s626_check_dio_interrupts(dev); + s626_check_counter_interrupts(dev); break; } /* enable interrupt */ - writel(irqstatus, devpriv->mmio + P_IER); + writel(irqstatus, devpriv->mmio + S626_P_IER); spin_unlock_irqrestore(&dev->spinlock, flags); return IRQ_HANDLED; } /* - * this functions build the RPS program for hardware driven acquistion + * This function builds the RPS program for hardware driven acquisition. */ -static void ResetADC(struct comedi_device *dev, uint8_t *ppl) +static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl) { struct s626_private *devpriv = dev->private; - register uint32_t *pRPS; - uint32_t JmpAdrs; + uint32_t *rps; + uint32_t jmp_adrs; uint16_t i; uint16_t n; - uint32_t LocalPPL; - struct comedi_cmd *cmd = &(dev->subdevices->async->cmd); + uint32_t local_ppl; + struct comedi_cmd *cmd = &dev->subdevices->async->cmd; /* Stop RPS program in case it is currently running */ - s626_mc_disable(dev, MC1_ERPS1, P_MC1); + s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); - /* Set starting logical address to write RPS commands. */ - pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase; + /* Set starting logical address to write RPS commands. */ + rps = (uint32_t *)devpriv->rps_buf.logical_base; /* Initialize RPS instruction pointer */ - writel((uint32_t)devpriv->RPSBuf.PhysicalBase, - devpriv->mmio + P_RPSADDR1); - - /* Construct RPS program in RPSBuf DMA buffer */ + writel((uint32_t)devpriv->rps_buf.physical_base, + devpriv->mmio + S626_P_RPSADDR1); + /* Construct RPS program in rps_buf DMA buffer */ if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) { - /* Wait for Start trigger. */ - *pRPS++ = RPS_PAUSE | RPS_SIGADC; - *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; + /* Wait for Start trigger. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC; + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; } - /* SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary + /* + * SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary * because the first RPS DEBI Write following a non-RPS DEBI write * seems to always fail. If we don't do this dummy write, the ADC * gain might not be set to the value required for the first slot in * the poll list; the ADC gain would instead remain unchanged from * the previously programmed value. */ - *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); /* Write DEBI Write command and address to shadow RAM. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2); + *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL; + *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2); + /* Write DEBI immediate data to shadow RAM: */ + *rps++ = S626_GSEL_BIPOLAR5V; /* arbitrary immediate data value. */ + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI; + /* Reset "shadow RAM uploaded" flag. */ + /* Invoke shadow RAM upload. */ + *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI; + /* Wait for shadow upload to finish. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI; - *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; - *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); - /* Write DEBI immediate data to shadow RAM: */ - - *pRPS++ = GSEL_BIPOLAR5V; - /* arbitrary immediate data value. */ - - *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; - /* Reset "shadow RAM uploaded" flag. */ - *pRPS++ = RPS_UPLOAD | RPS_DEBI; /* Invoke shadow RAM upload. */ - *pRPS++ = RPS_PAUSE | RPS_DEBI; /* Wait for shadow upload to finish. */ - - /* Digitize all slots in the poll list. This is implemented as a + /* + * Digitize all slots in the poll list. This is implemented as a * for loop to limit the slot count to 16 in case the application - * forgot to set the EOPL flag in the final slot. + * forgot to set the S626_EOPL flag in the final slot. */ - for (devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++) { - /* Convert application's poll list item to private board class + for (devpriv->adc_items = 0; devpriv->adc_items < 16; + devpriv->adc_items++) { + /* + * Convert application's poll list item to private board class * format. Each app poll list item is an uint8_t with form * (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 = * +-10V, 1 = +-5V, and EOPL = End of Poll List marker. */ - LocalPPL = - (*ppl << 8) | (*ppl & 0x10 ? GSEL_BIPOLAR5V : - GSEL_BIPOLAR10V); - - /* Switch ADC analog gain. */ - *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); /* Write DEBI command */ - /* and address to */ - /* shadow RAM. */ - *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; - *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); /* Write DEBI */ - /* immediate data to */ - /* shadow RAM. */ - *pRPS++ = LocalPPL; - *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; /* Reset "shadow RAM uploaded" */ - /* flag. */ - *pRPS++ = RPS_UPLOAD | RPS_DEBI; /* Invoke shadow RAM upload. */ - *pRPS++ = RPS_PAUSE | RPS_DEBI; /* Wait for shadow upload to */ - /* finish. */ - - /* Select ADC analog input channel. */ - *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); - /* Write DEBI command and address to shadow RAM. */ - *pRPS++ = DEBI_CMD_WRWORD | LP_ISEL; - *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); - /* Write DEBI immediate data to shadow RAM. */ - *pRPS++ = LocalPPL; - *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; - /* Reset "shadow RAM uploaded" flag. */ - - *pRPS++ = RPS_UPLOAD | RPS_DEBI; - /* Invoke shadow RAM upload. */ - - *pRPS++ = RPS_PAUSE | RPS_DEBI; - /* Wait for shadow upload to finish. */ - - /* Delay at least 10 microseconds for analog input settling. - * Instead of padding with NOPs, we use RPS_JUMP instructions - * here; this allows us to produce a longer delay than is - * possible with NOPs because each RPS_JUMP flushes the RPS' - * instruction prefetch pipeline. + local_ppl = (*ppl << 8) | (*ppl & 0x10 ? S626_GSEL_BIPOLAR5V : + S626_GSEL_BIPOLAR10V); + + /* Switch ADC analog gain. */ + /* Write DEBI command and address to shadow RAM. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2); + *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL; + /* Write DEBI immediate data to shadow RAM. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2); + *rps++ = local_ppl; + /* Reset "shadow RAM uploaded" flag. */ + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI; + /* Invoke shadow RAM upload. */ + *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI; + /* Wait for shadow upload to finish. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI; + /* Select ADC analog input channel. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2); + /* Write DEBI command and address to shadow RAM. */ + *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_ISEL; + *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2); + /* Write DEBI immediate data to shadow RAM. */ + *rps++ = local_ppl; + /* Reset "shadow RAM uploaded" flag. */ + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI; + /* Invoke shadow RAM upload. */ + *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI; + /* Wait for shadow upload to finish. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI; + + /* + * Delay at least 10 microseconds for analog input settling. + * Instead of padding with NOPs, we use S626_RPS_JUMP + * instructions here; this allows us to produce a longer delay + * than is possible with NOPs because each S626_RPS_JUMP + * flushes the RPS' instruction prefetch pipeline. */ - JmpAdrs = - (uint32_t) devpriv->RPSBuf.PhysicalBase + - (uint32_t) ((unsigned long)pRPS - - (unsigned long)devpriv->RPSBuf.LogicalBase); - for (i = 0; i < (10 * RPSCLK_PER_US / 2); i++) { - JmpAdrs += 8; /* Repeat to implement time delay: */ - *pRPS++ = RPS_JUMP; /* Jump to next RPS instruction. */ - *pRPS++ = JmpAdrs; + jmp_adrs = + (uint32_t)devpriv->rps_buf.physical_base + + (uint32_t)((unsigned long)rps - + (unsigned long)devpriv-> + rps_buf.logical_base); + for (i = 0; i < (10 * S626_RPSCLK_PER_US / 2); i++) { + jmp_adrs += 8; /* Repeat to implement time delay: */ + /* Jump to next RPS instruction. */ + *rps++ = S626_RPS_JUMP; + *rps++ = jmp_adrs; } if (cmd != NULL && cmd->convert_src != TRIG_NOW) { - /* Wait for Start trigger. */ - *pRPS++ = RPS_PAUSE | RPS_SIGADC; - *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; + /* Wait for Start trigger. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC; + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; } - /* Start ADC by pulsing GPIO1. */ - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* Begin ADC Start pulse. */ - *pRPS++ = GPIO_BASE | GPIO1_LO; - *pRPS++ = RPS_NOP; - /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */ - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* End ADC Start pulse. */ - *pRPS++ = GPIO_BASE | GPIO1_HI; - - /* Wait for ADC to complete (GPIO2 is asserted high when ADC not + /* Start ADC by pulsing GPIO1. */ + /* Begin ADC Start pulse. */ + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); + *rps++ = S626_GPIO_BASE | S626_GPIO1_LO; + *rps++ = S626_RPS_NOP; + /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */ + /* End ADC Start pulse. */ + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); + *rps++ = S626_GPIO_BASE | S626_GPIO1_HI; + /* + * Wait for ADC to complete (GPIO2 is asserted high when ADC not * busy) and for data from previous conversion to shift into FB * BUFFER 1 register. */ - *pRPS++ = RPS_PAUSE | RPS_GPIO2; /* Wait for ADC done. */ - - /* Transfer ADC data from FB BUFFER 1 register to DMA buffer. */ - *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); - *pRPS++ = - (uint32_t) devpriv->ANABuf.PhysicalBase + - (devpriv->AdcItems << 2); - - /* If this slot's EndOfPollList flag is set, all channels have */ - /* now been processed. */ - if (*ppl++ & EOPL) { - devpriv->AdcItems++; /* Adjust poll list item count. */ - break; /* Exit poll list processing loop. */ + /* Wait for ADC done. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2; + + /* Transfer ADC data from FB BUFFER 1 register to DMA buffer. */ + *rps++ = S626_RPS_STREG | + (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2); + *rps++ = (uint32_t)devpriv->ana_buf.physical_base + + (devpriv->adc_items << 2); + + /* + * If this slot's EndOfPollList flag is set, all channels have + * now been processed. + */ + if (*ppl++ & S626_EOPL) { + devpriv->adc_items++; /* Adjust poll list item count. */ + break; /* Exit poll list processing loop. */ } } - /* VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the + /* + * VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the * ADC to stabilize for 2 microseconds before starting the final * (dummy) conversion. This delay is necessary to allow sufficient * time between last conversion finished and the start of the dummy * conversion. Without this delay, the last conversion's data value * is sometimes set to the previous conversion's data value. */ - for (n = 0; n < (2 * RPSCLK_PER_US); n++) - *pRPS++ = RPS_NOP; + for (n = 0; n < (2 * S626_RPSCLK_PER_US); n++) + *rps++ = S626_RPS_NOP; - /* Start a dummy conversion to cause the data from the last + /* + * Start a dummy conversion to cause the data from the last * conversion of interest to be shifted in. */ - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* Begin ADC Start pulse. */ - *pRPS++ = GPIO_BASE | GPIO1_LO; - *pRPS++ = RPS_NOP; + /* Begin ADC Start pulse. */ + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); + *rps++ = S626_GPIO_BASE | S626_GPIO1_LO; + *rps++ = S626_RPS_NOP; /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */ - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* End ADC Start pulse. */ - *pRPS++ = GPIO_BASE | GPIO1_HI; + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); /* End ADC Start pulse. */ + *rps++ = S626_GPIO_BASE | S626_GPIO1_HI; - /* Wait for the data from the last conversion of interest to arrive + /* + * Wait for the data from the last conversion of interest to arrive * in FB BUFFER 1 register. */ - *pRPS++ = RPS_PAUSE | RPS_GPIO2; /* Wait for ADC done. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2; /* Wait for ADC done. */ - /* Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */ - *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); /* */ - *pRPS++ = - (uint32_t) devpriv->ANABuf.PhysicalBase + (devpriv->AdcItems << 2); + /* Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */ + *rps++ = S626_RPS_STREG | (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2); + *rps++ = (uint32_t)devpriv->ana_buf.physical_base + + (devpriv->adc_items << 2); - /* Indicate ADC scan loop is finished. */ - /* *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ; // Signal ReadADC() that scan is done. */ + /* Indicate ADC scan loop is finished. */ + /* Signal ReadADC() that scan is done. */ + /* *rps++= S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; */ /* invoke interrupt */ - if (devpriv->ai_cmd_running == 1) { - *pRPS++ = RPS_IRQ; - } - /* Restart RPS program at its beginning. */ - *pRPS++ = RPS_JUMP; /* Branch to start of RPS program. */ - *pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase; + if (devpriv->ai_cmd_running == 1) + *rps++ = S626_RPS_IRQ; + + /* Restart RPS program at its beginning. */ + *rps++ = S626_RPS_JUMP; /* Branch to start of RPS program. */ + *rps++ = (uint32_t)devpriv->rps_buf.physical_base; - /* End of RPS program build */ + /* End of RPS program build */ } #ifdef unused_code @@ -1111,14 +1815,14 @@ static int s626_ai_rinsn(struct comedi_device *dev, unsigned int *data) { struct s626_private *devpriv = dev->private; - register uint8_t i; - register int32_t *readaddr; + uint8_t i; + int32_t *readaddr; /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); /* Wait until ADC scan loop is finished (RPS Signal 0 reset) */ - while (s626_mc_test(dev, MC2_ADC_RPS, P_MC2)) + while (s626_mc_test(dev, S626_MC2_ADC_RPS, S626_P_MC2)) ; /* @@ -1126,13 +1830,13 @@ static int s626_ai_rinsn(struct comedi_device *dev, * first uint16_t in the buffer because it contains junk data from * the final ADC of the previous poll list scan. */ - readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; + readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1; /* * Convert ADC data to 16-bit integer values and * copy to application buffer. */ - for (i = 0; i < devpriv->AdcItems; i++) { + for (i = 0; i < devpriv->adc_items; i++) { *data = s626_ai_reg_to_uint(*readaddr++); data++; } @@ -1148,55 +1852,61 @@ static int s626_ai_insn_read(struct comedi_device *dev, struct s626_private *devpriv = dev->private; uint16_t chan = CR_CHAN(insn->chanspec); uint16_t range = CR_RANGE(insn->chanspec); - uint16_t AdcSpec = 0; - uint32_t GpioImage; - int tmp; + uint16_t adc_spec = 0; + uint32_t gpio_image; + uint32_t tmp; int n; - /* Convert application's ADC specification into form + /* + * Convert application's ADC specification into form * appropriate for register programming. */ if (range == 0) - AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V); + adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR5V); else - AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V); + adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR10V); - /* Switch ADC analog gain. */ - DEBIwrite(dev, LP_GSEL, AdcSpec); /* Set gain. */ + /* Switch ADC analog gain. */ + s626_debi_write(dev, S626_LP_GSEL, adc_spec); /* Set gain. */ - /* Select ADC analog input channel. */ - DEBIwrite(dev, LP_ISEL, AdcSpec); /* Select channel. */ + /* Select ADC analog input channel. */ + s626_debi_write(dev, S626_LP_ISEL, adc_spec); /* Select channel. */ for (n = 0; n < insn->n; n++) { - - /* Delay 10 microseconds for analog input settling. */ + /* Delay 10 microseconds for analog input settling. */ udelay(10); /* Start ADC by pulsing GPIO1 low */ - GpioImage = readl(devpriv->mmio + P_GPIO); + gpio_image = readl(devpriv->mmio + S626_P_GPIO); /* Assert ADC Start command */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, + devpriv->mmio + S626_P_GPIO); /* and stretch it out */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, + devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, + devpriv->mmio + S626_P_GPIO); /* Negate ADC Start command */ - writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); - /* Wait for ADC to complete (GPIO2 is asserted high when */ - /* ADC not busy) and for data from previous conversion to */ - /* shift into FB BUFFER 1 register. */ + /* + * Wait for ADC to complete (GPIO2 is asserted high when + * ADC not busy) and for data from previous conversion to + * shift into FB BUFFER 1 register. + */ /* Wait for ADC done */ - while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2)) + while (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_GPIO2)) ; /* Fetch ADC data */ if (n != 0) { - tmp = readl(devpriv->mmio + P_FB_BUFFER1); + tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1); data[n - 1] = s626_ai_reg_to_uint(tmp); } - /* Allow the ADC to stabilize for 4 microseconds before + /* + * Allow the ADC to stabilize for 4 microseconds before * starting the next (final) conversion. This delay is * necessary to allow sufficient time between last * conversion finished and the start of the next @@ -1207,28 +1917,30 @@ static int s626_ai_insn_read(struct comedi_device *dev, udelay(4); } - /* Start a dummy conversion to cause the data from the - * previous conversion to be shifted in. */ - GpioImage = readl(devpriv->mmio + P_GPIO); + /* + * Start a dummy conversion to cause the data from the + * previous conversion to be shifted in. + */ + gpio_image = readl(devpriv->mmio + S626_P_GPIO); /* Assert ADC Start command */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); /* and stretch it out */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); /* Negate ADC Start command */ - writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); - /* Wait for the data to arrive in FB BUFFER 1 register. */ + /* Wait for the data to arrive in FB BUFFER 1 register. */ /* Wait for ADC done */ - while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2)) + while (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_GPIO2)) ; - /* Fetch ADC data from audio interface's input shift register. */ + /* Fetch ADC data from audio interface's input shift register. */ /* Fetch ADC data */ if (n != 0) { - tmp = readl(devpriv->mmio + P_FB_BUFFER1); + tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1); data[n - 1] = s626_ai_reg_to_uint(tmp); } @@ -1237,17 +1949,16 @@ static int s626_ai_insn_read(struct comedi_device *dev, static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd) { - int n; for (n = 0; n < cmd->chanlist_len; n++) { - if (CR_RANGE((cmd->chanlist)[n]) == 0) - ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_5V); + if (CR_RANGE(cmd->chanlist[n]) == 0) + ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_5V; else - ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_10V); + ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_10V; } if (n != 0) - ppl[n - 1] |= EOPL; + ppl[n - 1] |= S626_EOPL; return n; } @@ -1259,18 +1970,20 @@ static int s626_ai_inttrig(struct comedi_device *dev, return -EINVAL; /* Start executing the RPS program */ - s626_mc_enable(dev, MC1_ERPS1, P_MC1); + s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1); s->async->inttrig = NULL; return 1; } -/* This function doesn't require a particular form, this is just what +/* + * This function doesn't require a particular form, this is just what * happens to be used in some of the drivers. It should convert ns * nanoseconds to a counter value suitable for programming the device. * Also, it should adjust ns so that it cooresponds to the actual time - * that the device will use. */ + * that the device will use. + */ static int s626_ns_to_timer(int *nanosec, int round_mode) { int divider, base; @@ -1294,68 +2007,75 @@ static int s626_ns_to_timer(int *nanosec, int round_mode) return divider - 1; } -static void s626_timer_load(struct comedi_device *dev, struct enc_private *k, - int tick) +static void s626_timer_load(struct comedi_device *dev, + const struct s626_enc_info *k, int tick) { - uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /* Preload upon */ - /* index. */ - (INDXSRC_SOFT << BF_INDXSRC) | /* Disable hardware index. */ - (CLKSRC_TIMER << BF_CLKSRC) | /* Operating mode is Timer. */ - (CLKPOL_POS << BF_CLKPOL) | /* Active high clock. */ - (CNTDIR_DOWN << BF_CLKPOL) | /* Count direction is Down. */ - (CLKMULT_1X << BF_CLKMULT) | /* Clock multiplier is 1x. */ - (CLKENAB_INDEX << BF_CLKENAB); - uint16_t valueSrclatch = LATCHSRC_A_INDXA; - /* uint16_t enab=CLKENAB_ALWAYS; */ + uint16_t setup = + /* Preload upon index. */ + S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) | + /* Disable hardware index. */ + S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) | + /* Operating mode is Timer. */ + S626_SET_STD_ENCMODE(S626_ENCMODE_TIMER) | + /* Count direction is Down. */ + S626_SET_STD_CLKPOL(S626_CNTDIR_DOWN) | + /* Clock multiplier is 1x. */ + S626_SET_STD_CLKMULT(S626_CLKMULT_1X) | + /* Enabled by index */ + S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX); + uint16_t value_latchsrc = S626_LATCHSRC_A_INDXA; + /* uint16_t enab = S626_CLKENAB_ALWAYS; */ - k->SetMode(dev, k, Setup, FALSE); + k->set_mode(dev, k, setup, false); - /* Set the preload register */ - Preload(dev, k, tick); + /* Set the preload register */ + s626_preload(dev, k, tick); - /* Software index pulse forces the preload register to load */ - /* into the counter */ - k->SetLoadTrig(dev, k, 0); - k->PulseIndex(dev, k); + /* + * Software index pulse forces the preload register to load + * into the counter + */ + k->set_load_trig(dev, k, 0); + k->pulse_index(dev, k); /* set reload on counter overflow */ - k->SetLoadTrig(dev, k, 1); + k->set_load_trig(dev, k, 1); /* set interrupt on overflow */ - k->SetIntSrc(dev, k, INTSRC_OVER); + k->set_int_src(dev, k, S626_INTSRC_OVER); - SetLatchSource(dev, k, valueSrclatch); - /* k->SetEnable(dev,k,(uint16_t)(enab != 0)); */ + s626_set_latch_source(dev, k, value_latchsrc); + /* k->set_enable(dev, k, (uint16_t)(enab != 0)); */ } -/* TO COMPLETE */ +/* TO COMPLETE */ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct s626_private *devpriv = dev->private; uint8_t ppl[16]; struct comedi_cmd *cmd = &s->async->cmd; - struct enc_private *k; + const struct s626_enc_info *k; int tick; if (devpriv->ai_cmd_running) { - printk(KERN_ERR "s626_ai_cmd: Another ai_cmd is running %d\n", - dev->minor); + dev_err(dev->class_dev, + "s626_ai_cmd: Another ai_cmd is running\n"); return -EBUSY; } /* disable interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* clear interrupt request */ - writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->mmio + P_ISR); + writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, devpriv->mmio + S626_P_ISR); /* clear any pending interrupt */ s626_dio_clear_irq(dev); - /* s626_enc_clear_irq(dev); */ + /* s626_enc_clear_irq(dev); */ /* reset ai_cmd_running flag */ devpriv->ai_cmd_running = 0; - /* test if cmd is valid */ + /* test if cmd is valid */ if (cmd == NULL) return -EINVAL; @@ -1373,17 +2093,20 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case TRIG_FOLLOW: break; case TRIG_TIMER: - /* set a conter to generate adc trigger at scan_begin_arg interval */ - k = &encpriv[5]; + /* + * set a counter to generate adc trigger at scan_begin_arg + * interval + */ + k = &s626_enc_chan_info[5]; tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); /* load timer value and enable interrupt */ s626_timer_load(dev, k, tick); - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); break; case TRIG_EXT: - /* set the digital line and interrupt for scan trigger */ + /* set the digital line and interrupt for scan trigger */ if (cmd->start_src != TRIG_EXT) s626_dio_set_irq(dev, cmd->scan_begin_arg); break; @@ -1393,52 +2116,53 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case TRIG_NOW: break; case TRIG_TIMER: - /* set a conter to generate adc trigger at convert_arg interval */ - k = &encpriv[4]; + /* + * set a counter to generate adc trigger at convert_arg + * interval + */ + k = &s626_enc_chan_info[4]; tick = s626_ns_to_timer((int *)&cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); /* load timer value and enable interrupt */ s626_timer_load(dev, k, tick); - k->SetEnable(dev, k, CLKENAB_INDEX); + k->set_enable(dev, k, S626_CLKENAB_INDEX); break; case TRIG_EXT: - /* set the digital line and interrupt for convert trigger */ - if (cmd->scan_begin_src != TRIG_EXT - && cmd->start_src == TRIG_EXT) + /* set the digital line and interrupt for convert trigger */ + if (cmd->scan_begin_src != TRIG_EXT && + cmd->start_src == TRIG_EXT) s626_dio_set_irq(dev, cmd->convert_arg); break; } switch (cmd->stop_src) { case TRIG_COUNT: - /* data arrives as one packet */ + /* data arrives as one packet */ devpriv->ai_sample_count = cmd->stop_arg; - devpriv->ai_continous = 0; + devpriv->ai_continuous = 0; break; case TRIG_NONE: - /* continous acquisition */ - devpriv->ai_continous = 1; + /* continuous acquisition */ + devpriv->ai_continuous = 1; devpriv->ai_sample_count = 1; break; } - ResetADC(dev, ppl); + s626_reset_adc(dev, ppl); switch (cmd->start_src) { case TRIG_NOW: /* Trigger ADC scan loop start */ - /* s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); */ + /* s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); */ /* Start executing the RPS program */ - s626_mc_enable(dev, MC1_ERPS1, P_MC1); - + s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1); s->async->inttrig = NULL; break; case TRIG_EXT: /* configure DIO channel for acquisition trigger */ s626_dio_set_irq(dev, cmd->start_arg); - s->async->inttrig = NULL; break; case TRIG_INT: @@ -1447,7 +2171,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* enable interrupt */ - writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->mmio + P_IER); + writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, devpriv->mmio + S626_P_IER); return 0; } @@ -1461,11 +2185,11 @@ static int s626_ai_cmdtest(struct comedi_device *dev, /* Step 1 : check if triggers are trivially valid */ err |= cfc_check_trigger_src(&cmd->start_src, - TRIG_NOW | TRIG_INT | TRIG_EXT); + TRIG_NOW | TRIG_INT | TRIG_EXT); err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW); + TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW); err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_EXT | TRIG_NOW); + TRIG_TIMER | TRIG_EXT | TRIG_NOW); err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); @@ -1490,34 +2214,34 @@ static int s626_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); if (cmd->start_src == TRIG_EXT) err |= cfc_check_trigger_arg_max(&cmd->start_arg, 39); - if (cmd->scan_begin_src == TRIG_EXT) err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 39); - if (cmd->convert_src == TRIG_EXT) err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 39); -#define MAX_SPEED 200000 /* in nanoseconds */ -#define MIN_SPEED 2000000000 /* in nanoseconds */ +#define S626_MAX_SPEED 200000 /* in nanoseconds */ +#define S626_MIN_SPEED 2000000000 /* in nanoseconds */ if (cmd->scan_begin_src == TRIG_TIMER) { err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, - MAX_SPEED); + S626_MAX_SPEED); err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, - MIN_SPEED); + S626_MIN_SPEED); } else { /* external trigger */ /* should be level/edge, hi/lo specification here */ /* should specify multiple external triggers */ -/* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ + /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ } if (cmd->convert_src == TRIG_TIMER) { - err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED); - err |= cfc_check_trigger_arg_max(&cmd->convert_arg, MIN_SPEED); + err |= cfc_check_trigger_arg_min(&cmd->convert_arg, + S626_MAX_SPEED); + err |= cfc_check_trigger_arg_max(&cmd->convert_arg, + S626_MIN_SPEED); } else { /* external trigger */ /* see above */ -/* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ + /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ } err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); @@ -1546,10 +2270,10 @@ static int s626_ai_cmdtest(struct comedi_device *dev, if (tmp != cmd->convert_arg) err++; if (cmd->scan_begin_src == TRIG_TIMER && - cmd->scan_begin_arg < - cmd->convert_arg * cmd->scan_end_arg) { - cmd->scan_begin_arg = - cmd->convert_arg * cmd->scan_end_arg; + cmd->scan_begin_arg < cmd->convert_arg * + cmd->scan_end_arg) { + cmd->scan_begin_arg = cmd->convert_arg * + cmd->scan_end_arg; err++; } } @@ -1565,10 +2289,10 @@ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) struct s626_private *devpriv = dev->private; /* Stop RPS program in case it is currently running */ - s626_mc_disable(dev, MC1_ERPS1, P_MC1); + s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); /* disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); devpriv->ai_cmd_running = 0; @@ -1588,7 +2312,7 @@ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[i]; dacdata -= (0x1fff); - SetDAC(dev, chan, dacdata); + s626_set_dac(dev, chan, dacdata); } return i; @@ -1606,7 +2330,9 @@ static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return i; } -/* *************** DIGITAL I/O FUNCTIONS *************** +/* *************** DIGITAL I/O FUNCTIONS *************** */ + +/* * All DIO functions address a group of DIO channels by means of * "group" argument. group may be 0, 1 or 2, which correspond to DIO * ports A, B and C, respectively. @@ -1616,19 +2342,19 @@ static void s626_dio_init(struct comedi_device *dev) { uint16_t group; - /* Prepare to treat writes to WRCapSel as capture disables. */ - DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); + /* Prepare to treat writes to WRCapSel as capture disables. */ + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP); - /* For each group of sixteen channels ... */ + /* For each group of sixteen channels ... */ for (group = 0; group < S626_DIO_BANKS; group++) { /* Disable all interrupts */ - DEBIwrite(dev, LP_WRINTSEL(group), 0); + s626_debi_write(dev, S626_LP_WRINTSEL(group), 0); /* Disable all event captures */ - DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff); /* Init all DIOs to default edge polarity */ - DEBIwrite(dev, LP_WREDGSEL(group), 0); + s626_debi_write(dev, S626_LP_WREDGSEL(group), 0); /* Program all outputs to inactive state */ - DEBIwrite(dev, LP_WRDOUT(group), 0); + s626_debi_write(dev, S626_LP_WRDOUT(group), 0); } } @@ -1638,20 +2364,11 @@ static int s626_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { unsigned long group = (unsigned long)s->private; - unsigned long mask = data[0]; - unsigned long bits = data[1]; - if (mask) { - /* Check if requested channels are configured for output */ - if ((s->io_bits & mask) != mask) - return -EIO; + if (comedi_dio_update_state(s, data)) + s626_debi_write(dev, S626_LP_WRDOUT(group), s->state); - s->state &= ~mask; - s->state |= (bits & mask); - - DEBIwrite(dev, LP_WRDOUT(group), s->state); - } - data[1] = DEBIread(dev, LP_RDDIN(group)); + data[1] = s626_debi_read(dev, S626_LP_RDDIN(group)); return insn->n; } @@ -1668,42 +2385,51 @@ static int s626_dio_insn_config(struct comedi_device *dev, if (ret) return ret; - DEBIwrite(dev, LP_WRDOUT(group), s->io_bits); + s626_debi_write(dev, S626_LP_WRDOUT(group), s->io_bits); return insn->n; } -/* Now this function initializes the value of the counter (data[0]) - and set the subdevice. To complete with trigger and interrupt - configuration */ -/* FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating +/* + * Now this function initializes the value of the counter (data[0]) + * and set the subdevice. To complete with trigger and interrupt + * configuration. + * + * FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating * what is being configured, but this function appears to be using data[0] - * as a variable. */ + * as a variable. + */ static int s626_enc_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /* Preload upon */ - /* index. */ - (INDXSRC_SOFT << BF_INDXSRC) | /* Disable hardware index. */ - (CLKSRC_COUNTER << BF_CLKSRC) | /* Operating mode is Counter. */ - (CLKPOL_POS << BF_CLKPOL) | /* Active high clock. */ - /* ( CNTDIR_UP << BF_CLKPOL ) | // Count direction is Down. */ - (CLKMULT_1X << BF_CLKMULT) | /* Clock multiplier is 1x. */ - (CLKENAB_INDEX << BF_CLKENAB); - /* uint16_t DisableIntSrc=TRUE; */ - /* uint32_t Preloadvalue; //Counter initial value */ - uint16_t valueSrclatch = LATCHSRC_AB_READ; - uint16_t enab = CLKENAB_ALWAYS; - struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; - - /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ - - k->SetMode(dev, k, Setup, TRUE); - Preload(dev, k, data[0]); - k->PulseIndex(dev, k); - SetLatchSource(dev, k, valueSrclatch); - k->SetEnable(dev, k, (uint16_t) (enab != 0)); + uint16_t setup = + /* Preload upon index. */ + S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) | + /* Disable hardware index. */ + S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) | + /* Operating mode is Counter. */ + S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) | + /* Active high clock. */ + S626_SET_STD_CLKPOL(S626_CLKPOL_POS) | + /* Clock multiplier is 1x. */ + S626_SET_STD_CLKMULT(S626_CLKMULT_1X) | + /* Enabled by index */ + S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX); + /* uint16_t disable_int_src = true; */ + /* uint32_t Preloadvalue; //Counter initial value */ + uint16_t value_latchsrc = S626_LATCHSRC_AB_READ; + uint16_t enab = S626_CLKENAB_ALWAYS; + const struct s626_enc_info *k = + &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; + + /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ + + k->set_mode(dev, k, setup, true); + s626_preload(dev, k, data[0]); + k->pulse_index(dev, k); + s626_set_latch_source(dev, k, value_latchsrc); + k->set_enable(dev, k, (enab != 0)); return insn->n; } @@ -1712,12 +2438,12 @@ static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - int n; - struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; + const struct s626_enc_info *k = + &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; for (n = 0; n < insn->n; n++) - data[n] = ReadLatch(dev, k); + data[n] = s626_read_latch(dev, k); return n; } @@ -1726,31 +2452,32 @@ static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct s626_enc_info *k = + &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; - struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; + /* Set the preload register */ + s626_preload(dev, k, data[0]); - /* Set the preload register */ - Preload(dev, k, data[0]); - - /* Software index pulse forces the preload register to load */ - /* into the counter */ - k->SetLoadTrig(dev, k, 0); - k->PulseIndex(dev, k); - k->SetLoadTrig(dev, k, 2); + /* + * Software index pulse forces the preload register to load + * into the counter + */ + k->set_load_trig(dev, k, 0); + k->pulse_index(dev, k); + k->set_load_trig(dev, k, 2); return 1; } -static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage) +static void s626_write_misc2(struct comedi_device *dev, uint16_t new_image) { - DEBIwrite(dev, LP_MISC1, MISC1_WENABLE); /* enab writes to */ - /* MISC2 register. */ - DEBIwrite(dev, LP_WRMISC2, NewImage); /* Write new image to MISC2. */ - DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE); /* Disable writes to MISC2. */ + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WENABLE); + s626_debi_write(dev, S626_LP_WRMISC2, new_image); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WDISABLE); } -static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, - size_t bsize) +static void s626_close_dma_b(struct comedi_device *dev, + struct s626_buffer_dma *pdma, size_t bsize) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); void *vbptr; @@ -1758,554 +2485,44 @@ static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, if (pdma == NULL) return; - /* find the matching allocation from the board struct */ - vbptr = pdma->LogicalBase; - vpptr = pdma->PhysicalBase; + /* find the matching allocation from the board struct */ + vbptr = pdma->logical_base; + vpptr = pdma->physical_base; if (vbptr) { pci_free_consistent(pcidev, bsize, vbptr, vpptr); - pdma->LogicalBase = NULL; - pdma->PhysicalBase = 0; - } -} - -/* ****** PRIVATE COUNTER FUNCTIONS ****** */ - -/* Reset a counter's index and overflow event capture flags. */ - -static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k) -{ - DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, - CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); -} - -static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k) -{ - DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, - CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B); -} - -/* Return counter setup in a format (COUNTER_SETUP) that is consistent */ -/* for both A and B counters. */ - -static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k) -{ - register uint16_t cra; - register uint16_t crb; - register uint16_t setup; - - /* Fetch CRA and CRB register images. */ - cra = DEBIread(dev, k->MyCRA); - crb = DEBIread(dev, k->MyCRB); - - /* Populate the standardized counter setup bit fields. Note: */ - /* IndexSrc is restricted to ENC_X or IndxPol. */ - setup = ((cra & STDMSK_LOADSRC) /* LoadSrc = LoadSrcA. */ - |((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) /* LatchSrc = LatchSrcA. */ - |((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC) /* IntSrc = IntSrcA. */ - |((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC) /* IndxSrc = IndxSrcA<1>. */ - |((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL) /* IndxPol = IndxPolA. */ - |((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB)); /* ClkEnab = ClkEnabA. */ - - /* Adjust mode-dependent parameters. */ - if (cra & (2 << CRABIT_CLKSRC_A)) /* If Timer mode (ClkSrcA<1> == 1): */ - setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) /* Indicate Timer mode. */ - |((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL) /* Set ClkPol to indicate count direction (ClkSrcA<0>). */ - |(MULT_X1 << STDBIT_CLKMULT)); /* ClkMult must be 1x in Timer mode. */ - - else /* If Counter mode (ClkSrcA<1> == 0): */ - setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) /* Indicate Counter mode. */ - |((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL) /* Pass through ClkPol. */ - |(((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ? /* Force ClkMult to 1x if not legal, else pass through. */ - (MULT_X1 << STDBIT_CLKMULT) : - ((cra >> (CRABIT_CLKMULT_A - - STDBIT_CLKMULT)) & STDMSK_CLKMULT))); - - /* Return adjusted counter setup. */ - return setup; -} - -static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k) -{ - register uint16_t cra; - register uint16_t crb; - register uint16_t setup; - - /* Fetch CRA and CRB register images. */ - cra = DEBIread(dev, k->MyCRA); - crb = DEBIread(dev, k->MyCRB); - - /* Populate the standardized counter setup bit fields. Note: */ - /* IndexSrc is restricted to ENC_X or IndxPol. */ - setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC) /* IntSrc = IntSrcB. */ - |((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) /* LatchSrc = LatchSrcB. */ - |((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC) /* LoadSrc = LoadSrcB. */ - |((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL) /* IndxPol = IndxPolB. */ - |((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB) /* ClkEnab = ClkEnabB. */ - |((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC)); /* IndxSrc = IndxSrcB<1>. */ - - /* Adjust mode-dependent parameters. */ - if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B)) /* If Extender mode (ClkMultB == MULT_X0): */ - setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC) /* Indicate Extender mode. */ - |(MULT_X1 << STDBIT_CLKMULT) /* Indicate multiplier is 1x. */ - |((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); /* Set ClkPol equal to Timer count direction (ClkSrcB<0>). */ - - else if (cra & (2 << CRABIT_CLKSRC_B)) /* If Timer mode (ClkSrcB<1> == 1): */ - setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) /* Indicate Timer mode. */ - |(MULT_X1 << STDBIT_CLKMULT) /* Indicate multiplier is 1x. */ - |((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); /* Set ClkPol equal to Timer count direction (ClkSrcB<0>). */ - - else /* If Counter mode (ClkSrcB<1> == 0): */ - setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) /* Indicate Timer mode. */ - |((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT) /* Clock multiplier is passed through. */ - |((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL)); /* Clock polarity is passed through. */ - - /* Return adjusted counter setup. */ - return setup; -} - -/* - * Set the operating mode for the specified counter. The setup - * parameter is treated as a COUNTER_SETUP data type. The following - * parameters are programmable (all other parms are ignored): ClkMult, - * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc. - */ - -static void SetMode_A(struct comedi_device *dev, struct enc_private *k, - uint16_t Setup, uint16_t DisableIntSrc) -{ - struct s626_private *devpriv = dev->private; - register uint16_t cra; - register uint16_t crb; - register uint16_t setup = Setup; /* Cache the Standard Setup. */ - - /* Initialize CRA and CRB images. */ - cra = ((setup & CRAMSK_LOADSRC_A) /* Preload trigger is passed through. */ - |((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1)))); /* IndexSrc is restricted to ENC_X or IndxPol. */ - - crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A /* Reset any pending CounterA event captures. */ - | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB))); /* Clock enable is passed through. */ - - /* Force IntSrc to Disabled if DisableIntSrc is asserted. */ - if (!DisableIntSrc) - cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - - CRABIT_INTSRC_A)); - - /* Populate all mode-dependent attributes of CRA & CRB images. */ - switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) { - case CLKSRC_EXTENDER: /* Extender Mode: Force to Timer mode */ - /* (Extender valid only for B counters). */ - - case CLKSRC_TIMER: /* Timer Mode: */ - cra |= ((2 << CRABIT_CLKSRC_A) /* ClkSrcA<1> selects system clock */ - |((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) /* with count direction (ClkSrcA<0>) obtained from ClkPol. */ - |(1 << CRABIT_CLKPOL_A) /* ClkPolA behaves as always-on clock enable. */ - |(MULT_X1 << CRABIT_CLKMULT_A)); /* ClkMult must be 1x. */ - break; - - default: /* Counter Mode: */ - cra |= (CLKSRC_COUNTER /* Select ENC_C and ENC_D as clock/direction inputs. */ - | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) /* Clock polarity is passed through. */ - |(((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? /* Force multiplier to x1 if not legal, otherwise pass through. */ - (MULT_X1 << CRABIT_CLKMULT_A) : - ((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A - - STDBIT_CLKMULT)))); + pdma->logical_base = NULL; + pdma->physical_base = 0; } - - /* Force positive index polarity if IndxSrc is software-driven only, */ - /* otherwise pass it through. */ - if (~setup & STDMSK_INDXSRC) - cra |= ((setup & STDMSK_INDXPOL) << (CRABIT_INDXPOL_A - - STDBIT_INDXPOL)); - - /* If IntSrc has been forced to Disabled, update the MISC2 interrupt */ - /* enable mask to indicate the counter interrupt is disabled. */ - if (DisableIntSrc) - devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; - - /* While retaining CounterB and LatchSrc configurations, program the */ - /* new counter operating mode. */ - DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra); - DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), crb); -} - -static void SetMode_B(struct comedi_device *dev, struct enc_private *k, - uint16_t Setup, uint16_t DisableIntSrc) -{ - struct s626_private *devpriv = dev->private; - register uint16_t cra; - register uint16_t crb; - register uint16_t setup = Setup; /* Cache the Standard Setup. */ - - /* Initialize CRA and CRB images. */ - cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)); /* IndexSrc field is restricted to ENC_X or IndxPol. */ - - crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B /* Reset event captures and disable interrupts. */ - | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) /* Clock enable is passed through. */ - |((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B))); /* Preload trigger source is passed through. */ - - /* Force IntSrc to Disabled if DisableIntSrc is asserted. */ - if (!DisableIntSrc) - crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - - CRBBIT_INTSRC_B)); - - /* Populate all mode-dependent attributes of CRA & CRB images. */ - switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) { - case CLKSRC_TIMER: /* Timer Mode: */ - cra |= ((2 << CRABIT_CLKSRC_B) /* ClkSrcB<1> selects system clock */ - |((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); /* with direction (ClkSrcB<0>) obtained from ClkPol. */ - crb |= ((1 << CRBBIT_CLKPOL_B) /* ClkPolB behaves as always-on clock enable. */ - |(MULT_X1 << CRBBIT_CLKMULT_B)); /* ClkMultB must be 1x. */ - break; - - case CLKSRC_EXTENDER: /* Extender Mode: */ - cra |= ((2 << CRABIT_CLKSRC_B) /* ClkSrcB source is OverflowA (same as "timer") */ - |((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); /* with direction obtained from ClkPol. */ - crb |= ((1 << CRBBIT_CLKPOL_B) /* ClkPolB controls IndexB -- always set to active. */ - |(MULT_X0 << CRBBIT_CLKMULT_B)); /* ClkMultB selects OverflowA as the clock source. */ - break; - - default: /* Counter Mode: */ - cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B); /* Select ENC_C and ENC_D as clock/direction inputs. */ - crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) /* ClkPol is passed through. */ - |(((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? /* Force ClkMult to x1 if not legal, otherwise pass through. */ - (MULT_X1 << CRBBIT_CLKMULT_B) : - ((setup & STDMSK_CLKMULT) << (CRBBIT_CLKMULT_B - - STDBIT_CLKMULT)))); - } - - /* Force positive index polarity if IndxSrc is software-driven only, */ - /* otherwise pass it through. */ - if (~setup & STDMSK_INDXSRC) - crb |= ((setup & STDMSK_INDXPOL) >> (STDBIT_INDXPOL - - CRBBIT_INDXPOL_B)); - - /* If IntSrc has been forced to Disabled, update the MISC2 interrupt */ - /* enable mask to indicate the counter interrupt is disabled. */ - if (DisableIntSrc) - devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; - - /* While retaining CounterA and LatchSrc configurations, program the */ - /* new counter operating mode. */ - DEBIreplace(dev, k->MyCRA, ~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B), cra); - DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb); -} - -/* Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index. */ - -static void SetEnable_A(struct comedi_device *dev, struct enc_private *k, - uint16_t enab) -{ - DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), - enab << CRBBIT_CLKENAB_A); -} - -static void SetEnable_B(struct comedi_device *dev, struct enc_private *k, - uint16_t enab) -{ - DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B), - enab << CRBBIT_CLKENAB_B); -} - -static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1; -} - -static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1; -} - -/* - * static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k ) - * { - * return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3; - * } - */ - -/* - * Return/set the event that will trigger transfer of the preload - * register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, - * 2=OverflowA (B counters only), 3=disabled. - */ - -static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k, - uint16_t Trig) -{ - DEBIreplace(dev, k->MyCRA, ~CRAMSK_LOADSRC_A, - Trig << CRABIT_LOADSRC_A); -} - -static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k, - uint16_t Trig) -{ - DEBIreplace(dev, k->MyCRB, ~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL), - Trig << CRBBIT_LOADSRC_B); -} - -static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3; -} - -static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3; -} - -/* Return/set counter interrupt source and clear any captured - * index/overflow events. IntSource: 0=Disabled, 1=OverflowOnly, - * 2=IndexOnly, 3=IndexAndOverflow. - */ - -static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k, - uint16_t IntSource) -{ - struct s626_private *devpriv = dev->private; - - /* Reset any pending counter overflow or index captures. */ - DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, - CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); - - /* Program counter interrupt source. */ - DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A, - IntSource << CRABIT_INTSRC_A); - - /* Update MISC2 interrupt enable mask. */ - devpriv->CounterIntEnabs = - (devpriv->CounterIntEnabs & ~k-> - MyEventBits[3]) | k->MyEventBits[IntSource]; -} - -static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k, - uint16_t IntSource) -{ - struct s626_private *devpriv = dev->private; - uint16_t crb; - - /* Cache writeable CRB register image. */ - crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; - - /* Reset any pending counter overflow or index captures. */ - DEBIwrite(dev, k->MyCRB, - (uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B)); - - /* Program counter interrupt source. */ - DEBIwrite(dev, k->MyCRB, - (uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource << - CRBBIT_INTSRC_B))); - - /* Update MISC2 interrupt enable mask. */ - devpriv->CounterIntEnabs = - (devpriv->CounterIntEnabs & ~k-> - MyEventBits[3]) | k->MyEventBits[IntSource]; -} - -static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3; -} - -static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3; -} - -/* Return/set the clock multiplier. */ - -/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value ) */ -/* { */ -/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */ -/* } */ - -/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */ -/* } */ - -/* Return/set the clock polarity. */ - -/* static void SetClkPol( struct comedi_device *dev,struct enc_private *k, uint16_t value ) */ -/* { */ -/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */ -/* } */ - -/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */ -/* } */ - -/* Return/set the clock source. */ - -/* static void SetClkSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value ) */ -/* { */ -/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */ -/* } */ - -/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */ -/* } */ - -/* Return/set the index polarity. */ - -/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value ) */ -/* { */ -/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */ -/* } */ - -/* static uint16_t GetIndexPol(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */ -/* } */ - -/* Return/set the index source. */ - -/* static void SetIndexSrc(struct comedi_device *dev, struct enc_private *k, uint16_t value ) */ -/* { */ -/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */ -/* } */ - -/* static uint16_t GetIndexSrc(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */ -/* } */ - -/* Generate an index pulse. */ - -static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k) -{ - register uint16_t cra; - - cra = DEBIread(dev, k->MyCRA); /* Pulse index. */ - DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A)); - DEBIwrite(dev, k->MyCRA, cra); -} - -static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k) -{ - register uint16_t crb; - - crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; /* Pulse index. */ - DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B)); - DEBIwrite(dev, k->MyCRB, crb); } -static struct enc_private enc_private_data[] = { - { - .GetEnable = GetEnable_A, - .GetIntSrc = GetIntSrc_A, - .GetLoadTrig = GetLoadTrig_A, - .GetMode = GetMode_A, - .PulseIndex = PulseIndex_A, - .SetEnable = SetEnable_A, - .SetIntSrc = SetIntSrc_A, - .SetLoadTrig = SetLoadTrig_A, - .SetMode = SetMode_A, - .ResetCapFlags = ResetCapFlags_A, - .MyCRA = LP_CR0A, - .MyCRB = LP_CR0B, - .MyLatchLsw = LP_CNTR0ALSW, - .MyEventBits = EVBITS(0), - }, { - .GetEnable = GetEnable_A, - .GetIntSrc = GetIntSrc_A, - .GetLoadTrig = GetLoadTrig_A, - .GetMode = GetMode_A, - .PulseIndex = PulseIndex_A, - .SetEnable = SetEnable_A, - .SetIntSrc = SetIntSrc_A, - .SetLoadTrig = SetLoadTrig_A, - .SetMode = SetMode_A, - .ResetCapFlags = ResetCapFlags_A, - .MyCRA = LP_CR1A, - .MyCRB = LP_CR1B, - .MyLatchLsw = LP_CNTR1ALSW, - .MyEventBits = EVBITS(1), - }, { - .GetEnable = GetEnable_A, - .GetIntSrc = GetIntSrc_A, - .GetLoadTrig = GetLoadTrig_A, - .GetMode = GetMode_A, - .PulseIndex = PulseIndex_A, - .SetEnable = SetEnable_A, - .SetIntSrc = SetIntSrc_A, - .SetLoadTrig = SetLoadTrig_A, - .SetMode = SetMode_A, - .ResetCapFlags = ResetCapFlags_A, - .MyCRA = LP_CR2A, - .MyCRB = LP_CR2B, - .MyLatchLsw = LP_CNTR2ALSW, - .MyEventBits = EVBITS(2), - }, { - .GetEnable = GetEnable_B, - .GetIntSrc = GetIntSrc_B, - .GetLoadTrig = GetLoadTrig_B, - .GetMode = GetMode_B, - .PulseIndex = PulseIndex_B, - .SetEnable = SetEnable_B, - .SetIntSrc = SetIntSrc_B, - .SetLoadTrig = SetLoadTrig_B, - .SetMode = SetMode_B, - .ResetCapFlags = ResetCapFlags_B, - .MyCRA = LP_CR0A, - .MyCRB = LP_CR0B, - .MyLatchLsw = LP_CNTR0BLSW, - .MyEventBits = EVBITS(3), - }, { - .GetEnable = GetEnable_B, - .GetIntSrc = GetIntSrc_B, - .GetLoadTrig = GetLoadTrig_B, - .GetMode = GetMode_B, - .PulseIndex = PulseIndex_B, - .SetEnable = SetEnable_B, - .SetIntSrc = SetIntSrc_B, - .SetLoadTrig = SetLoadTrig_B, - .SetMode = SetMode_B, - .ResetCapFlags = ResetCapFlags_B, - .MyCRA = LP_CR1A, - .MyCRB = LP_CR1B, - .MyLatchLsw = LP_CNTR1BLSW, - .MyEventBits = EVBITS(4), - }, { - .GetEnable = GetEnable_B, - .GetIntSrc = GetIntSrc_B, - .GetLoadTrig = GetLoadTrig_B, - .GetMode = GetMode_B, - .PulseIndex = PulseIndex_B, - .SetEnable = SetEnable_B, - .SetIntSrc = SetIntSrc_B, - .SetLoadTrig = SetLoadTrig_B, - .SetMode = SetMode_B, - .ResetCapFlags = ResetCapFlags_B, - .MyCRA = LP_CR2A, - .MyCRB = LP_CR2B, - .MyLatchLsw = LP_CNTR2BLSW, - .MyEventBits = EVBITS(5), - }, -}; - -static void CountersInit(struct comedi_device *dev) +static void s626_counters_init(struct comedi_device *dev) { int chan; - struct enc_private *k; - uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | /* Preload upon */ - /* index. */ - (INDXSRC_SOFT << BF_INDXSRC) | /* Disable hardware index. */ - (CLKSRC_COUNTER << BF_CLKSRC) | /* Operating mode is counter. */ - (CLKPOL_POS << BF_CLKPOL) | /* Active high clock. */ - (CNTDIR_UP << BF_CLKPOL) | /* Count direction is up. */ - (CLKMULT_1X << BF_CLKMULT) | /* Clock multiplier is 1x. */ - (CLKENAB_INDEX << BF_CLKENAB); /* Enabled by index */ - - /* Disable all counter interrupts and clear any captured counter events. */ + const struct s626_enc_info *k; + uint16_t setup = + /* Preload upon index. */ + S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) | + /* Disable hardware index. */ + S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) | + /* Operating mode is counter. */ + S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) | + /* Active high clock. */ + S626_SET_STD_CLKPOL(S626_CLKPOL_POS) | + /* Clock multiplier is 1x. */ + S626_SET_STD_CLKMULT(S626_CLKMULT_1X) | + /* Enabled by index */ + S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX); + + /* + * Disable all counter interrupts and clear any captured counter events. + */ for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) { - k = &encpriv[chan]; - k->SetMode(dev, k, Setup, TRUE); - k->SetIntSrc(dev, k, 0); - k->ResetCapFlags(dev, k); - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k = &s626_enc_chan_info[chan]; + k->set_mode(dev, k, setup, true); + k->set_int_src(dev, k, 0); + k->reset_cap_flags(dev, k); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); } } @@ -2316,17 +2533,17 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev) void *addr; dma_addr_t appdma; - addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma); + addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma); if (!addr) return -ENOMEM; - devpriv->ANABuf.LogicalBase = addr; - devpriv->ANABuf.PhysicalBase = appdma; + devpriv->ana_buf.logical_base = addr; + devpriv->ana_buf.physical_base = appdma; - addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma); + addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma); if (!addr) return -ENOMEM; - devpriv->RPSBuf.LogicalBase = addr; - devpriv->RPSBuf.PhysicalBase = appdma; + devpriv->rps_buf.logical_base = addr; + devpriv->rps_buf.physical_base = appdma; return 0; } @@ -2334,42 +2551,43 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev) static void s626_initialize(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; - dma_addr_t pPhysBuf; + dma_addr_t phys_buf; uint16_t chan; int i; /* Enable DEBI and audio pins, enable I2C interface */ - s626_mc_enable(dev, MC1_DEBI | MC1_AUDIO | MC1_I2C, P_MC1); + s626_mc_enable(dev, S626_MC1_DEBI | S626_MC1_AUDIO | S626_MC1_I2C, + S626_P_MC1); /* - * Configure DEBI operating mode + * Configure DEBI operating mode * - * Local bus is 16 bits wide - * Declare DEBI transfer timeout interval - * Set up byte lane steering - * Intel-compatible local bus (DEBI never times out) + * Local bus is 16 bits wide + * Declare DEBI transfer timeout interval + * Set up byte lane steering + * Intel-compatible local bus (DEBI never times out) */ - writel(DEBI_CFG_SLAVE16 | - (DEBI_TOUT << DEBI_CFG_TOUT_BIT) | - DEBI_SWAP | DEBI_CFG_INTEL, - devpriv->mmio + P_DEBICFG); + writel(S626_DEBI_CFG_SLAVE16 | + (S626_DEBI_TOUT << S626_DEBI_CFG_TOUT_BIT) | S626_DEBI_SWAP | + S626_DEBI_CFG_INTEL, devpriv->mmio + S626_P_DEBICFG); /* Disable MMU paging */ - writel(DEBI_PAGE_DISABLE, devpriv->mmio + P_DEBIPAGE); + writel(S626_DEBI_PAGE_DISABLE, devpriv->mmio + S626_P_DEBIPAGE); /* Init GPIO so that ADC Start* is negated */ - writel(GPIO_BASE | GPIO1_HI, devpriv->mmio + P_GPIO); + writel(S626_GPIO_BASE | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); /* I2C device address for onboard eeprom (revb) */ - devpriv->I2CAdrs = 0xA0; + devpriv->i2c_adrs = 0xA0; /* * Issue an I2C ABORT command to halt any I2C * operation in progress and reset BUSY flag. */ - writel(I2C_CLKSEL | I2C_ABORT, devpriv->mmio + P_I2CSTAT); - s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); - while (!(readl(devpriv->mmio + P_MC2) & MC2_UPLD_IIC)) + writel(S626_I2C_CLKSEL | S626_I2C_ABORT, + devpriv->mmio + S626_P_I2CSTAT); + s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); + while (!(readl(devpriv->mmio + S626_P_MC2) & S626_MC2_UPLD_IIC)) ; /* @@ -2377,9 +2595,9 @@ static void s626_initialize(struct comedi_device *dev) * reg twice to reset all I2C error flags. */ for (i = 0; i < 2; i++) { - writel(I2C_CLKSEL, devpriv->mmio + P_I2CSTAT); - s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); - while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2)) + writel(S626_I2C_CLKSEL, devpriv->mmio + S626_P_I2CSTAT); + s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); + while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2)) ; } @@ -2389,31 +2607,32 @@ static void s626_initialize(struct comedi_device *dev) * DAC data setup times are satisfied, enable DAC serial * clock out. */ - writel(ACON2_INIT, devpriv->mmio + P_ACON2); + writel(S626_ACON2_INIT, devpriv->mmio + S626_P_ACON2); /* * Set up TSL1 slot list, which is used to control the - * accumulation of ADC data: RSD1 = shift data in on SD1. - * SIB_A1 = store data uint8_t at next available location + * accumulation of ADC data: S626_RSD1 = shift data in on SD1. + * S626_SIB_A1 = store data uint8_t at next available location * in FB BUFFER1 register. */ - writel(RSD1 | SIB_A1, devpriv->mmio + P_TSL1); - writel(RSD1 | SIB_A1 | EOS, devpriv->mmio + P_TSL1 + 4); + writel(S626_RSD1 | S626_SIB_A1, devpriv->mmio + S626_P_TSL1); + writel(S626_RSD1 | S626_SIB_A1 | S626_EOS, + devpriv->mmio + S626_P_TSL1 + 4); /* Enable TSL1 slot list so that it executes all the time */ - writel(ACON1_ADCSTART, devpriv->mmio + P_ACON1); + writel(S626_ACON1_ADCSTART, devpriv->mmio + S626_P_ACON1); /* * Initialize RPS registers used for ADC */ /* Physical start of RPS program */ - writel((uint32_t)devpriv->RPSBuf.PhysicalBase, - devpriv->mmio + P_RPSADDR1); + writel((uint32_t)devpriv->rps_buf.physical_base, + devpriv->mmio + S626_P_RPSADDR1); /* RPS program performs no explicit mem writes */ - writel(0, devpriv->mmio + P_RPSPAGE1); + writel(0, devpriv->mmio + S626_P_RPSPAGE1); /* Disable RPS timeouts */ - writel(0, devpriv->mmio + P_RPS1_TOUT); + writel(0, devpriv->mmio + S626_P_RPS1_TOUT); #if 0 /* @@ -2425,38 +2644,37 @@ static void s626_initialize(struct comedi_device *dev) * because the SAA7146 ADC interface does not start up in * a defined state after a PCI reset. */ - { - uint8_t PollList; - uint16_t AdcData; - uint16_t StartVal; - uint16_t index; - unsigned int data[16]; + uint8_t poll_list; + uint16_t adc_data; + uint16_t start_val; + uint16_t index; + unsigned int data[16]; - /* Create a simple polling list for analog input channel 0 */ - PollList = EOPL; - ResetADC(dev, &PollList); + /* Create a simple polling list for analog input channel 0 */ + poll_list = S626_EOPL; + s626_reset_adc(dev, &poll_list); - /* Get initial ADC value */ - s626_ai_rinsn(dev, dev->subdevices, NULL, data); - StartVal = data[0]; - - /* - * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. - * - * Invoke ADCs until the new ADC value differs from the initial - * value or a timeout occurs. The timeout protects against the - * possibility that the driver is restarting and the ADC data is a - * fixed value resulting from the applied ADC analog input being - * unusually quiet or at the rail. - */ - for (index = 0; index < 500; index++) { + /* Get initial ADC value */ s626_ai_rinsn(dev, dev->subdevices, NULL, data); - AdcData = data[0]; - if (AdcData != StartVal) - break; - } + start_val = data[0]; + /* + * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED + * EXECUTION. + * + * Invoke ADCs until the new ADC value differs from the initial + * value or a timeout occurs. The timeout protects against the + * possibility that the driver is restarting and the ADC data is + * a fixed value resulting from the applied ADC analog input + * being unusually quiet or at the rail. + */ + for (index = 0; index < 500; index++) { + s626_ai_rinsn(dev, dev->subdevices, NULL, data); + adc_data = data[0]; + if (adc_data != start_val) + break; + } } #endif /* SAA7146 BUG WORKAROUND */ @@ -2469,7 +2687,7 @@ static void s626_initialize(struct comedi_device *dev) * burst length = 1 DWORD * threshold = 1 DWORD. */ - writel(0, devpriv->mmio + P_PCI_BT_A); + writel(0, devpriv->mmio + S626_P_PCI_BT_A); /* * Init Audio2's output DMA physical addresses. The protection @@ -2477,18 +2695,18 @@ static void s626_initialize(struct comedi_device *dev) * single DWORD will be transferred each time a DMA transfer is * enabled. */ - pPhysBuf = devpriv->ANABuf.PhysicalBase + - (DAC_WDMABUF_OS * sizeof(uint32_t)); - writel((uint32_t)pPhysBuf, devpriv->mmio + P_BASEA2_OUT); - writel((uint32_t)(pPhysBuf + sizeof(uint32_t)), - devpriv->mmio + P_PROTA2_OUT); + phys_buf = devpriv->ana_buf.physical_base + + (S626_DAC_WDMABUF_OS * sizeof(uint32_t)); + writel((uint32_t)phys_buf, devpriv->mmio + S626_P_BASEA2_OUT); + writel((uint32_t)(phys_buf + sizeof(uint32_t)), + devpriv->mmio + S626_P_PROTA2_OUT); /* * Cache Audio2's output DMA buffer logical address. This is * where DAC data is buffered for A2 output DMA transfers. */ - devpriv->pDacWBuf = (uint32_t *)devpriv->ANABuf.LogicalBase + - DAC_WDMABUF_OS; + devpriv->dac_wbuf = (uint32_t *)devpriv->ana_buf.logical_base + + S626_DAC_WDMABUF_OS; /* * Audio2's output channels does not use paging. The @@ -2496,7 +2714,7 @@ static void s626_initialize(struct comedi_device *dev) * DMAC will automatically halt and its PCI address pointer * will be reset when the protection address is reached. */ - writel(8, devpriv->mmio + P_PAGEA2_OUT); + writel(8, devpriv->mmio + S626_P_PAGEA2_OUT); /* * Initialize time slot list 2 (TSL2), which is used to control @@ -2511,7 +2729,8 @@ static void s626_initialize(struct comedi_device *dev) */ /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */ - writel(XSD2 | RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0)); + writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2 | S626_EOS, + devpriv->mmio + S626_VECTPORT(0)); /* * Initialize slot 1, which is constant. Slot 1 causes a @@ -2523,18 +2742,18 @@ static void s626_initialize(struct comedi_device *dev) */ /* Slot 1: Fetch DWORD from Audio2's output FIFO */ - writel(LF_A2, devpriv->mmio + VECTPORT(1)); + writel(S626_LF_A2, devpriv->mmio + S626_VECTPORT(1)); /* Start DAC's audio interface (TSL2) running */ - writel(ACON1_DACSTART, devpriv->mmio + P_ACON1); + writel(S626_ACON1_DACSTART, devpriv->mmio + S626_P_ACON1); /* * Init Trim DACs to calibrated values. Do it twice because the * SAA7146 audio channel does not always reset properly and * sometimes causes the first few TrimDAC writes to malfunction. */ - LoadTrimDACs(dev); - LoadTrimDACs(dev); + s626_load_trim_dacs(dev); + s626_load_trim_dacs(dev); /* * Manually init all gate array hardware in case this is a soft @@ -2549,10 +2768,10 @@ static void s626_initialize(struct comedi_device *dev) * polarity images. */ for (chan = 0; chan < S626_DAC_CHANNELS; chan++) - SetDAC(dev, chan, 0); + s626_set_dac(dev, chan, 0); /* Init counters */ - CountersInit(dev); + s626_counters_init(dev); /* * Without modifying the state of the Battery Backup enab, disable @@ -2560,8 +2779,8 @@ static void s626_initialize(struct comedi_device *dev) * standard DIO (vs. counter overflow) mode, disable the battery * charger, and reset the watchdog interval selector to zero. */ - WriteMISC2(dev, (uint16_t)(DEBIread(dev, LP_RDMISC2) & - MISC2_BATT_ENABLE)); + s626_write_misc2(dev, (s626_debi_read(dev, S626_LP_RDMISC2) & + S626_MISC2_BATT_ENABLE)); /* Initialize the digital I/O subsystem */ s626_dio_init(dev); @@ -2588,10 +2807,10 @@ static int s626_auto_attach(struct comedi_device *dev, return -ENOMEM; /* disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* soft reset */ - writel(MC1_SOFT_RESET, devpriv->mmio + P_MC1); + writel(S626_MC1_SOFT_RESET, devpriv->mmio + S626_P_MC1); /* DMA FIXME DMA// */ @@ -2670,7 +2889,7 @@ static int s626_auto_attach(struct comedi_device *dev, s->io_bits = 0xffff; s->private = (void *)2; /* DIO group 2 */ s->range_table = &range_digital; - s->insn_config = s626_dio_insn_config; + s->insn_config = s626_dio_insn_config; s->insn_bits = s626_dio_insn_bits; s = &dev->subdevices[5]; @@ -2679,7 +2898,6 @@ static int s626_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL; s->n_chan = S626_ENCODER_CHANNELS; s->maxdata = 0xffffff; - s->private = enc_private_data; s->range_table = &range_unknown; s->insn_config = s626_enc_insn_config; s->insn_read = s626_enc_insn_read; @@ -2703,20 +2921,22 @@ static void s626_detach(struct comedi_device *dev) if (devpriv->mmio) { /* interrupt mask */ /* Disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* Clear board's IRQ status flag */ - writel(IRQ_GPIO3 | IRQ_RPS1, - devpriv->mmio + P_ISR); + writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, + devpriv->mmio + S626_P_ISR); - /* Disable the watchdog timer and battery charger. */ - WriteMISC2(dev, 0); + /* Disable the watchdog timer and battery charger. */ + s626_write_misc2(dev, 0); /* Close all interfaces on 7146 device */ - writel(MC1_SHUTDOWN, devpriv->mmio + P_MC1); - writel(ACON1_BASE, devpriv->mmio + P_ACON1); + writel(S626_MC1_SHUTDOWN, devpriv->mmio + S626_P_MC1); + writel(S626_ACON1_BASE, devpriv->mmio + S626_P_ACON1); - CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE); - CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE); + s626_close_dma_b(dev, &devpriv->rps_buf, + S626_DMABUF_SIZE); + s626_close_dma_b(dev, &devpriv->ana_buf, + S626_DMABUF_SIZE); } if (dev->irq) @@ -2746,8 +2966,8 @@ static int s626_pci_probe(struct pci_dev *dev, * Philips SAA7146 media/dvb based cards. */ static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = { - { PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, - PCI_SUBVENDOR_ID_S626, PCI_SUBDEVICE_ID_S626, 0, 0, 0 }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, + 0x6000, 0x0272) }, { 0 } }; MODULE_DEVICE_TABLE(pci, s626_pci_table); diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index a85e6bdcad07..33b72739c1cb 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -1,690 +1,774 @@ /* - comedi/drivers/s626.h - Sensoray s626 Comedi driver, header file - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <ds@schleef.org> - - Based on Sensoray Model 626 Linux driver Version 0.2 - Copyright (C) 2002-2004 Sensoray Co., Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ - -/* - Driver: s626.o (s626.ko) - Description: Sensoray 626 driver - Devices: Sensoray s626 - Authors: Gianluca Palli <gpalli@deis.unibo.it>, - Updated: Thu, 12 Jul 2005 - Status: experimental - - Configuration Options: - analog input: - none - - analog output: - none - - digital channel: - s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels - supported configuration options: - INSN_CONFIG_DIO_QUERY - COMEDI_INPUT - COMEDI_OUTPUT - - encoder: - Every channel must be configured before reading. - - Example code - - insn.insn=INSN_CONFIG; // configuration instruction - insn.n=1; // number of operation (must be 1) - insn.data=&initialvalue; // initial value loaded into encoder - // during configuration - insn.subdev=5; // encoder subdevice - insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); // encoder_channel - // to configure - - comedi_do_insn(cf,&insn); // executing configuration -*/ - -#if !defined(TRUE) -#define TRUE (1) -#endif - -#if !defined(FALSE) -#define FALSE (0) -#endif - -#define S626_SIZE 0x0200 -#define DMABUF_SIZE 4096 /* 4k pages */ + * comedi/drivers/s626.h + * Sensoray s626 Comedi driver, header file + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> + * + * Based on Sensoray Model 626 Linux driver Version 0.2 + * Copyright (C) 2002-2004 Sensoray Co., Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef S626_H_INCLUDED +#define S626_H_INCLUDED + +#define S626_DMABUF_SIZE 4096 /* 4k pages */ #define S626_ADC_CHANNELS 16 #define S626_DAC_CHANNELS 4 #define S626_ENCODER_CHANNELS 6 #define S626_DIO_CHANNELS 48 -#define S626_DIO_BANKS 3 /* Number of DIO groups. */ -#define S626_DIO_EXTCHANS 40 /* Number of */ - /* extended-capability */ - /* DIO channels. */ - -#define NUM_TRIMDACS 12 /* Number of valid TrimDAC channels. */ - -/* PCI bus interface types. */ -#define INTEL 1 /* Intel bus type. */ -#define MOTOROLA 2 /* Motorola bus type. */ +#define S626_DIO_BANKS 3 /* Number of DIO groups. */ +#define S626_DIO_EXTCHANS 40 /* Number of extended-capability + * DIO channels. */ -#define PLATFORM INTEL /* *** SELECT PLATFORM TYPE *** */ +#define S626_NUM_TRIMDACS 12 /* Number of valid TrimDAC channels. */ -#define RANGE_5V 0x10 /* +/-5V range */ -#define RANGE_10V 0x00 /* +/-10V range */ +/* PCI bus interface types. */ +#define S626_INTEL 1 /* Intel bus type. */ +#define S626_MOTOROLA 2 /* Motorola bus type. */ -#define EOPL 0x80 /* End of ADC poll list marker. */ -#define GSEL_BIPOLAR5V 0x00F0 /* LP_GSEL setting for 5V bipolar range. */ -#define GSEL_BIPOLAR10V 0x00A0 /* LP_GSEL setting for 10V bipolar range. */ +#define S626_PLATFORM S626_INTEL /* *** SELECT PLATFORM TYPE *** */ -/* Error codes that must be visible to this base class. */ -#define ERR_ILLEGAL_PARM 0x00010000 /* Illegal function parameter value was specified. */ -#define ERR_I2C 0x00020000 /* I2C error. */ -#define ERR_COUNTERSETUP 0x00200000 /* Illegal setup specified for counter channel. */ -#define ERR_DEBI_TIMEOUT 0x00400000 /* DEBI transfer timed out. */ +#define S626_RANGE_5V 0x10 /* +/-5V range */ +#define S626_RANGE_10V 0x00 /* +/-10V range */ -/* Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF. */ -#define ADC_DMABUF_DWORDS 40 /* ADC DMA buffer must hold 16 samples, plus pre/post garbage samples. */ -#define DAC_WDMABUF_DWORDS 1 /* DAC output DMA buffer holds a single sample. */ +#define S626_EOPL 0x80 /* End of ADC poll list marker. */ +#define S626_GSEL_BIPOLAR5V 0x00F0 /* S626_LP_GSEL setting 5V bipolar. */ +#define S626_GSEL_BIPOLAR10V 0x00A0 /* S626_LP_GSEL setting 10V bipolar. */ -/* All remaining space in 4KB DMA buffer is available for the RPS1 program. */ +/* Error codes that must be visible to this base class. */ +#define S626_ERR_ILLEGAL_PARM 0x00010000 /* Illegal function parameter + * value was specified. */ +#define S626_ERR_I2C 0x00020000 /* I2C error. */ +#define S626_ERR_COUNTERSETUP 0x00200000 /* Illegal setup specified for + * counter channel. */ +#define S626_ERR_DEBI_TIMEOUT 0x00400000 /* DEBI transfer timed out. */ -/* Address offsets, in DWORDS, from base of DMA buffer. */ -#define DAC_WDMABUF_OS ADC_DMABUF_DWORDS - -/* Interrupt enab bit in ISR and IER. */ -#define IRQ_GPIO3 0x00000040 /* IRQ enable for GPIO3. */ -#define IRQ_RPS1 0x10000000 -#define ISR_AFOU 0x00000800 +/* + * Organization (physical order) and size (in DWORDs) of logical DMA buffers + * contained by ANA_DMABUF. + */ +#define S626_ADC_DMABUF_DWORDS 40 /* ADC DMA buffer must hold 16 samples, + * plus pre/post garbage samples. */ +#define S626_DAC_WDMABUF_DWORDS 1 /* DAC output DMA buffer holds a single + * sample. */ + +/* All remaining space in 4KB DMA buffer is available for the RPS1 program. */ + +/* Address offsets, in DWORDS, from base of DMA buffer. */ +#define S626_DAC_WDMABUF_OS S626_ADC_DMABUF_DWORDS + +/* Interrupt enable bit in ISR and IER. */ +#define S626_IRQ_GPIO3 0x00000040 /* IRQ enable for GPIO3. */ +#define S626_IRQ_RPS1 0x10000000 +#define S626_ISR_AFOU 0x00000800 /* Audio fifo under/overflow detected. */ -#define IRQ_COINT1A 0x0400 /* conter 1A overflow interrupt mask */ -#define IRQ_COINT1B 0x0800 /* conter 1B overflow interrupt mask */ -#define IRQ_COINT2A 0x1000 /* conter 2A overflow interrupt mask */ -#define IRQ_COINT2B 0x2000 /* conter 2B overflow interrupt mask */ -#define IRQ_COINT3A 0x4000 /* conter 3A overflow interrupt mask */ -#define IRQ_COINT3B 0x8000 /* conter 3B overflow interrupt mask */ - -/* RPS command codes. */ -#define RPS_CLRSIGNAL 0x00000000 /* CLEAR SIGNAL */ -#define RPS_SETSIGNAL 0x10000000 /* SET SIGNAL */ -#define RPS_NOP 0x00000000 /* NOP */ -#define RPS_PAUSE 0x20000000 /* PAUSE */ -#define RPS_UPLOAD 0x40000000 /* UPLOAD */ -#define RPS_JUMP 0x80000000 /* JUMP */ -#define RPS_LDREG 0x90000100 /* LDREG (1 uint32_t only) */ -#define RPS_STREG 0xA0000100 /* STREG (1 uint32_t only) */ -#define RPS_STOP 0x50000000 /* STOP */ -#define RPS_IRQ 0x60000000 /* IRQ */ - -#define RPS_LOGICAL_OR 0x08000000 /* Logical OR conditionals. */ -#define RPS_INVERT 0x04000000 /* Test for negated semaphores. */ -#define RPS_DEBI 0x00000002 /* DEBI done */ - -#define RPS_SIG0 0x00200000 /* RPS semaphore 0 (used by ADC). */ -#define RPS_SIG1 0x00400000 /* RPS semaphore 1 (used by DAC). */ -#define RPS_SIG2 0x00800000 /* RPS semaphore 2 (not used). */ -#define RPS_GPIO2 0x00080000 /* RPS GPIO2 */ -#define RPS_GPIO3 0x00100000 /* RPS GPIO3 */ - -#define RPS_SIGADC RPS_SIG0 /* Trigger/status for ADC's RPS program. */ -#define RPS_SIGDAC RPS_SIG1 /* Trigger/status for DAC's RPS program. */ - -/* RPS clock parameters. */ -#define RPSCLK_SCALAR 8 /* This is apparent ratio of PCI/RPS clks (undocumented!!). */ -#define RPSCLK_PER_US (33 / RPSCLK_SCALAR) /* Number of RPS clocks in one microsecond. */ - -/* Event counter source addresses. */ -#define SBA_RPS_A0 0x27 /* Time of RPS0 busy, in PCI clocks. */ - -/* GPIO constants. */ -#define GPIO_BASE 0x10004000 /* GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out. */ -#define GPIO1_LO 0x00000000 /* GPIO1 set to LOW. */ -#define GPIO1_HI 0x00001000 /* GPIO1 set to HIGH. */ - -/* Primary Status Register (PSR) constants. */ -#define PSR_DEBI_E 0x00040000 /* DEBI event flag. */ -#define PSR_DEBI_S 0x00080000 /* DEBI status flag. */ -#define PSR_A2_IN 0x00008000 /* Audio output DMA2 protection address reached. */ -#define PSR_AFOU 0x00000800 /* Audio FIFO under/overflow detected. */ -#define PSR_GPIO2 0x00000020 /* GPIO2 input pin: 0=AdcBusy, 1=AdcIdle. */ -#define PSR_EC0S 0x00000001 /* Event counter 0 threshold reached. */ - -/* Secondary Status Register (SSR) constants. */ -#define SSR_AF2_OUT 0x00000200 /* Audio 2 output FIFO under/overflow detected. */ - -/* Master Control Register 1 (MC1) constants. */ -#define MC1_SOFT_RESET 0x80000000 /* Invoke 7146 soft reset. */ -#define MC1_SHUTDOWN 0x3FFF0000 /* Shut down all MC1-controlled enables. */ - -#define MC1_ERPS1 0x2000 /* enab/disable RPS task 1. */ -#define MC1_ERPS0 0x1000 /* enab/disable RPS task 0. */ -#define MC1_DEBI 0x0800 /* enab/disable DEBI pins. */ -#define MC1_AUDIO 0x0200 /* enab/disable audio port pins. */ -#define MC1_I2C 0x0100 /* enab/disable I2C interface. */ -#define MC1_A2OUT 0x0008 /* enab/disable transfer on A2 out. */ -#define MC1_A2IN 0x0004 /* enab/disable transfer on A2 in. */ -#define MC1_A1IN 0x0001 /* enab/disable transfer on A1 in. */ - -/* Master Control Register 2 (MC2) constants. */ -#define MC2_UPLD_DEBIq 0x00020002 /* Upload DEBI registers. */ -#define MC2_UPLD_IICq 0x00010001 /* Upload I2C registers. */ -#define MC2_RPSSIG2_ONq 0x20002000 /* Assert RPS_SIG2. */ -#define MC2_RPSSIG1_ONq 0x10001000 /* Assert RPS_SIG1. */ -#define MC2_RPSSIG0_ONq 0x08000800 /* Assert RPS_SIG0. */ -#define MC2_UPLD_DEBI_MASKq 0x00000002 /* Upload DEBI mask. */ -#define MC2_UPLD_IIC_MASKq 0x00000001 /* Upload I2C mask. */ -#define MC2_RPSSIG2_MASKq 0x00002000 /* RPS_SIG2 bit mask. */ -#define MC2_RPSSIG1_MASKq 0x00001000 /* RPS_SIG1 bit mask. */ -#define MC2_RPSSIG0_MASKq 0x00000800 /* RPS_SIG0 bit mask. */ - -#define MC2_DELAYTRIG_4USq MC2_RPSSIG1_ON -#define MC2_DELAYBUSY_4USq MC2_RPSSIG1_MASK - -#define MC2_DELAYTRIG_6USq MC2_RPSSIG2_ON -#define MC2_DELAYBUSY_6USq MC2_RPSSIG2_MASK - -#define MC2_UPLD_DEBI 0x0002 /* Upload DEBI. */ -#define MC2_UPLD_IIC 0x0001 /* Upload I2C. */ -#define MC2_RPSSIG2 0x2000 /* RPS signal 2 (not used). */ -#define MC2_RPSSIG1 0x1000 /* RPS signal 1 (DAC RPS busy). */ -#define MC2_RPSSIG0 0x0800 /* RPS signal 0 (ADC RPS busy). */ - -#define MC2_ADC_RPS MC2_RPSSIG0 /* ADC RPS busy. */ -#define MC2_DAC_RPS MC2_RPSSIG1 /* DAC RPS busy. */ - -/* ***** oldies ***** */ -#define MC2_UPLD_DEBIQ 0x00020002 /* Upload DEBI registers. */ -#define MC2_UPLD_IICQ 0x00010001 /* Upload I2C registers. */ - -/* PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS */ -#define P_PCI_BT_A 0x004C /* Audio DMA burst/threshold control. */ -#define P_DEBICFG 0x007C /* DEBI configuration. */ -#define P_DEBICMD 0x0080 /* DEBI command. */ -#define P_DEBIPAGE 0x0084 /* DEBI page. */ -#define P_DEBIAD 0x0088 /* DEBI target address. */ -#define P_I2CCTRL 0x008C /* I2C control. */ -#define P_I2CSTAT 0x0090 /* I2C status. */ -#define P_BASEA2_IN 0x00AC /* Audio input 2 base physical DMAbuf +#define S626_IRQ_COINT1A 0x0400 /* counter 1A overflow interrupt mask */ +#define S626_IRQ_COINT1B 0x0800 /* counter 1B overflow interrupt mask */ +#define S626_IRQ_COINT2A 0x1000 /* counter 2A overflow interrupt mask */ +#define S626_IRQ_COINT2B 0x2000 /* counter 2B overflow interrupt mask */ +#define S626_IRQ_COINT3A 0x4000 /* counter 3A overflow interrupt mask */ +#define S626_IRQ_COINT3B 0x8000 /* counter 3B overflow interrupt mask */ + +/* RPS command codes. */ +#define S626_RPS_CLRSIGNAL 0x00000000 /* CLEAR SIGNAL */ +#define S626_RPS_SETSIGNAL 0x10000000 /* SET SIGNAL */ +#define S626_RPS_NOP 0x00000000 /* NOP */ +#define S626_RPS_PAUSE 0x20000000 /* PAUSE */ +#define S626_RPS_UPLOAD 0x40000000 /* UPLOAD */ +#define S626_RPS_JUMP 0x80000000 /* JUMP */ +#define S626_RPS_LDREG 0x90000100 /* LDREG (1 uint32_t only) */ +#define S626_RPS_STREG 0xA0000100 /* STREG (1 uint32_t only) */ +#define S626_RPS_STOP 0x50000000 /* STOP */ +#define S626_RPS_IRQ 0x60000000 /* IRQ */ + +#define S626_RPS_LOGICAL_OR 0x08000000 /* Logical OR conditionals. */ +#define S626_RPS_INVERT 0x04000000 /* Test for negated + * semaphores. */ +#define S626_RPS_DEBI 0x00000002 /* DEBI done */ + +#define S626_RPS_SIG0 0x00200000 /* RPS semaphore 0 + * (used by ADC). */ +#define S626_RPS_SIG1 0x00400000 /* RPS semaphore 1 + * (used by DAC). */ +#define S626_RPS_SIG2 0x00800000 /* RPS semaphore 2 + * (not used). */ +#define S626_RPS_GPIO2 0x00080000 /* RPS GPIO2 */ +#define S626_RPS_GPIO3 0x00100000 /* RPS GPIO3 */ + +#define S626_RPS_SIGADC S626_RPS_SIG0 /* Trigger/status for + * ADC's RPS program. */ +#define S626_RPS_SIGDAC S626_RPS_SIG1 /* Trigger/status for + * DAC's RPS program. */ + +/* RPS clock parameters. */ +#define S626_RPSCLK_SCALAR 8 /* This is apparent ratio of + * PCI/RPS clks (undocumented!!). */ +#define S626_RPSCLK_PER_US (33 / S626_RPSCLK_SCALAR) + /* Number of RPS clocks in one + * microsecond. */ + +/* Event counter source addresses. */ +#define S626_SBA_RPS_A0 0x27 /* Time of RPS0 busy, in PCI clocks. */ + +/* GPIO constants. */ +#define S626_GPIO_BASE 0x10004000 /* GPIO 0,2,3 = inputs, + * GPIO3 = IRQ; GPIO1 = out. */ +#define S626_GPIO1_LO 0x00000000 /* GPIO1 set to LOW. */ +#define S626_GPIO1_HI 0x00001000 /* GPIO1 set to HIGH. */ + +/* Primary Status Register (PSR) constants. */ +#define S626_PSR_DEBI_E 0x00040000 /* DEBI event flag. */ +#define S626_PSR_DEBI_S 0x00080000 /* DEBI status flag. */ +#define S626_PSR_A2_IN 0x00008000 /* Audio output DMA2 protection + * address reached. */ +#define S626_PSR_AFOU 0x00000800 /* Audio FIFO under/overflow + * detected. */ +#define S626_PSR_GPIO2 0x00000020 /* GPIO2 input pin: 0=AdcBusy, + * 1=AdcIdle. */ +#define S626_PSR_EC0S 0x00000001 /* Event counter 0 threshold + * reached. */ + +/* Secondary Status Register (SSR) constants. */ +#define S626_SSR_AF2_OUT 0x00000200 /* Audio 2 output FIFO + * under/overflow detected. */ + +/* Master Control Register 1 (MC1) constants. */ +#define S626_MC1_SOFT_RESET 0x80000000 /* Invoke 7146 soft reset. */ +#define S626_MC1_SHUTDOWN 0x3FFF0000 /* Shut down all MC1-controlled + * enables. */ + +#define S626_MC1_ERPS1 0x2000 /* Enab/disable RPS task 1. */ +#define S626_MC1_ERPS0 0x1000 /* Enab/disable RPS task 0. */ +#define S626_MC1_DEBI 0x0800 /* Enab/disable DEBI pins. */ +#define S626_MC1_AUDIO 0x0200 /* Enab/disable audio port pins. */ +#define S626_MC1_I2C 0x0100 /* Enab/disable I2C interface. */ +#define S626_MC1_A2OUT 0x0008 /* Enab/disable transfer on A2 out. */ +#define S626_MC1_A2IN 0x0004 /* Enab/disable transfer on A2 in. */ +#define S626_MC1_A1IN 0x0001 /* Enab/disable transfer on A1 in. */ + +/* Master Control Register 2 (MC2) constants. */ +#define S626_MC2_UPLD_DEBI 0x0002 /* Upload DEBI. */ +#define S626_MC2_UPLD_IIC 0x0001 /* Upload I2C. */ +#define S626_MC2_RPSSIG2 0x2000 /* RPS signal 2 (not used). */ +#define S626_MC2_RPSSIG1 0x1000 /* RPS signal 1 (DAC RPS busy). */ +#define S626_MC2_RPSSIG0 0x0800 /* RPS signal 0 (ADC RPS busy). */ + +#define S626_MC2_ADC_RPS S626_MC2_RPSSIG0 /* ADC RPS busy. */ +#define S626_MC2_DAC_RPS S626_MC2_RPSSIG1 /* DAC RPS busy. */ + +/* PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS */ +#define S626_P_PCI_BT_A 0x004C /* Audio DMA burst/threshold control. */ +#define S626_P_DEBICFG 0x007C /* DEBI configuration. */ +#define S626_P_DEBICMD 0x0080 /* DEBI command. */ +#define S626_P_DEBIPAGE 0x0084 /* DEBI page. */ +#define S626_P_DEBIAD 0x0088 /* DEBI target address. */ +#define S626_P_I2CCTRL 0x008C /* I2C control. */ +#define S626_P_I2CSTAT 0x0090 /* I2C status. */ +#define S626_P_BASEA2_IN 0x00AC /* Audio input 2 base physical DMAbuf * address. */ -#define P_PROTA2_IN 0x00B0 /* Audio input 2 physical DMAbuf +#define S626_P_PROTA2_IN 0x00B0 /* Audio input 2 physical DMAbuf * protection address. */ -#define P_PAGEA2_IN 0x00B4 /* Audio input 2 paging attributes. */ -#define P_BASEA2_OUT 0x00B8 /* Audio output 2 base physical DMAbuf +#define S626_P_PAGEA2_IN 0x00B4 /* Audio input 2 paging attributes. */ +#define S626_P_BASEA2_OUT 0x00B8 /* Audio output 2 base physical DMAbuf * address. */ -#define P_PROTA2_OUT 0x00BC /* Audio output 2 physical DMAbuf +#define S626_P_PROTA2_OUT 0x00BC /* Audio output 2 physical DMAbuf * protection address. */ -#define P_PAGEA2_OUT 0x00C0 /* Audio output 2 paging attributes. */ -#define P_RPSPAGE0 0x00C4 /* RPS0 page. */ -#define P_RPSPAGE1 0x00C8 /* RPS1 page. */ -#define P_RPS0_TOUT 0x00D4 /* RPS0 time-out. */ -#define P_RPS1_TOUT 0x00D8 /* RPS1 time-out. */ -#define P_IER 0x00DC /* Interrupt enable. */ -#define P_GPIO 0x00E0 /* General-purpose I/O. */ -#define P_EC1SSR 0x00E4 /* Event counter set 1 source select. */ -#define P_ECT1R 0x00EC /* Event counter threshold set 1. */ -#define P_ACON1 0x00F4 /* Audio control 1. */ -#define P_ACON2 0x00F8 /* Audio control 2. */ -#define P_MC1 0x00FC /* Master control 1. */ -#define P_MC2 0x0100 /* Master control 2. */ -#define P_RPSADDR0 0x0104 /* RPS0 instruction pointer. */ -#define P_RPSADDR1 0x0108 /* RPS1 instruction pointer. */ -#define P_ISR 0x010C /* Interrupt status. */ -#define P_PSR 0x0110 /* Primary status. */ -#define P_SSR 0x0114 /* Secondary status. */ -#define P_EC1R 0x0118 /* Event counter set 1. */ -#define P_ADP4 0x0138 /* Logical audio DMA pointer of audio +#define S626_P_PAGEA2_OUT 0x00C0 /* Audio output 2 paging attributes. */ +#define S626_P_RPSPAGE0 0x00C4 /* RPS0 page. */ +#define S626_P_RPSPAGE1 0x00C8 /* RPS1 page. */ +#define S626_P_RPS0_TOUT 0x00D4 /* RPS0 time-out. */ +#define S626_P_RPS1_TOUT 0x00D8 /* RPS1 time-out. */ +#define S626_P_IER 0x00DC /* Interrupt enable. */ +#define S626_P_GPIO 0x00E0 /* General-purpose I/O. */ +#define S626_P_EC1SSR 0x00E4 /* Event counter set 1 source select. */ +#define S626_P_ECT1R 0x00EC /* Event counter threshold set 1. */ +#define S626_P_ACON1 0x00F4 /* Audio control 1. */ +#define S626_P_ACON2 0x00F8 /* Audio control 2. */ +#define S626_P_MC1 0x00FC /* Master control 1. */ +#define S626_P_MC2 0x0100 /* Master control 2. */ +#define S626_P_RPSADDR0 0x0104 /* RPS0 instruction pointer. */ +#define S626_P_RPSADDR1 0x0108 /* RPS1 instruction pointer. */ +#define S626_P_ISR 0x010C /* Interrupt status. */ +#define S626_P_PSR 0x0110 /* Primary status. */ +#define S626_P_SSR 0x0114 /* Secondary status. */ +#define S626_P_EC1R 0x0118 /* Event counter set 1. */ +#define S626_P_ADP4 0x0138 /* Logical audio DMA pointer of audio * input FIFO A2_IN. */ -#define P_FB_BUFFER1 0x0144 /* Audio feedback buffer 1. */ -#define P_FB_BUFFER2 0x0148 /* Audio feedback buffer 2. */ -#define P_TSL1 0x0180 /* Audio time slot list 1. */ -#define P_TSL2 0x01C0 /* Audio time slot list 2. */ +#define S626_P_FB_BUFFER1 0x0144 /* Audio feedback buffer 1. */ +#define S626_P_FB_BUFFER2 0x0148 /* Audio feedback buffer 2. */ +#define S626_P_TSL1 0x0180 /* Audio time slot list 1. */ +#define S626_P_TSL2 0x01C0 /* Audio time slot list 2. */ -/* LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS */ -/* Analog I/O registers: */ -#define LP_DACPOL 0x0082 /* Write DAC polarity. */ -#define LP_GSEL 0x0084 /* Write ADC gain. */ -#define LP_ISEL 0x0086 /* Write ADC channel select. */ +/* LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS */ +/* Analog I/O registers: */ +#define S626_LP_DACPOL 0x0082 /* Write DAC polarity. */ +#define S626_LP_GSEL 0x0084 /* Write ADC gain. */ +#define S626_LP_ISEL 0x0086 /* Write ADC channel select. */ /* Digital I/O registers */ -#define LP_RDDIN(x) (0x0040 + (x) * 0x10) /* R: digital input */ -#define LP_WRINTSEL(x) (0x0042 + (x) * 0x10) /* W: int enable */ -#define LP_WREDGSEL(x) (0x0044 + (x) * 0x10) /* W: edge selection */ -#define LP_WRCAPSEL(x) (0x0046 + (x) * 0x10) /* W: capture enable */ -#define LP_RDCAPFLG(x) (0x0048 + (x) * 0x10) /* R: edges captured */ -#define LP_WRDOUT(x) (0x0048 + (x) * 0x10) /* W: digital output */ -#define LP_RDINTSEL(x) (0x004a + (x) * 0x10) /* R: int enable */ -#define LP_RDEDGSEL(x) (0x004c + (x) * 0x10) /* R: edge selection */ -#define LP_RDCAPSEL(x) (0x004e + (x) * 0x10) /* R: capture enable */ - -/* Counter Registers (read/write): */ -#define LP_CR0A 0x0000 /* 0A setup register. */ -#define LP_CR0B 0x0002 /* 0B setup register. */ -#define LP_CR1A 0x0004 /* 1A setup register. */ -#define LP_CR1B 0x0006 /* 1B setup register. */ -#define LP_CR2A 0x0008 /* 2A setup register. */ -#define LP_CR2B 0x000A /* 2B setup register. */ - -/* Counter PreLoad (write) and Latch (read) Registers: */ -#define LP_CNTR0ALSW 0x000C /* 0A lsw. */ -#define LP_CNTR0AMSW 0x000E /* 0A msw. */ -#define LP_CNTR0BLSW 0x0010 /* 0B lsw. */ -#define LP_CNTR0BMSW 0x0012 /* 0B msw. */ -#define LP_CNTR1ALSW 0x0014 /* 1A lsw. */ -#define LP_CNTR1AMSW 0x0016 /* 1A msw. */ -#define LP_CNTR1BLSW 0x0018 /* 1B lsw. */ -#define LP_CNTR1BMSW 0x001A /* 1B msw. */ -#define LP_CNTR2ALSW 0x001C /* 2A lsw. */ -#define LP_CNTR2AMSW 0x001E /* 2A msw. */ -#define LP_CNTR2BLSW 0x0020 /* 2B lsw. */ -#define LP_CNTR2BMSW 0x0022 /* 2B msw. */ - -/* Miscellaneous Registers (read/write): */ -#define LP_MISC1 0x0088 /* Read/write Misc1. */ -#define LP_WRMISC2 0x0090 /* Write Misc2. */ -#define LP_RDMISC2 0x0082 /* Read Misc2. */ - -/* Bit masks for MISC1 register that are the same for reads and writes. */ -#define MISC1_WENABLE 0x8000 /* enab writes to MISC2 (except Clear +#define S626_LP_RDDIN(x) (0x0040 + (x) * 0x10) /* R: digital input */ +#define S626_LP_WRINTSEL(x) (0x0042 + (x) * 0x10) /* W: int enable */ +#define S626_LP_WREDGSEL(x) (0x0044 + (x) * 0x10) /* W: edge selection */ +#define S626_LP_WRCAPSEL(x) (0x0046 + (x) * 0x10) /* W: capture enable */ +#define S626_LP_RDCAPFLG(x) (0x0048 + (x) * 0x10) /* R: edges captured */ +#define S626_LP_WRDOUT(x) (0x0048 + (x) * 0x10) /* W: digital output */ +#define S626_LP_RDINTSEL(x) (0x004a + (x) * 0x10) /* R: int enable */ +#define S626_LP_RDEDGSEL(x) (0x004c + (x) * 0x10) /* R: edge selection */ +#define S626_LP_RDCAPSEL(x) (0x004e + (x) * 0x10) /* R: capture enable */ + +/* Counter Registers (read/write): */ +#define S626_LP_CR0A 0x0000 /* 0A setup register. */ +#define S626_LP_CR0B 0x0002 /* 0B setup register. */ +#define S626_LP_CR1A 0x0004 /* 1A setup register. */ +#define S626_LP_CR1B 0x0006 /* 1B setup register. */ +#define S626_LP_CR2A 0x0008 /* 2A setup register. */ +#define S626_LP_CR2B 0x000A /* 2B setup register. */ + +/* Counter PreLoad (write) and Latch (read) Registers: */ +#define S626_LP_CNTR0ALSW 0x000C /* 0A lsw. */ +#define S626_LP_CNTR0AMSW 0x000E /* 0A msw. */ +#define S626_LP_CNTR0BLSW 0x0010 /* 0B lsw. */ +#define S626_LP_CNTR0BMSW 0x0012 /* 0B msw. */ +#define S626_LP_CNTR1ALSW 0x0014 /* 1A lsw. */ +#define S626_LP_CNTR1AMSW 0x0016 /* 1A msw. */ +#define S626_LP_CNTR1BLSW 0x0018 /* 1B lsw. */ +#define S626_LP_CNTR1BMSW 0x001A /* 1B msw. */ +#define S626_LP_CNTR2ALSW 0x001C /* 2A lsw. */ +#define S626_LP_CNTR2AMSW 0x001E /* 2A msw. */ +#define S626_LP_CNTR2BLSW 0x0020 /* 2B lsw. */ +#define S626_LP_CNTR2BMSW 0x0022 /* 2B msw. */ + +/* Miscellaneous Registers (read/write): */ +#define S626_LP_MISC1 0x0088 /* Read/write Misc1. */ +#define S626_LP_WRMISC2 0x0090 /* Write Misc2. */ +#define S626_LP_RDMISC2 0x0082 /* Read Misc2. */ + +/* Bit masks for MISC1 register that are the same for reads and writes. */ +#define S626_MISC1_WENABLE 0x8000 /* enab writes to MISC2 (except Clear * Watchdog bit). */ -#define MISC1_WDISABLE 0x0000 /* Disable writes to MISC2. */ -#define MISC1_EDCAP 0x1000 /* enab edge capture on DIO chans - * specified by LP_WRCAPSELx. */ -#define MISC1_NOEDCAP 0x0000 /* Disable edge capture on specified +#define S626_MISC1_WDISABLE 0x0000 /* Disable writes to MISC2. */ +#define S626_MISC1_EDCAP 0x1000 /* Enable edge capture on DIO chans + * specified by S626_LP_WRCAPSELx. */ +#define S626_MISC1_NOEDCAP 0x0000 /* Disable edge capture on specified * DIO chans. */ -/* Bit masks for MISC1 register reads. */ -#define RDMISC1_WDTIMEOUT 0x4000 /* Watchdog timer timed out. */ - -/* Bit masks for MISC2 register writes. */ -#define WRMISC2_WDCLEAR 0x8000 /* Reset watchdog timer to zero. */ -#define WRMISC2_CHARGE_ENABLE 0x4000 /* enab battery trickle charging. */ - -/* Bit masks for MISC2 register that are the same for reads and writes. */ -#define MISC2_BATT_ENABLE 0x0008 /* Backup battery enable. */ -#define MISC2_WDENABLE 0x0004 /* Watchdog timer enable. */ -#define MISC2_WDPERIOD_MASK 0x0003 /* Watchdog interval */ - /* select mask. */ - -/* Bit masks for ACON1 register. */ -#define A2_RUN 0x40000000 /* Run A2 based on TSL2. */ -#define A1_RUN 0x20000000 /* Run A1 based on TSL1. */ -#define A1_SWAP 0x00200000 /* Use big-endian for A1. */ -#define A2_SWAP 0x00100000 /* Use big-endian for A2. */ -#define WS_MODES 0x00019999 /* WS0 = TSL1 trigger */ - /* input, WS1-WS4 = */ - /* CS* outputs. */ - -#if PLATFORM == INTEL /* Base ACON1 config: always run A1 based - * on TSL1. */ -#define ACON1_BASE (WS_MODES | A1_RUN) -#elif PLATFORM == MOTOROLA -#define ACON1_BASE (WS_MODES | A1_RUN | A1_SWAP | A2_SWAP) +/* Bit masks for MISC1 register reads. */ +#define S626_RDMISC1_WDTIMEOUT 0x4000 /* Watchdog timer timed out. */ + +/* Bit masks for MISC2 register writes. */ +#define S626_WRMISC2_WDCLEAR 0x8000 /* Reset watchdog timer to zero. */ +#define S626_WRMISC2_CHARGE_ENABLE 0x4000 /* Enable battery trickle charging. */ + +/* Bit masks for MISC2 register that are the same for reads and writes. */ +#define S626_MISC2_BATT_ENABLE 0x0008 /* Backup battery enable. */ +#define S626_MISC2_WDENABLE 0x0004 /* Watchdog timer enable. */ +#define S626_MISC2_WDPERIOD_MASK 0x0003 /* Watchdog interval select mask. */ + +/* Bit masks for ACON1 register. */ +#define S626_A2_RUN 0x40000000 /* Run A2 based on TSL2. */ +#define S626_A1_RUN 0x20000000 /* Run A1 based on TSL1. */ +#define S626_A1_SWAP 0x00200000 /* Use big-endian for A1. */ +#define S626_A2_SWAP 0x00100000 /* Use big-endian for A2. */ +#define S626_WS_MODES 0x00019999 /* WS0 = TSL1 trigger input, + * WS1-WS4 = CS* outputs. */ + +#if S626_PLATFORM == S626_INTEL /* Base ACON1 config: always run + * A1 based on TSL1. */ +#define S626_ACON1_BASE (S626_WS_MODES | S626_A1_RUN) +#elif S626_PLATFORM == S626_MOTOROLA +#define S626_ACON1_BASE \ + (S626_WS_MODES | S626_A1_RUN | S626_A1_SWAP | S626_A2_SWAP) #endif -#define ACON1_ADCSTART ACON1_BASE /* Start ADC: run A1 - * based on TSL1. */ -#define ACON1_DACSTART (ACON1_BASE | A2_RUN) +#define S626_ACON1_ADCSTART S626_ACON1_BASE /* Start ADC: run A1 + * based on TSL1. */ +#define S626_ACON1_DACSTART (S626_ACON1_BASE | S626_A2_RUN) /* Start transmit to DAC: run A2 based on TSL2. */ -#define ACON1_DACSTOP ACON1_BASE /* Halt A2. */ - -/* Bit masks for ACON2 register. */ -#define A1_CLKSRC_BCLK1 0x00000000 /* A1 bit rate = BCLK1 (ADC). */ -#define A2_CLKSRC_X1 0x00800000 /* A2 bit rate = ACLK/1 (DACs). */ -#define A2_CLKSRC_X2 0x00C00000 /* A2 bit rate = ACLK/2 (DACs). */ -#define A2_CLKSRC_X4 0x01400000 /* A2 bit rate = ACLK/4 (DACs). */ -#define INVERT_BCLK2 0x00100000 /* Invert BCLK2 (DACs). */ -#define BCLK2_OE 0x00040000 /* enab BCLK2 (DACs). */ -#define ACON2_XORMASK 0x000C0000 /* XOR mask for ACON2 */ - /* active-low bits. */ - -#define ACON2_INIT (ACON2_XORMASK ^ (A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE)) - -/* Bit masks for timeslot records. */ -#define WS1 0x40000000 /* WS output to assert. */ -#define WS2 0x20000000 -#define WS3 0x10000000 -#define WS4 0x08000000 -#define RSD1 0x01000000 /* Shift A1 data in on SD1. */ -#define SDW_A1 0x00800000 /* Store rcv'd char at next - * char slot of DWORD1 buffer. */ -#define SIB_A1 0x00400000 /* Store rcv'd char at next +#define S626_ACON1_DACSTOP S626_ACON1_BASE /* Halt A2. */ + +/* Bit masks for ACON2 register. */ +#define S626_A1_CLKSRC_BCLK1 0x00000000 /* A1 bit rate = BCLK1 (ADC). */ +#define S626_A2_CLKSRC_X1 0x00800000 /* A2 bit rate = ACLK/1 + * (DACs). */ +#define S626_A2_CLKSRC_X2 0x00C00000 /* A2 bit rate = ACLK/2 + * (DACs). */ +#define S626_A2_CLKSRC_X4 0x01400000 /* A2 bit rate = ACLK/4 + * (DACs). */ +#define S626_INVERT_BCLK2 0x00100000 /* Invert BCLK2 (DACs). */ +#define S626_BCLK2_OE 0x00040000 /* Enable BCLK2 (DACs). */ +#define S626_ACON2_XORMASK 0x000C0000 /* XOR mask for ACON2 + * active-low bits. */ + +#define S626_ACON2_INIT (S626_ACON2_XORMASK ^ \ + (S626_A1_CLKSRC_BCLK1 | S626_A2_CLKSRC_X2 | \ + S626_INVERT_BCLK2 | S626_BCLK2_OE)) + +/* Bit masks for timeslot records. */ +#define S626_WS1 0x40000000 /* WS output to assert. */ +#define S626_WS2 0x20000000 +#define S626_WS3 0x10000000 +#define S626_WS4 0x08000000 +#define S626_RSD1 0x01000000 /* Shift A1 data in on SD1. */ +#define S626_SDW_A1 0x00800000 /* Store rcv'd char at next char + * slot of DWORD1 buffer. */ +#define S626_SIB_A1 0x00400000 /* Store rcv'd char at next * char slot of FB1 buffer. */ -#define SF_A1 0x00200000 /* Write unsigned long +#define S626_SF_A1 0x00200000 /* Write unsigned long * buffer to input FIFO. */ /* Select parallel-to-serial converter's data source: */ -#define XFIFO_0 0x00000000 /* Data fifo byte 0. */ -#define XFIFO_1 0x00000010 /* Data fifo byte 1. */ -#define XFIFO_2 0x00000020 /* Data fifo byte 2. */ -#define XFIFO_3 0x00000030 /* Data fifo byte 3. */ -#define XFB0 0x00000040 /* FB_BUFFER byte 0. */ -#define XFB1 0x00000050 /* FB_BUFFER byte 1. */ -#define XFB2 0x00000060 /* FB_BUFFER byte 2. */ -#define XFB3 0x00000070 /* FB_BUFFER byte 3. */ -#define SIB_A2 0x00000200 /* Store next dword from A2's - * input shifter to FB2 buffer. */ -#define SF_A2 0x00000100 /* Store next dword from A2's +#define S626_XFIFO_0 0x00000000 /* Data fifo byte 0. */ +#define S626_XFIFO_1 0x00000010 /* Data fifo byte 1. */ +#define S626_XFIFO_2 0x00000020 /* Data fifo byte 2. */ +#define S626_XFIFO_3 0x00000030 /* Data fifo byte 3. */ +#define S626_XFB0 0x00000040 /* FB_BUFFER byte 0. */ +#define S626_XFB1 0x00000050 /* FB_BUFFER byte 1. */ +#define S626_XFB2 0x00000060 /* FB_BUFFER byte 2. */ +#define S626_XFB3 0x00000070 /* FB_BUFFER byte 3. */ +#define S626_SIB_A2 0x00000200 /* Store next dword from A2's + * input shifter to FB2 + * buffer. */ +#define S626_SF_A2 0x00000100 /* Store next dword from A2's * input shifter to its input * fifo. */ -#define LF_A2 0x00000080 /* Load next dword from A2's +#define S626_LF_A2 0x00000080 /* Load next dword from A2's * output fifo into its * output dword buffer. */ -#define XSD2 0x00000008 /* Shift data out on SD2. */ -#define RSD3 0x00001800 /* Shift data in on SD3. */ -#define RSD2 0x00001000 /* Shift data in on SD2. */ -#define LOW_A2 0x00000002 /* Drive last SD low */ - /* for 7 clks, then */ - /* tri-state. */ -#define EOS 0x00000001 /* End of superframe. */ - -/* I2C configuration constants. */ -#define I2C_CLKSEL 0x0400 -/* I2C bit rate = PCIclk/480 = 68.75 KHz. */ - -#define I2C_BITRATE 68.75 -/* I2C bus data bit rate (determined by I2C_CLKSEL) in KHz. */ - -#define I2C_WRTIME 15.0 -/* Worst case time, in msec, for EEPROM internal write op. */ - -/* I2C manifest constants. */ - -/* Max retries to wait for EEPROM write. */ -#define I2C_RETRIES (I2C_WRTIME * I2C_BITRATE / 9.0) -#define I2C_ERR 0x0002 /* I2C control/status */ - /* flag ERROR. */ -#define I2C_BUSY 0x0001 /* I2C control/status */ - /* flag BUSY. */ -#define I2C_ABORT 0x0080 /* I2C status flag ABORT. */ -#define I2C_ATTRSTART 0x3 /* I2C attribute START. */ -#define I2C_ATTRCONT 0x2 /* I2C attribute CONT. */ -#define I2C_ATTRSTOP 0x1 /* I2C attribute STOP. */ -#define I2C_ATTRNOP 0x0 /* I2C attribute NOP. */ - -/* I2C read command | EEPROM address. */ -#define I2CR (devpriv->I2CAdrs | 1) - -/* I2C write command | EEPROM address. */ -#define I2CW (devpriv->I2CAdrs) - -/* Code macros used for constructing I2C command bytes. */ -#define I2C_B2(ATTR, VAL) (((ATTR) << 6) | ((VAL) << 24)) -#define I2C_B1(ATTR, VAL) (((ATTR) << 4) | ((VAL) << 16)) -#define I2C_B0(ATTR, VAL) (((ATTR) << 2) | ((VAL) << 8)) - -/* oldest */ -#define P_DEBICFGq 0x007C /* DEBI configuration. */ -#define P_DEBICMDq 0x0080 /* DEBI command. */ -#define P_DEBIPAGEq 0x0084 /* DEBI page. */ -#define P_DEBIADq 0x0088 /* DEBI target address. */ - -#define DEBI_CFG_TOQ 0x03C00000 /* timeout (15 PCI cycles) */ -#define DEBI_CFG_FASTQ 0x10000000 /* fast mode enable */ -#define DEBI_CFG_16Q 0x00080000 /* 16-bit access enable */ -#define DEBI_CFG_INCQ 0x00040000 /* enable address increment */ -#define DEBI_CFG_TIMEROFFQ 0x00010000 /* disable timer */ -#define DEBI_CMD_RDQ 0x00050000 /* read immediate 2 bytes */ -#define DEBI_CMD_WRQ 0x00040000 /* write immediate 2 bytes */ -#define DEBI_PAGE_DISABLEQ 0x00000000 /* paging disable */ - -/* DEBI command constants. */ -#define DEBI_CMD_SIZE16 (2 << 17) /* Transfer size is */ - /* always 2 bytes. */ -#define DEBI_CMD_READ 0x00010000 /* Read operation. */ -#define DEBI_CMD_WRITE 0x00000000 /* Write operation. */ - -/* Read immediate 2 bytes. */ -#define DEBI_CMD_RDWORD (DEBI_CMD_READ | DEBI_CMD_SIZE16) - -/* Write immediate 2 bytes. */ -#define DEBI_CMD_WRWORD (DEBI_CMD_WRITE | DEBI_CMD_SIZE16) - -/* DEBI configuration constants. */ -#define DEBI_CFG_XIRQ_EN 0x80000000 /* enab external */ - /* interrupt on GPIO3. */ -#define DEBI_CFG_XRESUME 0x40000000 /* Resume block */ - /* transfer when XIRQ */ - /* deasserted. */ -#define DEBI_CFG_FAST 0x10000000 /* Fast mode enable. */ - -/* 4-bit field that specifies DEBI timeout value in PCI clock cycles: */ -#define DEBI_CFG_TOUT_BIT 22 /* Finish DEBI cycle after */ - /* this many clocks. */ - -/* 2-bit field that specifies Endian byte lane steering: */ -#define DEBI_CFG_SWAP_NONE 0x00000000 /* Straight - don't */ - /* swap any bytes */ - /* (Intel). */ -#define DEBI_CFG_SWAP_2 0x00100000 /* 2-byte swap (Motorola). */ -#define DEBI_CFG_SWAP_4 0x00200000 /* 4-byte swap. */ -#define DEBI_CFG_16 0x00080000 /* Slave is able to */ - /* serve 16-bit */ - /* cycles. */ - -#define DEBI_CFG_SLAVE16 0x00080000 /* Slave is able to */ - /* serve 16-bit */ - /* cycles. */ -#define DEBI_CFG_INC 0x00040000 /* enab address */ - /* increment for block */ - /* transfers. */ -#define DEBI_CFG_INTEL 0x00020000 /* Intel style local bus. */ -#define DEBI_CFG_TIMEROFF 0x00010000 /* Disable timer. */ - -#if PLATFORM == INTEL - -#define DEBI_TOUT 7 /* Wait 7 PCI clocks */ - /* (212 ns) before */ - /* polling RDY. */ - -/* Intel byte lane steering (pass through all byte lanes). */ -#define DEBI_SWAP DEBI_CFG_SWAP_NONE - -#elif PLATFORM == MOTOROLA - -#define DEBI_TOUT 15 /* Wait 15 PCI clocks (454 ns) */ - /* maximum before timing out. */ -#define DEBI_SWAP DEBI_CFG_SWAP_2 /* Motorola byte lane steering. */ +#define S626_XSD2 0x00000008 /* Shift data out on SD2. */ +#define S626_RSD3 0x00001800 /* Shift data in on SD3. */ +#define S626_RSD2 0x00001000 /* Shift data in on SD2. */ +#define S626_LOW_A2 0x00000002 /* Drive last SD low for 7 clks, + * then tri-state. */ +#define S626_EOS 0x00000001 /* End of superframe. */ + +/* I2C configuration constants. */ +#define S626_I2C_CLKSEL 0x0400 /* I2C bit rate = + * PCIclk/480 = 68.75 KHz. */ +#define S626_I2C_BITRATE 68.75 /* I2C bus data bit rate + * (determined by + * S626_I2C_CLKSEL) in KHz. */ +#define S626_I2C_WRTIME 15.0 /* Worst case time, in msec, + * for EEPROM internal write + * op. */ + +/* I2C manifest constants. */ + +/* Max retries to wait for EEPROM write. */ +#define S626_I2C_RETRIES (S626_I2C_WRTIME * S626_I2C_BITRATE / 9.0) +#define S626_I2C_ERR 0x0002 /* I2C control/status flag ERROR. */ +#define S626_I2C_BUSY 0x0001 /* I2C control/status flag BUSY. */ +#define S626_I2C_ABORT 0x0080 /* I2C status flag ABORT. */ +#define S626_I2C_ATTRSTART 0x3 /* I2C attribute START. */ +#define S626_I2C_ATTRCONT 0x2 /* I2C attribute CONT. */ +#define S626_I2C_ATTRSTOP 0x1 /* I2C attribute STOP. */ +#define S626_I2C_ATTRNOP 0x0 /* I2C attribute NOP. */ + +/* Code macros used for constructing I2C command bytes. */ +#define S626_I2C_B2(ATTR, VAL) (((ATTR) << 6) | ((VAL) << 24)) +#define S626_I2C_B1(ATTR, VAL) (((ATTR) << 4) | ((VAL) << 16)) +#define S626_I2C_B0(ATTR, VAL) (((ATTR) << 2) | ((VAL) << 8)) + +/* DEBI command constants. */ +#define S626_DEBI_CMD_SIZE16 (2 << 17) /* Transfer size is always + * 2 bytes. */ +#define S626_DEBI_CMD_READ 0x00010000 /* Read operation. */ +#define S626_DEBI_CMD_WRITE 0x00000000 /* Write operation. */ + +/* Read immediate 2 bytes. */ +#define S626_DEBI_CMD_RDWORD (S626_DEBI_CMD_READ | S626_DEBI_CMD_SIZE16) + +/* Write immediate 2 bytes. */ +#define S626_DEBI_CMD_WRWORD (S626_DEBI_CMD_WRITE | S626_DEBI_CMD_SIZE16) + +/* DEBI configuration constants. */ +#define S626_DEBI_CFG_XIRQ_EN 0x80000000 /* Enable external interrupt + * on GPIO3. */ +#define S626_DEBI_CFG_XRESUME 0x40000000 /* Resume block */ + /* Transfer when XIRQ + * deasserted. */ +#define S626_DEBI_CFG_TOQ 0x03C00000 /* Timeout (15 PCI cycles). */ +#define S626_DEBI_CFG_FAST 0x10000000 /* Fast mode enable. */ + +/* 4-bit field that specifies DEBI timeout value in PCI clock cycles: */ +#define S626_DEBI_CFG_TOUT_BIT 22 /* Finish DEBI cycle after this many + * clocks. */ + +/* 2-bit field that specifies Endian byte lane steering: */ +#define S626_DEBI_CFG_SWAP_NONE 0x00000000 /* Straight - don't swap any + * bytes (Intel). */ +#define S626_DEBI_CFG_SWAP_2 0x00100000 /* 2-byte swap (Motorola). */ +#define S626_DEBI_CFG_SWAP_4 0x00200000 /* 4-byte swap. */ +#define S626_DEBI_CFG_SLAVE16 0x00080000 /* Slave is able to serve + * 16-bit cycles. */ +#define S626_DEBI_CFG_INC 0x00040000 /* Enable address increment + * for block transfers. */ +#define S626_DEBI_CFG_INTEL 0x00020000 /* Intel style local bus. */ +#define S626_DEBI_CFG_TIMEROFF 0x00010000 /* Disable timer. */ + +#if S626_PLATFORM == S626_INTEL + +#define S626_DEBI_TOUT 7 /* Wait 7 PCI clocks (212 ns) before + * polling RDY. */ + +/* Intel byte lane steering (pass through all byte lanes). */ +#define S626_DEBI_SWAP S626_DEBI_CFG_SWAP_NONE + +#elif S626_PLATFORM == S626_MOTOROLA + +#define S626_DEBI_TOUT 15 /* Wait 15 PCI clocks (454 ns) maximum + * before timing out. */ + +/* Motorola byte lane steering. */ +#define S626_DEBI_SWAP S626_DEBI_CFG_SWAP_2 #endif -/* DEBI page table constants. */ -#define DEBI_PAGE_DISABLE 0x00000000 /* Paging disable. */ - -/* ******* EXTRA FROM OTHER SANSORAY * .h ******* */ - -/* LoadSrc values: */ -#define LOADSRC_INDX 0 /* Preload core in response to */ - /* Index. */ -#define LOADSRC_OVER 1 /* Preload core in response to */ - /* Overflow. */ -#define LOADSRCB_OVERA 2 /* Preload B core in response */ - /* to A Overflow. */ -#define LOADSRC_NONE 3 /* Never preload core. */ - -/* IntSrc values: */ -#define INTSRC_NONE 0 /* Interrupts disabled. */ -#define INTSRC_OVER 1 /* Interrupt on Overflow. */ -#define INTSRC_INDX 2 /* Interrupt on Index. */ -#define INTSRC_BOTH 3 /* Interrupt on Index or Overflow. */ - -/* LatchSrc values: */ -#define LATCHSRC_AB_READ 0 /* Latch on read. */ -#define LATCHSRC_A_INDXA 1 /* Latch A on A Index. */ -#define LATCHSRC_B_INDXB 2 /* Latch B on B Index. */ -#define LATCHSRC_B_OVERA 3 /* Latch B on A Overflow. */ - -/* IndxSrc values: */ -#define INDXSRC_HARD 0 /* Hardware or software index. */ -#define INDXSRC_SOFT 1 /* Software index only. */ - -/* IndxPol values: */ -#define INDXPOL_POS 0 /* Index input is active high. */ -#define INDXPOL_NEG 1 /* Index input is active low. */ - -/* ClkSrc values: */ -#define CLKSRC_COUNTER 0 /* Counter mode. */ -#define CLKSRC_TIMER 2 /* Timer mode. */ -#define CLKSRC_EXTENDER 3 /* Extender mode. */ - -/* ClkPol values: */ -#define CLKPOL_POS 0 /* Counter/Extender clock is */ - /* active high. */ -#define CLKPOL_NEG 1 /* Counter/Extender clock is */ - /* active low. */ -#define CNTDIR_UP 0 /* Timer counts up. */ -#define CNTDIR_DOWN 1 /* Timer counts down. */ - -/* ClkEnab values: */ -#define CLKENAB_ALWAYS 0 /* Clock always enabled. */ -#define CLKENAB_INDEX 1 /* Clock is enabled by index. */ - -/* ClkMult values: */ -#define CLKMULT_4X 0 /* 4x clock multiplier. */ -#define CLKMULT_2X 1 /* 2x clock multiplier. */ -#define CLKMULT_1X 2 /* 1x clock multiplier. */ - -/* Bit Field positions in COUNTER_SETUP structure: */ -#define BF_LOADSRC 9 /* Preload trigger. */ -#define BF_INDXSRC 7 /* Index source. */ -#define BF_INDXPOL 6 /* Index polarity. */ -#define BF_CLKSRC 4 /* Clock source. */ -#define BF_CLKPOL 3 /* Clock polarity/count direction. */ -#define BF_CLKMULT 1 /* Clock multiplier. */ -#define BF_CLKENAB 0 /* Clock enable. */ - -/* Enumerated counter operating modes specified by ClkSrc bit field in */ -/* a COUNTER_SETUP. */ - -#define CLKSRC_COUNTER 0 /* Counter: ENC_C clock, ENC_D */ - /* direction. */ -#define CLKSRC_TIMER 2 /* Timer: SYS_C clock, */ - /* direction specified by */ - /* ClkPol. */ -#define CLKSRC_EXTENDER 3 /* Extender: OVR_A clock, */ - /* ENC_D direction. */ - -/* Enumerated counter clock multipliers. */ - -#define MULT_X0 0x0003 /* Supports no multipliers; */ - /* fixed physical multiplier = */ - /* 3. */ -#define MULT_X1 0x0002 /* Supports multiplier x1; */ - /* fixed physical multiplier = */ - /* 2. */ -#define MULT_X2 0x0001 /* Supports multipliers x1, */ - /* x2; physical multipliers = */ - /* 1 or 2. */ -#define MULT_X4 0x0000 /* Supports multipliers x1, */ - /* x2, x4; physical */ - /* multipliers = 0, 1 or 2. */ - -/* Sanity-check limits for parameters. */ - -#define NUM_COUNTERS 6 /* Maximum valid counter */ - /* logical channel number. */ -#define NUM_INTSOURCES 4 -#define NUM_LATCHSOURCES 4 -#define NUM_CLKMULTS 4 -#define NUM_CLKSOURCES 4 -#define NUM_CLKPOLS 2 -#define NUM_INDEXPOLS 2 -#define NUM_INDEXSOURCES 2 -#define NUM_LOADTRIGS 4 - -/* Bit field positions in CRA and CRB counter control registers. */ - -/* Bit field positions in CRA: */ -#define CRABIT_INDXSRC_B 14 /* B index source. */ -#define CRABIT_CLKSRC_B 12 /* B clock source. */ -#define CRABIT_INDXPOL_A 11 /* A index polarity. */ -#define CRABIT_LOADSRC_A 9 /* A preload trigger. */ -#define CRABIT_CLKMULT_A 7 /* A clock multiplier. */ -#define CRABIT_INTSRC_A 5 /* A interrupt source. */ -#define CRABIT_CLKPOL_A 4 /* A clock polarity. */ -#define CRABIT_INDXSRC_A 2 /* A index source. */ -#define CRABIT_CLKSRC_A 0 /* A clock source. */ - -/* Bit field positions in CRB: */ -#define CRBBIT_INTRESETCMD 15 /* Interrupt reset command. */ -#define CRBBIT_INTRESET_B 14 /* B interrupt reset enable. */ -#define CRBBIT_INTRESET_A 13 /* A interrupt reset enable. */ -#define CRBBIT_CLKENAB_A 12 /* A clock enable. */ -#define CRBBIT_INTSRC_B 10 /* B interrupt source. */ -#define CRBBIT_LATCHSRC 8 /* A/B latch source. */ -#define CRBBIT_LOADSRC_B 6 /* B preload trigger. */ -#define CRBBIT_CLKMULT_B 3 /* B clock multiplier. */ -#define CRBBIT_CLKENAB_B 2 /* B clock enable. */ -#define CRBBIT_INDXPOL_B 1 /* B index polarity. */ -#define CRBBIT_CLKPOL_B 0 /* B clock polarity. */ - -/* Bit field masks for CRA and CRB. */ - -#define CRAMSK_INDXSRC_B (3 << CRABIT_INDXSRC_B) -#define CRAMSK_CLKSRC_B (3 << CRABIT_CLKSRC_B) -#define CRAMSK_INDXPOL_A (1 << CRABIT_INDXPOL_A) -#define CRAMSK_LOADSRC_A (3 << CRABIT_LOADSRC_A) -#define CRAMSK_CLKMULT_A (3 << CRABIT_CLKMULT_A) -#define CRAMSK_INTSRC_A (3 << CRABIT_INTSRC_A) -#define CRAMSK_CLKPOL_A (3 << CRABIT_CLKPOL_A) -#define CRAMSK_INDXSRC_A (3 << CRABIT_INDXSRC_A) -#define CRAMSK_CLKSRC_A (3 << CRABIT_CLKSRC_A) - -#define CRBMSK_INTRESETCMD (1 << CRBBIT_INTRESETCMD) -#define CRBMSK_INTRESET_B (1 << CRBBIT_INTRESET_B) -#define CRBMSK_INTRESET_A (1 << CRBBIT_INTRESET_A) -#define CRBMSK_CLKENAB_A (1 << CRBBIT_CLKENAB_A) -#define CRBMSK_INTSRC_B (3 << CRBBIT_INTSRC_B) -#define CRBMSK_LATCHSRC (3 << CRBBIT_LATCHSRC) -#define CRBMSK_LOADSRC_B (3 << CRBBIT_LOADSRC_B) -#define CRBMSK_CLKMULT_B (3 << CRBBIT_CLKMULT_B) -#define CRBMSK_CLKENAB_B (1 << CRBBIT_CLKENAB_B) -#define CRBMSK_INDXPOL_B (1 << CRBBIT_INDXPOL_B) -#define CRBMSK_CLKPOL_B (1 << CRBBIT_CLKPOL_B) - -#define CRBMSK_INTCTRL (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B) /* Interrupt reset control bits. */ - -/* Bit field positions for standardized SETUP structure. */ - -#define STDBIT_INTSRC 13 -#define STDBIT_LATCHSRC 11 -#define STDBIT_LOADSRC 9 -#define STDBIT_INDXSRC 7 -#define STDBIT_INDXPOL 6 -#define STDBIT_CLKSRC 4 -#define STDBIT_CLKPOL 3 -#define STDBIT_CLKMULT 1 -#define STDBIT_CLKENAB 0 - -/* Bit field masks for standardized SETUP structure. */ - -#define STDMSK_INTSRC (3 << STDBIT_INTSRC) -#define STDMSK_LATCHSRC (3 << STDBIT_LATCHSRC) -#define STDMSK_LOADSRC (3 << STDBIT_LOADSRC) -#define STDMSK_INDXSRC (1 << STDBIT_INDXSRC) -#define STDMSK_INDXPOL (1 << STDBIT_INDXPOL) -#define STDMSK_CLKSRC (3 << STDBIT_CLKSRC) -#define STDMSK_CLKPOL (1 << STDBIT_CLKPOL) -#define STDMSK_CLKMULT (3 << STDBIT_CLKMULT) -#define STDMSK_CLKENAB (1 << STDBIT_CLKENAB) - -struct bufferDMA { - dma_addr_t PhysicalBase; - void *LogicalBase; - uint32_t DMAHandle; -}; +/* DEBI page table constants. */ +#define S626_DEBI_PAGE_DISABLE 0x00000000 /* Paging disable. */ + +/* ******* EXTRA FROM OTHER SENSORAY * .h ******* */ + +/* LoadSrc values: */ +#define S626_LOADSRC_INDX 0 /* Preload core in response to Index. */ +#define S626_LOADSRC_OVER 1 /* Preload core in response to + * Overflow. */ +#define S626_LOADSRCB_OVERA 2 /* Preload B core in response to + * A Overflow. */ +#define S626_LOADSRC_NONE 3 /* Never preload core. */ + +/* IntSrc values: */ +#define S626_INTSRC_NONE 0 /* Interrupts disabled. */ +#define S626_INTSRC_OVER 1 /* Interrupt on Overflow. */ +#define S626_INTSRC_INDX 2 /* Interrupt on Index. */ +#define S626_INTSRC_BOTH 3 /* Interrupt on Index or Overflow. */ + +/* LatchSrc values: */ +#define S626_LATCHSRC_AB_READ 0 /* Latch on read. */ +#define S626_LATCHSRC_A_INDXA 1 /* Latch A on A Index. */ +#define S626_LATCHSRC_B_INDXB 2 /* Latch B on B Index. */ +#define S626_LATCHSRC_B_OVERA 3 /* Latch B on A Overflow. */ + +/* IndxSrc values: */ +#define S626_INDXSRC_ENCODER 0 /* Encoder. */ +#define S626_INDXSRC_DIGIN 1 /* Digital inputs. */ +#define S626_INDXSRC_SOFT 2 /* S/w controlled by IndxPol bit. */ +#define S626_INDXSRC_DISABLED 3 /* Index disabled. */ + +/* IndxPol values: */ +#define S626_INDXPOL_POS 0 /* Index input is active high. */ +#define S626_INDXPOL_NEG 1 /* Index input is active low. */ + +/* Logical encoder mode values: */ +#define S626_ENCMODE_COUNTER 0 /* Counter mode. */ +#define S626_ENCMODE_TIMER 2 /* Timer mode. */ +#define S626_ENCMODE_EXTENDER 3 /* Extender mode. */ + +/* Physical CntSrc values (for Counter A source and Counter B source): */ +#define S626_CNTSRC_ENCODER 0 /* Encoder */ +#define S626_CNTSRC_DIGIN 1 /* Digital inputs */ +#define S626_CNTSRC_SYSCLK 2 /* System clock up */ +#define S626_CNTSRC_SYSCLK_DOWN 3 /* System clock down */ + +/* ClkPol values: */ +#define S626_CLKPOL_POS 0 /* Counter/Extender clock is + * active high. */ +#define S626_CLKPOL_NEG 1 /* Counter/Extender clock is + * active low. */ +#define S626_CNTDIR_UP 0 /* Timer counts up. */ +#define S626_CNTDIR_DOWN 1 /* Timer counts down. */ + +/* ClkEnab values: */ +#define S626_CLKENAB_ALWAYS 0 /* Clock always enabled. */ +#define S626_CLKENAB_INDEX 1 /* Clock is enabled by index. */ + +/* ClkMult values: */ +#define S626_CLKMULT_4X 0 /* 4x clock multiplier. */ +#define S626_CLKMULT_2X 1 /* 2x clock multiplier. */ +#define S626_CLKMULT_1X 2 /* 1x clock multiplier. */ +#define S626_CLKMULT_SPECIAL 3 /* Special clock multiplier value. */ + +/* Sanity-check limits for parameters. */ + +#define S626_NUM_COUNTERS 6 /* Maximum valid counter + * logical channel number. */ +#define S626_NUM_INTSOURCES 4 +#define S626_NUM_LATCHSOURCES 4 +#define S626_NUM_CLKMULTS 4 +#define S626_NUM_CLKSOURCES 4 +#define S626_NUM_CLKPOLS 2 +#define S626_NUM_INDEXPOLS 2 +#define S626_NUM_INDEXSOURCES 2 +#define S626_NUM_LOADTRIGS 4 + +/* General macros for manipulating bitfields: */ +#define S626_MAKE(x, w, p) (((x) & ((1 << (w)) - 1)) << (p)) +#define S626_UNMAKE(v, w, p) (((v) >> (p)) & ((1 << (w)) - 1)) + +/* Bit field positions in CRA: */ +#define S626_CRABIT_INDXSRC_B 14 /* B index source. */ +#define S626_CRABIT_CNTSRC_B 12 /* B counter source. */ +#define S626_CRABIT_INDXPOL_A 11 /* A index polarity. */ +#define S626_CRABIT_LOADSRC_A 9 /* A preload trigger. */ +#define S626_CRABIT_CLKMULT_A 7 /* A clock multiplier. */ +#define S626_CRABIT_INTSRC_A 5 /* A interrupt source. */ +#define S626_CRABIT_CLKPOL_A 4 /* A clock polarity. */ +#define S626_CRABIT_INDXSRC_A 2 /* A index source. */ +#define S626_CRABIT_CNTSRC_A 0 /* A counter source. */ + +/* Bit field widths in CRA: */ +#define S626_CRAWID_INDXSRC_B 2 +#define S626_CRAWID_CNTSRC_B 2 +#define S626_CRAWID_INDXPOL_A 1 +#define S626_CRAWID_LOADSRC_A 2 +#define S626_CRAWID_CLKMULT_A 2 +#define S626_CRAWID_INTSRC_A 2 +#define S626_CRAWID_CLKPOL_A 1 +#define S626_CRAWID_INDXSRC_A 2 +#define S626_CRAWID_CNTSRC_A 2 + +/* Bit field masks for CRA: */ +#define S626_CRAMSK_INDXSRC_B S626_SET_CRA_INDXSRC_B(~0) +#define S626_CRAMSK_CNTSRC_B S626_SET_CRA_CNTSRC_B(~0) +#define S626_CRAMSK_INDXPOL_A S626_SET_CRA_INDXPOL_A(~0) +#define S626_CRAMSK_LOADSRC_A S626_SET_CRA_LOADSRC_A(~0) +#define S626_CRAMSK_CLKMULT_A S626_SET_CRA_CLKMULT_A(~0) +#define S626_CRAMSK_INTSRC_A S626_SET_CRA_INTSRC_A(~0) +#define S626_CRAMSK_CLKPOL_A S626_SET_CRA_CLKPOL_A(~0) +#define S626_CRAMSK_INDXSRC_A S626_SET_CRA_INDXSRC_A(~0) +#define S626_CRAMSK_CNTSRC_A S626_SET_CRA_CNTSRC_A(~0) + +/* Construct parts of the CRA value: */ +#define S626_SET_CRA_INDXSRC_B(x) \ + S626_MAKE((x), S626_CRAWID_INDXSRC_B, S626_CRABIT_INDXSRC_B) +#define S626_SET_CRA_CNTSRC_B(x) \ + S626_MAKE((x), S626_CRAWID_CNTSRC_B, S626_CRABIT_CNTSRC_B) +#define S626_SET_CRA_INDXPOL_A(x) \ + S626_MAKE((x), S626_CRAWID_INDXPOL_A, S626_CRABIT_INDXPOL_A) +#define S626_SET_CRA_LOADSRC_A(x) \ + S626_MAKE((x), S626_CRAWID_LOADSRC_A, S626_CRABIT_LOADSRC_A) +#define S626_SET_CRA_CLKMULT_A(x) \ + S626_MAKE((x), S626_CRAWID_CLKMULT_A, S626_CRABIT_CLKMULT_A) +#define S626_SET_CRA_INTSRC_A(x) \ + S626_MAKE((x), S626_CRAWID_INTSRC_A, S626_CRABIT_INTSRC_A) +#define S626_SET_CRA_CLKPOL_A(x) \ + S626_MAKE((x), S626_CRAWID_CLKPOL_A, S626_CRABIT_CLKPOL_A) +#define S626_SET_CRA_INDXSRC_A(x) \ + S626_MAKE((x), S626_CRAWID_INDXSRC_A, S626_CRABIT_INDXSRC_A) +#define S626_SET_CRA_CNTSRC_A(x) \ + S626_MAKE((x), S626_CRAWID_CNTSRC_A, S626_CRABIT_CNTSRC_A) + +/* Extract parts of the CRA value: */ +#define S626_GET_CRA_INDXSRC_B(v) \ + S626_UNMAKE((v), S626_CRAWID_INDXSRC_B, S626_CRABIT_INDXSRC_B) +#define S626_GET_CRA_CNTSRC_B(v) \ + S626_UNMAKE((v), S626_CRAWID_CNTSRC_B, S626_CRABIT_CNTSRC_B) +#define S626_GET_CRA_INDXPOL_A(v) \ + S626_UNMAKE((v), S626_CRAWID_INDXPOL_A, S626_CRABIT_INDXPOL_A) +#define S626_GET_CRA_LOADSRC_A(v) \ + S626_UNMAKE((v), S626_CRAWID_LOADSRC_A, S626_CRABIT_LOADSRC_A) +#define S626_GET_CRA_CLKMULT_A(v) \ + S626_UNMAKE((v), S626_CRAWID_CLKMULT_A, S626_CRABIT_CLKMULT_A) +#define S626_GET_CRA_INTSRC_A(v) \ + S626_UNMAKE((v), S626_CRAWID_INTSRC_A, S626_CRABIT_INTSRC_A) +#define S626_GET_CRA_CLKPOL_A(v) \ + S626_UNMAKE((v), S626_CRAWID_CLKPOL_A, S626_CRABIT_CLKPOL_A) +#define S626_GET_CRA_INDXSRC_A(v) \ + S626_UNMAKE((v), S626_CRAWID_INDXSRC_A, S626_CRABIT_INDXSRC_A) +#define S626_GET_CRA_CNTSRC_A(v) \ + S626_UNMAKE((v), S626_CRAWID_CNTSRC_A, S626_CRABIT_CNTSRC_A) + +/* Bit field positions in CRB: */ +#define S626_CRBBIT_INTRESETCMD 15 /* (w) Interrupt reset command. */ +#define S626_CRBBIT_CNTDIR_B 15 /* (r) B counter direction. */ +#define S626_CRBBIT_INTRESET_B 14 /* (w) B interrupt reset enable. */ +#define S626_CRBBIT_OVERDO_A 14 /* (r) A overflow routed to dig. out. */ +#define S626_CRBBIT_INTRESET_A 13 /* (w) A interrupt reset enable. */ +#define S626_CRBBIT_OVERDO_B 13 /* (r) B overflow routed to dig. out. */ +#define S626_CRBBIT_CLKENAB_A 12 /* A clock enable. */ +#define S626_CRBBIT_INTSRC_B 10 /* B interrupt source. */ +#define S626_CRBBIT_LATCHSRC 8 /* A/B latch source. */ +#define S626_CRBBIT_LOADSRC_B 6 /* B preload trigger. */ +#define S626_CRBBIT_CLEAR_B 7 /* B cleared when A overflows. */ +#define S626_CRBBIT_CLKMULT_B 3 /* B clock multiplier. */ +#define S626_CRBBIT_CLKENAB_B 2 /* B clock enable. */ +#define S626_CRBBIT_INDXPOL_B 1 /* B index polarity. */ +#define S626_CRBBIT_CLKPOL_B 0 /* B clock polarity. */ + +/* Bit field widths in CRB: */ +#define S626_CRBWID_INTRESETCMD 1 +#define S626_CRBWID_CNTDIR_B 1 +#define S626_CRBWID_INTRESET_B 1 +#define S626_CRBWID_OVERDO_A 1 +#define S626_CRBWID_INTRESET_A 1 +#define S626_CRBWID_OVERDO_B 1 +#define S626_CRBWID_CLKENAB_A 1 +#define S626_CRBWID_INTSRC_B 2 +#define S626_CRBWID_LATCHSRC 2 +#define S626_CRBWID_LOADSRC_B 2 +#define S626_CRBWID_CLEAR_B 1 +#define S626_CRBWID_CLKMULT_B 2 +#define S626_CRBWID_CLKENAB_B 1 +#define S626_CRBWID_INDXPOL_B 1 +#define S626_CRBWID_CLKPOL_B 1 + +/* Bit field masks for CRB: */ +#define S626_CRBMSK_INTRESETCMD S626_SET_CRB_INTRESETCMD(~0) /* (w) */ +#define S626_CRBMSK_CNTDIR_B S626_CRBMSK_INTRESETCMD /* (r) */ +#define S626_CRBMSK_INTRESET_B S626_SET_CRB_INTRESET_B(~0) /* (w) */ +#define S626_CRBMSK_OVERDO_A S626_CRBMSK_INTRESET_B /* (r) */ +#define S626_CRBMSK_INTRESET_A S626_SET_CRB_INTRESET_A(~0) /* (w) */ +#define S626_CRBMSK_OVERDO_B S626_CRBMSK_INTRESET_A /* (r) */ +#define S626_CRBMSK_CLKENAB_A S626_SET_CRB_CLKENAB_A(~0) +#define S626_CRBMSK_INTSRC_B S626_SET_CRB_INTSRC_B(~0) +#define S626_CRBMSK_LATCHSRC S626_SET_CRB_LATCHSRC(~0) +#define S626_CRBMSK_LOADSRC_B S626_SET_CRB_LOADSRC_B(~0) +#define S626_CRBMSK_CLEAR_B S626_SET_CRB_CLEAR_B(~0) +#define S626_CRBMSK_CLKMULT_B S626_SET_CRB_CLKMULT_B(~0) +#define S626_CRBMSK_CLKENAB_B S626_SET_CRB_CLKENAB_B(~0) +#define S626_CRBMSK_INDXPOL_B S626_SET_CRB_INDXPOL_B(~0) +#define S626_CRBMSK_CLKPOL_B S626_SET_CRB_CLKPOL_B(~0) + +/* Interrupt reset control bits. */ +#define S626_CRBMSK_INTCTRL (S626_CRBMSK_INTRESETCMD | \ + S626_CRBMSK_INTRESET_A | \ + S626_CRBMSK_INTRESET_B) + +/* Construct parts of the CRB value: */ +#define S626_SET_CRB_INTRESETCMD(x) \ + S626_MAKE((x), S626_CRBWID_INTRESETCMD, S626_CRBBIT_INTRESETCMD) +#define S626_SET_CRB_INTRESET_B(x) \ + S626_MAKE((x), S626_CRBWID_INTRESET_B, S626_CRBBIT_INTRESET_B) +#define S626_SET_CRB_INTRESET_A(x) \ + S626_MAKE((x), S626_CRBWID_INTRESET_A, S626_CRBBIT_INTRESET_A) +#define S626_SET_CRB_CLKENAB_A(x) \ + S626_MAKE((x), S626_CRBWID_CLKENAB_A, S626_CRBBIT_CLKENAB_A) +#define S626_SET_CRB_INTSRC_B(x) \ + S626_MAKE((x), S626_CRBWID_INTSRC_B, S626_CRBBIT_INTSRC_B) +#define S626_SET_CRB_LATCHSRC(x) \ + S626_MAKE((x), S626_CRBWID_LATCHSRC, S626_CRBBIT_LATCHSRC) +#define S626_SET_CRB_LOADSRC_B(x) \ + S626_MAKE((x), S626_CRBWID_LOADSRC_B, S626_CRBBIT_LOADSRC_B) +#define S626_SET_CRB_CLEAR_B(x) \ + S626_MAKE((x), S626_CRBWID_CLEAR_B, S626_CRBBIT_CLEAR_B) +#define S626_SET_CRB_CLKMULT_B(x) \ + S626_MAKE((x), S626_CRBWID_CLKMULT_B, S626_CRBBIT_CLKMULT_B) +#define S626_SET_CRB_CLKENAB_B(x) \ + S626_MAKE((x), S626_CRBWID_CLKENAB_B, S626_CRBBIT_CLKENAB_B) +#define S626_SET_CRB_INDXPOL_B(x) \ + S626_MAKE((x), S626_CRBWID_INDXPOL_B, S626_CRBBIT_INDXPOL_B) +#define S626_SET_CRB_CLKPOL_B(x) \ + S626_MAKE((x), S626_CRBWID_CLKPOL_B, S626_CRBBIT_CLKPOL_B) + +/* Extract parts of the CRB value: */ +#define S626_GET_CRB_CNTDIR_B(v) \ + S626_UNMAKE((v), S626_CRBWID_CNTDIR_B, S626_CRBBIT_CNTDIR_B) +#define S626_GET_CRB_OVERDO_A(v) \ + S626_UNMAKE((v), S626_CRBWID_OVERDO_A, S626_CRBBIT_OVERDO_A) +#define S626_GET_CRB_OVERDO_B(v) \ + S626_UNMAKE((v), S626_CRBWID_OVERDO_B, S626_CRBBIT_OVERDO_B) +#define S626_GET_CRB_CLKENAB_A(v) \ + S626_UNMAKE((v), S626_CRBWID_CLKENAB_A, S626_CRBBIT_CLKENAB_A) +#define S626_GET_CRB_INTSRC_B(v) \ + S626_UNMAKE((v), S626_CRBWID_INTSRC_B, S626_CRBBIT_INTSRC_B) +#define S626_GET_CRB_LATCHSRC(v) \ + S626_UNMAKE((v), S626_CRBWID_LATCHSRC, S626_CRBBIT_LATCHSRC) +#define S626_GET_CRB_LOADSRC_B(v) \ + S626_UNMAKE((v), S626_CRBWID_LOADSRC_B, S626_CRBBIT_LOADSRC_B) +#define S626_GET_CRB_CLEAR_B(v) \ + S626_UNMAKE((v), S626_CRBWID_CLEAR_B, S626_CRBBIT_CLEAR_B) +#define S626_GET_CRB_CLKMULT_B(v) \ + S626_UNMAKE((v), S626_CRBWID_CLKMULT_B, S626_CRBBIT_CLKMULT_B) +#define S626_GET_CRB_CLKENAB_B(v) \ + S626_UNMAKE((v), S626_CRBWID_CLKENAB_B, S626_CRBBIT_CLKENAB_B) +#define S626_GET_CRB_INDXPOL_B(v) \ + S626_UNMAKE((v), S626_CRBWID_INDXPOL_B, S626_CRBBIT_INDXPOL_B) +#define S626_GET_CRB_CLKPOL_B(v) \ + S626_UNMAKE((v), S626_CRBWID_CLKPOL_B, S626_CRBBIT_CLKPOL_B) + +/* Bit field positions for standardized SETUP structure: */ +#define S626_STDBIT_INTSRC 13 +#define S626_STDBIT_LATCHSRC 11 +#define S626_STDBIT_LOADSRC 9 +#define S626_STDBIT_INDXSRC 7 +#define S626_STDBIT_INDXPOL 6 +#define S626_STDBIT_ENCMODE 4 +#define S626_STDBIT_CLKPOL 3 +#define S626_STDBIT_CLKMULT 1 +#define S626_STDBIT_CLKENAB 0 + +/* Bit field widths for standardized SETUP structure: */ +#define S626_STDWID_INTSRC 2 +#define S626_STDWID_LATCHSRC 2 +#define S626_STDWID_LOADSRC 2 +#define S626_STDWID_INDXSRC 2 +#define S626_STDWID_INDXPOL 1 +#define S626_STDWID_ENCMODE 2 +#define S626_STDWID_CLKPOL 1 +#define S626_STDWID_CLKMULT 2 +#define S626_STDWID_CLKENAB 1 + +/* Bit field masks for standardized SETUP structure: */ +#define S626_STDMSK_INTSRC S626_SET_STD_INTSRC(~0) +#define S626_STDMSK_LATCHSRC S626_SET_STD_LATCHSRC(~0) +#define S626_STDMSK_LOADSRC S626_SET_STD_LOADSRC(~0) +#define S626_STDMSK_INDXSRC S626_SET_STD_INDXSRC(~0) +#define S626_STDMSK_INDXPOL S626_SET_STD_INDXPOL(~0) +#define S626_STDMSK_ENCMODE S626_SET_STD_ENCMODE(~0) +#define S626_STDMSK_CLKPOL S626_SET_STD_CLKPOL(~0) +#define S626_STDMSK_CLKMULT S626_SET_STD_CLKMULT(~0) +#define S626_STDMSK_CLKENAB S626_SET_STD_CLKENAB(~0) + +/* Construct parts of standardized SETUP structure: */ +#define S626_SET_STD_INTSRC(x) \ + S626_MAKE((x), S626_STDWID_INTSRC, S626_STDBIT_INTSRC) +#define S626_SET_STD_LATCHSRC(x) \ + S626_MAKE((x), S626_STDWID_LATCHSRC, S626_STDBIT_LATCHSRC) +#define S626_SET_STD_LOADSRC(x) \ + S626_MAKE((x), S626_STDWID_LOADSRC, S626_STDBIT_LOADSRC) +#define S626_SET_STD_INDXSRC(x) \ + S626_MAKE((x), S626_STDWID_INDXSRC, S626_STDBIT_INDXSRC) +#define S626_SET_STD_INDXPOL(x) \ + S626_MAKE((x), S626_STDWID_INDXPOL, S626_STDBIT_INDXPOL) +#define S626_SET_STD_ENCMODE(x) \ + S626_MAKE((x), S626_STDWID_ENCMODE, S626_STDBIT_ENCMODE) +#define S626_SET_STD_CLKPOL(x) \ + S626_MAKE((x), S626_STDWID_CLKPOL, S626_STDBIT_CLKPOL) +#define S626_SET_STD_CLKMULT(x) \ + S626_MAKE((x), S626_STDWID_CLKMULT, S626_STDBIT_CLKMULT) +#define S626_SET_STD_CLKENAB(x) \ + S626_MAKE((x), S626_STDWID_CLKENAB, S626_STDBIT_CLKENAB) + +/* Extract parts of standardized SETUP structure: */ +#define S626_GET_STD_INTSRC(v) \ + S626_UNMAKE((v), S626_STDWID_INTSRC, S626_STDBIT_INTSRC) +#define S626_GET_STD_LATCHSRC(v) \ + S626_UNMAKE((v), S626_STDWID_LATCHSRC, S626_STDBIT_LATCHSRC) +#define S626_GET_STD_LOADSRC(v) \ + S626_UNMAKE((v), S626_STDWID_LOADSRC, S626_STDBIT_LOADSRC) +#define S626_GET_STD_INDXSRC(v) \ + S626_UNMAKE((v), S626_STDWID_INDXSRC, S626_STDBIT_INDXSRC) +#define S626_GET_STD_INDXPOL(v) \ + S626_UNMAKE((v), S626_STDWID_INDXPOL, S626_STDBIT_INDXPOL) +#define S626_GET_STD_ENCMODE(v) \ + S626_UNMAKE((v), S626_STDWID_ENCMODE, S626_STDBIT_ENCMODE) +#define S626_GET_STD_CLKPOL(v) \ + S626_UNMAKE((v), S626_STDWID_CLKPOL, S626_STDBIT_CLKPOL) +#define S626_GET_STD_CLKMULT(v) \ + S626_UNMAKE((v), S626_STDWID_CLKMULT, S626_STDBIT_CLKMULT) +#define S626_GET_STD_CLKENAB(v) \ + S626_UNMAKE((v), S626_STDWID_CLKENAB, S626_STDBIT_CLKENAB) + +#endif diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 9e964950a560..daee2f42bde0 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -332,30 +332,44 @@ static int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return i; } -/* DIO devices are slightly special. Although it is possible to +/* + * DIO devices are slightly special. Although it is possible to * implement the insn_read/insn_write interface, it is much more * 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 */ + * This allows packed reading/writing of the DIO channels. The + * comedi core can convert between insn_bits and insn_read/write. + */ static int skel_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - if (data[0]) { - s->state &= ~data[0]; - s->state |= data[0] & data[1]; + /* + * The insn data is a mask in data[0] and the new data + * in data[1], each channel cooresponding to a bit. + * + * The core provided comedi_dio_update_state() function can + * be used to handle the internal state update to DIO subdevices + * with <= 32 channels. This function will return '0' if the + * state does not change or the mask of the channels that need + * to be updated. + */ + if (comedi_dio_update_state(s, data)) { /* Write out the new digital output lines */ - /* outw(s->state,dev->iobase + SKEL_DIO); */ + /* outw(s->state, dev->iobase + SKEL_DIO); */ } - /* on return, data[1] contains the value of the digital - * input and output lines. */ - /* data[1]=inw(dev->iobase + SKEL_DIO); */ - /* or we could just return the software copy of the output values if - * it was a purely digital output subdevice */ - /* data[1]=s->state; */ + /* + * On return, data[1] contains the value of the digital + * input and output lines. + */ + /* data[1] = inw(dev->iobase + SKEL_DIO); */ + + /* + * Or we could just return the software copy of the output + * values if it was a purely digital output subdevice. + */ + /* data[1] = s->state; */ return insn->n; } diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 11758a515c1b..df22a78d2b7e 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -46,51 +46,43 @@ Status: unknown #define PCMR 0xa3 /* Port C Mode Register */ #define PCDR 0xa7 /* Port C Data Register */ -/* ------------------------------------------------------------------------- */ -/* The insn_bits interface allows packed reading/writing of DIO channels. */ -/* The comedi core can convert between insn_bits and insn_read/write, so you */ -/* are able to use these instructions as well. */ -/* ------------------------------------------------------------------------- */ - static int dnp_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - /* The insn data is a mask in data[0] and the new data in data[1], */ - /* each channel cooresponding to a bit. */ - - /* Ports A and B are straight forward: each bit corresponds to an */ - /* output pin with the same order. Port C is different: bits 0...3 */ - /* correspond to bits 4...7 of the output register (PCDR). */ + unsigned int mask; + unsigned int val; - if (data[0]) { + /* + * Ports A and B are straight forward: each bit corresponds to an + * output pin with the same order. Port C is different: bits 0...3 + * correspond to bits 4...7 of the output register (PCDR). + */ + mask = comedi_dio_update_state(s, data); + if (mask) { outb(PADR, CSCIR); - outb((inb(CSCDR) - & ~(u8) (data[0] & 0x0000FF)) - | (u8) (data[1] & 0x0000FF), CSCDR); + outb(s->state & 0xff, CSCDR); outb(PBDR, CSCIR); - outb((inb(CSCDR) - & ~(u8) ((data[0] & 0x00FF00) >> 8)) - | (u8) ((data[1] & 0x00FF00) >> 8), CSCDR); + outb((s->state >> 8) & 0xff, CSCDR); outb(PCDR, CSCIR); - outb((inb(CSCDR) - & ~(u8) ((data[0] & 0x0F0000) >> 12)) - | (u8) ((data[1] & 0x0F0000) >> 12), CSCDR); + val = inb(CSCDR) & 0x0f; + outb(((s->state >> 12) & 0xf0) | val, CSCDR); } - /* on return, data[1] contains the value of the digital input lines. */ outb(PADR, CSCIR); - data[0] = inb(CSCDR); + val = inb(CSCDR); outb(PBDR, CSCIR); - data[0] += inb(CSCDR) << 8; + val |= (inb(CSCDR) << 8); outb(PCDR, CSCIR); - data[0] += ((inb(CSCDR) & 0xF0) << 12); + val |= ((inb(CSCDR) & 0xf0) << 12); - return insn->n; + data[1] = val; + return insn->n; } static int dnp_dio_insn_config(struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 701ad1a69394..da1d501d9e4e 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -122,7 +122,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define PWM_DEFAULT_PERIOD ((long)(1E9/100)) /* Size of one A/D value */ -#define SIZEADIN ((sizeof(int16_t))) +#define SIZEADIN ((sizeof(uint16_t))) /* * Size of the input-buffer IN BYTES @@ -134,7 +134,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define SIZEINSNBUF 16 /* size of one value for the D/A converter: channel and value */ -#define SIZEDAOUT ((sizeof(int8_t)+sizeof(int16_t))) +#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t))) /* * Size of the output-buffer in bytes @@ -195,15 +195,15 @@ struct usbdux_private { /* PWM period */ unsigned int pwm_period; /* PWM internal delay for the GPIF in the FX2 */ - int8_t pwm_delay; + uint8_t pwm_delay; /* size of the PWM buffer which holds the bit pattern */ int pwm_buf_sz; /* input buffer for the ISO-transfer */ - int16_t *in_buf; + uint16_t *in_buf; /* input buffer for single insn */ - int16_t *insn_buf; + uint16_t *insn_buf; - int8_t ao_chanlist[USBDUX_NUM_AO_CHAN]; + uint8_t ao_chanlist[USBDUX_NUM_AO_CHAN]; unsigned int ao_readback[USBDUX_NUM_AO_CHAN]; unsigned int high_speed:1; @@ -225,7 +225,7 @@ struct usbdux_private { /* interval in frames/uframes */ unsigned int ai_interval; /* commands */ - int8_t *dux_commands; + uint8_t *dux_commands; struct semaphore sem; }; @@ -367,7 +367,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) n = s->async->cmd.chanlist_len; for (i = 0; i < n; i++) { unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]); - int16_t val = le16_to_cpu(devpriv->in_buf[i]); + uint16_t val = le16_to_cpu(devpriv->in_buf[i]); /* bipolar data is two's-complement */ if (comedi_range_is_bipolar(s, range)) @@ -415,7 +415,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) struct comedi_device *dev = urb->context; struct comedi_subdevice *s = dev->write_subdev; struct usbdux_private *devpriv = dev->private; - int8_t *datap; + uint8_t *datap; int len; int ret; int i; @@ -483,7 +483,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) *datap++ = len; for (i = 0; i < s->async->cmd.chanlist_len; i++) { unsigned int chan = devpriv->ao_chanlist[i]; - short val; + unsigned short val; ret = comedi_buf_get(s->async, &val); if (ret < 0) { @@ -649,14 +649,15 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, * creates the ADC command for the MAX1271 * range is the range value from comedi */ -static int8_t create_adc_command(unsigned int chan, int range) +static uint8_t create_adc_command(unsigned int chan, unsigned int range) { - int8_t p = (range <= 1); - int8_t r = ((range % 2) == 0); + uint8_t p = (range <= 1); + uint8_t r = ((range % 2) == 0); + return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3); } -static int send_dux_commands(struct comedi_device *dev, int cmd_type) +static int send_dux_commands(struct comedi_device *dev, unsigned int cmd_type) { struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; @@ -669,7 +670,7 @@ static int send_dux_commands(struct comedi_device *dev, int cmd_type) &nsent, BULK_TIMEOUT); } -static int receive_dux_commands(struct comedi_device *dev, int command) +static int receive_dux_commands(struct comedi_device *dev, unsigned int command) { struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; @@ -879,7 +880,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int val = devpriv->ao_readback[chan]; - int16_t *p = (int16_t *)&devpriv->dux_commands[2]; + uint16_t *p = (uint16_t *)&devpriv->dux_commands[2]; int ret = -EBUSY; int i; @@ -1133,15 +1134,13 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, { struct usbdux_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; int ret; down(&devpriv->sem); - s->state &= ~mask; - s->state |= (bits & mask); + comedi_dio_update_state(s, data); + /* Always update the hardware. See the (*insn_config). */ devpriv->dux_commands[1] = s->io_bits; devpriv->dux_commands[2] = s->state; @@ -1200,7 +1199,7 @@ static int usbdux_counter_write(struct comedi_device *dev, { struct usbdux_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - int16_t *p = (int16_t *)&devpriv->dux_commands[2]; + uint16_t *p = (uint16_t *)&devpriv->dux_commands[2]; int ret = 0; int i; diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index c47f4087568f..a5363ded3668 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -78,7 +78,7 @@ #define USBDUXSIGMA_NUM_AO_CHAN 4 /* Size of one A/D value */ -#define SIZEADIN ((sizeof(int32_t))) +#define SIZEADIN ((sizeof(uint32_t))) /* * Size of the async input-buffer IN BYTES, the DIO state is transmitted @@ -93,7 +93,7 @@ #define NUMOUTCHANNELS 8 /* size of one value for the D/A converter: channel and value */ -#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(int16_t))) +#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t))) /* * Size of the output-buffer in bytes @@ -157,11 +157,11 @@ struct usbduxsigma_private { /* size of the PWM buffer which holds the bit pattern */ int pwm_buf_sz; /* input buffer for the ISO-transfer */ - int32_t *in_buf; + uint32_t *in_buf; /* input buffer for single insn */ - int8_t *insn_buf; + uint8_t *insn_buf; - int8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN]; + uint8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN]; unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN]; unsigned high_speed:1; @@ -224,7 +224,7 @@ static void usbduxsigma_ai_urb_complete(struct urb *urb) struct usbduxsigma_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int dio_state; - int32_t val; + uint32_t val; int ret; int i; @@ -421,7 +421,7 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb) *datap++ = len; for (i = 0; i < len; i++) { unsigned int chan = devpriv->ao_chanlist[i]; - short val; + unsigned short val; ret = comedi_buf_get(s->async, &val); if (ret < 0) { @@ -784,7 +784,7 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, } for (i = 0; i < insn->n; i++) { - int32_t val; + uint32_t val; ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD); if (ret < 0) { @@ -793,7 +793,7 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, } /* 32 bits big endian from the A/D converter */ - val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf) + 1))); + val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf) + 1))); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ @@ -1059,15 +1059,13 @@ static int usbduxsigma_dio_insn_bits(struct comedi_device *dev, unsigned int *data) { struct usbduxsigma_private *devpriv = dev->private; - unsigned int mask = data[0]; - unsigned int bits = data[1]; int ret; down(&devpriv->sem); - s->state &= ~mask; - s->state |= (bits & mask); + comedi_dio_update_state(s, data); + /* Always update the hardware. See the (*insn_config). */ devpriv->dux_commands[1] = s->io_bits & 0xff; devpriv->dux_commands[4] = s->state & 0xff; devpriv->dux_commands[2] = (s->io_bits >> 8) & 0xff; @@ -1360,7 +1358,7 @@ static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan) return ret; /* 32 bits big endian from the A/D converter */ - val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf)+1))); + val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf)+1))); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 06efa16b9af2..933b01a0f03d 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -462,9 +462,10 @@ static int vmk80xx_do_insn_bits(struct comedi_device *dev, unsigned int *data) { struct vmk80xx_private *devpriv = dev->private; - unsigned char *rx_buf, *tx_buf; + unsigned char *rx_buf = devpriv->usb_rx_buf; + unsigned char *tx_buf = devpriv->usb_tx_buf; int reg, cmd; - int retval; + int ret; if (devpriv->model == VMK8061_MODEL) { reg = VMK8061_DO_REG; @@ -476,37 +477,27 @@ static int vmk80xx_do_insn_bits(struct comedi_device *dev, down(&devpriv->limit_sem); - rx_buf = devpriv->usb_rx_buf; - tx_buf = devpriv->usb_tx_buf; - - if (data[0]) { - tx_buf[reg] &= ~data[0]; - tx_buf[reg] |= (data[0] & data[1]); - - retval = vmk80xx_write_packet(dev, cmd); - - if (retval) + if (comedi_dio_update_state(s, data)) { + tx_buf[reg] = s->state; + ret = vmk80xx_write_packet(dev, cmd); + if (ret) goto out; } if (devpriv->model == VMK8061_MODEL) { tx_buf[0] = VMK8061_CMD_RD_DO; - - retval = vmk80xx_read_packet(dev); - - if (!retval) { - data[1] = rx_buf[reg]; - retval = 2; - } + ret = vmk80xx_read_packet(dev); + if (ret) + goto out; + data[1] = rx_buf[reg]; } else { - data[1] = tx_buf[reg]; - retval = 2; + data[1] = s->state; } out: up(&devpriv->limit_sem); - return retval; + return ret ? ret : insn->n; } static int vmk80xx_cnt_insn_read(struct comedi_device *dev, |