diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/dt3000.c')
-rw-r--r-- | drivers/staging/comedi/drivers/dt3000.c | 620 |
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); |