These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / dt3000.c
index 031282c..ab7a332 100644 (file)
@@ -1,52 +1,53 @@
 /*
-    comedi/drivers/dt3000.c
-    Data Translation DT3000 series driver
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1999 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
-/*
-Driver: dt3000
-Description: Data Translation DT3000 series
-Author: ds
-Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
-  DT3003-PGL, DT3004, DT3005, DT3004-200
-Updated: Mon, 14 Apr 2008 15:41:24 +0100
-Status: works
-
-Configuration Options: not applicable, uses PCI auto config
-
-There is code to support AI commands, but it may not work.
+ * dt3000.c
+ * Data Translation DT3000 series driver
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1999 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-AO commands are not supported.
-*/
+/*
+ * Driver: dt3000
+ * Description: Data Translation DT3000 series
+ * Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
+ *   DT3003-PGL, DT3004, DT3005, DT3004-200
+ * Author: ds
+ * Updated: Mon, 14 Apr 2008 15:41:24 +0100
+ * Status: works
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ *
+ * There is code to support AI commands, but it may not work.
+ *
+ * AO commands are not supported.
+ */
 
 /*
  The DT3000 series is Data Translation's attempt to make a PCI
  data acquisition board.  The design of this series is very nice,
  since each board has an on-board DSP (Texas Instruments TMS320C52).
  However, a few details are a little annoying.  The boards lack
  bus-mastering DMA, which eliminates them from serious work.
  They also are not capable of autocalibration, which is a common
  feature in modern hardware.  The default firmware is pretty bad,
  making it nearly impossible to write an RT compatible driver.
  It would make an interesting project to write a decent firmware
  for these boards.
-
  Data Translation originally wanted an NDA for the documentation
  for the 3k series.  However, if you ask nicely, they might send
  you the docs without one, also.
-*/
* The DT3000 series is Data Translation's attempt to make a PCI
* data acquisition board.  The design of this series is very nice,
* since each board has an on-board DSP (Texas Instruments TMS320C52).
* However, a few details are a little annoying.  The boards lack
* bus-mastering DMA, which eliminates them from serious work.
* They also are not capable of autocalibration, which is a common
* feature in modern hardware.  The default firmware is pretty bad,
* making it nearly impossible to write an RT compatible driver.
* It would make an interesting project to write a decent firmware
* for these boards.
+ *
* Data Translation originally wanted an NDA for the documentation
* for the 3k series.  However, if you ask nicely, they might send
* you the docs without one, also.
+ */
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -54,6 +55,88 @@ AO commands are not supported.
 
 #include "../comedi_pci.h"
 
