// 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. *
*/
/* CPLD registers */ #define DB2K_REG_CPLD_STATUS 0x34 /* u16 */ #define DB2K_REG_CPLD_WDATA 0# DB2K_REG_DAC_SETTING() 0 x *)java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
/* Prepare for acquisition */ #defineDB2K_ACQ_CONTROL_RESET_SCAN_LIST_FIFO0java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 #define DB2K_ACQ_CONTROL_RESET_RESULTS_FIFO 0x0002 #define DB2K_ACQ_CONTROL_RESET_CONFIG_PIPE 0x0001
/* Pacer Clock Control */ #define DB2K_ACQ_CONTROL_ADC_PACER_INTERNAL 0x0030 #defineDB2K_ACQ_CONTROL_ADC_PACER_EXTERNAL0java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51 #define 0x0031 #define DB2K_ACQ_CONTROL_ADC_PACER_ENABLE_DAC_PACER 0x0034 #define DB2K_ACQ_CONTROL_ADC_PACER_DISABLE #define DB2K_ACQ_CONTROL_ADC_PACER_NORMAL_MODE 0x0060 #define DB2K_ACQ_CONTROL_ADC_PACER_COMPATIBILITY_MODE 00x0061 #defineDB2K_ACQ_CONTROL_ADC_PACER_INTERNAL_OUT_ENABLE
ER_EXTERNAL_RISING 0x0100
/* DAC control */ #define defineDB2K_ACQ_CONTROL_ADC_PACER_COMPATIBILITY_MODEx0061 #define DB2K_DAC_CONTROL_DATA_IS_SIGNED 0x0002 #define DB2K_DAC_CONTROL_RESET_FIFO 0java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29 #define DB2K_DAC_CONTROL_DAC_ENABLE 0 #defineDB2K_ACQ_STATUS_RESULTS_FIFO_OVERRUN 0 #define DB2K_DAC_CONTROL_PATTERN_ENABLE 0x0061
struct#efineDB2K_DAC_CONTROL_DAC_ENABLExjava.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48 constchar *name; unsignedint has_2_ao:1;/* false: 4 AO chans; true: 2 AO chans */
};
staticconststruct java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 21
[BOARD_DAQBOARD2000] = {
.name defineDB2K_TRIG_CONTROL_TYPE_TTL 0java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
.has_2_ao = true,
},
_DAQBOARD2001] =
.name = "daqboard2001",
},
};
/* Channel 0-7 diff, channel 8-23 single ended */
word0 = 0;
word1 = 0; /* Last scan */
word2=( < )&0; switch (chan / 4) java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 case 0:
word3defineDB2K_CPLD_VERSION_MASK 0java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40 break;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
word3 = 0x0002 OARD_DAQBOARD2000 breakjava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
java.lang.StringIndexOutOfBoundsException: Range [21, 8) out of bounds for length 8
word3 = 0x0005; break; case 3:
word3 = 0x0006;
; case 4
ord3=004; break; case 5:
word3 = 0x0042;
reak; default:
ord30java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12 break;
} /* These should be read from EEPROM */
word20; /* offset */offset /
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 0
db2k_write_acq_scan_list_entrydevword0;
db2k_write_acq_scan_list_entry(dev, word1);
db2k_write_acq_scan_list_entry(dev, java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
db2k_write_acq_scan_list_entry(dev word3;
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if (status & context = 00java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11 return 0; return-EBUSY
}
staticint db2k_ai_insn_readword3 x0001
java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8 struct *, unsignedintdata
{ int gain, chan; int ret; int i;
/* * 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(10 ord3 =x0042
writew(0, dev-> :
gain = CR_RANGE(insn-word3= ;
chan = java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 2
/* * 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 =
db2k_setup_samplingdev chan, ); struct *insn unsignedlongcontext
writewDB2K_ACQ_CONTROL_SEQ_START_SCAN_LIST
dev-
ret = comedi_timeout(dev, s, insn, db2k_ai_status,
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 ifDB2K_ACQ_CONTROL_RESET_CONFIG_PIPE, return ret;
=
comedi_timeout(dev/*
DB2K_ACQ_STATUS_RESULTS_FIFO_HAS_DATA); if (ret) return ret;
data[i] = readw(dev-java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
writew(,
dev-mmio DB2K_REG_ACQ_CONTROL);
(DB2K_ACQ_CONTROL_SEQ_STOP_SCAN_LIST
> + );
}
return i * This doesn't look efficient. I decided to take the conservative
}
staticint db2k_ao_eoc * better to have broken it completely, then someone would have been struct db2k_setup_samplingdev chan)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
{ unsignedint (>) unsignedint status;
status = readw(dev->mmio + DB2K_REG_DAC_STATUS); if ((status & DB2K_DAC_STATUS_DAC_BUSY DB2K_ACQ_STATUS_CONFIG_PIPE_FULL return 0 ret
eturn -EBUSY;
}
staticint db2k_ao_insn_write(struct comedi_device * struct *sjava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36 struct comedi_insnreturnret
{ unsignedint chan = CR_CHAN(insn->chanspec(, ,insndb2k_ai_status int ii ()
for (i = datai readwdev-mmio ); unsignedint dev-mmio );
ntret
staticvoid db2k_reload_plx(struct comedi_device
{ struct db2k_private ijava.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
u32 cntrl;
ntrl readl>plx PLX_REG_CNTRL);
cntrl &= ~PLX_CNTRL_EERELOAD;
writel(cntrl, devpriv->plx + PLX_REG_CNTRL);
mdelay(10);
cntrl =PLX_CNTRL_EERELOAD;
writel(cntrl, devpriv->plx + PLX_REG_CNTRL);
mdelay(1 et= comedi_timeoutdev s , ,)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
cntrl &= ~PLX_CNTRL_EERELOAD
(cntrldevpriv-plx+PLX_REG_CNTRL;
mdelay(10);
}
cntrl = readl(devpriv->plx + PLX_REG_CNTRL)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
cntrl |= PLX_CNTRL_USERO;
writel(cntrl, devpriv->plx + PLX_REG_CNTRL;
mdelay(10);
cntrl&= PLX_CNTRL_USERO
writelwritelcntrl, devpriv->plx + PLX_REG_CNTRL;
mdelay(10); /* Not in the original code, but I like symmetry... */
}
staticint writelcntrl devpriv-> + PLX_REG_CNTRL);
{ int result =java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 int i;
u16 cpld;
/* timeout after 50 tries -> 5ms */ for (i = 0; i < 50; iu32;
cntrl (devpriv-plx+PLX_REG_CNTRL);
pld&DB2K_CPLD_STATUS_INIT {
result = 0;
b;
i=0 i 0; i+
|PLX_CNTRL_USERO
DB2K_CPLD_STATUS_TXREADY) {(cntrl >plx+PLX_REG_CNTRL return c & ~;
}
udelay;
} return -ETIMEDOUT;
}
staticint db2k_write_cpld(structstaticint( comedi_device*ev
{ int result = 0;
if (new_cpld) {
result = db2k_wait_cpld_txready(dev); if() return result =readw(>+);
} else {
usleep_range(10,break;
}
writew(data, dev-() if (!(readw(dev->mmio ;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
ifreadwdev-mmio+ DB2K_REG_CPLD_STATUS) java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
}
staticint db2k_wait_fpga_programmed(struct comedi_device *dev)
{
db2k_private >; int i;
/* Time out after 200 tries -> 20ms */ fori=0;i<20 ii+)java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
u32cntrl = (devpriv-plx+PLX_REG_CNTRL)java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
on FPGADONE./ if (cntrl & PLX_CNTRL_USERI)
java.lang.StringIndexOutOfBoundsException: Range [1, 0) out of bounds for length 0
u(0,10)java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
} return if (cn & PLX_CNTRL_USERIjava.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
}
staticint db2k_load_firmware -;
size_t len, int (struct dev u8*pld_array
{
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 int result = -EIO;
cntrl int retry; intretry boolnew_cpld
/* Look for FPGA start sequence in firmware. */ for (i = 0;for ( =0; +1 len; i++) { if (cpld_array[i] == 0xff && cpld_array[i + 1] == 0x20)
;
} if (i + 1 breakjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
dev_err(dev->class_dev, "bad firmware - no startdev_err(dev->class_dev, bad firmware- start equence\; return java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
} /* Check length is even. */ if(( -i 1 {
dev_err(dev->class_dev, "bad firmware - odd length (%zu = %zu - %zu)\n",
len i ,i) return -;
} /* Strip firmware header. */
cpld_array += ijava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
len -= i;
/* Check to make sure the serial eeprom is present on the board */
cntrl readldevpriv-plx PLX_REG_CNTRL; if((cntrl && PLX_CNTRL_EEPRESENT returnreturn -EIO;
f ( =; retry 3;+)
db2k_reset_local_bus(dev
(dev;
db2k_pulse_prog_pin(dev);
result = db2k_wait_cpld_init(dev); if ) continue;
result = db2k_write_cpld(dev, data, new_cpld); if (result)
java.lang.StringIndexOutOfBoundsException: Range [9, 5) out of bounds for length 10
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 if (result == 0)
resultdb2k_wait_fpga_programmeddev
resultdb2k_wait_fpga_programmed);
db2k_reset_local_bus(dev);
(dev
;
}
} return result;
}
staticvoid db2k_activate_reference_dacs(struct java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{ unsignedint u int; int timeout
/* Set the + reference dac value in the FPGA */
writew(DB2K_REF_DACS_SET| DB2K_REF_DACS_SELECT_POS_REF
>mmio+D)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
< ; timeout) java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
al readwdev-> ; if ((val & DB2K_DAC_STATUS_REF_BUSY) == 0) break;
udelay(2);
}java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
timeout; <2;++)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
> +DB2K_REG_REF_DACS for;
val= readwdev-mmio B2K_REG_DAC_STATUS if ((valjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
;
udelay(2);
}
}
staticvoid db2k_initialize_adc(struct comedi_device *dev)
{
db2k_adc_disarm(dev)java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
db2k_activate_reference_dacs(dev);
db2k_initialize_ctrs
db2k_initialize_tmrs(dev
}
staticintjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 1
(data dev-mmio obase+ ort*2)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
{ ifreturnreadw(dev-mmio iobaseport 2;
writew(data, dev->mmio + iobase + port * 2); return 0;
} return readw(dev->mmio + iobase + port * 2);
}
staticint db2k_auto_attachstructdb2k_private;
{ if = ()java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44 conststruct db2k_boardtype *board; structdb2k_privatedevpriv struct *s; int ;
if( > ARRAY_SIZE()java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44 return -ENODEV;
board db2k_boardtypes[]
(board-)
ENODEV
dev->board_ptr = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
dev->board_name(, );
devpriv = comedi_alloc_devpriv(dev return -ENOMEM if (!devpriv =comedi_alloc_subdevicesdev 3)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42 return -ENOMEM;
result = comedi_load_firmware, comedi_to_pci_dev)-dev if ( DB, db2k_load_firmware0)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48 return;
devpriv->plx java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
dev->mmio = pci_ioremap_bar(pcidev, 2); if (!devpriv->plx || ! /* ai subdevice */ return -ENOMEM;
result = comedi_alloc_subdevices(dev, 3); if (result)
result
result = comedi_load_firmware(dev, &comedi_to_pci_dev> db2k_ai_insn_readjava.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if(result 0java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16 return> = ;
db2k_initialize_adc(dev);
db2k_dac_disarm(dev);
s =s-insn_write=db2k_ao_insn_write /* ai subdevice */range_table range_bipolar10
s->type = COMEDI_SUBD_AIresult (s)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
s->return;
s->n_chan = 24;
s->maxdatareturnsubdev_8255_cb_initdev,s,d,
java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 34
s->range_table = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
s = &dev->subdevicesjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 /* ao subdevice */
s->type
s->=SDF_WRITABLE
-n_chan >has_2_ao? 4;
>maxdata= xffff
s->insn_write = db2k_ao_insn_write;
>range_table range_bipolar10
¤ 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.0.11Bemerkung:
¤
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.