aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers/amplc_pci230.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers/amplc_pci230.c')
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci230.c1224
1 files changed, 481 insertions, 743 deletions
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 684275d76e8c..01796cd28e5b 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -24,24 +24,19 @@
* Author: Allan Willcox <allanwillcox@ozemail.com.au>,
* Steve D Sharples <steve.sharples@nottingham.ac.uk>,
* Ian Abbott <abbotti@mev.co.uk>
- * Updated: Wed, 22 Oct 2008 12:34:49 +0100
- * Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
- * PCI230+ (pci230+ or amplc_pci230),
- * PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
+ * Updated: Mon, 01 Sep 2014 10:09:16 +0000
+ * Devices: [Amplicon] PCI230 (amplc_pci230), PCI230+, PCI260, PCI260+
* Status: works
*
* Configuration options:
- * [0] - PCI bus of device (optional).
- * [1] - PCI slot of device (optional).
- * If bus/slot is not specified, the first available PCI device
- * will be used.
+ * none
*
- * Configuring a "amplc_pci230" will match any supported card and it will
- * choose the best match, picking the "+" models if possible. Configuring
- * a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
- * a PCI230. Configuring a "pci260" will match a PCI260 or PCI260+ card
- * and it will be treated as a PCI260. Configuring a "pci230+" will match
- * a PCI230+ card. Configuring a "pci260+" will match a PCI260+ card.
+ * Manual configuration of PCI cards is not supported; they are configured
+ * automatically.
+ *
+ * The PCI230+ and PCI260+ have the same PCI device IDs as the PCI230 and
+ * PCI260, but can be distinguished by the the size of the PCI regions. A
+ * card will be configured as a "+" model if detected as such.
*
* Subdevices:
*
@@ -201,7 +196,6 @@
*/
#define PCI_DEVICE_ID_PCI230 0x0000
#define PCI_DEVICE_ID_PCI260 0x0006
-#define PCI_DEVICE_ID_INVALID 0xffff
/*
* PCI230 i/o space 1 registers.
@@ -427,16 +421,15 @@
* (Potentially) shared resources and their owners
*/
enum {
- RES_Z2CT0, /* Z2-CT0 */
- RES_Z2CT1, /* Z2-CT1 */
- RES_Z2CT2, /* Z2-CT2 */
- NUM_RESOURCES /* Number of (potentially) shared resources. */
+ RES_Z2CT0 = (1U << 0), /* Z2-CT0 */
+ RES_Z2CT1 = (1U << 1), /* Z2-CT1 */
+ RES_Z2CT2 = (1U << 2) /* Z2-CT2 */
};
enum {
- OWNER_NONE, /* Not owned */
OWNER_AICMD, /* Owned by AI command */
- OWNER_AOCMD /* Owned by AO command */
+ OWNER_AOCMD, /* Owned by AO command */
+ NUM_OWNERS /* Number of owners */
};
/*
@@ -449,10 +442,6 @@ enum {
/* Current CPU. XXX should this be hard_smp_processor_id()? */
#define THISCPU smp_processor_id()
-/* State flags for atomic bit operations */
-#define AI_CMD_STARTED 0
-#define AO_CMD_STARTED 1
-
/*
* Board descriptions for the two boards supported.
*/
@@ -460,52 +449,39 @@ enum {
struct pci230_board {
const char *name;
unsigned short id;
- int ai_chans;
- int ai_bits;
- int ao_chans;
- int ao_bits;
- int have_dio;
- unsigned int min_hwver; /* Minimum hardware version supported. */
+ unsigned char ai_bits;
+ unsigned char ao_bits;
+ unsigned char min_hwver; /* Minimum hardware version supported. */
+ bool have_dio:1;
};
static const struct pci230_board pci230_boards[] = {
{
.name = "pci230+",
.id = PCI_DEVICE_ID_PCI230,
- .ai_chans = 16,
.ai_bits = 16,
- .ao_chans = 2,
.ao_bits = 12,
- .have_dio = 1,
+ .have_dio = true,
.min_hwver = 1,
},
{
.name = "pci260+",
.id = PCI_DEVICE_ID_PCI260,
- .ai_chans = 16,
.ai_bits = 16,
.min_hwver = 1,
},
{
.name = "pci230",
.id = PCI_DEVICE_ID_PCI230,
- .ai_chans = 16,
.ai_bits = 12,
- .ao_chans = 2,
.ao_bits = 12,
- .have_dio = 1,
+ .have_dio = true,
},
{
.name = "pci260",
.id = PCI_DEVICE_ID_PCI260,
- .ai_chans = 16,
.ai_bits = 12,
},
- {
- /* Wildcard matches any above */
- .name = "amplc_pci230",
- .id = PCI_DEVICE_ID_INVALID,
- },
};
struct pci230_private {
@@ -513,9 +489,7 @@ struct pci230_private {
spinlock_t res_spinlock; /* Shared resources spin lock */
spinlock_t ai_stop_spinlock; /* Spin lock for stopping AI command */
spinlock_t ao_stop_spinlock; /* Spin lock for stopping AO command */
- unsigned long state; /* State flags */
- unsigned long iobase1; /* PCI230's I/O space 1 */
- unsigned int ao_readback[2]; /* Used for AO readback */
+ unsigned long daqio; /* PCI230's DAQ I/O space */
unsigned int ai_scan_count; /* Number of AI scans remaining */
unsigned int ai_scan_pos; /* Current position within AI scan */
unsigned int ao_scan_count; /* Number of AO scans remaining. */
@@ -525,12 +499,13 @@ struct pci230_private {
unsigned short daccon; /* DACCON register value */
unsigned short adcfifothresh; /* ADC FIFO threshold (PCI230+/260+) */
unsigned short adcg; /* ADCG register value */
- unsigned char int_en; /* Interrupt enable bits */
- unsigned char ai_bipolar; /* Flag AI range is bipolar */
- unsigned char ao_bipolar; /* Flag AO range is bipolar */
- unsigned char ier; /* Copy of interrupt enable register */
- unsigned char intr_running; /* Flag set in interrupt routine */
- unsigned char res_owner[NUM_RESOURCES]; /* Shared resource owners */
+ unsigned char ier; /* Interrupt enable bits */
+ unsigned char res_owned[NUM_OWNERS]; /* Owned resources */
+ bool intr_running:1; /* Flag set in interrupt routine */
+ bool ai_bipolar:1; /* Flag AI range is bipolar */
+ bool ao_bipolar:1; /* Flag AO range is bipolar */
+ bool ai_cmd_started:1; /* Flag AI command started */
+ bool ao_cmd_started:1; /* Flag AO command started */
};
/* PCI230 clock source periods in ns */
@@ -558,9 +533,6 @@ static const struct comedi_lrange pci230_ai_range = {
/* PCI230 analogue gain bits for each input range. */
static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
-/* PCI230 adccon bipolar flag for each analogue input range. */
-static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
-
/* PCI230 analogue output range table */
static const struct comedi_lrange pci230_ao_range = {
2, {
@@ -569,170 +541,122 @@ static const struct comedi_lrange pci230_ao_range = {
}
};
-/* PCI230 daccon bipolar flag for each analogue output range. */
-static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
-
static unsigned short pci230_ai_read(struct comedi_device *dev)
{
- const struct pci230_board *thisboard = comedi_board(dev);
+ const struct pci230_board *thisboard = dev->board_ptr;
struct pci230_private *devpriv = dev->private;
unsigned short data;
/* Read sample. */
- data = inw(dev->iobase + PCI230_ADCDATA);
+ data = inw(devpriv->daqio + PCI230_ADCDATA);
/*
* PCI230 is 12 bit - stored in upper bits of 16 bit register
* (lower four bits reserved for expansion). PCI230+ is 16 bit AI.
- */
- data = data >> (16 - thisboard->ai_bits);
-
- /*
+ *
* If a bipolar range was specified, mangle it
* (twos complement->straight binary).
*/
if (devpriv->ai_bipolar)
- data ^= 1 << (thisboard->ai_bits - 1);
-
+ data ^= 0x8000;
+ data >>= (16 - thisboard->ai_bits);
return data;
}
-static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
- unsigned short datum)
+static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
+ unsigned short datum)
{
- const struct pci230_board *thisboard = comedi_board(dev);
+ const struct pci230_board *thisboard = dev->board_ptr;
struct pci230_private *devpriv = dev->private;
/*
- * If a bipolar range was specified, mangle it
- * (straight binary->twos complement).
- */
- if (devpriv->ao_bipolar)
- datum ^= 1 << (thisboard->ao_bits - 1);
-
- /*
* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
* four bits reserved for expansion). PCI230+ is also 12 bit AO.
*/
datum <<= (16 - thisboard->ao_bits);
+ /*
+ * If a bipolar range was specified, mangle it
+ * (straight binary->twos complement).
+ */
+ if (devpriv->ao_bipolar)
+ datum ^= 0x8000;
return datum;
}
-static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
- unsigned short datum,
- unsigned int chan)
+static void pci230_ao_write_nofifo(struct comedi_device *dev,
+ unsigned short datum, unsigned int chan)
{
struct pci230_private *devpriv = dev->private;
- /* Store unmangled datum to be read back later. */
- devpriv->ao_readback[chan] = datum;
-
/* Write mangled datum to appropriate DACOUT register. */
outw(pci230_ao_mangle_datum(dev, datum),
- dev->iobase + (((chan) == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
+ devpriv->daqio + ((chan == 0) ? PCI230_DACOUT1 : PCI230_DACOUT2));
}
-static inline void pci230_ao_write_fifo(struct comedi_device *dev,
- unsigned short datum, unsigned int chan)
+static void pci230_ao_write_fifo(struct comedi_device *dev,
+ unsigned short datum, unsigned int chan)
{
struct pci230_private *devpriv = dev->private;
- /* Store unmangled datum to be read back later. */
- devpriv->ao_readback[chan] = datum;
-
/* Write mangled datum to appropriate DACDATA register. */
outw(pci230_ao_mangle_datum(dev, datum),
- dev->iobase + PCI230P2_DACDATA);
+ devpriv->daqio + PCI230P2_DACDATA);
}
-static int get_resources(struct comedi_device *dev, unsigned int res_mask,
- unsigned char owner)
+static bool pci230_claim_shared(struct comedi_device *dev,
+ unsigned char res_mask, unsigned int owner)
{
struct pci230_private *devpriv = dev->private;
- int ok;
- unsigned int i;
- unsigned int b;
- unsigned int claimed;
+ unsigned int o;
unsigned long irqflags;
- ok = 1;
- claimed = 0;
spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
- for (b = 1, i = 0; (i < NUM_RESOURCES) && res_mask; b <<= 1, i++) {
- if (res_mask & b) {
- res_mask &= ~b;
- if (devpriv->res_owner[i] == OWNER_NONE) {
- devpriv->res_owner[i] = owner;
- claimed |= b;
- } else if (devpriv->res_owner[i] != owner) {
- for (b = 1, i = 0; claimed; b <<= 1, i++) {
- if (claimed & b) {
- devpriv->res_owner[i] =
- OWNER_NONE;
- claimed &= ~b;
- }
- }
- ok = 0;
- break;
- }
+ for (o = 0; o < NUM_OWNERS; o++) {
+ if (o == owner)
+ continue;
+ if (devpriv->res_owned[o] & res_mask) {
+ spin_unlock_irqrestore(&devpriv->res_spinlock,
+ irqflags);
+ return false;
}
}
+ devpriv->res_owned[owner] |= res_mask;
spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
- return ok;
-}
-
-static inline int get_one_resource(struct comedi_device *dev,
- unsigned int resource, unsigned char owner)
-{
- return get_resources(dev, (1U << resource), owner);
+ return true;
}
-static void put_resources(struct comedi_device *dev, unsigned int res_mask,
- unsigned char owner)
+static void pci230_release_shared(struct comedi_device *dev,
+ unsigned char res_mask, unsigned int owner)
{
struct pci230_private *devpriv = dev->private;
- unsigned int i;
- unsigned int b;
unsigned long irqflags;
spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
- for (b = 1, i = 0; (i < NUM_RESOURCES) && res_mask; b <<= 1, i++) {
- if (res_mask & b) {
- res_mask &= ~b;
- if (devpriv->res_owner[i] == owner)
- devpriv->res_owner[i] = OWNER_NONE;
- }
- }
+ devpriv->res_owned[owner] &= ~res_mask;
spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
}
-static inline void put_one_resource(struct comedi_device *dev,
- unsigned int resource, unsigned char owner)
+static void pci230_release_all_resources(struct comedi_device *dev,
+ unsigned int owner)
{
- put_resources(dev, (1U << resource), owner);
+ pci230_release_shared(dev, (unsigned char)~0, owner);
}
-static inline void put_all_resources(struct comedi_device *dev,
- unsigned char owner)
-{
- put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
-}
-
-static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
- unsigned int flags)
+static unsigned int pci230_divide_ns(uint64_t ns, unsigned int timebase,
+ unsigned int flags)
{
uint64_t div;
unsigned int rem;
div = ns;
rem = do_div(div, timebase);
- switch (flags & TRIG_ROUND_MASK) {
+ switch (flags & CMDF_ROUND_MASK) {
default:
- case TRIG_ROUND_NEAREST:
+ case CMDF_ROUND_NEAREST:
div += (rem + (timebase / 2)) / timebase;
break;
- case TRIG_ROUND_DOWN:
+ case CMDF_ROUND_DOWN:
break;
- case TRIG_ROUND_UP:
+ case CMDF_ROUND_UP:
div += (rem + timebase - 1) / timebase;
break;
}
@@ -749,8 +673,8 @@ static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
unsigned int clk_src, cnt;
for (clk_src = CLK_10MHZ;; clk_src++) {
- cnt = divide_ns(ns, pci230_timebase[clk_src], flags);
- if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
+ cnt = pci230_divide_ns(ns, pci230_timebase[clk_src], flags);
+ if (cnt <= 65536 || clk_src == CLK_1KHZ)
break;
}
*count = cnt;
@@ -770,29 +694,25 @@ static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
unsigned int mode, uint64_t ns,
unsigned int flags)
{
- struct pci230_private *devpriv = dev->private;
unsigned int clk_src;
unsigned int count;
/* Set mode. */
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, mode);
/* Determine clock source and count. */
clk_src = pci230_choose_clk_count(ns, &count, flags);
/* Program clock source. */
- outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
+ outb(CLK_CONFIG(ct, clk_src), dev->iobase + PCI230_ZCLK_SCE);
/* Set initial count. */
if (count >= 65536)
count = 0;
- i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
+ i8254_write(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, count);
}
static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
{
- struct pci230_private *devpriv = dev->private;
-
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
- I8254_MODE1);
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, ct, I8254_MODE1);
/* Counter ct, 8254 mode 1, initial count not written. */
}
@@ -801,17 +721,18 @@ static int pci230_ai_eoc(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned long context)
{
+ struct pci230_private *devpriv = dev->private;
unsigned int status;
- status = inw(dev->iobase + PCI230_ADCCON);
+ status = inw(devpriv->daqio + PCI230_ADCCON);
if ((status & PCI230_ADC_FIFO_EMPTY) == 0)
return 0;
return -EBUSY;
}
-static int pci230_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
+static int pci230_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
{
struct pci230_private *devpriv = dev->private;
unsigned int n;
@@ -842,8 +763,8 @@ static int pci230_ai_rinsn(struct comedi_device *dev,
*/
adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
/* Set Z2-CT2 output low to avoid any false triggers. */
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
- devpriv->ai_bipolar = pci230_ai_bipolar[range];
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
+ devpriv->ai_bipolar = comedi_range_is_bipolar(s, range);
if (aref == AREF_DIFF) {
/* Differential. */
gainshift = chan * 2;
@@ -874,19 +795,18 @@ static int pci230_ai_rinsn(struct comedi_device *dev,
else
adccon |= PCI230_ADC_IR_UNI;
-
/*
* Enable only this channel in the scan list - otherwise by default
* we'll get one sample from each channel.
*/
- outw(adcen, dev->iobase + PCI230_ADCEN);
+ outw(adcen, devpriv->daqio + PCI230_ADCEN);
/* Set gain for channel. */
- outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
+ outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
/* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
devpriv->adccon = adccon;
- outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
+ outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
/* Convert n samples */
for (n = 0; n < insn->n; n++) {
@@ -894,10 +814,10 @@ static int pci230_ai_rinsn(struct comedi_device *dev,
* Trigger conversion by toggling Z2-CT2 output
* (finish with output high).
*/
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
- I8254_MODE0);
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
- I8254_MODE1);
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0,
+ 2, I8254_MODE0);
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0,
+ 2, I8254_MODE1);
/* wait for conversion to end */
ret = comedi_timeout(dev, s, insn, pci230_ai_eoc, 0);
@@ -912,57 +832,31 @@ static int pci230_ai_rinsn(struct comedi_device *dev,
return n;
}
-/*
- * COMEDI_SUBD_AO instructions;
- */
-static int pci230_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
+static int pci230_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pci230_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val = s->readback[chan];
int i;
- int chan, range;
-
- /* Unpack channel and range. */
- chan = CR_CHAN(insn->chanspec);
- range = CR_RANGE(insn->chanspec);
/*
* Set range - see analogue output range table; 0 => unipolar 10V,
* 1 => bipolar +/-10V range scale
*/
- devpriv->ao_bipolar = pci230_ao_bipolar[range];
- outw(range, dev->iobase + PCI230_DACCON);
+ devpriv->ao_bipolar = comedi_range_is_bipolar(s, range);
+ outw(range, devpriv->daqio + PCI230_DACCON);
- /*
- * Writing a list of values to an AO channel is probably not
- * very useful, but that's how the interface is defined.
- */
for (i = 0; i < insn->n; i++) {
- /* Write value to DAC and store it. */
- pci230_ao_write_nofifo(dev, data[i], chan);
+ val = data[i];
+ pci230_ao_write_nofifo(dev, val, chan);
}
+ s->readback[chan] = val;
- /* return the number of samples read/written */
- return i;
-}
-
-/*
- * AO subdevices should have a read insn as well as a write insn.
- * Usually this means copying a value stored in devpriv.
- */
-static int pci230_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_insn *insn,
- unsigned int *data)
-{
- struct pci230_private *devpriv = dev->private;
- int i;
- int chan = CR_CHAN(insn->chanspec);
-
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->ao_readback[chan];
-
- return i;
+ return insn->n;
}
static int pci230_ao_check_chanlist(struct comedi_device *dev,
@@ -1000,7 +894,7 @@ static int pci230_ao_check_chanlist(struct comedi_device *dev,
static int pci230_ao_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
- const struct pci230_board *thisboard = comedi_board(dev);
+ const struct pci230_board *thisboard = dev->board_ptr;
struct pci230_private *devpriv = dev->private;
int err = 0;
unsigned int tmp;
@@ -1010,7 +904,7 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
tmp = TRIG_TIMER | TRIG_INT;
- if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
+ if (thisboard->min_hwver > 0 && devpriv->hwver >= 2) {
/*
* For PCI230+ hardware version 2 onwards, allow external
* trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
@@ -1078,11 +972,11 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
* The only flags allowed are CR_EDGE and CR_INVERT.
* The CR_EDGE flag is ignored.
*/
- if (cmd->scan_begin_arg &
- (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) {
- cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
- CR_FLAGS_MASK &
- ~(CR_EDGE | CR_INVERT));
+ if (cmd->scan_begin_arg & CR_FLAGS_MASK &
+ ~(CR_EDGE | CR_INVERT)) {
+ cmd->scan_begin_arg =
+ COMBINE(cmd->scan_begin_arg, 0,
+ CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
err |= -EINVAL;
}
break;
@@ -1093,7 +987,9 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
- if (cmd->stop_src == TRIG_NONE)
+ if (cmd->stop_src == TRIG_COUNT)
+ err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+ else /* TRIG_NONE */
err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
if (err)
@@ -1127,11 +1023,12 @@ static void pci230_ao_stop(struct comedi_device *dev,
struct pci230_private *devpriv = dev->private;
unsigned long irqflags;
unsigned char intsrc;
- int started;
+ bool started;
struct comedi_cmd *cmd;
spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
- started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
+ started = devpriv->ao_cmd_started;
+ devpriv->ao_cmd_started = false;
spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
if (!started)
return;
@@ -1153,15 +1050,12 @@ static void pci230_ao_stop(struct comedi_device *dev,
* unless we are called from the interrupt routine.
*/
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
- devpriv->int_en &= ~intsrc;
+ devpriv->ier &= ~intsrc;
while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
}
- if (devpriv->ier != devpriv->int_en) {
- devpriv->ier = devpriv->int_en;
- outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
- }
+ outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
if (devpriv->hwver >= 2) {
/*
@@ -1171,10 +1065,10 @@ static void pci230_ao_stop(struct comedi_device *dev,
devpriv->daccon &= PCI230_DAC_OR_MASK;
outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET |
PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
- dev->iobase + PCI230_DACCON);
+ devpriv->daqio + PCI230_DACCON);
}
/* Release resources. */
- put_all_resources(dev, OWNER_AOCMD);
+ pci230_release_all_resources(dev, OWNER_AOCMD);
}
static void pci230_handle_ao_nofifo(struct comedi_device *dev,
@@ -1189,6 +1083,8 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev,
if (cmd->stop_src == TRIG_COUNT && devpriv->ao_scan_count == 0)
return;
for (i = 0; i < cmd->chanlist_len; i++) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+
/* Read sample from Comedi's circular buffer. */
ret = comedi_buf_get(s, &data);
if (ret == 0) {
@@ -1197,8 +1093,8 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev,
dev_err(dev->class_dev, "AO buffer underrun\n");
return;
}
- /* Write value to DAC. */
- pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
+ pci230_ao_write_nofifo(dev, data, chan);
+ s->readback[chan] = data;
}
async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
if (cmd->stop_src == TRIG_COUNT) {
@@ -1211,10 +1107,12 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev,
}
}
-/* Loads DAC FIFO (if using it) from buffer. */
-/* Returns 0 if AO finished due to completion or error, 1 if still going. */
-static int pci230_handle_ao_fifo(struct comedi_device *dev,
- struct comedi_subdevice *s)
+/*
+ * Loads DAC FIFO (if using it) from buffer.
+ * Returns false if AO finished due to completion or error, true if still going.
+ */
+static bool pci230_handle_ao_fifo(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
struct pci230_private *devpriv = dev->private;
struct comedi_async *async = s->async;
@@ -1224,10 +1122,10 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
unsigned short dacstat;
unsigned int i, n;
unsigned int events = 0;
- int running;
+ bool running;
/* Get DAC FIFO status. */
- dacstat = inw(dev->iobase + PCI230_DACCON);
+ dacstat = inw(devpriv->daqio + PCI230_DACCON);
/* Determine number of scans available in buffer. */
num_scans = comedi_buf_read_n_available(s) / cfc_bytes_per_scan(s);
if (cmd->stop_src == TRIG_COUNT) {
@@ -1250,8 +1148,8 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
* (otherwise there will be loads of "DAC FIFO not half full"
* interrupts).
*/
- if ((num_scans == 0) &&
- ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
+ if (num_scans == 0 &&
+ (dacstat & PCI230P2_DAC_FIFO_HALF) == 0) {
dev_err(dev->class_dev, "AO buffer underrun\n");
events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
}
@@ -1274,11 +1172,12 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
/* Process scans. */
for (n = 0; n < num_scans; n++) {
for (i = 0; i < cmd->chanlist_len; i++) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
unsigned short datum;
comedi_buf_get(s, &datum);
- pci230_ao_write_fifo(dev, datum,
- CR_CHAN(cmd->chanlist[i]));
+ pci230_ao_write_fifo(dev, datum, chan);
+ s->readback[chan] = datum;
}
}
events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
@@ -1295,11 +1194,11 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
~PCI230P2_DAC_INT_FIFO_MASK) |
PCI230P2_DAC_INT_FIFO_EMPTY;
outw(devpriv->daccon,
- dev->iobase + PCI230_DACCON);
+ devpriv->daqio + PCI230_DACCON);
}
}
/* Check if FIFO underrun occurred while writing to FIFO. */
- dacstat = inw(dev->iobase + PCI230_DACCON);
+ dacstat = inw(devpriv->daqio + PCI230_DACCON);
if (dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) {
dev_err(dev->class_dev, "AO FIFO underrun\n");
events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
@@ -1308,9 +1207,9 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
if (events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
/* Stopping AO due to completion or error. */
pci230_ao_stop(dev, s);
- running = 0;
+ running = false;
} else {
- running = 1;
+ running = true;
}
async->events |= events;
return running;
@@ -1327,28 +1226,25 @@ static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
return -EINVAL;
spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
- if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
- /* Perform scan. */
- if (devpriv->hwver < 2) {
- /* Not using DAC FIFO. */
- spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
- irqflags);
- pci230_handle_ao_nofifo(dev, s);
- comedi_event(dev, s);
- } else {
- /* Using DAC FIFO. */
- /* Read DACSWTRIG register to trigger conversion. */
- inw(dev->iobase + PCI230P2_DACSWTRIG);
- spin_unlock_irqrestore(&devpriv->ao_stop_spinlock,
- irqflags);
- }
- /* Delay. Should driver be responsible for this? */
- /* XXX TODO: See if DAC busy bit can be used. */
- udelay(8);
+ if (!devpriv->ao_cmd_started) {
+ spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
+ return 1;
+ }
+ /* Perform scan. */
+ if (devpriv->hwver < 2) {
+ /* Not using DAC FIFO. */
+ spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
+ pci230_handle_ao_nofifo(dev, s);
+ comedi_event(dev, s);
} else {
+ /* Using DAC FIFO. */
+ /* Read DACSWTRIG register to trigger conversion. */
+ inw(devpriv->daqio + PCI230P2_DACSWTRIG);
spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
}
-
+ /* Delay. Should driver be responsible for this? */
+ /* XXX TODO: See if DAC busy bit can be used. */
+ udelay(8);
return 1;
}
@@ -1360,84 +1256,71 @@ static void pci230_ao_start(struct comedi_device *dev,
struct comedi_cmd *cmd = &async->cmd;
unsigned long irqflags;
- set_bit(AO_CMD_STARTED, &devpriv->state);
- if (cmd->stop_src == TRIG_COUNT && devpriv->ao_scan_count == 0) {
- /* An empty acquisition! */
- async->events |= COMEDI_CB_EOA;
- pci230_ao_stop(dev, s);
+ devpriv->ao_cmd_started = true;
+
+ if (devpriv->hwver >= 2) {
+ /* Using DAC FIFO. */
+ unsigned short scantrig;
+ bool run;
+
+ /* Preload FIFO data. */
+ run = pci230_handle_ao_fifo(dev, s);
comedi_event(dev, s);
- } else {
- if (devpriv->hwver >= 2) {
- /* Using DAC FIFO. */
- unsigned short scantrig;
- int run;
-
- /* Preload FIFO data. */
- run = pci230_handle_ao_fifo(dev, s);
- comedi_event(dev, s);
- if (!run) {
- /* Stopped. */
- return;
- }
- /* Set scan trigger source. */
- switch (cmd->scan_begin_src) {
- case TRIG_TIMER:
- scantrig = PCI230P2_DAC_TRIG_Z2CT1;
- break;
- case TRIG_EXT:
- /* Trigger on EXTTRIG/EXTCONVCLK pin. */
- if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
- /* +ve edge */
- scantrig = PCI230P2_DAC_TRIG_EXTP;
- } else {
- /* -ve edge */
- scantrig = PCI230P2_DAC_TRIG_EXTN;
- }
- break;
- case TRIG_INT:
- scantrig = PCI230P2_DAC_TRIG_SW;
- break;
- default:
- /* Shouldn't get here. */
- scantrig = PCI230P2_DAC_TRIG_NONE;
- break;
- }
- devpriv->daccon =
- (devpriv->daccon & ~PCI230P2_DAC_TRIG_MASK) |
- scantrig;
- outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
+ if (!run) {
+ /* Stopped. */
+ return;
}
+ /* Set scan trigger source. */
switch (cmd->scan_begin_src) {
case TRIG_TIMER:
- if (devpriv->hwver < 2) {
- /* Not using DAC FIFO. */
- /* Enable CT1 timer interrupt. */
- spin_lock_irqsave(&devpriv->isr_spinlock,
- irqflags);
- devpriv->int_en |= PCI230_INT_ZCLK_CT1;
- devpriv->ier |= PCI230_INT_ZCLK_CT1;
- outb(devpriv->ier,
- devpriv->iobase1 + PCI230_INT_SCE);
- spin_unlock_irqrestore(&devpriv->isr_spinlock,
- irqflags);
+ scantrig = PCI230P2_DAC_TRIG_Z2CT1;
+ break;
+ case TRIG_EXT:
+ /* Trigger on EXTTRIG/EXTCONVCLK pin. */
+ if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
+ /* +ve edge */
+ scantrig = PCI230P2_DAC_TRIG_EXTP;
+ } else {
+ /* -ve edge */
+ scantrig = PCI230P2_DAC_TRIG_EXTN;
}
- /* Set CT1 gate high to start counting. */
- outb(GAT_CONFIG(1, GAT_VCC),
- devpriv->iobase1 + PCI230_ZGAT_SCE);
break;
case TRIG_INT:
- async->inttrig = pci230_ao_inttrig_scan_begin;
+ scantrig = PCI230P2_DAC_TRIG_SW;
+ break;
+ default:
+ /* Shouldn't get here. */
+ scantrig = PCI230P2_DAC_TRIG_NONE;
break;
}
- if (devpriv->hwver >= 2) {
- /* Using DAC FIFO. Enable DAC FIFO interrupt. */
+ devpriv->daccon =
+ (devpriv->daccon & ~PCI230P2_DAC_TRIG_MASK) | scantrig;
+ outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
+ }
+ switch (cmd->scan_begin_src) {
+ case TRIG_TIMER:
+ if (devpriv->hwver < 2) {
+ /* Not using DAC FIFO. */
+ /* Enable CT1 timer interrupt. */
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
- devpriv->int_en |= PCI230P2_INT_DAC;
- devpriv->ier |= PCI230P2_INT_DAC;
- outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
+ devpriv->ier |= PCI230_INT_ZCLK_CT1;
+ outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
spin_unlock_irqrestore(&devpriv->isr_spinlock,
irqflags);
}
+ /* Set CT1 gate high to start counting. */
+ outb(GAT_CONFIG(1, GAT_VCC), dev->iobase + PCI230_ZGAT_SCE);
+ break;
+ case TRIG_INT:
+ async->inttrig = pci230_ao_inttrig_scan_begin;
+ break;
+ }
+ if (devpriv->hwver >= 2) {
+ /* Using DAC FIFO. Enable DAC FIFO interrupt. */
+ spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
+ devpriv->ier |= PCI230P2_INT_DAC;
+ outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
+ spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
}
}
@@ -1467,22 +1350,18 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (cmd->scan_begin_src == TRIG_TIMER) {
/* Claim Z2-CT1. */
- if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
+ if (!pci230_claim_shared(dev, RES_Z2CT1, OWNER_AOCMD))
return -EBUSY;
}
- /* Get number of scans required. */
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ao_scan_count = cmd->stop_arg;
- else /* TRIG_NONE, user calls cancel */
- devpriv->ao_scan_count = 0;
+ devpriv->ao_scan_count = cmd->stop_arg;
/*
* Set range - see analogue output range table; 0 => unipolar 10V,
* 1 => bipolar +/-10V range scale
*/
range = CR_RANGE(cmd->chanlist[0]);
- devpriv->ao_bipolar = pci230_ao_bipolar[range];
+ devpriv->ao_bipolar = comedi_range_is_bipolar(s, range);
daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
/* Use DAC FIFO for hardware version 2 onwards. */
if (devpriv->hwver >= 2) {
@@ -1494,7 +1373,7 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
/* Set channel scan list. */
- outw(dacen, dev->iobase + PCI230P2_DACEN);
+ outw(dacen, devpriv->daqio + PCI230P2_DACEN);
/*
* Enable DAC FIFO.
* Set DAC scan source to 'none'.
@@ -1509,7 +1388,7 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
/* Set DACCON. */
- outw(daccon, dev->iobase + PCI230_DACCON);
+ outw(daccon, devpriv->daqio + PCI230_DACCON);
/* Preserve most of DACCON apart from write-only, transient bits. */
devpriv->daccon = daccon & ~(PCI230P2_DAC_FIFO_RESET |
PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
@@ -1520,8 +1399,7 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
* cmd->scan_begin_arg is sampling period in ns.
* Gate it off for now.
*/
- outb(GAT_CONFIG(1, GAT_GND),
- devpriv->iobase1 + PCI230_ZGAT_SCE);
+ outb(GAT_CONFIG(1, GAT_GND), dev->iobase + PCI230_ZGAT_SCE);
pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
cmd->scan_begin_arg,
cmd->flags);
@@ -1550,8 +1428,8 @@ static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
chanlist_len = 1;
min_scan_period = chanlist_len * cmd->convert_arg;
- if ((min_scan_period < chanlist_len) ||
- (min_scan_period < cmd->convert_arg)) {
+ if (min_scan_period < chanlist_len ||
+ min_scan_period < cmd->convert_arg) {
/* Arithmetic overflow. */
min_scan_period = UINT_MAX;
err++;
@@ -1573,7 +1451,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev,
unsigned int prev_chan = 0;
unsigned int prev_range = 0;
unsigned int prev_aref = 0;
- unsigned int prev_polarity = 0;
+ bool prev_bipolar = false;
unsigned int subseq_len = 0;
int i;
@@ -1582,7 +1460,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev,
unsigned int chan = CR_CHAN(chanspec);
unsigned int range = CR_RANGE(chanspec);
unsigned int aref = CR_AREF(chanspec);
- unsigned int polarity = pci230_ai_bipolar[range];
+ bool bipolar = comedi_range_is_bipolar(s, range);
if (aref == AREF_DIFF && chan >= max_diff_chan) {
dev_dbg(dev->class_dev,
@@ -1614,7 +1492,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev,
return -EINVAL;
}
- if (polarity != prev_polarity) {
+ if (bipolar != prev_bipolar) {
dev_dbg(dev->class_dev,
"%s: channel sequence ranges must be all bipolar or all unipolar\n",
__func__);
@@ -1632,7 +1510,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev,
prev_chan = chan;
prev_range = range;
prev_aref = aref;
- prev_polarity = polarity;
+ prev_bipolar = bipolar;
}
if (subseq_len == 0)
@@ -1670,7 +1548,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev,
static int pci230_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
- const struct pci230_board *thisboard = comedi_board(dev);
+ const struct pci230_board *thisboard = dev->board_ptr;
struct pci230_private *devpriv = dev->private;
int err = 0;
unsigned int tmp;
@@ -1680,7 +1558,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
- if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
+ if (thisboard->have_dio || thisboard->min_hwver > 0) {
/*
* Unfortunately, we cannot trigger a scan off an external
* source on the PCI260 board, since it uses the PPIC0 (DIO)
@@ -1711,8 +1589,8 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
* set up to generate a fixed number of timed conversion pulses.
*/
- if ((cmd->scan_begin_src != TRIG_FOLLOW) &&
- (cmd->convert_src != TRIG_TIMER))
+ if (cmd->scan_begin_src != TRIG_FOLLOW &&
+ cmd->convert_src != TRIG_TIMER)
err |= -EINVAL;
if (err)
@@ -1739,7 +1617,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
* PCI230 or PCI260. Max speed depends whether
* single-ended or pseudo-differential.
*/
- if (cmd->chanlist && (cmd->chanlist_len > 0)) {
+ if (cmd->chanlist && cmd->chanlist_len > 0) {
/* Peek analogue reference of first channel. */
if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
max_speed_ai = MAX_SPEED_AI_DIFF;
@@ -1779,13 +1657,12 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
* The only flags allowed are CR_INVERT and CR_EDGE.
* CR_EDGE is required.
*/
- if ((cmd->convert_arg &
- (CR_FLAGS_MASK & ~CR_INVERT)) != CR_EDGE) {
+ if ((cmd->convert_arg & CR_FLAGS_MASK & ~CR_INVERT) !=
+ CR_EDGE) {
/* Set CR_EDGE, preserve CR_INVERT. */
- cmd->convert_arg = COMBINE(cmd->start_arg,
- (CR_EDGE | 0),
- CR_FLAGS_MASK &
- ~CR_INVERT);
+ cmd->convert_arg =
+ COMBINE(cmd->start_arg, CR_EDGE | 0,
+ CR_FLAGS_MASK & ~CR_INVERT);
err |= -EINVAL;
}
} else {
@@ -1802,7 +1679,9 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
- if (cmd->stop_src == TRIG_NONE)
+ if (cmd->stop_src == TRIG_COUNT)
+ err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+ else /* TRIG_NONE */
err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
if (cmd->scan_begin_src == TRIG_EXT) {
@@ -1850,7 +1729,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
if (!pci230_ai_check_scan_period(cmd)) {
/* Was below minimum required. Round up. */
pci230_ns_to_single_timer(&cmd->scan_begin_arg,
- TRIG_ROUND_UP);
+ CMDF_ROUND_UP);
pci230_ai_check_scan_period(cmd);
}
if (tmp != cmd->scan_begin_arg)
@@ -1880,37 +1759,30 @@ static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
unsigned short triglev;
unsigned short adccon;
- if (cmd->flags & TRIG_WAKE_EOS) {
- /* Wake at end of scan. */
+ if (cmd->flags & CMDF_WAKE_EOS)
wake = scanlen - devpriv->ai_scan_pos;
- } else {
- if (cmd->stop_src != TRIG_COUNT ||
- devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL ||
- scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
- wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
- } else {
- wake = (devpriv->ai_scan_count * scanlen) -
- devpriv->ai_scan_pos;
- }
- }
+ else if (cmd->stop_src != TRIG_COUNT ||
+ devpriv->ai_scan_count >= PCI230_ADC_FIFOLEVEL_HALFFULL ||
+ scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)
+ wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
+ else
+ wake = devpriv->ai_scan_count * scanlen - devpriv->ai_scan_pos;
if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
triglev = PCI230_ADC_INT_FIFO_HALF;
- } else {
- if ((wake > 1) && (devpriv->hwver > 0)) {
- /* PCI230+/260+ programmable FIFO interrupt level. */
- if (devpriv->adcfifothresh != wake) {
- devpriv->adcfifothresh = wake;
- outw(wake, dev->iobase + PCI230P_ADCFFTH);
- }
- triglev = PCI230P_ADC_INT_FIFO_THRESH;
- } else {
- triglev = PCI230_ADC_INT_FIFO_NEMPTY;
+ } else if (wake > 1 && devpriv->hwver > 0) {
+ /* PCI230+/260+ programmable FIFO interrupt level. */
+ if (devpriv->adcfifothresh != wake) {
+ devpriv->adcfifothresh = wake;
+ outw(wake, devpriv->daqio + PCI230P_ADCFFTH);
}
+ triglev = PCI230P_ADC_INT_FIFO_THRESH;
+ } else {
+ triglev = PCI230_ADC_INT_FIFO_NEMPTY;
}
adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
if (adccon != devpriv->adccon) {
devpriv->adccon = adccon;
- outw(adccon, dev->iobase + PCI230_ADCCON);
+ outw(adccon, devpriv->daqio + PCI230_ADCCON);
}
}
@@ -1920,43 +1792,39 @@ static int pci230_ai_inttrig_convert(struct comedi_device *dev,
{
struct pci230_private *devpriv = dev->private;
unsigned long irqflags;
+ unsigned int delayus;
if (trig_num)
return -EINVAL;
spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
- if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
- unsigned int delayus;
-
- /*
- * Trigger conversion by toggling Z2-CT2 output.
- * Finish with output high.
- */
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
- I8254_MODE0);
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
- I8254_MODE1);
- /*
- * Delay. Should driver be responsible for this? An
- * alternative would be to wait until conversion is complete,
- * but we can't tell when it's complete because the ADC busy
- * bit has a different meaning when FIFO enabled (and when
- * FIFO not enabled, it only works for software triggers).
- */
- if (((devpriv->adccon & PCI230_ADC_IM_MASK) ==
- PCI230_ADC_IM_DIF) && (devpriv->hwver == 0)) {
- /* PCI230/260 in differential mode */
- delayus = 8;
- } else {
- /* single-ended or PCI230+/260+ */
- delayus = 4;
- }
+ if (!devpriv->ai_cmd_started) {
spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
- udelay(delayus);
+ return 1;
+ }
+ /*
+ * Trigger conversion by toggling Z2-CT2 output.
+ * Finish with output high.
+ */
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
+ /*
+ * Delay. Should driver be responsible for this? An
+ * alternative would be to wait until conversion is complete,
+ * but we can't tell when it's complete because the ADC busy
+ * bit has a different meaning when FIFO enabled (and when
+ * FIFO not enabled, it only works for software triggers).
+ */
+ if ((devpriv->adccon & PCI230_ADC_IM_MASK) == PCI230_ADC_IM_DIF &&
+ devpriv->hwver == 0) {
+ /* PCI230/260 in differential mode */
+ delayus = 8;
} else {
- spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
+ /* single-ended or PCI230+/260+ */
+ delayus = 4;
}
-
+ spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
+ udelay(delayus);
return 1;
}
@@ -1972,12 +1840,12 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
return -EINVAL;
spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
- if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
+ if (devpriv->ai_cmd_started) {
/* Trigger scan by waggling CT0 gate source. */
zgat = GAT_CONFIG(0, GAT_GND);
- outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
zgat = GAT_CONFIG(0, GAT_VCC);
- outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
}
spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
@@ -1990,10 +1858,11 @@ static void pci230_ai_stop(struct comedi_device *dev,
struct pci230_private *devpriv = dev->private;
unsigned long irqflags;
struct comedi_cmd *cmd;
- int started;
+ bool started;
spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
- started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
+ started = devpriv->ai_cmd_started;
+ devpriv->ai_cmd_started = false;
spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
if (!started)
return;
@@ -2011,15 +1880,12 @@ static void pci230_ai_stop(struct comedi_device *dev,
* Disable ADC interrupt and wait for interrupt routine to finish
* running unless we are called from the interrupt routine.
*/
- devpriv->int_en &= ~PCI230_INT_ADC;
+ devpriv->ier &= ~PCI230_INT_ADC;
while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
}
- if (devpriv->ier != devpriv->int_en) {
- devpriv->ier = devpriv->int_en;
- outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
- }
+ outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
/*
* Reset FIFO, disable FIFO and set start conversion source to none.
@@ -2029,9 +1895,9 @@ static void pci230_ai_stop(struct comedi_device *dev,
(devpriv->adccon & (PCI230_ADC_IR_MASK | PCI230_ADC_IM_MASK)) |
PCI230_ADC_TRIG_NONE;
outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
- dev->iobase + PCI230_ADCCON);
+ devpriv->daqio + PCI230_ADCCON);
/* Release resources. */
- put_all_resources(dev, OWNER_AICMD);
+ pci230_release_all_resources(dev, OWNER_AICMD);
}
static void pci230_ai_start(struct comedi_device *dev,
@@ -2043,145 +1909,132 @@ static void pci230_ai_start(struct comedi_device *dev,
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- set_bit(AI_CMD_STARTED, &devpriv->state);
- if (cmd->stop_src == TRIG_COUNT && devpriv->ai_scan_count == 0) {
- /* An empty acquisition! */
- async->events |= COMEDI_CB_EOA;
- pci230_ai_stop(dev, s);
- comedi_event(dev, s);
- } else {
- /* Enable ADC FIFO trigger level interrupt. */
- spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
- devpriv->int_en |= PCI230_INT_ADC;
- devpriv->ier |= PCI230_INT_ADC;
- outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
- spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
+ devpriv->ai_cmd_started = true;
- /*
- * Update conversion trigger source which is currently set
- * to CT2 output, which is currently stuck high.
- */
- switch (cmd->convert_src) {
- default:
- conv = PCI230_ADC_TRIG_NONE;
- break;
- case TRIG_TIMER:
- /* Using CT2 output. */
- conv = PCI230_ADC_TRIG_Z2CT2;
- break;
- case TRIG_EXT:
- if (cmd->convert_arg & CR_EDGE) {
- if ((cmd->convert_arg & CR_INVERT) == 0) {
- /* Trigger on +ve edge. */
- conv = PCI230_ADC_TRIG_EXTP;
- } else {
- /* Trigger on -ve edge. */
- conv = PCI230_ADC_TRIG_EXTN;
- }
+ /* Enable ADC FIFO trigger level interrupt. */
+ spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
+ devpriv->ier |= PCI230_INT_ADC;
+ outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
+ spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
+
+ /*
+ * Update conversion trigger source which is currently set
+ * to CT2 output, which is currently stuck high.
+ */
+ switch (cmd->convert_src) {
+ default:
+ conv = PCI230_ADC_TRIG_NONE;
+ break;
+ case TRIG_TIMER:
+ /* Using CT2 output. */
+ conv = PCI230_ADC_TRIG_Z2CT2;
+ break;
+ case TRIG_EXT:
+ if (cmd->convert_arg & CR_EDGE) {
+ if ((cmd->convert_arg & CR_INVERT) == 0) {
+ /* Trigger on +ve edge. */
+ conv = PCI230_ADC_TRIG_EXTP;
} else {
- /* Backwards compatibility. */
- if (cmd->convert_arg) {
- /* Trigger on +ve edge. */
- conv = PCI230_ADC_TRIG_EXTP;
- } else {
- /* Trigger on -ve edge. */
- conv = PCI230_ADC_TRIG_EXTN;
- }
+ /* Trigger on -ve edge. */
+ conv = PCI230_ADC_TRIG_EXTN;
+ }
+ } else {
+ /* Backwards compatibility. */
+ if (cmd->convert_arg) {
+ /* Trigger on +ve edge. */
+ conv = PCI230_ADC_TRIG_EXTP;
+ } else {
+ /* Trigger on -ve edge. */
+ conv = PCI230_ADC_TRIG_EXTN;
}
- break;
- case TRIG_INT:
- /*
- * Use CT2 output for software trigger due to problems
- * in differential mode on PCI230/260.
- */
- conv = PCI230_ADC_TRIG_Z2CT2;
- break;
}
- devpriv->adccon =
- (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) | conv;
- outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
- if (cmd->convert_src == TRIG_INT)
- async->inttrig = pci230_ai_inttrig_convert;
-
+ break;
+ case TRIG_INT:
/*
- * Update FIFO interrupt trigger level, which is currently
- * set to "full".
+ * Use CT2 output for software trigger due to problems
+ * in differential mode on PCI230/260.
*/
- pci230_ai_update_fifo_trigger_level(dev, s);
- if (cmd->convert_src == TRIG_TIMER) {
- /* Update timer gates. */
- unsigned char zgat;
+ conv = PCI230_ADC_TRIG_Z2CT2;
+ break;
+ }
+ devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK) | conv;
+ outw(devpriv->adccon, devpriv->daqio + PCI230_ADCCON);
+ if (cmd->convert_src == TRIG_INT)
+ async->inttrig = pci230_ai_inttrig_convert;
- if (cmd->scan_begin_src != TRIG_FOLLOW) {
+ /*
+ * Update FIFO interrupt trigger level, which is currently
+ * set to "full".
+ */
+ pci230_ai_update_fifo_trigger_level(dev, s);
+ if (cmd->convert_src == TRIG_TIMER) {
+ /* Update timer gates. */
+ unsigned char zgat;
+
+ if (cmd->scan_begin_src != TRIG_FOLLOW) {
+ /*
+ * Conversion timer CT2 needs to be gated by
+ * inverted output of monostable CT2.
+ */
+ zgat = GAT_CONFIG(2, GAT_NOUTNM2);
+ } else {
+ /*
+ * Conversion timer CT2 needs to be gated on
+ * continuously.
+ */
+ zgat = GAT_CONFIG(2, GAT_VCC);
+ }
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
+ if (cmd->scan_begin_src != TRIG_FOLLOW) {
+ /* Set monostable CT0 trigger source. */
+ switch (cmd->scan_begin_src) {
+ default:
+ zgat = GAT_CONFIG(0, GAT_VCC);
+ break;
+ case TRIG_EXT:
/*
- * Conversion timer CT2 needs to be gated by
- * inverted output of monostable CT2.
+ * For CT0 on PCI230, the external trigger
+ * (gate) signal comes from PPC0, which is
+ * channel 16 of the DIO subdevice. The
+ * application needs to configure this as an
+ * input in order to use it as an external scan
+ * trigger.
*/
- zgat = GAT_CONFIG(2, GAT_NOUTNM2);
- } else {
+ zgat = GAT_CONFIG(0, GAT_EXT);
+ break;
+ case TRIG_TIMER:
/*
- * Conversion timer CT2 needs to be gated on
- * continuously.
+ * Monostable CT0 triggered by rising edge on
+ * inverted output of CT1 (falling edge on CT1).
*/
- zgat = GAT_CONFIG(2, GAT_VCC);
+ zgat = GAT_CONFIG(0, GAT_NOUTNM2);
+ break;
+ case TRIG_INT:
+ /*
+ * Monostable CT0 is triggered by inttrig
+ * function waggling the CT0 gate source.
+ */
+ zgat = GAT_CONFIG(0, GAT_VCC);
+ break;
}
- outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
- if (cmd->scan_begin_src != TRIG_FOLLOW) {
- /* Set monostable CT0 trigger source. */
- switch (cmd->scan_begin_src) {
- default:
- zgat = GAT_CONFIG(0, GAT_VCC);
- break;
- case TRIG_EXT:
- /*
- * For CT0 on PCI230, the external
- * trigger (gate) signal comes from
- * PPC0, which is channel 16 of the DIO
- * subdevice. The application needs to
- * configure this as an input in order
- * to use it as an external scan
- * trigger.
- */
- zgat = GAT_CONFIG(0, GAT_EXT);
- break;
- case TRIG_TIMER:
- /*
- * Monostable CT0 triggered by rising
- * edge on inverted output of CT1
- * (falling edge on CT1).
- */
- zgat = GAT_CONFIG(0, GAT_NOUTNM2);
- break;
- case TRIG_INT:
- /*
- * Monostable CT0 is triggered by
- * inttrig function waggling the CT0
- * gate source.
- */
- zgat = GAT_CONFIG(0, GAT_VCC);
- break;
- }
- outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
- switch (cmd->scan_begin_src) {
- case TRIG_TIMER:
- /*
- * Scan period timer CT1 needs to be
- * gated on to start counting.
- */
- zgat = GAT_CONFIG(1, GAT_VCC);
- outb(zgat, devpriv->iobase1 +
- PCI230_ZGAT_SCE);
- break;
- case TRIG_INT:
- async->inttrig =
- pci230_ai_inttrig_scan_begin;
- break;
- }
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
+ switch (cmd->scan_begin_src) {
+ case TRIG_TIMER:
+ /*
+ * Scan period timer CT1 needs to be
+ * gated on to start counting.
+ */
+ zgat = GAT_CONFIG(1, GAT_VCC);
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
+ break;
+ case TRIG_INT:
+ async->inttrig = pci230_ai_inttrig_scan_begin;
+ break;
}
- } else if (cmd->convert_src != TRIG_INT) {
- /* No longer need Z2-CT2. */
- put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
}
+ } else if (cmd->convert_src != TRIG_INT) {
+ /* No longer need Z2-CT2. */
+ pci230_release_shared(dev, RES_Z2CT2, OWNER_AICMD);
}
}
@@ -2218,12 +2071,11 @@ static void pci230_handle_ai(struct comedi_device *dev,
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
} else if (devpriv->ai_scan_count == 0) {
todo = 0;
- } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL) ||
- (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
+ } else if (devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL ||
+ scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL) {
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
} else {
- todo = (devpriv->ai_scan_count * scanlen) -
- devpriv->ai_scan_pos;
+ todo = devpriv->ai_scan_count * scanlen - devpriv->ai_scan_pos;
if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
}
@@ -2233,7 +2085,7 @@ static void pci230_handle_ai(struct comedi_device *dev,
for (i = 0; i < todo; i++) {
if (fifoamount == 0) {
/* Read FIFO state. */
- status_fifo = inw(dev->iobase + PCI230_ADCCON);
+ status_fifo = inw(devpriv->daqio + PCI230_ADCCON);
if (status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) {
/*
* Report error otherwise FIFO overruns will go
@@ -2248,19 +2100,15 @@ static void pci230_handle_ai(struct comedi_device *dev,
} else if (status_fifo & PCI230_ADC_FIFO_HALF) {
/* FIFO half full. */
fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
+ } else if (devpriv->hwver > 0) {
+ /* Read PCI230+/260+ ADC FIFO level. */
+ fifoamount = inw(devpriv->daqio +
+ PCI230P_ADCFFLEV);
+ if (fifoamount == 0)
+ break; /* Shouldn't happen. */
} else {
/* FIFO not empty. */
- if (devpriv->hwver > 0) {
- /* Read PCI230+/260+ ADC FIFO level. */
- fifoamount =
- inw(dev->iobase + PCI230P_ADCFFLEV);
- if (fifoamount == 0) {
- /* Shouldn't happen. */
- break;
- }
- } else {
- fifoamount = 1;
- }
+ fifoamount = 1;
}
}
/* Read sample and store in Comedi's circular buffer. */
@@ -2316,25 +2164,20 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
* Need Z2-CT2 to supply a conversion trigger source at a high
* logic level, even if not doing timed conversions.
*/
- res_mask |= (1U << RES_Z2CT2);
+ res_mask |= RES_Z2CT2;
if (cmd->scan_begin_src != TRIG_FOLLOW) {
/* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
- res_mask |= (1U << RES_Z2CT0);
+ res_mask |= RES_Z2CT0;
if (cmd->scan_begin_src == TRIG_TIMER) {
/* Using Z2-CT1 for scan frequency */
- res_mask |= (1U << RES_Z2CT1);
+ res_mask |= RES_Z2CT1;
}
}
/* Claim resources. */
- if (!get_resources(dev, res_mask, OWNER_AICMD))
+ if (!pci230_claim_shared(dev, res_mask, OWNER_AICMD))
return -EBUSY;
-
- /* Get number of scans required. */
- if (cmd->stop_src == TRIG_COUNT)
- devpriv->ai_scan_count = cmd->stop_arg;
- else /* TRIG_NONE, user calls cancel */
- devpriv->ai_scan_count = 0;
+ devpriv->ai_scan_count = cmd->stop_arg;
devpriv->ai_scan_pos = 0; /* Position within scan. */
/*
@@ -2369,7 +2212,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
range = CR_RANGE(cmd->chanlist[0]);
- devpriv->ai_bipolar = pci230_ai_bipolar[range];
+ devpriv->ai_bipolar = comedi_range_is_bipolar(s, range);
if (devpriv->ai_bipolar)
adccon |= PCI230_ADC_IR_BIP;
else
@@ -2396,7 +2239,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
adcen |= 1 << gainshift;
}
} else {
- gainshift = (chan & ~1);
+ gainshift = chan & ~1;
adcen |= 1 << chan;
}
devpriv->adcg = (devpriv->adcg & ~(3 << gainshift)) |
@@ -2404,16 +2247,16 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
/* Set channel scan list. */
- outw(adcen, dev->iobase + PCI230_ADCEN);
+ outw(adcen, devpriv->daqio + PCI230_ADCEN);
/* Set channel gains. */
- outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
+ outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
/*
* Set counter/timer 2 output high for use as the initial start
* conversion source.
*/
- i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
+ i8254_set_mode(dev->iobase + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
/*
* Temporarily use CT2 output as conversion trigger source and
@@ -2429,7 +2272,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
* PCI230/260, but that will be dealt with later.
*/
devpriv->adccon = adccon;
- outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
+ outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
/*
* Delay -
@@ -2443,7 +2286,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
usleep_range(25, 100);
/* Reset FIFO again. */
- outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
+ outw(adccon | PCI230_ADC_FIFO_RESET, devpriv->daqio + PCI230_ADCCON);
if (cmd->convert_src == TRIG_TIMER) {
/*
@@ -2452,7 +2295,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
* connector: PCI230 pin 21, PCI260 pin 18.
*/
zgat = GAT_CONFIG(2, GAT_GND);
- outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
/* Set counter/timer 2 to the specified conversion period. */
pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
cmd->flags);
@@ -2470,11 +2313,11 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
* source will be changed later.
*/
zgat = GAT_CONFIG(0, GAT_VCC);
- outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
((uint64_t)cmd->convert_arg *
cmd->scan_end_arg),
- TRIG_ROUND_UP);
+ CMDF_ROUND_UP);
if (cmd->scan_begin_src == TRIG_TIMER) {
/*
* Monostable on CT0 will be triggered by
@@ -2483,7 +2326,7 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
* Set up CT1 but gate it off for now.
*/
zgat = GAT_CONFIG(1, GAT_GND);
- outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
+ outb(zgat, dev->iobase + PCI230_ZGAT_SCE);
pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
cmd->scan_begin_arg,
cmd->flags);
@@ -2509,29 +2352,28 @@ static int pci230_ai_cancel(struct comedi_device *dev,
/* Interrupt handler */
static irqreturn_t pci230_interrupt(int irq, void *d)
{
- unsigned char status_int, valid_status_int;
+ unsigned char status_int, valid_status_int, temp_ier;
struct comedi_device *dev = (struct comedi_device *)d;
struct pci230_private *devpriv = dev->private;
struct comedi_subdevice *s;
unsigned long irqflags;
/* Read interrupt status/enable register. */
- status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
+ status_int = inb(dev->iobase + PCI230_INT_STAT);
if (status_int == PCI230_INT_DISABLE)
return IRQ_NONE;
-
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
- valid_status_int = devpriv->int_en & status_int;
+ valid_status_int = devpriv->ier & status_int;
/*
* Disable triggered interrupts.
* (Only those interrupts that need re-enabling, are, later in the
* handler).
*/
- devpriv->ier = devpriv->int_en & ~status_int;
- outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
- devpriv->intr_running = 1;
+ temp_ier = devpriv->ier & ~status_int;
+ outb(temp_ier, dev->iobase + PCI230_INT_SCE);
+ devpriv->intr_running = true;
devpriv->intr_cpuid = THISCPU;
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
@@ -2563,11 +2405,9 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
/* Reenable interrupts. */
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
- if (devpriv->ier != devpriv->int_en) {
- devpriv->ier = devpriv->int_en;
- outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
- }
- devpriv->intr_running = 0;
+ if (devpriv->ier != temp_ier)
+ outb(devpriv->ier, dev->iobase + PCI230_INT_SCE);
+ devpriv->intr_running = false;
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
return IRQ_HANDLED;
@@ -2603,49 +2443,17 @@ static const struct pci230_board *pci230_find_pci_board(struct pci_dev *pci_dev)
return NULL;
}
-/* Look for PCI device matching requested board name, bus and slot. */
-static struct pci_dev *pci230_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- const struct pci230_board *thisboard = comedi_board(dev);
- struct pci_dev *pci_dev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pci_dev) {
- /* Check vendor ID (same for all supported PCI boards). */
- if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
- continue;
- /* If bus/slot specified, check them. */
- if ((bus || slot) &&
- (bus != pci_dev->bus->number ||
- slot != PCI_SLOT(pci_dev->devfn)))
- continue;
- if (thisboard->id == PCI_DEVICE_ID_INVALID) {
- /* Wildcard board matches any supported PCI board. */
- const struct pci230_board *foundboard;
-
- foundboard = pci230_find_pci_board(pci_dev);
- if (foundboard == NULL)
- continue;
- /* Replace wildcard board_ptr. */
- dev->board_ptr = foundboard;
- } else {
- /* Need to match a specific board. */
- if (!pci230_match_pci_board(thisboard, pci_dev))
- continue;
- }
- return pci_dev;
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int pci230_alloc_private(struct comedi_device *dev)
+static int pci230_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
{
+ struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
+ const struct pci230_board *thisboard;
struct pci230_private *devpriv;
+ struct comedi_subdevice *s;
+ int rc;
+
+ dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
+ pci_name(pci_dev));
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
@@ -2655,22 +2463,14 @@ static int pci230_alloc_private(struct comedi_device *dev)
spin_lock_init(&devpriv->res_spinlock);
spin_lock_init(&devpriv->ai_stop_spinlock);
spin_lock_init(&devpriv->ao_stop_spinlock);
- return 0;
-}
-
-/* Common part of attach and auto_attach. */
-static int pci230_attach_common(struct comedi_device *dev,
- struct pci_dev *pci_dev)
-{
- const struct pci230_board *thisboard = comedi_board(dev);
- struct pci230_private *devpriv = dev->private;
- struct comedi_subdevice *s;
- unsigned long iobase1, iobase2;
- /* PCI230's I/O spaces 1 and 2 respectively. */
- int rc;
-
- comedi_set_hw_dev(dev, &pci_dev->dev);
+ dev->board_ptr = pci230_find_pci_board(pci_dev);
+ if (dev->board_ptr == NULL) {
+ dev_err(dev->class_dev,
+ "amplc_pci230: BUG! cannot determine board type!\n");
+ return -EINVAL;
+ }
+ thisboard = dev->board_ptr;
dev->board_name = thisboard->name;
rc = comedi_pci_enable(dev);
@@ -2681,15 +2481,14 @@ static int pci230_attach_common(struct comedi_device *dev,
* Read base addresses of the PCI230's two I/O regions from PCI
* configuration register.
*/
- iobase1 = pci_resource_start(pci_dev, 2);
- iobase2 = pci_resource_start(pci_dev, 3);
+ dev->iobase = pci_resource_start(pci_dev, 2);
+ devpriv->daqio = pci_resource_start(pci_dev, 3);
dev_dbg(dev->class_dev,
"%s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
- dev->board_name, iobase1, iobase2);
- devpriv->iobase1 = iobase1;
- dev->iobase = iobase2;
+ dev->board_name, dev->iobase, devpriv->daqio);
/* Read bits of DACCON register - only the output range. */
- devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
+ devpriv->daccon = inw(devpriv->daqio + PCI230_DACCON) &
+ PCI230_DAC_OR_MASK;
/*
* Read hardware version register and set extended function register
* if they exist.
@@ -2697,7 +2496,7 @@ static int pci230_attach_common(struct comedi_device *dev,
if (pci_resource_len(pci_dev, 3) >= 32) {
unsigned short extfunc = 0;
- devpriv->hwver = inw(dev->iobase + PCI230P_HWVER);
+ devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER);
if (devpriv->hwver < thisboard->min_hwver) {
dev_err(dev->class_dev,
"%s - bad hardware version - got %u, need %u\n",
@@ -2716,13 +2515,12 @@ static int pci230_attach_common(struct comedi_device *dev,
*/
extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
}
- if ((thisboard->ao_chans > 0) &&
- (devpriv->hwver >= 2)) {
+ if (thisboard->ao_bits && devpriv->hwver >= 2) {
/* Enable DAC FIFO functionality. */
extfunc |= PCI230P2_EXTFUNC_DACFIFO;
}
}
- outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
+ outw(extfunc, devpriv->daqio + PCI230P_EXTFUNC);
if (extfunc & PCI230P2_EXTFUNC_DACFIFO) {
/*
* Temporarily enable DAC FIFO, reset it and disable
@@ -2730,23 +2528,23 @@ static int pci230_attach_common(struct comedi_device *dev,
*/
outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN |
PCI230P2_DAC_FIFO_RESET,
- dev->iobase + PCI230_DACCON);
+ devpriv->daqio + PCI230_DACCON);
/* Clear DAC FIFO channel enable register. */
- outw(0, dev->iobase + PCI230P2_DACEN);
+ outw(0, devpriv->daqio + PCI230P2_DACEN);
/* Disable DAC FIFO. */
- outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
+ outw(devpriv->daccon, devpriv->daqio + PCI230_DACCON);
}
}
/* Disable board's interrupts. */
- outb(0, devpriv->iobase1 + PCI230_INT_SCE);
+ outb(0, dev->iobase + PCI230_INT_SCE);
/* Set ADC to a reasonable state. */
devpriv->adcg = 0;
devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE |
PCI230_ADC_IR_BIP;
- outw(1 << 0, dev->iobase + PCI230_ADCEN);
- outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
+ outw(1 << 0, devpriv->daqio + PCI230_ADCEN);
+ outw(devpriv->adcg, devpriv->daqio + PCI230_ADCG);
outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
- dev->iobase + PCI230_ADCCON);
+ devpriv->daqio + PCI230_ADCCON);
if (pci_dev->irq) {
rc = request_irq(pci_dev->irq, pci230_interrupt, IRQF_SHARED,
@@ -2763,10 +2561,10 @@ static int pci230_attach_common(struct comedi_device *dev,
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
- s->n_chan = thisboard->ai_chans;
+ s->n_chan = 16;
s->maxdata = (1 << thisboard->ai_bits) - 1;
s->range_table = &pci230_ai_range;
- s->insn_read = pci230_ai_rinsn;
+ s->insn_read = pci230_ai_insn_read;
s->len_chanlist = 256; /* but there are restrictions. */
if (dev->irq) {
dev->read_subdev = s;
@@ -2778,15 +2576,15 @@ static int pci230_attach_common(struct comedi_device *dev,
s = &dev->subdevices[1];
/* analog output subdevice */
- if (thisboard->ao_chans > 0) {
+ if (thisboard->ao_bits) {
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
- s->n_chan = thisboard->ao_chans;
+ s->n_chan = 2;
s->maxdata = (1 << thisboard->ao_bits) - 1;
s->range_table = &pci230_ao_range;
- s->insn_write = pci230_ao_winsn;
- s->insn_read = pci230_ao_rinsn;
- s->len_chanlist = thisboard->ao_chans;
+ s->insn_write = pci230_ao_insn_write;
+ s->insn_read = comedi_readback_insn_read;
+ s->len_chanlist = 2;
if (dev->irq) {
dev->write_subdev = s;
s->subdev_flags |= SDF_CMD_WRITE;
@@ -2794,6 +2592,10 @@ static int pci230_attach_common(struct comedi_device *dev,
s->do_cmdtest = pci230_ao_cmdtest;
s->cancel = pci230_ao_cancel;
}
+
+ rc = comedi_alloc_subdev_readback(s);
+ if (rc)
+ return rc;
} else {
s->type = COMEDI_SUBD_UNUSED;
}
@@ -2801,8 +2603,7 @@ static int pci230_attach_common(struct comedi_device *dev,
s = &dev->subdevices[2];
/* digital i/o subdevice */
if (thisboard->have_dio) {
- rc = subdev_8255_init(dev, s, NULL,
- devpriv->iobase1 + PCI230_PPI_X_BASE);
+ rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE);
if (rc)
return rc;
} else {
@@ -2812,74 +2613,11 @@ static int pci230_attach_common(struct comedi_device *dev,
return 0;
}
-static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- const struct pci230_board *thisboard = comedi_board(dev);
- struct pci_dev *pci_dev;
- int rc;
-
- dev_info(dev->class_dev, "amplc_pci230: attach %s %d,%d\n",
- thisboard->name, it->options[0], it->options[1]);
-
- rc = pci230_alloc_private(dev);
- if (rc)
- return rc;
-
- pci_dev = pci230_find_pci_dev(dev, it);
- if (!pci_dev)
- return -EIO;
- return pci230_attach_common(dev, pci_dev);
-}
-
-static int pci230_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
-{
- struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
- int rc;
-
- dev_info(dev->class_dev, "amplc_pci230: attach pci %s\n",
- pci_name(pci_dev));
-
- rc = pci230_alloc_private(dev);
- if (rc)
- return rc;
-
- dev->board_ptr = pci230_find_pci_board(pci_dev);
- if (dev->board_ptr == NULL) {
- dev_err(dev->class_dev,
- "amplc_pci230: BUG! cannot determine board type!\n");
- return -EINVAL;
- }
- /*
- * Need to 'get' the PCI device to match the 'put' in pci230_detach().
- * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
- * support for manual attachment of PCI devices via pci230_attach()
- * has been removed.
- */
- pci_dev_get(pci_dev);
- return pci230_attach_common(dev, pci_dev);
-}
-
-static void pci230_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
- comedi_pci_disable(dev);
- if (pcidev)
- pci_dev_put(pcidev);
-}
-
static struct comedi_driver amplc_pci230_driver = {
.driver_name = "amplc_pci230",
.module = THIS_MODULE,
- .attach = pci230_attach,
.auto_attach = pci230_auto_attach,
- .detach = pci230_detach,
- .board_name = &pci230_boards[0].name,
- .offset = sizeof(pci230_boards[0]),
- .num_names = ARRAY_SIZE(pci230_boards),
+ .detach = comedi_pci_detach,
};
static int amplc_pci230_pci_probe(struct pci_dev *dev,
@@ -2905,5 +2643,5 @@ static struct pci_driver amplc_pci230_pci_driver = {
module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Amplicon PCI230(+) and PCI260(+)");
MODULE_LICENSE("GPL");