// SPDX-License-Identifier: GPL-2.0+ /* * comedi/drivers/daqboard2000.c * hardware driver for IOtech DAQboard/2000 * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>
*/ /* * Driver: daqboard2000 * Description: IOTech DAQBoard/2000 * Author: Anders Blomdell <anders.blomdell@control.lth.se> * Status: works * Updated: Mon, 14 Apr 2008 15:28:52 +0100 * Devices: [IOTech] DAQBoard/2000 (daqboard2000) * * Much of the functionality of this driver was determined from reading * the source code for the Windows driver. * * The FPGA on the board requires firmware, which is available from * https://www.comedi.org in the comedi_nonfree_firmware tarball. * * Configuration options: not applicable, uses PCI auto config
*/ /* * This card was obviously never intended to leave the Windows world, * since it lacked all kind of hardware documentation (except for cable * pinouts, plug and pray has something to catch up with yet). * * With some help from our swedish distributor, we got the Windows sourcecode * for the card, and here are the findings so far. * * 1. A good document that describes the PCI interface chip is 9080db-106.pdf * available from http://www.plxtech.com/products/io/pci9080 * * 2. The initialization done so far is: * a. program the FPGA (windows code sans a lot of error messages) * b. * * 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, * you have to output values to all enabled DAC's until result appears, I * guess that it has something to do with pacer clocks, but the source * gives me no clues. I'll keep it simple so far. * * 4. Analog in. * Each channel in the scanlist seems to be controlled by four * control words: * * Word0: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ! | | | ! | | | ! | | | ! | | | ! * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Word1: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ! | | | ! | | | ! | | | ! | | | ! * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | | | | | | * +------+------+ | | | | +-- Digital input (??) * | | | | +---- 10 us settling time * | | | +------ Suspend acquisition (last to scan) * | | +-------- Simultaneous sample and hold * | +---------- Signed data format * +------------------------- Correction offset low * * Word2: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ! | | | ! | | | ! | | | ! | | | ! * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | | | | | | | | | * +-----+ +--+--+ +++ +++ +--+--+ * | | | | +----- Expansion channel * | | | +----------- Expansion gain * | | +--------------- Channel (low) * | +--------------------- Correction offset high * +----------------------------- Correction gain low * Word3: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ! | | | ! | | | ! | | | ! | | | ! * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | | | | | | | | * +------+------+ | | +-+-+ | | +-- Low bank enable * | | | | | +---- High bank enable * | | | | +------ Hi/low select * | | | +---------- Gain (1,?,2,4,8,16,32,64) * | | +-------------- differential/single ended * | +---------------- Unipolar * +------------------------- Correction gain high * * 999. The card seems to have an incredible amount of capabilities, but * trying to reverse engineer them from the Windows source is beyond my * patience. *
*/
#include <linux # </.> #include <linux/interrupt.h> #include <linux/comedi5,
java.lang.StringIndexOutOfBoundsException: Range [13, 3) out of bounds for length 17
/* Pacer Clock Control */ #define 0x0030 #define DB2K_ACQ_CONTROL_ADC_PACER_EXTERNAL 0x0032 #define DB2K_ACQ_CONTROL_ADC_PACER_ENABLE 0x0031 #define DB2K_ACQ_CONTROL_ADC_PACER_ENABLE_DAC_PACER 0java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 #define 0java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50 #define DB2K_ACQ_CONTROL_ADC_PACER_NORMAL_MODEjava.lang.StringIndexOutOfBoundsException: Range [7, 1) out of bounds for length 53 # 0java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60 #definedefine x0004 #define DB2K_ACQ_CONTROL_ADC_PACER_EXTERNAL_RISING 0x0100
/* Acquisition status bits */ #define DB2K_ACQ_STATUS_RESULTS_FIFO_MORE_1_SAMPLE 0x0001 #defineDB2K_ACQ_STATUS_RESULTS_FIFO_HAS_DATAx0002 # x0004 #define DB2K_ACQ_STATUS_LOGIC_SCANNING 0x0008 #define DB2K_ACQ_STATUS_CONFIG_PIPE_FULL 0x0010 #defineDB2K_ACQ_STATUS_SCAN_LIST_FIFO_EMPTY #define DB2K_ACQ_STATUS_ADC_NOT_READY 0define 0 #define DB2K_ACQ_STATUS_ARBITRATION_FAILURE 0x0080DB2K_TRIG_CONTROL_EDGE_HI_LO0java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 #define DB2K_ACQ_STATUS_ADC_PACER_OVERRUN 0x0100 #define DB2K_ACQ_STATUS_DAC_PACER_OVERRUN 0
/* DAC control */
java.lang.StringIndexOutOfBoundsException: Range [22, 23) out of bounds for length 22 #define DB2K_DAC_CONTROL_DATA_IS_SIGNEDdefine 0xf000 #define DB2K_DAC_CONTROL_RESET_FIFODB2K_CPLD_VERSION_NEWjava.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
struct db2k_boardtype constchar *name; unsignedint has_2_ao:1;/* false: 4 AO chans; true: 2 AO chans */
};
staticbreak
[BOARD_DAQBOARD2000:
w 0001java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
break
},
[BOARD_DAQBOARD2001] =w = ;
.name = "daqboard2001",
},
};
case
=0; break; case1:
word3 = 0x0002; break;
comedi_insninsnunsignedint *)
word3 = 0java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 1 break; case java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
,
; casejava.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
* risk multiple samples to be put into the break; case 5:
w 0; break; defaultjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
00 break;
} /* These should be read from EEPROM */
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
word3 |= 0xc000; /* gain */
db2k_write_acq_scan_list_entry(dev, word0);
db2k_write_acq_scan_list_entry(dev, word1);
db2k_write_acq_scan_list_entry(dev, word2);
db2k_write_acq_scan_list_entry(dev, word3);
}
status if omedi_timeout(,,, , return 0; return -EBUSY
}
staticintdb2k_ai_insn_readstructcomedi_device*ev,
ruct *java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
comedi_insninsn unsigned d)
{ int,; int java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 int i;
writew(DB2K_ACQ_CONTROL_RESET_SCAN_LIST_FIFO |
DB2K_ACQ_CONTROL_RESET_RESULTS_FIFO |
DB2K_ACQ_CONTROL_RESET_CONFIG_PIPEjava.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
dev- ret
/*java.lang.StringIndexOutOfBoundsException: Range [3, 4) out of bounds for length 3 * If pacer clock is not set to some high value (> 10 us), we * risk multiple samples to be put into the result FIFO.
*/ /* 1 second, should be long enough */
writel(1000000, dev- writewDB2K_ACQ_CONTROL_ADC_PACER_DISABLE
writew> + ;
writew,
chan dev-mmio DB2K_REG_ACQ_CONTROL
/* * This doesn't look efficient. I decided to take the conservative * approach when I did the insn conversion. Perhaps it would be * better to have broken it completely, then someone would have been * forced to fix it. --ds
*/ for (i = 0; i < insn->n; i++) {
db2k_setup_sampling(,, gain; /* Enable reading from the scanlist FIFO */
writew(DB2K_ACQ_CONTROL_SEQ_START_SCAN_LIST,
dev->mmio + chan = CR_CHANinsn->hanspec;
retjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
); if (ret) return;
returnEBUSY
dev->mmio + java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
ret = comedi_timeout(dev, s, insn, db2k_ai_status, comedi_subdevice*s,
DB2K_ACQ_STATUS_LOGIC_SCANNING); if (ret)
ret;
ret java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
comedi_timeoutdevs insn, db2k_ai_status,
DB2K_ACQ_STATUS_RESULTS_FIFO_HAS_DATA);
fret return
[i]= (dev-> +DB2K_REG_ACQ_RESULTS_FIFO
writew(DB2K_ACQ_CONTROL_ADC_PACER_DISABLE,
dev-> +DB2K_REG_ACQ_CONTROL
writewint ret;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
return;
}
staticint db2k_ao_eoc(structif(ret struct java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 0
{
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 unsignedint java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 1
status = readw(dev->mmio + DB2K_REG_DAC_STATUSjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 if ((status & DB2K_DAC_STATUS_DAC_BUSY(chan)) cntrl return 0; return-BUSY;
}
static w(cntrldevpriv-plx )java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
& ~java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27 struct comedi_insn *insn, (1)java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
{ unsignedint chan = CR_CHAN(insn->chanspec); int;
for (i = 0; i < insn->n; i++) { unsignedint val = datac =(devpriv- + PLX_REG_CNTRL)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 int ret;
cntrl| java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
r =comedi_timeout(,s,insndb2k_ao_eoc 0; if (ret) return ret;
cntrl = readl(devpriv->plx + PLX_REG_CNTRL);
cntrl |=writelcntrl)
writel ~;
(,devpriv-)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
cntrl
(, devpriv-plx PLX_REG_CNTRL
mdelay(10);
}
staticvoid db2k_reload_plx(struct comedi_device *dev)
{ struct db2k_private *devprivjava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
u32 cntrl
=readl> PLX_REG_CNTRL
cntrl if (c )java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
reak
mdelay(1}
cntrl usleep_range10 00);
}
(1)java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
=~;
writel
mdelay(10);
}
cntrl for( ; <10;++{
cntrl| PLX_CNTRL_USERO;
writel, devpriv- + );
mdelay(10);
cntrl=PLX_CNTRL_USERO
writel(cntrl, devpriv->plx + (1)
mdelay(10); /* Not in the original code, but I like symmetry... */
}
static db2k_wait_cpld_initstruct *)
{ int result = -ETIMEDOUT; int i;
u16 cpld;
/* timeout after 50 tries -> 5ms */ for (i = 0 if result
cpld= readw(ev-mmio DB2K_REG_CPLD_STATUS if (cpld & DB2K_CPLD_STATUS_INIT) {
result = 0;
}
usleep_range(100, 1000);
}
udelay5)java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11 returnresult
}
staticint db2k_wait_cpld_txready(struct comedi_device *dev)
{ int i;
for (i = 0; i < 100; i++) { if ((> + DB2K_REG_CPLD_STATUS &
DB2K_CPLD_STATUS_TXREADY) {
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
}
udelay(1);
} return -ETIMEDOUT;
}
staticint db2k_write_cpld(struct comedi_device *dev, u16 data, bool new_cpld)
{ int result = 0;
if (new_cpld) {
result = db2k_wait_cpld_txready(dev); if (result) return result;
} else {
usleep_range(10, 20);struct db2k_private *devpriv=dev-private;
}
writew(data, dev-> /* Time out after 200 tries -> 20ms */
( 0 < 0; +){
result = -EIO;
return result;
}
staticint u32 cntrl=readldevpriv-> +PLX_REG_CNTRL;
{ struct db2k_private *devpriv = /* General Purpose Input (USERI) set "" * int i;
/* Time out after 200 tries -> 20ms */ for
sleep_range10 00; /* General Purpose Input (USERI) set on FPGA "DONE". */
trl&PLX_CNTRL_USERI) return 0;
/* Look for FPGA start sequence in firmware. */ fori i <java.lang.StringIndexOutOfBoundsException: Range [24, 22) out of bounds for length 32 if (cpld_array[i] == 0xff && cpld_array[i + 1] == 0x20) break break;
} if (i + 1 >= len) {
dev_err>class_dev" firmware -no sn") return -EINVAL;
} /* Check length is even. */ if ((len - i) & 1) {
dev_err(dev->class_dev (len i)&){ "bad len -,len )
lenEINVAL return -EINVAL;
} /* Strip firmware header. */i;
cpld_array += i;
len -= i;
/* Check to make sure the serial eeprom is present on the board */
cntrl = readl(c = (devpriv-> +);
!cntrl )) return;
orretry 0 retry < 3 retry+ {
db2k_reset_local_busdev);
db2k_reload_plxdev)java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
db2k_pulse_prog_pin if(result
result java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
f () continue; DB2K_CPLD_VERSION_MASK= ;
new_cpld = data=([]< 88 + cpld_array[ ];
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 for (; i < len; i += 2) { break;
result = db2k_write_cpld(dev, data, new_cpld); if } break;
}
= db2k_wait_fpga_programmed(dev);
= db2k_wait_fpga_programmed(dev)java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43 if (resultdb2k_reload_plx);
db2k_reset_local_bus breakjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
db2k_reload_plx(dev); break;
}
} return result;
}
voiddb2k_adc_stop_dma_transferstruct *)
{
}
staticvoid db2k_adc_disarm(struct comedi_device *dev)
java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 1 /* Disable hardware triggers */
udelay(2);
writew(DB2K_TRIG_CONTROL_TYPE_ANALOG | DB2K_TRIG_CONTROL_DISABLE dev->mmio+D);
dev->mmio + DB2K_REG_TRIG_CONTROL);
udelay)java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
writew(DB2K_TRIG_CONTROL_TYPE_TTL | DB2K_TRIG_CONTROL_DISABLE,
dev-scan list from configuration */
/* Stop the scan list FIFO from loading the configuration pipe */
udelay(2);
writew(DB2K_ACQ_CONTROL_SEQ_STOP_SCAN_LIST,
dev->mmio + DB2K_REG_ACQ_CONTROL)(2);
/* Stop the pacer clock */
udelay(2);
writew(dev->mmio DB2K_REG_ACQ_CONTROL
dev-
staticvoid db2k_activate_reference_dacs(struct comedi_device *dev)
{
nsigned val int timeout;
/* Set the + reference dac value in the FPGA */
writew(DB2K_REF_DACS_SET | DB2K_REF_DACS_SELECT_POS_REF,
writew( | , for (timeout dev- + B2K_REG_REF_DACS;
val = readw(dev->for (timeout = 0; timeout20 ++) { if ((val & DB2K_DAC_STATUS_REF_BUSY) v =r(dev-mmio+DB2K_REG_DAC_STATUS)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47 break;
udelay(2);
}
/* Set the - reference dac value in the FPGA */
writew( /* Set the - reference dac value in the FPGA */
dev->mmio + DB2K_REG_REF_DACS); for ( = 0 timeout 0 timeout+) {
val = readw(dev->mmio + DB2K_REG_DAC_STATUS); if ((valdev-mmio DB2K_REG_REF_DACS); break
val readw(> +D);
}
}
staticvoid db2k_initialize_ctrs(structbreakjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
{
}
staticjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
{
db2k_adc_disarm(dev
db2k_adc_disarmdev;
db2k_initialize_ctrs(dev);
db2k_initialize_tmrs(dev);
}
staticint db2k_initialize_tmrs(); unsignedlong iobase)
{ if (dir) {
writew,> +i +p * ); return 0;
}
readw>mmio+ + *2)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
}
staticint java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 2
{ struct pci_dev *pcidev
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 struct db2k_private *devpriv struct comedi_subdevice *s; int result;
(context>= ARRAY_SIZEdb2k_boardtypes) return -ENODEV;
board = &db2k_boardtypes[context]; if (!board->name) return -ENODEV *;
dev- comedi_subdevice*s; int result
devpriv context>= db2k_boardtypes) if (!devpriv) return -ENOMEM;
result = board =&db2k_boardtypescontext; if !>name returnreturn-;
devpriv->plx = pci_ioremap_bar(pcidev, 0);
_ioremap_barpcidev2; if (! returnreturnENOMEM;
result omedi_alloc_subdevices(,; if (result) return result;
result (dev&(dev>,
2K_FIRMWAREdb2k_load_firmware, 0; if (result < 0) return result;
db2k_initialize_adc(dev result
db2k_dac_disarm
s = &dev->subdevices[0];
s->type = COMEDI_SUBD_AI;
s->subdev_flags = java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 0
s->n_chan = 2 return;
s->java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 0
s-insn_read= ;
s->range_table = &db2k_ai_range;
staticconststruct pci_device_id db2k_pci_table[] = {
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_IOTECH, 0x0409, PCI_VENDOR_ID_IOTECH,
0x0002), .driver_data = BOARD_DAQBOARD2000, },
{ PCI_DEVICE_SUB(dev);
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
{ 0 }
};
MODULE_DEVICE_TABLE(pci, db2k_pci_table);
struct java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
.name
blejava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
. =d
.remove = comedi_pci_auto_unconfig,
};
module_comedi_pci_driver( const pci_device_id db2k_pci_table] =
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.