+/*
+ * PCI BAR0 - dual-ported RAM location definitions (dev->mmio)
+ */
+#define DPR_DAC_BUFFER         (4 * 0x000)
+#define DPR_ADC_BUFFER         (4 * 0x800)
+#define DPR_COMMAND            (4 * 0xfd3)
+#define DPR_SUBSYS             (4 * 0xfd3)
+#define DPR_SUBSYS_AI          0
+#define DPR_SUBSYS_AO          1
+#define DPR_SUBSYS_DIN         2
+#define DPR_SUBSYS_DOUT                3
+#define DPR_SUBSYS_MEM         4
+#define DPR_SUBSYS_CT          5
+#define DPR_ENCODE             (4 * 0xfd4)
+#define DPR_PARAMS(x)          (4 * (0xfd5 + (x)))
+#define DPR_TICK_REG_LO                (4 * 0xff5)
+#define DPR_TICK_REG_HI                (4 * 0xff6)
+#define DPR_DA_BUF_FRONT       (4 * 0xff7)
+#define DPR_DA_BUF_REAR                (4 * 0xff8)
+#define DPR_AD_BUF_FRONT       (4 * 0xff9)
+#define DPR_AD_BUF_REAR                (4 * 0xffa)
+#define DPR_INT_MASK           (4 * 0xffb)
+#define DPR_INTR_FLAG          (4 * 0xffc)
+#define DPR_INTR_CMDONE                BIT(7)
+#define DPR_INTR_CTDONE                BIT(6)
+#define DPR_INTR_DAHWERR       BIT(5)
+#define DPR_INTR_DASWERR       BIT(4)
+#define DPR_INTR_DAEMPTY       BIT(3)
+#define DPR_INTR_ADHWERR       BIT(2)
+#define DPR_INTR_ADSWERR       BIT(1)
+#define DPR_INTR_ADFULL                BIT(0)
+#define DPR_RESPONSE_MBX       (4 * 0xffe)
+#define DPR_CMD_MBX            (4 * 0xfff)
+#define DPR_CMD_COMPLETION(x)  ((x) << 8)
+#define DPR_CMD_NOTPROCESSED   DPR_CMD_COMPLETION(0x00)
+#define DPR_CMD_NOERROR                DPR_CMD_COMPLETION(0x55)
+#define DPR_CMD_ERROR          DPR_CMD_COMPLETION(0xaa)
+#define DPR_CMD_NOTSUPPORTED   DPR_CMD_COMPLETION(0xff)
+#define DPR_CMD_COMPLETION_MASK        DPR_CMD_COMPLETION(0xff)
+#define DPR_CMD(x)             ((x) << 0)
+#define DPR_CMD_GETBRDINFO     DPR_CMD(0)
+#define DPR_CMD_CONFIG         DPR_CMD(1)
+#define DPR_CMD_GETCONFIG      DPR_CMD(2)
+#define DPR_CMD_START          DPR_CMD(3)
+#define DPR_CMD_STOP           DPR_CMD(4)
+#define DPR_CMD_READSINGLE     DPR_CMD(5)
+#define DPR_CMD_WRITESINGLE    DPR_CMD(6)
+#define DPR_CMD_CALCCLOCK      DPR_CMD(7)
+#define DPR_CMD_READEVENTS     DPR_CMD(8)
+#define DPR_CMD_WRITECTCTRL    DPR_CMD(16)
+#define DPR_CMD_READCTCTRL     DPR_CMD(17)
+#define DPR_CMD_WRITECT                DPR_CMD(18)
+#define DPR_CMD_READCT         DPR_CMD(19)
+#define DPR_CMD_WRITEDATA      DPR_CMD(32)
+#define DPR_CMD_READDATA       DPR_CMD(33)
+#define DPR_CMD_WRITEIO                DPR_CMD(34)
+#define DPR_CMD_READIO         DPR_CMD(35)
+#define DPR_CMD_WRITECODE      DPR_CMD(36)
+#define DPR_CMD_READCODE       DPR_CMD(37)
+#define DPR_CMD_EXECUTE                DPR_CMD(38)
+#define DPR_CMD_HALT           DPR_CMD(48)
+#define DPR_CMD_MASK           DPR_CMD(0xff)
+
+#define DPR_PARAM5_AD_TRIG(x)          (((x) & 0x7) << 2)
+#define DPR_PARAM5_AD_TRIG_INT         DPR_PARAM5_AD_TRIG(0)
+#define DPR_PARAM5_AD_TRIG_EXT         DPR_PARAM5_AD_TRIG(1)
+#define DPR_PARAM5_AD_TRIG_INT_RETRIG  DPR_PARAM5_AD_TRIG(2)
+#define DPR_PARAM5_AD_TRIG_EXT_RETRIG  DPR_PARAM5_AD_TRIG(3)
+#define DPR_PARAM5_AD_TRIG_INT_RETRIG2 DPR_PARAM5_AD_TRIG(4)
+
+#define DPR_PARAM6_AD_DIFF             BIT(0)
+
+#define DPR_AI_FIFO_DEPTH              2003
+#define DPR_AO_FIFO_DEPTH              2048
+
+#define DPR_EXTERNAL_CLOCK             1
+#define DPR_RISING_EDGE                        2
+
+#define DPR_TMODE_MASK                 0x1c
+
+#define DPR_CMD_TIMEOUT                        100
+
 static const struct comedi_lrange range_dt3000_ai = {
        4, {
                BIP_RANGE(10),
@@ -85,184 +168,87 @@ enum dt3k_boardid {
 struct dt3k_boardtype {
        const char *name;
        int adchan;
-       int adbits;
        int ai_speed;
        const struct comedi_lrange *adrange;
-       int dachan;
-       int dabits;
+       unsigned int ai_is_16bit:1;
+       unsigned int has_ao:1;
 };
 
 static const struct dt3k_boardtype dt3k_boardtypes[] = {
        [BOARD_DT3001] = {
                .name           = "dt3001",
                .adchan         = 16,
-               .adbits         = 12,
                .adrange        = &range_dt3000_ai,
                .ai_speed       = 3000,
-               .dachan         = 2,
-               .dabits         = 12,
+               .has_ao         = 1,
        },
        [BOARD_DT3001_PGL] = {
                .name           = "dt3001-pgl",
                .adchan         = 16,
-               .adbits         = 12,
                .adrange        = &range_dt3000_ai_pgl,
                .ai_speed       = 3000,
-               .dachan         = 2,
-               .dabits         = 12,
+               .has_ao         = 1,
        },
        [BOARD_DT3002] = {
                .name           = "dt3002",
                .adchan         = 32,
-               .adbits         = 12,
                .adrange        = &range_dt3000_ai,
                .ai_speed       = 3000,
        },
        [BOARD_DT3003] = {
                .name           = "dt3003",
                .adchan         = 64,
-               .adbits         = 12,
                .adrange        = &range_dt3000_ai,
                .ai_speed       = 3000,
-               .dachan         = 2,
-               .dabits         = 12,
+               .has_ao         = 1,
        },
        [BOARD_DT3003_PGL] = {
                .name           = "dt3003-pgl",
                .adchan         = 64,
-               .adbits         = 12,
                .adrange        = &range_dt3000_ai_pgl,
                .ai_speed       = 3000,
-               .dachan         = 2,
-               .dabits         = 12,
+               .has_ao         = 1,
        },
        [BOARD_DT3004] = {
                .name           = "dt3004",
                .adchan         = 16,
-               .adbits         = 16,
                .adrange        = &range_dt3000_ai,
                .ai_speed       = 10000,
-               .dachan         = 2,
-               .dabits         = 12,
+               .ai_is_16bit    = 1,
+               .has_ao         = 1,
        },
        [BOARD_DT3005] = {
                .name           = "dt3005",     /* a.k.a. 3004-200 */
                .adchan         = 16,
-               .adbits         = 16,
                .adrange        = &range_dt3000_ai,
                .ai_speed       = 5000,
-               .dachan         = 2,
-               .dabits         = 12,
+               .ai_is_16bit    = 1,
+               .has_ao         = 1,
        },
 };
 
-/* dual-ported RAM location definitions */
-
-#define DPR_DAC_buffer         (4*0x000)
-#define DPR_ADC_buffer         (4*0x800)
-#define DPR_Command            (4*0xfd3)
-#define DPR_SubSys             (4*0xfd3)
-#define DPR_Encode             (4*0xfd4)
-#define DPR_Params(a)          (4*(0xfd5+(a)))
-#define DPR_Tick_Reg_Lo                (4*0xff5)
-#define DPR_Tick_Reg_Hi                (4*0xff6)
-#define DPR_DA_Buf_Front       (4*0xff7)
-#define DPR_DA_Buf_Rear                (4*0xff8)
-#define DPR_AD_Buf_Front       (4*0xff9)
-#define DPR_AD_Buf_Rear                (4*0xffa)
-#define DPR_Int_Mask           (4*0xffb)
-#define DPR_Intr_Flag          (4*0xffc)
-#define DPR_Response_Mbx       (4*0xffe)
-#define DPR_Command_Mbx                (4*0xfff)
-
-#define AI_FIFO_DEPTH  2003
-#define AO_FIFO_DEPTH  2048
-
-/* command list */
-
-#define CMD_GETBRDINFO         0
-#define CMD_CONFIG             1
-#define CMD_GETCONFIG          2
-#define CMD_START              3
-#define CMD_STOP               4
-#define CMD_READSINGLE         5
-#define CMD_WRITESINGLE                6
-#define CMD_CALCCLOCK          7
-#define CMD_READEVENTS         8
-#define CMD_WRITECTCTRL                16
-#define CMD_READCTCTRL         17
-#define CMD_WRITECT            18
-#define CMD_READCT             19
-#define CMD_WRITEDATA          32
-#define CMD_READDATA           33
-#define CMD_WRITEIO            34
-#define CMD_READIO             35
-#define CMD_WRITECODE          36
-#define CMD_READCODE           37
-#define CMD_EXECUTE            38
-#define CMD_HALT               48
-
-#define SUBS_AI                0
-#define SUBS_AO                1
-#define SUBS_DIN       2
-#define SUBS_DOUT      3
-#define SUBS_MEM       4
-#define SUBS_CT                5
-
-/* interrupt flags */
-#define DT3000_CMDONE          0x80
-#define DT3000_CTDONE          0x40
-#define DT3000_DAHWERR         0x20
-#define DT3000_DASWERR         0x10
-#define DT3000_DAEMPTY         0x08
-#define DT3000_ADHWERR         0x04
-#define DT3000_ADSWERR         0x02
-#define DT3000_ADFULL          0x01
-
-#define DT3000_COMPLETION_MASK 0xff00
-#define DT3000_COMMAND_MASK    0x00ff
-#define DT3000_NOTPROCESSED    0x0000
-#define DT3000_NOERROR         0x5500
-#define DT3000_ERROR           0xaa00
-#define DT3000_NOTSUPPORTED    0xff00
-
-#define DT3000_EXTERNAL_CLOCK  1
-#define DT3000_RISING_EDGE     2
-
-#define TMODE_MASK             0x1c
-
-#define DT3000_AD_TRIG_INTERNAL                (0<<2)
-#define DT3000_AD_TRIG_EXTERNAL                (1<<2)
-#define DT3000_AD_RETRIG_INTERNAL      (2<<2)
-#define DT3000_AD_RETRIG_EXTERNAL      (3<<2)
-#define DT3000_AD_EXTRETRIG            (4<<2)
-
-#define DT3000_CHANNEL_MODE_SE         0
-#define DT3000_CHANNEL_MODE_DI         1
-
 struct dt3k_private {
        unsigned int lock;
        unsigned int ai_front;
        unsigned int ai_rear;
 };
 
-#define TIMEOUT 100
-
 static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
 {
        int i;
        unsigned int status = 0;
 
-       writew(cmd, dev->mmio + DPR_Command_Mbx);
+       writew(cmd, dev->mmio + DPR_CMD_MBX);
 
-       for (i = 0; i < TIMEOUT; i++) {
-               status = readw(dev->mmio + DPR_Command_Mbx);
-               if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
+       for (i = 0; i < DPR_CMD_TIMEOUT; i++) {
+               status = readw(dev->mmio + DPR_CMD_MBX);
+               status &= DPR_CMD_COMPLETION_MASK;
+               if (status != DPR_CMD_NOTPROCESSED)
                        break;
                udelay(1);
        }
 
-       if ((status & DT3000_COMPLETION_MASK) != DT3000_NOERROR)
+       if (status != DPR_CMD_NOERROR)
                dev_dbg(dev->class_dev, "%s: timeout/error status=0x%04x\n",
                        __func__, status);
 }
@@ -271,26 +257,26 @@ static unsigned int dt3k_readsingle(struct comedi_device *dev,
                                    unsigned int subsys, unsigned int chan,
                                    unsigned int gain)
 {
-       writew(subsys, dev->mmio + DPR_SubSys);
+       writew(subsys, dev->mmio + DPR_SUBSYS);
 
-       writew(chan, dev->mmio + DPR_Params(0));
-       writew(gain, dev->mmio + DPR_Params(1));
+       writew(chan, dev->mmio + DPR_PARAMS(0));
+       writew(gain, dev->mmio + DPR_PARAMS(1));
 
-       dt3k_send_cmd(dev, CMD_READSINGLE);
+       dt3k_send_cmd(dev, DPR_CMD_READSINGLE);
 
-       return readw(dev->mmio + DPR_Params(2));
+       return readw(dev->mmio + DPR_PARAMS(2));
 }
 
 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
                             unsigned int chan, unsigned int data)
 {
-       writew(subsys, dev->mmio + DPR_SubSys);
+       writew(subsys, dev->mmio + DPR_SUBSYS);
 
-       writew(chan, dev->mmio + DPR_Params(0));
-       writew(0, dev->mmio + DPR_Params(1));
-       writew(data, dev->mmio + DPR_Params(2));
+       writew(chan, dev->mmio + DPR_PARAMS(0));
+       writew(0, dev->mmio + DPR_PARAMS(1));
+       writew(data, dev->mmio + DPR_PARAMS(2));
 
-       dt3k_send_cmd(dev, CMD_WRITESINGLE);
+       dt3k_send_cmd(dev, DPR_CMD_WRITESINGLE);
 }
 
 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
@@ -303,32 +289,32 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev,
        int i;
        unsigned short data;
 
-       front = readw(dev->mmio + DPR_AD_Buf_Front);
+       front = readw(dev->mmio + DPR_AD_BUF_FRONT);
        count = front - devpriv->ai_front;
        if (count < 0)
-               count += AI_FIFO_DEPTH;
+               count += DPR_AI_FIFO_DEPTH;
 
        rear = devpriv->ai_rear;
 
        for (i = 0; i < count; i++) {
-               data = readw(dev->mmio + DPR_ADC_buffer + rear);
+               data = readw(dev->mmio + DPR_ADC_BUFFER + rear);
                comedi_buf_write_samples(s, &data, 1);
                rear++;
-               if (rear >= AI_FIFO_DEPTH)
+               if (rear >= DPR_AI_FIFO_DEPTH)
                        rear = 0;
        }
 
        devpriv->ai_rear = rear;
-       writew(rear, dev->mmio + DPR_AD_Buf_Rear);
+       writew(rear, dev->mmio + DPR_AD_BUF_REAR);
 }
 
 static int dt3k_ai_cancel(struct comedi_device *dev,
                          struct comedi_subdevice *s)
 {
-       writew(SUBS_AI, dev->mmio + DPR_SubSys);
-       dt3k_send_cmd(dev, CMD_STOP);
+       writew(DPR_SUBSYS_AI, dev->mmio + DPR_SUBSYS);
+       dt3k_send_cmd(dev, DPR_CMD_STOP);
 
-       writew(0, dev->mmio + DPR_Int_Mask);
+       writew(0, dev->mmio + DPR_INT_MASK);
 
        return 0;
 }
@@ -346,12 +332,12 @@ static irqreturn_t dt3k_interrupt(int irq, void *d)
        if (!dev->attached)
                return IRQ_NONE;
 
-       status = readw(dev->mmio + DPR_Intr_Flag);
+       status = readw(dev->mmio + DPR_INTR_FLAG);
 
-       if (status & DT3000_ADFULL)
+       if (status & DPR_INTR_ADFULL)
                dt3k_ai_empty_fifo(dev, s);
 
-       if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
+       if (status & (DPR_INTR_ADSWERR | DPR_INTR_ADHWERR))
                s->async->events |= COMEDI_CB_ERROR;
 
        debug_n_ints++;
@@ -400,7 +386,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
 static int dt3k_ai_cmdtest(struct comedi_device *dev,
                           struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-       const struct dt3k_boardtype *this_board = dev->board_ptr;
+       const struct dt3k_boardtype *board = dev->board_ptr;
        int err = 0;
        unsigned int arg;
 
@@ -424,14 +410,14 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev,
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
-                                                   this_board->ai_speed);
+                                                   board->ai_speed);
                err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
                                                    100 * 16 * 65535);
        }
 
        if (cmd->convert_src == TRIG_TIMER) {
                err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
-                                                   this_board->ai_speed);
+                                                   board->ai_speed);
                err |= comedi_check_trigger_arg_max(&cmd->convert_arg,
                                                    50 * 16 * 65535);
        }
