/*
ni_labpc.c driver for National Instruments Lab-PC series boards and compatibles
- Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
+ Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13
from the pcmcia package.
Lab-PC-1200AI (labpc-1200ai), Lab-PC+ (lab-pc+), PCI-1200 (pci-1200)
Status: works
+Thanks go to Fredrik Lingvall for much testing and perseverance in
+helping to debug daqcard-1200 support.
+
Tested with lab-pc-1200. For the older Lab-PC+, not all input ranges
and analog references will work, the available ranges/arefs will
depend on how you have configured the jumpers on your board
Configuration options - PCMCIA boards:
none
-Lab-pc+ has quirky chanlist when scanning multiple channels. Scan
+The Lab-pc+ and daqcard-1200 have quirky chanlist requirements
+when scanning multiple channels. Scan
sequence must start at highest channel, then decrement down to
-channel 0. 1200 series cards can scan down like lab-pc+ or scan
+channel 0. The rest of the cards can scan down like lab-pc+ or scan
up from channel zero.
*/
/*
TODO:
+Move calibration stuff out of driver and into comedi_calibrate
+(requires more infrastructure for comedi_calibrate and comedilib)
+
+
NI manuals:
341309a (labpc-1200 register manual)
340988a (daqcard-1200)
static int labpc_cancel(comedi_device *dev, comedi_subdevice *s)
{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
+
devpriv->command3_bits = 0;
thisboard->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
comedi_cmd *cmd = &async->cmd;
int scan_up, scan_enable;
enum transfer_type xfer;
+ unsigned long flags;
if(!dev->irq)
{
aref = CR_AREF(cmd->chanlist[0]);
// make sure board is disabled before setting up aquisition
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
+
devpriv->command3_bits = 0;
thisboard->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
// setup command6 register for 1200 boards
if(thisboard->register_layout == labpc_1200_layout)
{
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
// reference inputs to ground or common?
if(aref != AREF_GROUND)
devpriv->command6_bits |= ADC_COMMON_BIT;
devpriv->command6_bits &= ~ADC_SCAN_UP_BIT;
// write to register
thisboard->write_byte(devpriv->command6_bits, dev->iobase + COMMAND6_REG);
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
// if range has changed, update calibration dacs
if(range != devpriv->ai_range)
default:
break;
}
- if(cmd->scan_begin_src == TRIG_EXT)
- devpriv->command4_bits |= EXT_SCAN_MASTER_EN_BIT | EXT_SCAN_EN_BIT;
// single-ended/differential
if(aref == AREF_DIFF)
devpriv->command4_bits |= ADC_DIFF_BIT;
// command2 reg
// use 2 cascaded counters for pacing
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
devpriv->command2_bits |= CASCADE_BIT;
switch(cmd->start_src)
{
return -1;
}
thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
return 0;
}
int chan, range;
int lsb, msb;
int timeout = 1000;
+ unsigned long flags;
// disable timed conversions
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
// disable interrupt generation and dma
devpriv->command3_bits = 0;
// setup command6 register for 1200 boards
if(thisboard->register_layout == labpc_1200_layout)
{
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
// reference inputs to ground or common?
if(CR_AREF(insn->chanspec) != AREF_GROUND)
devpriv->command6_bits |= ADC_COMMON_BIT;
devpriv->command6_bits &= ~A1_INTR_EN_BIT;
// write to register
thisboard->write_byte(devpriv->command6_bits, dev->iobase + COMMAND6_REG);
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
// if range has changed, update calibration dacs
if(range != devpriv->ai_range)
comedi_insn *insn, lsampl_t *data)
{
int channel, range;
+ unsigned long flags;
int lsb, msb;
channel = CR_CHAN(insn->chanspec);
// turn off pacing of analog output channel
/* note: hardware bug in daqcard-1200 means pacing cannot
* be independently enabled/disabled for its the two channels */
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
devpriv->command2_bits &= ~DAC_PACED_BIT(channel);
thisboard->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
// set range
if(thisboard->register_layout == labpc_1200_layout)
{
+ comedi_spin_lock_irqsave( &dev->spinlock, flags );
range = CR_RANGE(insn->chanspec);
if(range & AO_RANGE_IS_UNIPOLAR)
devpriv->command6_bits |= DAC_UNIP_BIT(channel);
devpriv->command6_bits &= ~DAC_UNIP_BIT(channel);
// write to register
thisboard->write_byte(devpriv->command6_bits, dev->iobase + COMMAND6_REG);
-
+ comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
// if range has changed, update calibration dacs
if(range != devpriv->ao_range[channel])
{