static int dmm32at_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); unsigned int range0 = CR_RANGE(cmd->chanlist[0]); int i; for (i = 1; i < cmd->chanlist_len; i++) { unsigned int chan = CR_CHAN(cmd->chanlist[i]); unsigned int range = CR_RANGE(cmd->chanlist[i]); if (chan != (chan0 + i) % s->n_chan) { dev_dbg(dev->class_dev, "entries in chanlist must be consecutive channels, counting upwards\n"); return -EINVAL; } if (range != range0) { dev_dbg(dev->class_dev, "entries in chanlist must all have the same gain\n"); return -EINVAL; } } return 0; }
static int ni_pcidio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { if (insn->n != 1) return -EINVAL; switch (data[0]) { case INSN_CONFIG_DIO_OUTPUT: s->io_bits |= 1 << CR_CHAN(insn->chanspec); break; case INSN_CONFIG_DIO_INPUT: s->io_bits &= ~(1 << CR_CHAN(insn->chanspec)); break; case INSN_CONFIG_DIO_QUERY: data[1] = (s-> io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT : COMEDI_INPUT; return insn->n; break; default: return -EINVAL; } writel(s->io_bits, devpriv->mite->daq_io_addr + Port_Pin_Directions(0)); return 1; }
static int ni_m_series_set_second_gate(struct ni_gpct *counter, lsampl_t gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned second_gate_reg = NITIO_Gi_Second_Gate_Reg(counter->counter_index); const unsigned selected_second_gate = CR_CHAN(gate_source); /* bits of second_gate that may be meaningful to second gate register */ static const unsigned selected_second_gate_mask = 0x1f; unsigned ni_m_series_second_gate_select; /* FIXME: We don't know what the m-series second gate codes are, so we'll just pass the bits through for now. */ switch (selected_second_gate) { default: ni_m_series_second_gate_select = selected_second_gate & selected_second_gate_mask; break; }; counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Select_Bits(ni_m_series_second_gate_select); write_register(counter, counter_dev->regs[second_gate_reg], second_gate_reg); return 0; }
static int multiq3_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int n; int chan; unsigned int hi, lo; int ret; chan = CR_CHAN(insn->chanspec); outw(MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3), dev->iobase + MULTIQ3_CONTROL); ret = comedi_timeout(dev, s, insn, multiq3_ai_status, MULTIQ3_STATUS_EOC); if (ret) return ret; for (n = 0; n < insn->n; n++) { outw(0, dev->iobase + MULTIQ3_AD_CS); ret = comedi_timeout(dev, s, insn, multiq3_ai_status, MULTIQ3_STATUS_EOC_I); if (ret) return ret; hi = inb(dev->iobase + MULTIQ3_AD_CS); lo = inb(dev->iobase + MULTIQ3_AD_CS); data[n] = (((hi << 8) | lo) + 0x1000) & 0x1fff; } return n; }
static int usbduxsigma_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct usbduxsigma_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); int ret; int i; down(&devpriv->sem); if (devpriv->ao_cmd_running) { up(&devpriv->sem); return -EBUSY; } for (i = 0; i < insn->n; i++) { devpriv->dux_commands[1] = 1; /* num channels */ devpriv->dux_commands[2] = data[i]; /* value */ devpriv->dux_commands[3] = chan; /* channel number */ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DA_CMD); if (ret < 0) { up(&devpriv->sem); return ret; } s->readback[chan] = data[i]; } up(&devpriv->sem); return insn->n; }
static int pci6208_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); unsigned int val = s->readback[chan]; int ret; int i; for (i = 0; i < insn->n; i++) { val = data[i]; /* D/A transfer rate is 2.2us */ ret = comedi_timeout(dev, s, insn, pci6208_ao_eoc, 0); if (ret) return ret; /* the hardware expects two's complement values */ outw(comedi_offset_munge(s, val), dev->iobase + PCI6208_AO_CONTROL(chan)); s->readback[chan] = val; } return insn->n; }
static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct dt2815_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); unsigned int status; unsigned int lo, hi; for (i = 0; i < insn->n; i++) { lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01; hi = (data[i] & 0xff0) >> 4; status = dt2815_wait_for_status(dev, 0x00); if (status != 0) { dev_dbg(dev->class_dev, "failed to write low byte on %d reason %x\n", chan, status); return -EBUSY; } outb(lo, dev->iobase + DT2815_DATA); status = dt2815_wait_for_status(dev, 0x10); if (status != 0x10) { dev_dbg(dev->class_dev, "failed to write high byte on %d reason %x\n", chan, status); return -EBUSY; } devpriv->ao_readback[chan] = data[i]; } return i; }
/* * Called to start acquisition for an 'INTERRUPT' subdevice. */ static int dio200_start_intr(struct comedi_device *dev, struct comedi_subdevice *s) { unsigned int n; unsigned isn_bits; const struct dio200_layout *layout = dio200_dev_layout(dev); struct dio200_subdev_intr *subpriv = s->private; struct comedi_cmd *cmd = &s->async->cmd; int retval = 0; if (cmd->stop_src == TRIG_COUNT && subpriv->stopcount == 0) { /* An empty acquisition! */ s->async->events |= COMEDI_CB_EOA; subpriv->active = false; retval = 1; } else { /* Determine interrupt sources to enable. */ isn_bits = 0; if (cmd->chanlist) { for (n = 0; n < cmd->chanlist_len; n++) isn_bits |= (1U << CR_CHAN(cmd->chanlist[n])); } isn_bits &= subpriv->valid_isns; /* Enable interrupt sources. */ subpriv->enabled_isns = isn_bits; if (layout->has_int_sce) dio200_write8(dev, subpriv->ofs, isn_bits); } return retval; }
static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct dt2815_private *devpriv = dev->private; int i; int chan = CR_CHAN(insn->chanspec); unsigned int lo, hi; int ret; for (i = 0; i < insn->n; i++) { lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01; hi = (data[i] & 0xff0) >> 4; ret = comedi_timeout(dev, s, insn, dt2815_ao_status, 0x00); if (ret) return ret; outb(lo, dev->iobase + DT2815_DATA); ret = comedi_timeout(dev, s, insn, dt2815_ao_status, 0x10); if (ret) return ret; devpriv->ao_readback[chan] = data[i]; } return i; }
static void pcl711_set_changain(struct comedi_device *dev, int chan) { int chan_register; outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN); chan_register = CR_CHAN(chan); if (this_board->is_8112) { /* * 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 */ if (chan_register >= 8) chan_register = 0x20 | (chan_register & 0x7); else chan_register |= 0x10; } else { outb(chan_register, dev->iobase + PCL711_MUX); } }
static int dmm32at_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); int i; for (i = 0; i < insn->n; i++) { unsigned int val = data[i]; int ret; /* write LSB then MSB + chan to load DAC */ outb(val & 0xff, dev->iobase + DMM32AT_AO_LSB_REG); outb((val >> 8) | DMM32AT_AO_MSB_DACH(chan), dev->iobase + DMM32AT_AO_MSB_REG); /* wait for circuit to settle */ ret = comedi_timeout(dev, s, insn, dmm32at_ao_eoc, 0); if (ret) return ret; /* dummy read to update DAC */ inb(dev->iobase + DMM32AT_AO_MSB_REG); s->readback[chan] = val; } return insn->n; }
static int cb_pcimdda_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan); unsigned int val = s->readback[chan]; int i; for (i = 0; i < insn->n; i++) { val = data[i]; /* * Write the LSB then MSB. * * If the simultaneous xfer mode is selected by the * jumper on the card, a read instruction is needed * in order to initiate the simultaneous transfer. * Otherwise, the DAC will be updated when the MSB * is written. */ outb(val & 0x00ff, offset); outb((val >> 8) & 0x00ff, offset + 1); } s->readback[chan] = val; return insn->n; }
static int dac02_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { 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]; s->readback[chan] = val; /* * Unipolar outputs are true binary encoding. * Bipolar outputs are complementary offset binary * (that is, 0 = +full scale, maxdata = -full scale). */ if (comedi_range_is_bipolar(s, range)) val = s->maxdata - val; /* * DACs are double-buffered. * Write LSB then MSB to latch output. */ outb((val << 4) & 0xf0, dev->iobase + DAC02_AO_LSB(chan)); outb((val >> 4) & 0xff, dev->iobase + DAC02_AO_MSB(chan)); } return insn->n; }
static int pci1720_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); unsigned int val; int i; /* set the channel range and polarity */ val = inb(dev->iobase + PCI1720_AO_RANGE_REG); val &= ~PCI1720_AO_RANGE_MASK(chan); val |= PCI1720_AO_RANGE(chan, range); outb(val, dev->iobase + PCI1720_AO_RANGE_REG); val = s->readback[chan]; for (i = 0; i < insn->n; i++) { val = data[i]; outb(val & 0xff, dev->iobase + PCI1720_AO_LSB_REG(chan)); outb((val >> 8) & 0xff, dev->iobase + PCI1720_AO_MSB_REG(chan)); /* conversion time is 2us (500 kHz throughput) */ usleep_range(2, 100); } s->readback[chan] = val; return insn->n; }
static int ni_m_series_set_second_gate(struct ni_gpct *counter, unsigned int gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned second_gate_reg = NITIO_Gi_Second_Gate_Reg(counter->counter_index); const unsigned selected_second_gate = CR_CHAN(gate_source); static const unsigned selected_second_gate_mask = 0x1f; unsigned ni_m_series_second_gate_select; switch (selected_second_gate) { default: ni_m_series_second_gate_select = selected_second_gate & selected_second_gate_mask; break; }; counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Select_Bits(ni_m_series_second_gate_select); write_register(counter, counter_dev->regs[second_gate_reg], second_gate_reg); return 0; }
static int multiq3_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i, n; int chan; unsigned int hi, lo; chan = CR_CHAN(insn->chanspec); outw(MULTIQ3_CONTROL_MUST | MULTIQ3_AD_MUX_EN | (chan << 3), dev->iobase + MULTIQ3_CONTROL); for (i = 0; i < MULTIQ3_TIMEOUT; i++) { if (inw(dev->iobase + MULTIQ3_STATUS) & MULTIQ3_STATUS_EOC) break; } if (i == MULTIQ3_TIMEOUT) return -ETIMEDOUT; for (n = 0; n < insn->n; n++) { outw(0, dev->iobase + MULTIQ3_AD_CS); for (i = 0; i < MULTIQ3_TIMEOUT; i++) { if (inw(dev->iobase + MULTIQ3_STATUS) & MULTIQ3_STATUS_EOC_I) break; } if (i == MULTIQ3_TIMEOUT) return -ETIMEDOUT; hi = inb(dev->iobase + MULTIQ3_AD_CS); lo = inb(dev->iobase + MULTIQ3_AD_CS); data[n] = (((hi << 8) | lo) + 0x1000) & 0x1fff; } return n; }
/* overriding the 8255 insn config */ static int subdev_3724_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); unsigned int mask; int ret; if (chan < 8) mask = 0x0000ff; else if (chan < 16) mask = 0x00ff00; else if (chan < 20) mask = 0x0f0000; else mask = 0xf00000; ret = comedi_dio_insn_config(dev, s, insn, data, mask); if (ret) return ret; do_3724_config(dev, s, insn->chanspec); enable_chan(dev, s, insn->chanspec); return insn->n; }
static int usbduxsigma_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct usbduxsigma_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int len = cmd->chanlist_len; uint8_t muxsg0 = 0; uint8_t muxsg1 = 0; uint8_t sysred = 0; int ret; int i; down(&devpriv->sem); /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; for (i = 0; i < len; i++) { unsigned int chan = CR_CHAN(cmd->chanlist[i]); create_adc_command(chan, &muxsg0, &muxsg1); } devpriv->dux_commands[1] = len; /* num channels per time step */ devpriv->dux_commands[2] = 0x12; /* CONFIG0 */ devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */ devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */ devpriv->dux_commands[5] = muxsg0; devpriv->dux_commands[6] = muxsg1; devpriv->dux_commands[7] = sysred; ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD); if (ret < 0) { up(&devpriv->sem); return ret; } devpriv->ai_counter = devpriv->ai_timer; if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ devpriv->ai_cmd_running = 1; ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs, devpriv->n_ai_urbs, 1); if (ret < 0) { devpriv->ai_cmd_running = 0; up(&devpriv->sem); return ret; } s->async->inttrig = NULL; } else { /* TRIG_INT */ /* wait for an internal signal and submit the urbs later */ s->async->inttrig = usbduxsigma_ai_inttrig; } up(&devpriv->sem); return 0; }
static int ni_660x_set_second_gate(struct ni_gpct *counter, lsampl_t gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned second_gate_reg = NITIO_Gi_Second_Gate_Reg(counter->counter_index); const unsigned selected_second_gate = CR_CHAN(gate_source); /* bits of second_gate that may be meaningful to second gate register */ static const unsigned selected_second_gate_mask = 0x1f; unsigned ni_660x_second_gate_select; unsigned i; switch (selected_second_gate) { case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: case NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT: case NI_GPCT_SELECTED_GATE_GATE_SELECT: case NI_GPCT_NEXT_OUT_GATE_SELECT: case NI_GPCT_LOGIC_LOW_GATE_SELECT: ni_660x_second_gate_select = selected_second_gate & selected_second_gate_mask; break; case NI_GPCT_NEXT_SOURCE_GATE_SELECT: ni_660x_second_gate_select = NI_660x_Next_SRC_Second_Gate_Select; break; default: for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { if (selected_second_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { ni_660x_second_gate_select = selected_second_gate & selected_second_gate_mask; break; } } if (i <= ni_660x_max_rtsi_channel) break; for (i = 0; i <= ni_660x_max_up_down_pin; ++i) { if (selected_second_gate == NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) { ni_660x_second_gate_select = selected_second_gate & selected_second_gate_mask; break; } } if (i <= ni_660x_max_up_down_pin) break; return -EINVAL; break; }; counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Select_Bits(ni_660x_second_gate_select); write_register(counter, counter_dev->regs[second_gate_reg], second_gate_reg); return 0; }
static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { const struct das16_board *board = comedi_board(dev); int i, n; int range; int chan; int msb, lsb; /* disable interrupts and pacing */ devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK; outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); /* set multiplexer */ chan = CR_CHAN(insn->chanspec); chan |= CR_CHAN(insn->chanspec) << 4; outb(chan, dev->iobase + DAS16_MUX); /* set gain */ if (board->ai_pg != das16_pg_none) { range = CR_RANGE(insn->chanspec); outb((das16_gainlists[board->ai_pg])[range], dev->iobase + DAS16_GAIN); } for (n = 0; n < insn->n; n++) { /* trigger conversion */ outb_p(0, dev->iobase + DAS16_TRIG); for (i = 0; i < DAS16_TIMEOUT; i++) { if (!(inb(dev->iobase + DAS16_STATUS) & BUSY)) break; } if (i == DAS16_TIMEOUT) { printk("das16: timeout\n"); return -ETIME; } msb = inb(dev->iobase + DAS16_AI_MSB); lsb = inb(dev->iobase + DAS16_AI_LSB); if (board->ai_nbits == 12) data[n] = ((lsb >> 4) & 0xf) | (msb << 4); else data[n] = lsb | (msb << 8); }
static int daq700_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int n, i, chan; int d; unsigned int status; enum { TIMEOUT = 100 }; chan = CR_CHAN(insn->chanspec); /* write channel to multiplexer */ /* set mask scan bit high to disable scanning */ outb(chan | 0x80, dev->iobase + CMD_R1); /* mux needs 2us to really settle [Fred Brooks]. */ udelay(2); /* convert n samples */ for (n = 0; n < insn->n; n++) { /* trigger conversion with out0 L to H */ outb(0x00, dev->iobase + CMD_R2); /* enable ADC conversions */ outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */ /* mode 1 out0 H, L to H, start conversion */ outb(0x32, dev->iobase + CMO_R); /* wait for conversion to end */ for (i = 0; i < TIMEOUT; i++) { status = inb(dev->iobase + STA_R2); if ((status & 0x03) != 0) { dev_info(dev->class_dev, "Overflow/run Error\n"); return -EOVERFLOW; } status = inb(dev->iobase + STA_R1); if ((status & 0x02) != 0) { dev_info(dev->class_dev, "Data Error\n"); return -ENODATA; } if ((status & 0x11) == 0x01) { /* ADC conversion complete */ break; } udelay(1); } if (i == TIMEOUT) { dev_info(dev->class_dev, "timeout during ADC conversion\n"); return -ETIMEDOUT; } /* read data */ d = inw(dev->iobase + ADFIFO_R); /* mangle the data as necessary */ /* Bipolar Offset Binary: 0 to 4095 for -10 to +10 */ d &= 0x0fff; d ^= 0x0800; data[n] = d; } return n; }
static int usbduxsigma_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct usbduxsigma_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); uint8_t muxsg0 = 0; uint8_t muxsg1 = 0; uint8_t sysred = 0; int ret; int i; down(&devpriv->sem); if (devpriv->ai_cmd_running) { up(&devpriv->sem); return -EBUSY; } create_adc_command(chan, &muxsg0, &muxsg1); /* Mode 0 is used to get a single conversion on demand */ devpriv->dux_commands[1] = 0x16; /* CONFIG0: chopper on */ devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */ devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */ devpriv->dux_commands[4] = muxsg0; devpriv->dux_commands[5] = muxsg1; devpriv->dux_commands[6] = sysred; /* adc commands */ ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD); if (ret < 0) { up(&devpriv->sem); return ret; } for (i = 0; i < insn->n; i++) { uint32_t val; ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD); if (ret < 0) { up(&devpriv->sem); return ret; } /* 32 bits big endian from the A/D converter */ val = be32_to_cpu(get_unaligned((__be32 *)(devpriv->insn_buf + 1))); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ data[i] = val; } up(&devpriv->sem); return insn->n; }
static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { const struct das08_board_struct *thisboard = comedi_board(dev); struct das08_private_struct *devpriv = dev->private; int i, n; int chan; int range; int lsb, msb; chan = CR_CHAN(insn->chanspec); range = CR_RANGE(insn->chanspec); /* clear crap */ inb(dev->iobase + DAS08_LSB); inb(dev->iobase + DAS08_MSB); /* set multiplexer */ /* lock to prevent race with digital output */ spin_lock(&dev->spinlock); devpriv->do_mux_bits &= ~DAS08_MUX_MASK; devpriv->do_mux_bits |= DAS08_MUX(chan); outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); spin_unlock(&dev->spinlock); if (s->range_table->length > 1) { /* set gain/range */ range = CR_RANGE(insn->chanspec); outb(devpriv->pg_gainlist[range], dev->iobase + DAS08AO_GAIN_CONTROL); } for (n = 0; n < insn->n; n++) { /* clear over-range bits for 16-bit boards */ if (thisboard->ai_nbits == 16) if (inb(dev->iobase + DAS08_MSB) & 0x80) dev_info(dev->class_dev, "over-range\n"); /* trigger conversion */ outb_p(0, dev->iobase + DAS08_TRIG_12BIT); for (i = 0; i < TIMEOUT; i++) { if (!(inb(dev->iobase + DAS08_STATUS) & DAS08_EOC)) break; } if (i == TIMEOUT) { dev_err(dev->class_dev, "timeout\n"); return -ETIME; } msb = inb(dev->iobase + DAS08_MSB); lsb = inb(dev->iobase + DAS08_LSB); if (thisboard->ai_encoding == das08_encode12) { data[n] = (lsb >> 4) | (msb << 4); } else if (thisboard->ai_encoding == das08_pcm_encode12) {
int i_APCI2032_ReadDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int ui_Temp; unsigned int ui_NoOfChannel; ui_NoOfChannel = CR_CHAN(insn->chanspec); ui_Temp = data[0]; *data = inl(devpriv->iobase + APCI2032_DIGITAL_OP_RW); if (ui_Temp == 0) { *data = (*data >> ui_NoOfChannel) & 0x1; } /* if (ui_Temp==0) */
static int dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct dio200_subdev_8254 *subpriv = s->private; int ret = 0; int chan = CR_CHAN(insn->chanspec); unsigned long flags; spin_lock_irqsave(&subpriv->spinlock, flags); switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: if (data[1] > (I8254_MODE5 | I8254_BCD)) ret = -EINVAL; else dio200_subdev_8254_set_mode(dev, s, chan, data[1]); break; case INSN_CONFIG_8254_READ_STATUS: data[1] = dio200_subdev_8254_status(dev, s, chan); break; case INSN_CONFIG_SET_GATE_SRC: ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]); if (ret < 0) ret = -EINVAL; break; case INSN_CONFIG_GET_GATE_SRC: ret = dio200_subdev_8254_get_gate_src(dev, s, chan); if (ret < 0) { ret = -EINVAL; break; } data[2] = ret; break; case INSN_CONFIG_SET_CLOCK_SRC: ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]); if (ret < 0) ret = -EINVAL; break; case INSN_CONFIG_GET_CLOCK_SRC: ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]); if (ret < 0) { ret = -EINVAL; break; } data[1] = ret; break; default: ret = -EINVAL; break; } spin_unlock_irqrestore(&subpriv->spinlock, flags); return ret < 0 ? ret : insn->n; }
static int multiq3_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int i; int chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; return i; }
int ni_tio_rinsn(struct ni_gpct *counter, struct comedi_insn *insn, unsigned int *data) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned channel = CR_CHAN(insn->chanspec); unsigned first_read; unsigned second_read; unsigned correct_read; if (insn->n < 1) return 0; switch (channel) { case 0: ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), Gi_Save_Trace_Bit, 0); ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), Gi_Save_Trace_Bit, Gi_Save_Trace_Bit); /* The count doesn't get latched until the next clock edge, so it is possible the count may change (once) while we are reading. Since the read of the SW_Save_Reg isn't atomic (apparently even when it's a 32 bit register according to 660x docs), we need to read twice and make sure the reading hasn't changed. If it has, a third read will be correct since the count value will definitely have latched by then. */ first_read = read_register(counter, NITIO_Gi_SW_Save_Reg(counter->counter_index)); second_read = read_register(counter, NITIO_Gi_SW_Save_Reg(counter->counter_index)); if (first_read != second_read) correct_read = read_register(counter, NITIO_Gi_SW_Save_Reg(counter-> counter_index)); else correct_read = first_read; data[0] = correct_read; return 0; break; case 1: data[0] = counter_dev-> regs[NITIO_Gi_LoadA_Reg(counter->counter_index)]; break; case 2: data[0] = counter_dev-> regs[NITIO_Gi_LoadB_Reg(counter->counter_index)]; break; } return 0; }
/* * fl512_ao_insn_readback : used to read previous values written to * DA port */ static int fl512_ao_insn_readback(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int n; int chan = CR_CHAN(insn->chanspec); for (n = 0; n < insn->n; n++) data[n] = devpriv->ao_readback[chan]; return n; }
static int cb_pcimdda_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { unsigned int chan = CR_CHAN(insn->chanspec); /* Initiate the simultaneous transfer */ inw(dev->iobase + PCIMDDA_DA_CHAN(chan)); return comedi_readback_insn_read(dev, s, insn, data); }
static int daq700_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { int n; int d; int ret; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int aref = CR_AREF(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); unsigned int r3_bits = 0; /* set channel input modes */ if (aref == AREF_DIFF) r3_bits |= CMD_R3_DIFF; /* write channel mode/range */ if (range >= 1) range++; /* convert range to hardware value */ outb(r3_bits | (range & 0x03), dev->iobase + CMD_R3); /* write channel to multiplexer */ /* set mask scan bit high to disable scanning */ outb(chan | 0x80, dev->iobase + CMD_R1); /* mux needs 2us to really settle [Fred Brooks]. */ udelay(2); /* convert n samples */ for (n = 0; n < insn->n; n++) { /* trigger conversion with out0 L to H */ outb(0x00, dev->iobase + CMD_R2); /* enable ADC conversions */ outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */ outb(0x00, dev->iobase + ADCLEAR_R); /* clear the ADC FIFO */ /* read 16bit junk from FIFO to clear */ inw(dev->iobase + ADFIFO_R); /* mode 1 out0 H, L to H, start conversion */ outb(0x32, dev->iobase + CMO_R); /* wait for conversion to end */ ret = comedi_timeout(dev, s, insn, daq700_ai_eoc, 0); if (ret) return ret; /* read data */ d = inw(dev->iobase + ADFIFO_R); /* mangle the data as necessary */ /* Bipolar Offset Binary: 0 to 4095 for -10 to +10 */ d &= 0x0fff; d ^= 0x0800; data[n] = d; } return n; }