@@ -486,46 +472,49 @@ static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                chan = CR_CHAN(cmd->chanlist[i]);
                range = CR_RANGE(cmd->chanlist[i]);
 
-               writew((range << 6) | chan, dev->mmio + DPR_ADC_buffer + i);
+               writew((range << 6) | chan, dev->mmio + DPR_ADC_BUFFER + i);
        }
        aref = CR_AREF(cmd->chanlist[0]);
 
-       writew(cmd->scan_end_arg, dev->mmio + DPR_Params(0));
+       writew(cmd->scan_end_arg, dev->mmio + DPR_PARAMS(0));
 
        if (cmd->convert_src == TRIG_TIMER) {
                divider = dt3k_ns_to_timer(50, &cmd->convert_arg, cmd->flags);
-               writew((divider >> 16), dev->mmio + DPR_Params(1));
-               writew((divider & 0xffff), dev->mmio + DPR_Params(2));
+               writew((divider >> 16), dev->mmio + DPR_PARAMS(1));
+               writew((divider & 0xffff), dev->mmio + DPR_PARAMS(2));
        }
 
        if (cmd->scan_begin_src == TRIG_TIMER) {
                tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
                                            cmd->flags);
-               writew((tscandiv >> 16), dev->mmio + DPR_Params(3));
-               writew((tscandiv & 0xffff), dev->mmio + DPR_Params(4));
+               writew((tscandiv >> 16), dev->mmio + DPR_PARAMS(3));
+               writew((tscandiv & 0xffff), dev->mmio + DPR_PARAMS(4));
        }
 
