Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 317164
b: refs/heads/master
c: 5d3b0d1
h: refs/heads/master
v: v3
  • Loading branch information
Ian Abbott authored and Greg Kroah-Hartman committed Jun 5, 2012
1 parent 38af970 commit fc33e74
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 165 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bd4447e597e0609fccb91aeeb2add40a7fcf3289
refs/heads/master: 5d3b0d1859722a855b0310fcdc34c2e545cc1c7d
310 changes: 146 additions & 164 deletions trunk/drivers/staging/comedi/drivers/amplc_pci230.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,11 +579,6 @@ static const struct comedi_lrange pci230_ao_range = { 2, {
/* PCI230 daccon bipolar flag for each analogue output range. */
static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };

static void pci230_ai_stop(struct comedi_device *dev,
struct comedi_subdevice *s);
static void pci230_handle_ai(struct comedi_device *dev,
struct comedi_subdevice *s);

static short pci230_ai_read(struct comedi_device *dev)
{
const struct pci230_board *thisboard = comedi_board(dev);
Expand Down Expand Up @@ -2103,6 +2098,52 @@ static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
return 1;
}

static void pci230_ai_stop(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct pci230_private *devpriv = dev->private;
unsigned long irqflags;
struct comedi_cmd *cmd;
int started;

spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
if (!started)
return;
cmd = &s->async->cmd;
if (cmd->convert_src == TRIG_TIMER) {
/* Stop conversion rate generator. */
pci230_cancel_ct(dev, 2);
}
if (cmd->scan_begin_src != TRIG_FOLLOW) {
/* Stop scan period monostable. */
pci230_cancel_ct(dev, 0);
}
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
/* 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;
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);
}
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
/* Reset FIFO, disable FIFO and set start conversion source to none.
* Keep se/diff and bip/uni settings */
devpriv->adccon = (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);
/* Release resources. */
put_all_resources(dev, OWNER_AICMD);
}

static void pci230_ai_start(struct comedi_device *dev,
struct comedi_subdevice *s)
{
Expand Down Expand Up @@ -2255,6 +2296,99 @@ static int pci230_ai_inttrig_start(struct comedi_device *dev,
return 1;
}

static void pci230_handle_ai(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct pci230_private *devpriv = dev->private;
unsigned int events = 0;
unsigned int status_fifo;
unsigned int i;
unsigned int todo;
unsigned int fifoamount;
struct comedi_async *async = s->async;
unsigned int scanlen = async->cmd.scan_end_arg;

/* Determine number of samples to read. */
if (devpriv->ai_continuous) {
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)) {
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
} else {
todo = (devpriv->ai_scan_count * scanlen)
- devpriv->ai_scan_pos;
if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
}
if (todo == 0)
return;
fifoamount = 0;
for (i = 0; i < todo; i++) {
if (fifoamount == 0) {
/* Read FIFO state. */
status_fifo = inw(dev->iobase + PCI230_ADCCON);
if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
/* Report error otherwise FIFO overruns will go
* unnoticed by the caller. */
comedi_error(dev, "AI FIFO overrun");
events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
break;
} else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
/* FIFO empty. */
break;
} else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
/* FIFO half full. */
fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
} 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;
}
}
}
/* Read sample and store in Comedi's circular buffer. */
if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
comedi_error(dev, "AI buffer overflow");
break;
}
fifoamount--;
devpriv->ai_scan_pos++;
if (devpriv->ai_scan_pos == scanlen) {
/* End of scan. */
devpriv->ai_scan_pos = 0;
devpriv->ai_scan_count--;
async->events |= COMEDI_CB_EOS;
}
}
if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
/* End of acquisition. */
events |= COMEDI_CB_EOA;
} else {
/* More samples required, tell Comedi to block. */
events |= COMEDI_CB_BLOCK;
}
async->events |= events;
if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
COMEDI_CB_OVERFLOW)) != 0) {
/* disable hardware conversions */
pci230_ai_stop(dev, s);
} else {
/* update FIFO interrupt trigger level */
pci230_ai_update_fifo_trigger_level(dev, s);
}
}

static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct pci230_private *devpriv = dev->private;
Expand Down Expand Up @@ -2449,6 +2583,13 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return 0;
}

static int pci230_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
pci230_ai_stop(dev, s);
return 0;
}

/* Interrupt handler */
static irqreturn_t pci230_interrupt(int irq, void *d)
{
Expand Down Expand Up @@ -2514,165 +2655,6 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
return IRQ_HANDLED;
}

static void pci230_handle_ai(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct pci230_private *devpriv = dev->private;
unsigned int events = 0;
unsigned int status_fifo;
unsigned int i;
unsigned int todo;
unsigned int fifoamount;
struct comedi_async *async = s->async;
unsigned int scanlen = async->cmd.scan_end_arg;

/* Determine number of samples to read. */
if (devpriv->ai_continuous) {
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)) {
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
} else {
todo = (devpriv->ai_scan_count * scanlen)
- devpriv->ai_scan_pos;
if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;

}

if (todo == 0)
return;


fifoamount = 0;
for (i = 0; i < todo; i++) {
if (fifoamount == 0) {
/* Read FIFO state. */
status_fifo = inw(dev->iobase + PCI230_ADCCON);

if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
/* Report error otherwise FIFO overruns will go
* unnoticed by the caller. */
comedi_error(dev, "AI FIFO overrun");
events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
break;
} else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
/* FIFO empty. */
break;
} else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
/* FIFO half full. */
fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
} 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;
}
}
}

/* Read sample and store in Comedi's circular buffer. */
if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
comedi_error(dev, "AI buffer overflow");
break;
}
fifoamount--;
devpriv->ai_scan_pos++;
if (devpriv->ai_scan_pos == scanlen) {
/* End of scan. */
devpriv->ai_scan_pos = 0;
devpriv->ai_scan_count--;
async->events |= COMEDI_CB_EOS;
}
}

if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
/* End of acquisition. */
events |= COMEDI_CB_EOA;
} else {
/* More samples required, tell Comedi to block. */
events |= COMEDI_CB_BLOCK;
}
async->events |= events;

if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
COMEDI_CB_OVERFLOW)) != 0) {
/* disable hardware conversions */
pci230_ai_stop(dev, s);
} else {
/* update FIFO interrupt trigger level */
pci230_ai_update_fifo_trigger_level(dev, s);
}
}

static void pci230_ai_stop(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct pci230_private *devpriv = dev->private;
unsigned long irqflags;
struct comedi_cmd *cmd;
int started;

spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
if (!started)
return;


cmd = &s->async->cmd;
if (cmd->convert_src == TRIG_TIMER) {
/* Stop conversion rate generator. */
pci230_cancel_ct(dev, 2);
}
if (cmd->scan_begin_src != TRIG_FOLLOW) {
/* Stop scan period monostable. */
pci230_cancel_ct(dev, 0);
}

spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
/* 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;
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);
}
spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);

/* Reset FIFO, disable FIFO and set start conversion source to none.
* Keep se/diff and bip/uni settings */
devpriv->adccon = (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);

/* Release resources. */
put_all_resources(dev, OWNER_AICMD);
}

static int pci230_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
pci230_ai_stop(dev, s);
return 0;
}

/* Check if PCI device matches a specific board. */
static bool pci230_match_pci_board(const struct pci230_board *board,
struct pci_dev *pci_dev)
Expand Down

0 comments on commit fc33e74

Please sign in to comment.