提交 860f7c09 编写于 作者: H H Hartley Sweeten 提交者: Greg Kroah-Hartman

staging: comedi: dt282x: remove depends on ISA_DMA_API limitation

Use the new comedi_isadma module to provide the ISA DMA support. This removes
all the ISA_DMA_API code from this driver and allows the driver to be used on
platforms that don't support the ISA_DMA_API.
Signed-off-by: NH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: NIan Abbott <abbotti@mev.co.uk>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 99dfc335
...@@ -372,7 +372,7 @@ config COMEDI_DT2817 ...@@ -372,7 +372,7 @@ config COMEDI_DT2817
config COMEDI_DT282X config COMEDI_DT282X
tristate "Data Translation DT2821 series and DT-EZ ISA card support" tristate "Data Translation DT2821 series and DT-EZ ISA card support"
depends on ISA_DMA_API select COMEDI_ISADMA if ISA_DMA_API
---help--- ---help---
Enable support for Data Translation DT2821 series including DT-EZ Enable support for Data Translation DT2821 series including DT-EZ
DT2821, DT2821-F-16SE, DT2821-F-8DI, DT2821-G-16SE, DT2821-G-8DI, DT2821, DT2821-F-16SE, DT2821-F-8DI, DT2821-G-16SE, DT2821-G-8DI,
......
...@@ -56,15 +56,14 @@ ...@@ -56,15 +56,14 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include "../comedidev.h"
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/dma.h> #include "../comedidev.h"
#include "comedi_isadma.h"
#include "comedi_fc.h" #include "comedi_fc.h"
/* /*
...@@ -300,72 +299,37 @@ static const struct dt282x_board boardtypes[] = { ...@@ -300,72 +299,37 @@ static const struct dt282x_board boardtypes[] = {
}, },
}; };
struct dt282x_dma_desc {
unsigned int chan; /* DMA channel */
void *virt_addr; /* virtual address of DMA buffer */
dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */
unsigned int size; /* transfer size (in bytes) */
char mode; /* DMA_MODE_* */
};
struct dt282x_private { struct dt282x_private {
struct comedi_isadma *dma;
unsigned int ad_2scomp:1; unsigned int ad_2scomp:1;
unsigned int divisor; unsigned int divisor;
int dacsr; /* software copies of registers */ int dacsr; /* software copies of registers */
int adcsr; int adcsr;
int supcsr; int supcsr;
int ntrig; int ntrig;
int nread; int nread;
struct dt282x_dma_desc dma_desc[2];
int dma_maxsize; /* max size of DMA transfer (in bytes) */
int cur_dma;
int dma_dir; int dma_dir;
}; };
static void dt282x_isadma_program(struct dt282x_dma_desc *dma)
{
unsigned long flags;
flags = claim_dma_lock();
clear_dma_ff(dma->chan);
set_dma_mode(dma->chan, dma->mode);
set_dma_addr(dma->chan, dma->hw_addr);
set_dma_count(dma->chan, dma->size);
enable_dma(dma->chan);
release_dma_lock(flags);
}
static void dt282x_isadma_disable(struct dt282x_dma_desc *dma)
{
unsigned long flags;
flags = claim_dma_lock();
disable_dma(dma->chan);
release_dma_lock(flags);
}
static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; struct comedi_isadma *dma = devpriv->dma;
struct comedi_isadma_desc *desc = &dma->desc[dma_index];
if (!devpriv->ntrig) if (!devpriv->ntrig)
return 0; return 0;
if (n == 0) if (n == 0)
n = devpriv->dma_maxsize; n = desc->maxsize;
if (n > devpriv->ntrig * 2) if (n > devpriv->ntrig * 2)
n = devpriv->ntrig * 2; n = devpriv->ntrig * 2;
devpriv->ntrig -= n / 2; devpriv->ntrig -= n / 2;
dma->size = n; desc->size = n;
dma->mode = DMA_MODE_READ; comedi_isadma_set_mode(desc, devpriv->dma_dir);
dt282x_isadma_program(dma); comedi_isadma_program(desc);
return n; return n;
} }
...@@ -373,12 +337,13 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) ...@@ -373,12 +337,13 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; struct comedi_isadma *dma = devpriv->dma;
struct comedi_isadma_desc *desc = &dma->desc[dma_index];
dma->size = n; desc->size = n;
dma->mode = DMA_MODE_WRITE; comedi_isadma_set_mode(desc, devpriv->dma_dir);
dt282x_isadma_program(dma); comedi_isadma_program(desc);
return n; return n;
} }
...@@ -386,10 +351,14 @@ static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) ...@@ -386,10 +351,14 @@ static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
static void dt282x_disable_dma(struct comedi_device *dev) static void dt282x_disable_dma(struct comedi_device *dev)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct comedi_isadma *dma = devpriv->dma;
struct comedi_isadma_desc *desc;
int i; int i;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++) {
dt282x_isadma_disable(&devpriv->dma_desc[i]); desc = &dma->desc[i];
comedi_isadma_disable(desc->chan);
}
} }
static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
...@@ -451,11 +420,12 @@ static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev, ...@@ -451,11 +420,12 @@ static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev,
int cur_dma) int cur_dma)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct dt282x_dma_desc *dma = &devpriv->dma_desc[cur_dma]; struct comedi_isadma *dma = devpriv->dma;
unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize); struct comedi_isadma_desc *desc = &dma->desc[cur_dma];
unsigned int nsamples = comedi_bytes_to_samples(s, desc->maxsize);
unsigned int nbytes; unsigned int nbytes;
nbytes = comedi_buf_read_samples(s, dma->virt_addr, nsamples); nbytes = comedi_buf_read_samples(s, desc->virt_addr, nsamples);
if (nbytes) if (nbytes)
dt282x_prep_ao_dma(dev, cur_dma, nbytes); dt282x_prep_ao_dma(dev, cur_dma, nbytes);
else else
...@@ -468,35 +438,37 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev, ...@@ -468,35 +438,37 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s) struct comedi_subdevice *s)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; struct comedi_isadma *dma = devpriv->dma;
struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
dev->iobase + DT2821_SUPCSR_REG); dev->iobase + DT2821_SUPCSR_REG);
dt282x_isadma_disable(dma); comedi_isadma_disable(desc->chan);
if (!dt282x_ao_setup_dma(dev, s, devpriv->cur_dma)) if (!dt282x_ao_setup_dma(dev, s, dma->cur_dma))
s->async->events |= COMEDI_CB_OVERFLOW; s->async->events |= COMEDI_CB_OVERFLOW;
devpriv->cur_dma = 1 - devpriv->cur_dma; dma->cur_dma = 1 - dma->cur_dma;
} }
static void dt282x_ai_dma_interrupt(struct comedi_device *dev, static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s) struct comedi_subdevice *s)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; struct comedi_isadma *dma = devpriv->dma;
unsigned int nsamples = comedi_bytes_to_samples(s, dma->size); struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
unsigned int nsamples = comedi_bytes_to_samples(s, desc->size);
int ret; int ret;
outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
dev->iobase + DT2821_SUPCSR_REG); dev->iobase + DT2821_SUPCSR_REG);
dt282x_isadma_disable(dma); comedi_isadma_disable(desc->chan);
dt282x_munge(dev, s, dma->virt_addr, dma->size); dt282x_munge(dev, s, desc->virt_addr, desc->size);
ret = comedi_buf_write_samples(s, dma->virt_addr, nsamples); ret = comedi_buf_write_samples(s, desc->virt_addr, nsamples);
if (ret != dma->size) if (ret != desc->size)
return; return;
devpriv->nread -= nsamples; devpriv->nread -= nsamples;
...@@ -517,9 +489,9 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev, ...@@ -517,9 +489,9 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
} }
#endif #endif
/* restart the channel */ /* restart the channel */
dt282x_prep_ai_dma(dev, devpriv->cur_dma, 0); dt282x_prep_ai_dma(dev, dma->cur_dma, 0);
devpriv->cur_dma = 1 - devpriv->cur_dma; dma->cur_dma = 1 - dma->cur_dma;
} }
static irqreturn_t dt282x_interrupt(int irq, void *d) static irqreturn_t dt282x_interrupt(int irq, void *d)
...@@ -540,7 +512,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) ...@@ -540,7 +512,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d)
dacsr = inw(dev->iobase + DT2821_DACSR_REG); dacsr = inw(dev->iobase + DT2821_DACSR_REG);
supcsr = inw(dev->iobase + DT2821_SUPCSR_REG); supcsr = inw(dev->iobase + DT2821_SUPCSR_REG);
if (supcsr & DT2821_SUPCSR_DMAD) { if (supcsr & DT2821_SUPCSR_DMAD) {
if (devpriv->dma_dir == DMA_MODE_READ) if (devpriv->dma_dir == COMEDI_ISADMA_READ)
dt282x_ai_dma_interrupt(dev, s); dt282x_ai_dma_interrupt(dev, s);
else else
dt282x_ao_dma_interrupt(dev, s_ao); dt282x_ao_dma_interrupt(dev, s_ao);
...@@ -752,6 +724,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, ...@@ -752,6 +724,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev,
static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct comedi_isadma *dma = devpriv->dma;
struct comedi_cmd *cmd = &s->async->cmd; struct comedi_cmd *cmd = &s->async->cmd;
int ret; int ret;
...@@ -773,8 +746,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -773,8 +746,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg; devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg;
devpriv->nread = devpriv->ntrig; devpriv->nread = devpriv->ntrig;
devpriv->dma_dir = DMA_MODE_READ; devpriv->dma_dir = COMEDI_ISADMA_READ;
devpriv->cur_dma = 0; dma->cur_dma = 0;
dt282x_prep_ai_dma(dev, 0, 0); dt282x_prep_ai_dma(dev, 0, 0);
if (devpriv->ntrig) { if (devpriv->ntrig) {
dt282x_prep_ai_dma(dev, 1, 0); dt282x_prep_ai_dma(dev, 1, 0);
...@@ -937,6 +910,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, ...@@ -937,6 +910,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev,
static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct comedi_isadma *dma = devpriv->dma;
struct comedi_cmd *cmd = &s->async->cmd; struct comedi_cmd *cmd = &s->async->cmd;
dt282x_disable_dma(dev); dt282x_disable_dma(dev);
...@@ -953,8 +927,8 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -953,8 +927,8 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len; devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len;
devpriv->nread = devpriv->ntrig; devpriv->nread = devpriv->ntrig;
devpriv->dma_dir = DMA_MODE_WRITE; devpriv->dma_dir = COMEDI_ISADMA_WRITE;
devpriv->cur_dma = 0; dma->cur_dma = 0;
outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG); outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
...@@ -1058,13 +1032,12 @@ static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x) ...@@ -1058,13 +1032,12 @@ static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x)
return ai_range_table[x]; return ai_range_table[x];
} }
static int dt282x_alloc_dma(struct comedi_device *dev, static void dt282x_alloc_dma(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
unsigned int irq_num = it->options[1]; unsigned int irq_num = it->options[1];
unsigned int dma_chan[2]; unsigned int dma_chan[2];
int i;
if (it->options[2] < it->options[3]) { if (it->options[2] < it->options[3]) {
dma_chan[0] = it->options[2]; dma_chan[0] = it->options[2];
...@@ -1077,53 +1050,24 @@ static int dt282x_alloc_dma(struct comedi_device *dev, ...@@ -1077,53 +1050,24 @@ static int dt282x_alloc_dma(struct comedi_device *dev,
if (!irq_num || dma_chan[0] == dma_chan[1] || if (!irq_num || dma_chan[0] == dma_chan[1] ||
dma_chan[0] < 5 || dma_chan[0] > 7 || dma_chan[0] < 5 || dma_chan[0] > 7 ||
dma_chan[1] < 5 || dma_chan[1] > 7) dma_chan[1] < 5 || dma_chan[1] > 7)
return 0; return;
if (request_irq(irq_num, dt282x_interrupt, 0, dev->board_name, dev)) if (request_irq(irq_num, dt282x_interrupt, 0, dev->board_name, dev))
return 0; return;
if (request_dma(dma_chan[0], dev->board_name)) {
free_irq(irq_num, dev);
return 0;
}
if (request_dma(dma_chan[1], dev->board_name)) {
free_dma(dma_chan[0]);
free_irq(irq_num, dev);
return 0;
}
dev->irq = irq_num;
devpriv->dma_maxsize = PAGE_SIZE;
for (i = 0; i < 2; i++) {
struct dt282x_dma_desc *dma = &devpriv->dma_desc[i];
dma->chan = dma_chan[i];
dma->virt_addr = dma_alloc_coherent(NULL, devpriv->dma_maxsize,
&dma->hw_addr, GFP_KERNEL);
if (!dma->virt_addr)
return -ENOMEM;
}
return 0; /* DMA uses two 4K buffers with separate DMA channels */
devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan[0], dma_chan[1],
PAGE_SIZE, 0);
if (!devpriv->dma)
free_irq(irq_num, dev);
} }
static void dt282x_free_dma(struct comedi_device *dev) static void dt282x_free_dma(struct comedi_device *dev)
{ {
struct dt282x_private *devpriv = dev->private; struct dt282x_private *devpriv = dev->private;
struct dt282x_dma_desc *dma;
int i;
if (!devpriv) if (devpriv)
return; comedi_isadma_free(devpriv->dma);
for (i = 0; i < 2; i++) {
dma = &devpriv->dma_desc[i];
if (dma->chan)
free_dma(dma->chan);
if (dma->virt_addr)
dma_free_coherent(NULL, devpriv->dma_maxsize,
dma->virt_addr, dma->hw_addr);
}
} }
static int dt282x_initialize(struct comedi_device *dev) static int dt282x_initialize(struct comedi_device *dev)
...@@ -1181,9 +1125,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) ...@@ -1181,9 +1125,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return -ENOMEM; return -ENOMEM;
/* an IRQ and 2 DMA channels are required for async command support */ /* an IRQ and 2 DMA channels are required for async command support */
ret = dt282x_alloc_dma(dev, it); dt282x_alloc_dma(dev, it);
if (ret)
return ret;
ret = comedi_alloc_subdevices(dev, 3); ret = comedi_alloc_subdevices(dev, 3);
if (ret) if (ret)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册