-       writew(DT3000_AD_RETRIG_INTERNAL, dev->mmio + DPR_Params(5));
-       writew(aref == AREF_DIFF, dev->mmio + DPR_Params(6));
+       writew(DPR_PARAM5_AD_TRIG_INT_RETRIG, dev->mmio + DPR_PARAMS(5));
+       writew((aref == AREF_DIFF) ? DPR_PARAM6_AD_DIFF : 0,
+              dev->mmio + DPR_PARAMS(6));
 
-       writew(AI_FIFO_DEPTH / 2, dev->mmio + DPR_Params(7));
+       writew(DPR_AI_FIFO_DEPTH / 2, dev->mmio + DPR_PARAMS(7));
 
-       writew(SUBS_AI, dev->mmio + DPR_SubSys);
-       dt3k_send_cmd(dev, CMD_CONFIG);
+       writew(DPR_SUBSYS_AI, dev->mmio + DPR_SUBSYS);
+       dt3k_send_cmd(dev, DPR_CMD_CONFIG);
 
-       writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
-              dev->mmio + DPR_Int_Mask);
+       writew(DPR_INTR_ADFULL | DPR_INTR_ADSWERR | DPR_INTR_ADHWERR,
+              dev->mmio + DPR_INT_MASK);
 
        debug_n_ints = 0;
 
