aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers/dt3000.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers/dt3000.c')
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c620
1 files changed, 282 insertions, 338 deletions
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 43d05ef97157..960da8debe17 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -29,11 +29,7 @@ Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
Updated: Mon, 14 Apr 2008 15:41:24 +0100
Status: works
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration Options: not applicable, uses PCI auto config
There is code to support AI commands, but it may not work.
@@ -65,26 +61,36 @@ AO commands are not supported.
#include "comedi_fc.h"
-#define PCI_VENDOR_ID_DT 0x1116
-
-static const struct comedi_lrange range_dt3000_ai = { 4, {
- RANGE(-10, 10),
- RANGE(-5, 5),
- RANGE(-2.5, 2.5),
- RANGE(-1.25, 1.25)
- }
+/*
+ * PCI device id's supported by this driver
+ */
+#define PCI_DEVICE_ID_DT3001 0x0022
+#define PCI_DEVICE_ID_DT3002 0x0023
+#define PCI_DEVICE_ID_DT3003 0x0024
+#define PCI_DEVICE_ID_DT3004 0x0025
+#define PCI_DEVICE_ID_DT3005 0x0026
+#define PCI_DEVICE_ID_DT3001_PGL 0x0027
+#define PCI_DEVICE_ID_DT3003_PGL 0x0028
+
+static const struct comedi_lrange range_dt3000_ai = {
+ 4, {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25)
+ }
};
-static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
- RANGE(-10, 10),
- RANGE(-1, 1),
- RANGE(-0.1, 0.1),
- RANGE(-0.02, 0.02)
- }
+static const struct comedi_lrange range_dt3000_ai_pgl = {
+ 4, {
+ BIP_RANGE(10),
+ BIP_RANGE(1),
+ BIP_RANGE(0.1),
+ BIP_RANGE(0.02)
+ }
};
struct dt3k_boardtype {
-
const char *name;
unsigned int device_id;
int adchan;
@@ -96,73 +102,70 @@ struct dt3k_boardtype {
};
static const struct dt3k_boardtype dt3k_boardtypes[] = {
- {.name = "dt3001",
- .device_id = 0x22,
- .adchan = 16,
- .adbits = 12,
- .adrange = &range_dt3000_ai,
- .ai_speed = 3000,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt3001-pgl",
- .device_id = 0x27,
- .adchan = 16,
- .adbits = 12,
- .adrange = &range_dt3000_ai_pgl,
- .ai_speed = 3000,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt3002",
- .device_id = 0x23,
- .adchan = 32,
- .adbits = 12,
- .adrange = &range_dt3000_ai,
- .ai_speed = 3000,
- .dachan = 0,
- .dabits = 0,
- },
- {.name = "dt3003",
- .device_id = 0x24,
- .adchan = 64,
- .adbits = 12,
- .adrange = &range_dt3000_ai,
- .ai_speed = 3000,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt3003-pgl",
- .device_id = 0x28,
- .adchan = 64,
- .adbits = 12,
- .adrange = &range_dt3000_ai_pgl,
- .ai_speed = 3000,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt3004",
- .device_id = 0x25,
- .adchan = 16,
- .adbits = 16,
- .adrange = &range_dt3000_ai,
- .ai_speed = 10000,
- .dachan = 2,
- .dabits = 12,
- },
- {.name = "dt3005", /* a.k.a. 3004-200 */
- .device_id = 0x26,
- .adchan = 16,
- .adbits = 16,
- .adrange = &range_dt3000_ai,
- .ai_speed = 5000,
- .dachan = 2,
- .dabits = 12,
- },
+ {
+ .name = "dt3001",
+ .device_id = PCI_DEVICE_ID_DT3001,
+ .adchan = 16,
+ .adbits = 12,
+ .adrange = &range_dt3000_ai,
+ .ai_speed = 3000,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt3001-pgl",
+ .device_id = PCI_DEVICE_ID_DT3001_PGL,
+ .adchan = 16,
+ .adbits = 12,
+ .adrange = &range_dt3000_ai_pgl,
+ .ai_speed = 3000,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt3002",
+ .device_id = PCI_DEVICE_ID_DT3002,
+ .adchan = 32,
+ .adbits = 12,
+ .adrange = &range_dt3000_ai,
+ .ai_speed = 3000,
+ }, {
+ .name = "dt3003",
+ .device_id = PCI_DEVICE_ID_DT3003,
+ .adchan = 64,
+ .adbits = 12,
+ .adrange = &range_dt3000_ai,
+ .ai_speed = 3000,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt3003-pgl",
+ .device_id = PCI_DEVICE_ID_DT3003_PGL,
+ .adchan = 64,
+ .adbits = 12,
+ .adrange = &range_dt3000_ai_pgl,
+ .ai_speed = 3000,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt3004",
+ .device_id = PCI_DEVICE_ID_DT3004,
+ .adchan = 16,
+ .adbits = 16,
+ .adrange = &range_dt3000_ai,
+ .ai_speed = 10000,
+ .dachan = 2,
+ .dabits = 12,
+ }, {
+ .name = "dt3005", /* a.k.a. 3004-200 */
+ .device_id = PCI_DEVICE_ID_DT3005,
+ .adchan = 16,
+ .adbits = 16,
+ .adrange = &range_dt3000_ai,
+ .ai_speed = 5000,
+ .dachan = 2,
+ .dabits = 12,
+ },
};
-#define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
-
#define DT3000_SIZE (4*0x1000)
/* dual-ported RAM location definitions */
@@ -257,22 +260,29 @@ struct dt3k_private {
unsigned int ai_rear;
};
-#define devpriv ((struct dt3k_private *)dev->private)
-
-static void dt3k_ai_empty_fifo(struct comedi_device *dev,
- struct comedi_subdevice *s);
-static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
- unsigned int round_mode);
-static int dt3k_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
#ifdef DEBUG
-static void debug_intr_flags(unsigned int flags);
+static char *intr_flags[] = {
+ "AdFull", "AdSwError", "AdHwError", "DaEmpty",
+ "DaSwError", "DaHwError", "CtDone", "CmDone",
+};
+
+static void debug_intr_flags(unsigned int flags)
+{
+ int i;
+ printk(KERN_DEBUG "dt3k: intr_flags:");
+ for (i = 0; i < 8; i++) {
+ if (flags & (1 << i))
+ printk(KERN_CONT " %s", intr_flags[i]);
+ }
+ printk(KERN_CONT "\n");
+}
#endif
#define TIMEOUT 100
-static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
+static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
{
+ struct dt3k_private *devpriv = dev->private;
int i;
unsigned int status = 0;
@@ -284,19 +294,18 @@ static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
break;
udelay(1);
}
- if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
- return 0;
-
- dev_dbg(dev->class_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n",
- status);
- return -ETIME;
+ if ((status & DT3000_COMPLETION_MASK) != DT3000_NOERROR)
+ dev_dbg(dev->class_dev, "%s: timeout/error status=0x%04x\n",
+ __func__, status);
}
static unsigned int dt3k_readsingle(struct comedi_device *dev,
unsigned int subsys, unsigned int chan,
unsigned int gain)
{
+ struct dt3k_private *devpriv = dev->private;
+
writew(subsys, devpriv->io_addr + DPR_SubSys);
writew(chan, devpriv->io_addr + DPR_Params(0));
@@ -310,6 +319,8 @@ static unsigned int dt3k_readsingle(struct comedi_device *dev,
static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
unsigned int chan, unsigned int data)
{
+ struct dt3k_private *devpriv = dev->private;
+
writew(subsys, devpriv->io_addr + DPR_SubSys);
writew(chan, devpriv->io_addr + DPR_Params(0));
@@ -319,6 +330,47 @@ static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
dt3k_send_cmd(dev, CMD_WRITESINGLE);
}
+static void dt3k_ai_empty_fifo(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct dt3k_private *devpriv = dev->private;
+ int front;
+ int rear;
+ int count;
+ int i;
+ short data;
+
+ front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
+ count = front - devpriv->ai_front;
+ if (count < 0)
+ count += AI_FIFO_DEPTH;
+
+ rear = devpriv->ai_rear;
+
+ for (i = 0; i < count; i++) {
+ data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
+ comedi_buf_put(s->async, data);
+ rear++;
+ if (rear >= AI_FIFO_DEPTH)
+ rear = 0;
+ }
+
+ devpriv->ai_rear = rear;
+ writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+}
+
+static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+ struct dt3k_private *devpriv = dev->private;
+
+ writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
+ dt3k_send_cmd(dev, CMD_STOP);
+
+ writew(0, devpriv->io_addr + DPR_Int_Mask);
+
+ return 0;
+}
+
static int debug_n_ints;
/* FIXME! Assumes shared interrupt is for this card. */
@@ -326,6 +378,7 @@ static int debug_n_ints;
static irqreturn_t dt3k_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
+ struct dt3k_private *devpriv = dev->private;
struct comedi_subdevice *s;
unsigned int status;
@@ -356,57 +409,45 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
return IRQ_HANDLED;
}
-#ifdef DEBUG
-static char *intr_flags[] = {
- "AdFull", "AdSwError", "AdHwError", "DaEmpty",
- "DaSwError", "DaHwError", "CtDone", "CmDone",
-};
-
-static void debug_intr_flags(unsigned int flags)
-{
- int i;
- printk(KERN_DEBUG "dt3k: intr_flags:");
- for (i = 0; i < 8; i++) {
- if (flags & (1 << i))
- printk(KERN_CONT " %s", intr_flags[i]);
- }
- printk(KERN_CONT "\n");
-}
-#endif
-
-static void dt3k_ai_empty_fifo(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
+ unsigned int round_mode)
{
- int front;
- int rear;
- int count;
- int i;
- short data;
-
- front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
- count = front - devpriv->ai_front;
- if (count < 0)
- count += AI_FIFO_DEPTH;
-
- dev_dbg(dev->class_dev, "reading %d samples\n", count);
+ int divider, base, prescale;
- rear = devpriv->ai_rear;
+ /* This function needs improvment */
+ /* Don't know if divider==0 works. */
- for (i = 0; i < count; i++) {
- data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
- comedi_buf_put(s->async, data);
- rear++;
- if (rear >= AI_FIFO_DEPTH)
- rear = 0;
+ for (prescale = 0; prescale < 16; prescale++) {
+ base = timer_base * (prescale + 1);
+ switch (round_mode) {
+ case TRIG_ROUND_NEAREST:
+ default:
+ divider = (*nanosec + base / 2) / base;
+ break;
+ case TRIG_ROUND_DOWN:
+ divider = (*nanosec) / base;
+ break;
+ case TRIG_ROUND_UP:
+ divider = (*nanosec) / base;
+ break;
+ }
+ if (divider < 65536) {
+ *nanosec = divider * base;
+ return (prescale << 16) | (divider);
+ }
}
- devpriv->ai_rear = rear;
- writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
+ prescale = 15;
+ base = timer_base * (1 << prescale);
+ divider = 65535;
+ *nanosec = divider * base;
+ return (prescale << 16) | (divider);
}
static int dt3k_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd)
{
+ const struct dt3k_boardtype *this_board = comedi_board(dev);
int err = 0;
int tmp;
@@ -427,54 +468,30 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
if (err)
return 2;
- /* step 3: make sure arguments are trivially compatible */
+ /* Step 3: check if arguments are trivially valid */
- if (cmd->start_arg != 0) {
- cmd->start_arg = 0;
- err++;
- }
+ err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
if (cmd->scan_begin_src == TRIG_TIMER) {
- if (cmd->scan_begin_arg < this_board->ai_speed) {
- cmd->scan_begin_arg = this_board->ai_speed;
- err++;
- }
- if (cmd->scan_begin_arg > 100 * 16 * 65535) {
- cmd->scan_begin_arg = 100 * 16 * 65535;
- err++;
- }
- } else {
- /* not supported */
+ err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
+ this_board->ai_speed);
+ err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
+ 100 * 16 * 65535);
}
+
if (cmd->convert_src == TRIG_TIMER) {
- if (cmd->convert_arg < this_board->ai_speed) {
- cmd->convert_arg = this_board->ai_speed;
- err++;
- }
- if (cmd->convert_arg > 50 * 16 * 65535) {
- cmd->convert_arg = 50 * 16 * 65535;
- err++;
- }
- } else {
- /* not supported */
+ err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+ this_board->ai_speed);
+ err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
+ 50 * 16 * 65535);
}
- if (cmd->scan_end_arg != cmd->chanlist_len) {
- cmd->scan_end_arg = cmd->chanlist_len;
- err++;
- }
- if (cmd->stop_src == TRIG_COUNT) {
- if (cmd->stop_arg > 0x00ffffff) {
- cmd->stop_arg = 0x00ffffff;
- err++;
- }
- } else {
- /* TRIG_NONE */
- if (cmd->stop_arg != 0) {
- cmd->stop_arg = 0;
- err++;
- }
- }
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+ if (cmd->stop_src == TRIG_COUNT)
+ err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
+ else /* TRIG_NONE */
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
if (err)
return 3;
@@ -487,9 +504,8 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
cmd->flags & TRIG_ROUND_MASK);
if (tmp != cmd->scan_begin_arg)
err++;
- } else {
- /* not supported */
}
+
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
dt3k_ns_to_timer(50, &cmd->convert_arg,
@@ -503,8 +519,6 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
cmd->convert_arg * cmd->scan_end_arg;
err++;
}
- } else {
- /* not supported */
}
if (err)
@@ -513,52 +527,16 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
return 0;
}
-static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
- unsigned int round_mode)
-{
- int divider, base, prescale;
-
- /* This function needs improvment */
- /* Don't know if divider==0 works. */
-
- for (prescale = 0; prescale < 16; prescale++) {
- base = timer_base * (prescale + 1);
- switch (round_mode) {
- case TRIG_ROUND_NEAREST:
- default:
- divider = (*nanosec + base / 2) / base;
- break;
- case TRIG_ROUND_DOWN:
- divider = (*nanosec) / base;
- break;
- case TRIG_ROUND_UP:
- divider = (*nanosec) / base;
- break;
- }
- if (divider < 65536) {
- *nanosec = divider * base;
- return (prescale << 16) | (divider);
- }
- }
-
- prescale = 15;
- base = timer_base * (1 << prescale);
- divider = 65535;
- *nanosec = divider * base;
- return (prescale << 16) | (divider);
-}
-
static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct dt3k_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
int i;
unsigned int chan, range, aref;
unsigned int divider;
unsigned int tscandiv;
- int ret;
unsigned int mode;
- dev_dbg(dev->class_dev, "dt3k_ai_cmd:\n");
for (i = 0; i < cmd->chanlist_len; i++) {
chan = CR_CHAN(cmd->chanlist[i]);
range = CR_RANGE(cmd->chanlist[i]);
@@ -569,41 +547,29 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
aref = CR_AREF(cmd->chanlist[0]);
writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
- dev_dbg(dev->class_dev, "param[0]=0x%04x\n", cmd->scan_end_arg);
if (cmd->convert_src == TRIG_TIMER) {
divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
cmd->flags & TRIG_ROUND_MASK);
writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
- dev_dbg(dev->class_dev, "param[1]=0x%04x\n", divider >> 16);
writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
- dev_dbg(dev->class_dev, "param[2]=0x%04x\n", divider & 0xffff);
- } else {
- /* not supported */
}
if (cmd->scan_begin_src == TRIG_TIMER) {
tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
cmd->flags & TRIG_ROUND_MASK);
writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
- dev_dbg(dev->class_dev, "param[3]=0x%04x\n", tscandiv >> 16);
writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
- dev_dbg(dev->class_dev, "param[4]=0x%04x\n", tscandiv & 0xffff);
- } else {
- /* not supported */
}
mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
writew(mode, devpriv->io_addr + DPR_Params(5));
- dev_dbg(dev->class_dev, "param[5]=0x%04x\n", mode);
writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
- dev_dbg(dev->class_dev, "param[6]=0x%04x\n", aref == AREF_DIFF);
writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
- dev_dbg(dev->class_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
- ret = dt3k_send_cmd(dev, CMD_CONFIG);
+ dt3k_send_cmd(dev, CMD_CONFIG);
writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
devpriv->io_addr + DPR_Int_Mask);
@@ -611,19 +577,7 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
debug_n_ints = 0;
writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
- ret = dt3k_send_cmd(dev, CMD_START);
-
- return 0;
-}
-
-static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
-{
- int ret;
-
- writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
- ret = dt3k_send_cmd(dev, CMD_STOP);
-
- writew(0, devpriv->io_addr + DPR_Int_Mask);
+ dt3k_send_cmd(dev, CMD_START);
return 0;
}
@@ -648,6 +602,7 @@ static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dt3k_private *devpriv = dev->private;
int i;
unsigned int chan;
@@ -664,6 +619,7 @@ static int dt3k_ao_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dt3k_private *devpriv = dev->private;
int i;
unsigned int chan;
@@ -676,6 +632,8 @@ static int dt3k_ao_insn_read(struct comedi_device *dev,
static void dt3k_dio_config(struct comedi_device *dev, int bits)
{
+ struct dt3k_private *devpriv = dev->private;
+
/* XXX */
writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
@@ -739,6 +697,7 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dt3k_private *devpriv = dev->private;
unsigned int addr = CR_CHAN(insn->chanspec);
int i;
@@ -755,54 +714,42 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
return i;
}
-static struct pci_dev *dt3000_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *dt3000_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
+ const struct dt3k_boardtype *this_board;
int i;
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_DT)
- continue;
- for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) {
- if (dt3k_boardtypes[i].device_id != pcidev->device)
- continue;
- dev->board_ptr = dt3k_boardtypes + i;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) {
+ this_board = &dt3k_boardtypes[i];
+ if (this_board->device_id == pcidev->device)
+ return this_board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int dt3000_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
{
- struct pci_dev *pcidev;
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ const struct dt3k_boardtype *this_board;
+ struct dt3k_private *devpriv;
struct comedi_subdevice *s;
resource_size_t pci_base;
int ret = 0;
- dev_dbg(dev->class_dev, "dt3000:\n");
-
- ret = alloc_private(dev, sizeof(struct dt3k_private));
- if (ret < 0)
- return ret;
+ this_board = dt3000_find_boardinfo(dev, pcidev);
+ if (!this_board)
+ return -ENODEV;
+ dev->board_ptr = this_board;
+ dev->board_name = this_board->name;
- pcidev = dt3000_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
- ret = comedi_pci_enable(pcidev, "dt3000");
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret < 0)
return ret;
dev->iobase = 1; /* the "detach" needs this */
@@ -812,14 +759,10 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv->io_addr)
return -ENOMEM;
- dev->board_name = this_board->name;
-
- if (request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED,
- "dt3000", dev)) {
- dev_err(dev->class_dev, "unable to allocate IRQ %u\n",
- pcidev->irq);
- return -EINVAL;
- }
+ ret = request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED,
+ dev->board_name, dev);
+ if (ret)
+ return ret;
dev->irq = pcidev->irq;
ret = comedi_alloc_subdevices(dev, 4);
@@ -828,50 +771,49 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s = &dev->subdevices[0];
dev->read_subdev = s;
-
/* ai subdevice */
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
- s->n_chan = this_board->adchan;
- s->insn_read = dt3k_ai_insn;
- s->maxdata = (1 << this_board->adbits) - 1;
- s->len_chanlist = 512;
- s->range_table = &range_dt3000_ai; /* XXX */
- s->do_cmd = dt3k_ai_cmd;
- s->do_cmdtest = dt3k_ai_cmdtest;
- s->cancel = dt3k_ai_cancel;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
+ s->n_chan = this_board->adchan;
+ s->insn_read = dt3k_ai_insn;
+ s->maxdata = (1 << this_board->adbits) - 1;
+ s->len_chanlist = 512;
+ s->range_table = &range_dt3000_ai; /* XXX */
+ s->do_cmd = dt3k_ai_cmd;
+ s->do_cmdtest = dt3k_ai_cmdtest;
+ s->cancel = dt3k_ai_cancel;
s = &dev->subdevices[1];
/* ao subsystem */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = 2;
- s->insn_read = dt3k_ao_insn_read;
- s->insn_write = dt3k_ao_insn;
- s->maxdata = (1 << this_board->dabits) - 1;
- s->len_chanlist = 1;
- s->range_table = &range_bipolar10;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 2;
+ s->insn_read = dt3k_ao_insn_read;
+ s->insn_write = dt3k_ao_insn;
+ s->maxdata = (1 << this_board->dabits) - 1;
+ s->len_chanlist = 1;
+ s->range_table = &range_bipolar10;
s = &dev->subdevices[2];
/* dio subsystem */
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
- s->insn_config = dt3k_dio_insn_config;
- s->insn_bits = dt3k_dio_insn_bits;
- s->maxdata = 1;
- s->len_chanlist = 8;
- s->range_table = &range_digital;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->insn_config = dt3k_dio_insn_config;
+ s->insn_bits = dt3k_dio_insn_bits;
+ s->maxdata = 1;
+ s->len_chanlist = 8;
+ s->range_table = &range_digital;
s = &dev->subdevices[3];
/* mem subsystem */
- s->type = COMEDI_SUBD_MEMORY;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 0x1000;
- s->insn_read = dt3k_mem_insn_read;
- s->maxdata = 0xff;
- s->len_chanlist = 1;
- s->range_table = &range_unknown;
+ s->type = COMEDI_SUBD_MEMORY;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 0x1000;
+ s->insn_read = dt3k_mem_insn_read;
+ s->maxdata = 0xff;
+ s->len_chanlist = 1;
+ s->range_table = &range_unknown;
#if 0
s = &dev->subdevices[4];
@@ -879,12 +821,15 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_PROC;
#endif
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
return 0;
}
static void dt3000_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct dt3k_private *devpriv = dev->private;
if (dev->irq)
free_irq(dev->irq, dev);
@@ -895,36 +840,35 @@ static void dt3000_detach(struct comedi_device *dev)
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver dt3000_driver = {
.driver_name = "dt3000",
.module = THIS_MODULE,
- .attach = dt3000_attach,
+ .auto_attach = dt3000_auto_attach,
.detach = dt3000_detach,
};
-static int __devinit dt3000_pci_probe(struct pci_dev *dev,
+static int dt3000_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, &dt3000_driver);
}
-static void __devexit dt3000_pci_remove(struct pci_dev *dev)
+static void dt3000_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) },
- { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3001_PGL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3002) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3003_PGL) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3004) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DT, PCI_DEVICE_ID_DT3005) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, dt3000_pci_table);
@@ -933,7 +877,7 @@ static struct pci_driver dt3000_pci_driver = {
.name = "dt3000",
.id_table = dt3000_pci_table,
.probe = dt3000_pci_probe,
- .remove = __devexit_p(dt3000_pci_remove),
+ .remove = dt3000_pci_remove,
};
module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);