// SPDX-License-Identifier: GPL-2.0+ /* * Hardware driver for DAQ-STC based boards * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org> * Copyright (C) 2002-2006 Frank Mori Hess <fmhess@users.sourceforge.net>
*/
/* * This file is meant to be included by another file, e.g., * ni_atmio.c or ni_pcimio.c. * * Interrupt support originally added by Truxton Fulton <trux@truxton.com> * * References (ftp://ftp.natinst.com/support/manuals): * 340747b.pdf AT-MIO E series Register Level Programmer Manual * 341079b.pdf PCI E Series RLPM * 340934b.pdf DAQ-STC reference manual * * 67xx and 611x registers (ftp://ftp.ni.com/support/daq/mhddk/documentation/) * release_ni611x.pdf * release_ni67xx.pdf * * Other possibly relevant info: * 320517c.pdf User manual (obsolete) * 320517f.pdf User manual (new) * 320889a.pdf delete * 320906c.pdf maximum signal ratings * 321066a.pdf about 16x * 321791a.pdf discontinuation of at-mio-16e-10 rev. c * 321808a.pdf about at-mio-16e-10 rev P * 321837a.pdf discontinuation of at-mio-16de-10 rev d * 321838a.pdf about at-mio-16de-10 rev N * * ISSUES: * - the interrupt routine needs to be cleaned up * * 2006-02-07: S-Series PCI-6143: Support has been added but is not * fully tested as yet. Terry Barnaby, BEAM Ltd.
*/
/* * We automatically take advantage of STC registers that can be * read/written directly in the I/O space of the board. * * The AT-MIO and DAQCard devices map the low 8 STC registers to * iobase+reg*2. * * Most PCIMIO devices also map the low 8 STC registers but the * 611x devices map the read registers to iobase+(addr-1)*2. * For now non-windowed STC access is disabled if a PCIMIO device * is detected (devpriv->mite has been initialized). * * The M series devices do not used windowed registers for the * STC registers. The functions below handle the mapping of the * windowed STC registers to the m series register offsets.
*/
struct mio_regmap { unsignedint mio_reg; int size;
};
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
mite_chan = mite_request_channel(devpriv->mite, devpriv->cdo_mite_ring); if (!mite_chan) {
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
dev_err(dev->class_dev, "failed to reserve mite dma channel for correlated digital output\n"); return -EBUSY;
}
mite_chan->dir = COMEDI_OUTPUT;
devpriv->cdo_mite_chan = mite_chan;
/* * XXX just guessing NI_STC_DMA_CHAN_SEL() * returns the right bits, under the assumption the cdio dma * selection works just like ai/ao/gpct. * Definitely works for dma channels 0 and 1.
*/
bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel);
ni_set_bitfield(dev, NI_M_CDIO_DMA_SEL_REG,
NI_M_CDIO_DMA_SEL_CDO_MASK,
NI_M_CDIO_DMA_SEL_CDO(bits));
staticvoid ni_e_series_enable_second_irq(struct comedi_device *dev, unsignedint gpct_index, short enable)
{ struct ni_private *devpriv = dev->private; unsignedint val = 0; int reg;
if (devpriv->is_m_series || gpct_index > 1) return;
/* * e-series boards use the second irq signals to generate * dma requests for their counters
*/ if (gpct_index == 0) {
reg = NISTC_INTA2_ENA_REG; if (enable)
val = NISTC_INTA_ENA_G0_GATE;
} else {
reg = NISTC_INTB2_ENA_REG; if (enable)
val = NISTC_INTB_ENA_G1_GATE;
}
ni_stc_writew(dev, val, reg);
} #endif/* PCIDMA */
if (devpriv->is_6143) { /* Flush the 6143 data FIFO */
ni_writel(dev, 0x10, NI6143_AI_FIFO_CTRL_REG);
ni_writel(dev, 0x00, NI6143_AI_FIFO_CTRL_REG); /* Wait for complete */ for (i = 0; i < timeout; i++) { if (!(ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x10)) break;
udelay(1);
} if (i == timeout)
dev_err(dev->class_dev, "FIFO flush timeout\n");
} else {
ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG); if (devpriv->is_625x) {
ni_writeb(dev, 0, NI_M_STATIC_AI_CTRL_REG(0));
ni_writeb(dev, 1, NI_M_STATIC_AI_CTRL_REG(0)); #if 0 /* * The NI example code does 3 convert pulses for 625x * boards, But that appears to be wrong in practice.
*/
ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
NISTC_AI_CMD1_REG);
ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
NISTC_AI_CMD1_REG);
ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
NISTC_AI_CMD1_REG); #endif
}
}
}
/* * ni_set_bits( ) allows different parts of the ni_mio_common driver to * share registers (such as Interrupt_A_Register) without interfering with * each other. * * NOTE: the switch/case statements are optimized out for a constant argument * so this is actually quite fast--- If you must wrap another function around * this make it inline to avoid a large speed penalty. * * value should only be 1 or 0.
*/ staticinlinevoid ni_set_bits(struct comedi_device *dev, int reg, unsignedint bits, unsignedint value)
{ unsignedint bit_values;
for (i = 0; i < timeout; i++) { unsignedshort b_status;
b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); if (b_status & NISTC_AO_STATUS1_FIFO_HF) break; /* * If we poll too often, the pci bus activity seems * to slow the dma transfer down.
*/
usleep_range(10, 100);
} if (i == timeout) {
dev_err(dev->class_dev, "timed out waiting for dma load\n"); return -EPIPE;
} return 0;
} #endif/* PCIDMA */
for (i = 0; i < n; i++) {
comedi_buf_read_samples(s, &d, 1);
if (devpriv->is_6xxx) {
packed_data = d & 0xffff; /* 6711 only has 16 bit wide ao fifo */ if (!devpriv->is_6711) {
comedi_buf_read_samples(s, &d, 1);
i++;
packed_data |= (d << 16) & 0xffff0000;
}
ni_writel(dev, packed_data, NI611X_AO_FIFO_DATA_REG);
} else {
ni_writew(dev, d, NI_E_AO_FIFO_DATA_REG);
}
}
}
/* * There's a small problem if the FIFO gets really low and we * don't have the data to fill it. Basically, if after we fill * the FIFO with all the data available, the FIFO is _still_ * less than half full, we never clear the interrupt. If the * IRQ is in edge mode, we never get another interrupt, because * this one wasn't cleared. If in level mode, we get flooded * with interrupts that we can't fulfill, because nothing ever * gets put into the buffer. * * This kind of situation is recoverable, but it is easier to * just pretend we had a FIFO underrun, since there is a good * chance it will happen anyway. This is _not_ the case for * RT code, as RT code might purposely be running close to the * metal. Needs to be fixed eventually.
*/ staticint ni_ao_fifo_half_empty(struct comedi_device *dev, struct comedi_subdevice *s)
{ conststruct ni_board_struct *board = dev->board_ptr; unsignedint nbytes; unsignedint nsamples;
if (devpriv->is_611x) { for (i = 0; i < n / 2; i++) {
dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); /* This may get the hi/lo data in the wrong order */
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
} /* Check if there's a single sample stuck in the FIFO */ if (n % 2) {
dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
} elseif (devpriv->is_6143) { /* * This just reads the FIFO assuming the data is present, * no checks on the FIFO status are performed.
*/ for (i = 0; i < n / 2; i++) {
dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
} if (n % 2) { /* Assume there is a single sample stuck in the FIFO */ /* Get stranded sample into FIFO */
ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG);
dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
} else { if (n > ARRAY_SIZE(devpriv->ai_fifo_buffer)) {
dev_err(dev->class_dev, "bug! ai_fifo_buffer too small\n");
async->events |= COMEDI_CB_ERROR; return;
} for (i = 0; i < n; i++) {
devpriv->ai_fifo_buffer[i] =
ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
}
comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, n);
}
}
/* Empties the AI fifo */ staticvoid ni_handle_fifo_dregs(struct comedi_device *dev)
{ struct ni_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsignedint dl; unsignedshort data; int i;
if (devpriv->is_611x) { while ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_E) == 0) {
dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG);
/* This may get the hi/lo data in the wrong order */
data = dl >> 16;
comedi_buf_write_samples(s, &data, 1);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
} elseif (devpriv->is_6143) {
i = 0; while (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x04) {
dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
/* This may get the hi/lo data in the wrong order */
data = dl >> 16;
comedi_buf_write_samples(s, &data, 1);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
i += 2;
} /* Check if stranded sample is present */ if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { /* Get stranded sample into FIFO */
ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG);
dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
} else { unsignedshort fe; /* fifo empty */
fe = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_E; while (fe == 0) { for (i = 0;
i < ARRAY_SIZE(devpriv->ai_fifo_buffer); i++) {
fe = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_E; if (fe) break;
devpriv->ai_fifo_buffer[i] =
ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
}
comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, i);
}
}
}
/* Check if there's a single sample stuck in the FIFO */ if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) {
dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
}
/* Check if there's a single sample stuck in the FIFO */ if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { /* Get stranded sample into FIFO */
ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG);
dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
/* This may get the hi/lo data in the wrong order */
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
}
if (devpriv->aimode == AIMODE_SCAN) { #ifdef PCIDMA staticconstint timeout = 10; int i;
for (i = 0; i < timeout; i++) {
ni_sync_ai_dma(dev); if ((s->async->events & COMEDI_CB_EOS)) break;
udelay(1);
} #else
ni_handle_fifo_dregs(dev);
s->async->events |= COMEDI_CB_EOS; #endif
} /* handle special case of single scan */ if (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS)
shutdown_ai_command(dev);
}
/* test for all uncommon interrupt events at the same time */ if (status & (NISTC_AI_STATUS1_ERR |
NISTC_AI_STATUS1_SC_TC | NISTC_AI_STATUS1_START1)) { if (status == 0xffff) {
dev_err(dev->class_dev, "Card removed?\n"); /* * We probably aren't even running a command now, * so it's a good idea to be careful.
*/ if (comedi_is_subdevice_running(s))
s->async->events |= COMEDI_CB_ERROR; return;
} if (status & NISTC_AI_STATUS1_ERR) {
dev_err(dev->class_dev, "ai error a_status=%04x\n",
status);
shutdown_ai_command(dev);
s->async->events |= COMEDI_CB_ERROR; if (status & NISTC_AI_STATUS1_OVER)
s->async->events |= COMEDI_CB_OVERFLOW; return;
} if (status & NISTC_AI_STATUS1_SC_TC) { if (cmd->stop_src == TRIG_COUNT)
shutdown_ai_command(dev);
}
} #ifndef PCIDMA if (status & NISTC_AI_STATUS1_FIFO_HF) { int i; staticconstint timeout = 10; /* * PCMCIA cards (at least 6036) seem to stop producing * interrupts if we fail to get the fifo less than half * full, so loop to be sure.
*/ for (i = 0; i < timeout; ++i) {
ni_handle_fifo_half_full(dev); if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_HF) == 0) break;
}
} #endif/* !PCIDMA */
if (status & NISTC_AI_STATUS1_STOP)
ni_handle_eos(dev, s);
}
retval = ni_request_ao_mite_channel(dev); if (retval) return retval;
/* read alloc the entire buffer */
comedi_buf_read_alloc(s, s->async->prealloc_bufsz);
spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ao_mite_chan) { if (devpriv->is_611x || devpriv->is_6713) {
mite_prep_dma(devpriv->ao_mite_chan, 32, 32);
} else { /* * Doing 32 instead of 16 bit wide transfers from * memory makes the mite do 32 bit pci transfers, * doubling pci bandwidth.
*/
mite_prep_dma(devpriv->ao_mite_chan, 16, 32);
}
mite_dma_arm(devpriv->ao_mite_chan);
} else {
retval = -EIO;
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
return retval;
}
#endif/* PCIDMA */
/* * used for both cancel ioctl and board initialization * * this is pretty harsh for a cancel, but it works...
*/ staticint ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
{ struct ni_private *devpriv = dev->private; unsignedint ai_personal; unsignedint ai_out_ctrl;
ni_release_ai_mite_channel(dev); /* ai configuration */
ni_stc_writew(dev, NISTC_RESET_AI_CFG_START | NISTC_RESET_AI,
NISTC_RESET_REG);
/* the following registers should not be changed, because there * are no backup registers in devpriv. If you want to change * any of these, add a backup register and other appropriate code: * NISTC_AI_MODE1_REG * NISTC_AI_MODE3_REG * NISTC_AI_PERSONAL_REG * NISTC_AI_OUT_CTRL_REG
*/
range_code = ni_gainlkup[board->gainlkup][range];
devpriv->ai_offset[i] = 0; switch (aref) { case AREF_DIFF:
config_bits |= NI_M_AI_CFG_CHAN_TYPE_DIFF; break; case AREF_COMMON:
config_bits |= NI_M_AI_CFG_CHAN_TYPE_COMMON; break; case AREF_GROUND:
config_bits |= NI_M_AI_CFG_CHAN_TYPE_GROUND; break; case AREF_OTHER: break;
}
config_bits |= NI_M_AI_CFG_CHAN_SEL(chan);
config_bits |= NI_M_AI_CFG_BANK_SEL(chan);
config_bits |= NI_M_AI_CFG_GAIN(range_code); if (i == n_chan - 1)
config_bits |= NI_M_AI_CFG_LAST_CHAN; if (dither)
config_bits |= NI_M_AI_CFG_DITHER; /* don't use 2's complement encoding */
config_bits |= NI_M_AI_CFG_POLARITY;
ni_writew(dev, config_bits, NI_M_AI_CFG_FIFO_DATA_REG);
}
ni_prime_channelgain_list(dev);
}
/* * Notes on the 6110 and 6111: * These boards a slightly different than the rest of the series, since * they have multiple A/D converters. * From the driver side, the configuration memory is a * little different. * Configuration Memory Low: * bits 15-9: same * bit 8: unipolar/bipolar (should be 0 for bipolar) * bits 0-3: gain. This is 4 bits instead of 3 for the other boards * 1001 gain=0.1 (+/- 50) * 1010 0.2 * 1011 0.1 * 0001 1 * 0010 2 * 0011 5 * 0100 10 * 0101 20 * 0110 50 * Configuration Memory High: * bits 12-14: Channel Type * 001 for differential * 000 for calibration * bit 11: coupling (this is not currently handled) * 1 AC coupling * 0 DC coupling * bits 0-2: channel * valid channels are 0-3
*/ staticvoid ni_load_channelgain_list(struct comedi_device *dev, struct comedi_subdevice *s, unsignedint n_chan, unsignedint *list)
{ conststruct ni_board_struct *board = dev->board_ptr; struct ni_private *devpriv = dev->private; unsignedint offset = (s->maxdata + 1) >> 1; unsignedint chan, range, aref; unsignedint i; unsignedint hi, lo; unsignedint dither;
/* Set up Calibration mode if required */ if (devpriv->is_6143) { if ((list[0] & CR_ALT_SOURCE) &&
!devpriv->ai_calib_source_enabled) { /* Strobe Relay enable bit */
ni_writew(dev, devpriv->ai_calib_source |
NI6143_CALIB_CHAN_RELAY_ON,
NI6143_CALIB_CHAN_REG);
ni_writew(dev, devpriv->ai_calib_source,
NI6143_CALIB_CHAN_REG);
devpriv->ai_calib_source_enabled = 1; /* Allow relays to change */
msleep_interruptible(100);
} elseif (!(list[0] & CR_ALT_SOURCE) &&
devpriv->ai_calib_source_enabled) { /* Strobe Relay disable bit */
ni_writew(dev, devpriv->ai_calib_source |
NI6143_CALIB_CHAN_RELAY_OFF,
NI6143_CALIB_CHAN_REG);
ni_writew(dev, devpriv->ai_calib_source,
NI6143_CALIB_CHAN_REG);
devpriv->ai_calib_source_enabled = 0; /* Allow relays to change */
msleep_interruptible(100);
}
}
for (i = 0; i < n_chan; i++) { if (!devpriv->is_6143 && (list[i] & CR_ALT_SOURCE))
chan = devpriv->ai_calib_source; else
chan = CR_CHAN(list[i]);
aref = CR_AREF(list[i]);
range = CR_RANGE(list[i]);
dither = (list[i] & CR_ALT_FILTER) != 0;
/* fix the external/internal range differences */
range = ni_gainlkup[board->gainlkup][range]; if (devpriv->is_611x)
devpriv->ai_offset[i] = offset; else
devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset;
hi = 0; if ((list[i] & CR_ALT_SOURCE)) { if (devpriv->is_611x)
ni_writew(dev, CR_CHAN(list[i]) & 0x0003,
NI611X_CALIB_CHAN_SEL_REG);
} else { if (devpriv->is_611x)
aref = AREF_DIFF; elseif (devpriv->is_6143)
aref = AREF_OTHER; switch (aref) { case AREF_DIFF:
hi |= NI_E_AI_CFG_HI_TYPE_DIFF; break; case AREF_COMMON:
hi |= NI_E_AI_CFG_HI_TYPE_COMMON; break; case AREF_GROUND:
hi |= NI_E_AI_CFG_HI_TYPE_GROUND; break; case AREF_OTHER: break;
}
}
hi |= NI_E_AI_CFG_HI_CHAN(chan);
ni_writew(dev, hi, NI_E_AI_CFG_HI_REG);
if (!devpriv->is_6143) {
lo = NI_E_AI_CFG_LO_GAIN(range);
if (i == n_chan - 1)
lo |= NI_E_AI_CFG_LO_LAST_CHAN; if (dither)
lo |= NI_E_AI_CFG_LO_DITHER;
ni_writew(dev, lo, NI_E_AI_CFG_LO_REG);
}
}
/* prime the channel/gain list */ if (!devpriv->is_611x && !devpriv->is_6143)
ni_prime_channelgain_list(dev);
}
signbits = devpriv->ai_offset[0]; if (devpriv->is_611x) { for (n = 0; n < num_adc_stages_611x; n++) {
ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
NISTC_AI_CMD1_REG);
udelay(1);
} for (n = 0; n < insn->n; n++) {
ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
NISTC_AI_CMD1_REG); /* The 611x has screwy 32-bit FIFOs. */
d = 0; for (i = 0; i < NI_TIMEOUT; i++) { if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) {
d = ni_readl(dev,
NI611X_AI_FIFO_DATA_REG);
d >>= 16;
d &= 0xffff; break;
} if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_E)) {
d = ni_readl(dev,
NI611X_AI_FIFO_DATA_REG);
d &= 0xffff; break;
}
} if (i == NI_TIMEOUT) {
dev_err(dev->class_dev, "timeout\n"); return -ETIME;
}
d += signbits;
data[n] = d & 0xffff;
}
} elseif (devpriv->is_6143) { for (n = 0; n < insn->n; n++) {
ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
NISTC_AI_CMD1_REG);
/* * The 6143 has 32-bit FIFOs. You need to strobe a * bit to move a single 16bit stranded sample into * the FIFO.
*/
d = 0; for (i = 0; i < NI_TIMEOUT; i++) { if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) &
0x01) { /* Get stranded sample into FIFO */
ni_writel(dev, 0x01,
NI6143_AI_FIFO_CTRL_REG);
d = ni_readl(dev,
NI6143_AI_FIFO_DATA_REG); break;
}
} if (i == NI_TIMEOUT) {
dev_err(dev->class_dev, "timeout\n"); return -ETIME;
}
data[n] = (((d >> 16) & 0xFFFF) + signbits) & 0xFFFF;
}
} else { for (n = 0; n < insn->n; n++) {
ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
NISTC_AI_CMD1_REG); for (i = 0; i < NI_TIMEOUT; i++) { if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
NISTC_AI_STATUS1_FIFO_E)) break;
} if (i == NI_TIMEOUT) {
dev_err(dev->class_dev, "timeout\n"); return -ETIME;
} if (devpriv->is_m_series) {
d = ni_readl(dev, NI_M_AI_FIFO_DATA_REG);
d &= mask;
data[n] = d;
} else {
d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
d += signbits;
data[n] = d & 0xffff;
}
}
} return insn->n;
}
if (nbytes > sdev->async->prealloc_bufsz) { if (cmd->stop_arg > 0)
dev_err(sdev->device->class_dev, "%s: tried exact data transfer limits greater than buffer size\n",
__func__);
/* * we can only transfer up to the size of the buffer. In this * case, the user is expected to continue to write into the * comedi buffer (already implemented as a ring buffer).
*/
nbytes = sdev->async->prealloc_bufsz;
}
mite_init_ring_descriptors(ring, sdev, nbytes); #else
dev_err(sdev->device->class_dev, "%s: exact data transfer limits not implemented yet without DMA\n",
__func__); #endif
}
/* * Disable analog triggering for now, since it interferes * with the use of pfi0.
*/
devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_ENA;
ni_stc_writew(dev, devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG);
ai_trig = NISTC_AI_TRIG_START2_SEL(0) | NISTC_AI_TRIG_START1_SYNC; switch (cmd->start_src) { case TRIG_INT: case TRIG_NOW:
ai_trig |= NISTC_AI_TRIG_START1_EDGE |
NISTC_AI_TRIG_START1_SEL(0); break; case TRIG_EXT:
ai_trig |= NISTC_AI_TRIG_START1_SEL(
ni_get_reg_value_roffs(
CR_CHAN(cmd->start_arg),
NI_AI_StartTrigger,
&devpriv->routing_tables, 1));
if (cmd->start_arg & CR_INVERT)
ai_trig |= NISTC_AI_TRIG_START1_POLARITY; if (cmd->start_arg & CR_EDGE)
ai_trig |= NISTC_AI_TRIG_START1_EDGE; break;
}
ni_stc_writew(dev, ai_trig, NISTC_AI_TRIG_SEL_REG);
if (devpriv->is_611x) { /* have to take 3 stage adc pipeline into account */
stop_count += num_adc_stages_611x;
} /* stage number of scans */
ni_stc_writel(dev, stop_count, NISTC_AI_SC_LOADA_REG);
if (stop_count == 0) {
devpriv->ai_cmd2 |= NISTC_AI_CMD2_END_ON_EOS;
interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; /* * This is required to get the last sample for * chanlist_len > 1, not sure why.
*/ if (cmd->chanlist_len > 1)
start_stop_select |= NISTC_AI_STOP_POLARITY |
NISTC_AI_STOP_EDGE;
} break; case TRIG_NONE: /* stage number of scans */
ni_stc_writel(dev, 0, NISTC_AI_SC_LOADA_REG);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.