-       writew(SUBS_AI, dev->mmio + DPR_SubSys);
-       dt3k_send_cmd(dev, CMD_START);
+       writew(DPR_SUBSYS_AI, dev->mmio + DPR_SUBSYS);
+       dt3k_send_cmd(dev, DPR_CMD_START);
 
        return 0;
 }
 
-static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
-                       struct comedi_insn *insn, unsigned int *data)
+static int dt3k_ai_insn_read(struct comedi_device *dev,
+                            struct comedi_subdevice *s,
+                            struct comedi_insn *insn,
+                            unsigned int *data)
 {
        int i;
        unsigned int chan, gain, aref;
@@ -536,7 +525,7 @@ static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
        aref = CR_AREF(insn->chanspec);
 
        for (i = 0; i < insn->n; i++)
-               data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
+               data[i] = dt3k_readsingle(dev, DPR_SUBSYS_AI, chan, gain);
 
        return i;
 }
@@ -552,7 +541,7 @@ static int dt3k_ao_insn_write(struct comedi_device *dev,
 
        for (i = 0; i < insn->n; i++) {
                val = data[i];
-               dt3k_writesingle(dev, SUBS_AO, chan, val);
+               dt3k_writesingle(dev, DPR_SUBSYS_AO, chan, val);
        }
        s->readback[chan] = val;
 
@@ -562,16 +551,13 @@ static int dt3k_ao_insn_write(struct comedi_device *dev,
 static void dt3k_dio_config(struct comedi_device *dev, int bits)
 {
        /* XXX */
-       writew(SUBS_DOUT, dev->mmio + DPR_SubSys);
+       writew(DPR_SUBSYS_DOUT, dev->mmio + DPR_SUBSYS);
 
-       writew(bits, dev->mmio + DPR_Params(0));
-#if 0
-       /* don't know */
-       writew(0, dev->mmio + DPR_Params(1));
-       writew(0, dev->mmio + DPR_Params(2));
-#endif
+       writew(bits, dev->mmio + DPR_PARAMS(0));
 
-       dt3k_send_cmd(dev, CMD_CONFIG);
+       /* XXX write 0 to DPR_PARAMS(1) and DPR_PARAMS(2) ? */
+
+       dt3k_send_cmd(dev, DPR_CMD_CONFIG);
 }
 
 static int dt3k_dio_insn_config(struct comedi_device *dev,
@@ -603,9 +589,9 @@ static int dt3k_dio_insn_bits(struct comedi_device *dev,
                              unsigned int *data)
 {
        if (comedi_dio_update_state(s, data))
-               dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
+               dt3k_writesingle(dev, DPR_SUBSYS_DOUT, 0, s->state);
 
-       data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
+       data[1] = dt3k_readsingle(dev, DPR_SUBSYS_DIN, 0, 0);
 
        return insn->n;
 }
@@ -619,13 +605,13 @@ static int dt3k_mem_insn_read(struct comedi_device *dev,
        int i;
 
        for (i = 0; i < insn->n; i++) {
-               writew(SUBS_MEM, dev->mmio + DPR_SubSys);
-               writew(addr, dev->mmio + DPR_Params(0));
-               writew(1, dev->mmio + DPR_Params(1));
+               writew(DPR_SUBSYS_MEM, dev->mmio + DPR_SUBSYS);
+               writew(addr, dev->mmio + DPR_PARAMS(0));
+               writew(1, dev->mmio + DPR_PARAMS(1));
 
-               dt3k_send_cmd(dev, CMD_READCODE);
+               dt3k_send_cmd(dev, DPR_CMD_READCODE);
 
-               data[i] = readw(dev->mmio + DPR_Params(2));
+               data[i] = readw(dev->mmio + DPR_PARAMS(2));
        }
 
        return i;
@@ -635,17 +621,17 @@ static int dt3000_auto_attach(struct comedi_device *dev,
                              unsigned long context)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-       const struct dt3k_boardtype *this_board = NULL;
+       const struct dt3k_boardtype *board = NULL;
        struct dt3k_private *devpriv;
        struct comedi_subdevice *s;
        int ret = 0;
 
        if (context < ARRAY_SIZE(dt3k_boardtypes))
-               this_board = &dt3k_boardtypes[context];
-       if (!this_board)
+               board = &dt3k_boardtypes[context];
+       if (!board)
                return -ENODEV;
-       dev->board_ptr = this_board;
-       dev->board_name = this_board->name;
+       dev->board_ptr = board;
+       dev->board_name = board->name;
 
        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
        if (!devpriv)
@@ -670,14 +656,14 @@ static int dt3000_auto_attach(struct comedi_device *dev,
        if (ret)
                return ret;
 
+       /* Analog Input subdevice */
        s = &dev->subdevices[0];
-       /* ai subdevice */
        s->type         = COMEDI_SUBD_AI;
        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
-       s->n_chan       = this_board->adchan;
-       s->insn_read    = dt3k_ai_insn;
-       s->maxdata      = (1 << this_board->adbits) - 1;
+       s->n_chan       = board->adchan;
+       s->maxdata      = board->ai_is_16bit ? 0xffff : 0x0fff;
        s->range_table  = &range_dt3000_ai;     /* XXX */
+       s->insn_read    = dt3k_ai_insn_read;
        if (dev->irq) {
                dev->read_subdev = s;
                s->subdev_flags |= SDF_CMD_READ;
@@ -687,46 +673,42 @@ static int dt3000_auto_attach(struct comedi_device *dev,
                s->cancel       = dt3k_ai_cancel;
        }
 
+       /* Analog Output subdevice */
        s = &dev->subdevices[1];
-       /* ao subsystem */
-       s->type         = COMEDI_SUBD_AO;
-       s->subdev_flags = SDF_WRITABLE;
-       s->n_chan       = 2;
-       s->maxdata      = (1 << this_board->dabits) - 1;
-       s->len_chanlist = 1;
-       s->range_table  = &range_bipolar10;
-       s->insn_write   = dt3k_ao_insn_write;
-
-       ret = comedi_alloc_subdev_readback(s);
-       if (ret)
-               return ret;
+       if (board->has_ao) {
+               s->type         = COMEDI_SUBD_AO;
+               s->subdev_flags = SDF_WRITABLE;
+               s->n_chan       = 2;
+               s->maxdata      = 0x0fff;
+               s->range_table  = &range_bipolar10;
+               s->insn_write   = dt3k_ao_insn_write;
+
+               ret = comedi_alloc_subdev_readback(s);
+               if (ret)
+                       return ret;
+
+       } else {
+               s->type         = COMEDI_SUBD_UNUSED;
+       }
 
+       /* Digital I/O subdevice */
        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->insn_config  = dt3k_dio_insn_config;
+       s->insn_bits    = dt3k_dio_insn_bits;
 
+       /* Memory subdevice */
        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;
-
-#if 0
-       s = &dev->subdevices[4];
-       /* proc subsystem */
-       s->type = COMEDI_SUBD_PROC;
-#endif
+       s->insn_read    = dt3k_mem_insn_read;
 
        return 0;
 }
@@ -765,5 +747,5 @@ static struct pci_driver dt3000_pci_driver = {
 module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Data Translation DT3000 series boards");
 MODULE_LICENSE("GPL");