staging: comedi: drivers: use comedi_fc.h cmdtest helpers
[pandora-kernel.git] / drivers / staging / comedi / drivers / adl_pci9111.c
index 0c20c8d..a87192a 100644 (file)
@@ -89,125 +89,49 @@ TODO:
 
 #define PCI9111_8254_CLOCK_PERIOD_NS           500
 
-/* IO address map */
-
-#define PCI9111_AI_FIFO_REG                            0x00
-#define PCI9111_AO_REG                                 0x00
-#define PCI9111_DIO_REG                                        0x02
-#define PCI9111_REGISTER_EXTENDED_IO_PORTS             0x04
-#define PCI9111_REGISTER_AD_CHANNEL_CONTROL            0x06 /* Channel
-                                                               selection */
-#define PCI9111_REGISTER_AD_CHANNEL_READBACK           0x06
-#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE            0x08
-#define PCI9111_REGISTER_RANGE_STATUS_READBACK         0x08
-#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL          0x0A
-#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK    0x0A
-#define PCI9111_REGISTER_SOFTWARE_TRIGGER              0x0E
-#define PCI9111_REGISTER_INTERRUPT_CONTROL             0x0C
-#define PCI9111_8254_BASE_REG                          0x40
-#define PCI9111_REGISTER_INTERRUPT_CLEAR               0x48
-
-#define PCI9111_TRIGGER_MASK                           0x0F
-#define PCI9111_PTRG_OFF                               (0 << 3)
-#define PCI9111_PTRG_ON                                        (1 << 3)
-#define PCI9111_EITS_EXTERNAL                          (1 << 2)
-#define PCI9111_EITS_INTERNAL                          (0 << 2)
-#define PCI9111_TPST_SOFTWARE_TRIGGER                  (0 << 1)
-#define PCI9111_TPST_TIMER_PACER                       (1 << 1)
-#define PCI9111_ASCAN_ON                               (1 << 0)
-#define PCI9111_ASCAN_OFF                              (0 << 0)
-
-#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
-#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL         (1 << 0)
-#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK             (0 << 1)
-#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG                        (1 << 1)
-#define PCI9111_FFEN_SET_FIFO_ENABLE                   (0 << 2)
-#define PCI9111_FFEN_SET_FIFO_DISABLE                  (1 << 2)
-
-#define PCI9111_CHANNEL_MASK                           0x0F
-
-#define PCI9111_RANGE_MASK                             0x07
-#define PCI9111_FIFO_EMPTY_MASK                                0x10
-#define PCI9111_FIFO_HALF_FULL_MASK                    0x20
-#define PCI9111_FIFO_FULL_MASK                         0x40
-#define PCI9111_AD_BUSY_MASK                           0x80
-
 /*
- * Define inlined function
+ * IO address map and bit defines
  */
-
-#define pci9111_trigger_and_autoscan_get() \
-       (inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
-
-#define pci9111_trigger_and_autoscan_set(flags) \
-       outb(flags, dev->iobase + PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
-
-#define pci9111_interrupt_and_fifo_get() \
-       ((inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) \
-               >> 4) & 0x03)
-
-#define pci9111_interrupt_and_fifo_set(flags) \
-       outb(flags, dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL)
-
-#define pci9111_interrupt_clear() \
-       outb(0, dev->iobase + PCI9111_REGISTER_INTERRUPT_CLEAR)
-
-#define pci9111_software_trigger() \
-       outb(0, dev->iobase + PCI9111_REGISTER_SOFTWARE_TRIGGER)
-
-#define pci9111_fifo_reset() do { \
-       outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
-               dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
-       outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
-               dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
-       outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
-               dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
-       } while (0)
-
-#define pci9111_is_fifo_full() \
-       ((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
-               PCI9111_FIFO_FULL_MASK) == 0)
-
-#define pci9111_is_fifo_half_full() \
-       ((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
-               PCI9111_FIFO_HALF_FULL_MASK) == 0)
-
-#define pci9111_is_fifo_empty() \
-       ((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
-               PCI9111_FIFO_EMPTY_MASK) == 0)
-
-#define pci9111_ai_channel_set(channel) \
-       outb((channel)&PCI9111_CHANNEL_MASK, \
-               dev->iobase + PCI9111_REGISTER_AD_CHANNEL_CONTROL)
-
-#define pci9111_ai_channel_get() \
-       (inb(dev->iobase + PCI9111_REGISTER_AD_CHANNEL_READBACK) \
-               &PCI9111_CHANNEL_MASK)
-
-#define pci9111_ai_range_set(range) \
-       outb((range)&PCI9111_RANGE_MASK, \
-               dev->iobase + PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
-
-#define pci9111_ai_range_get() \
-       (inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK) \
-               &PCI9111_RANGE_MASK)
-
-static const struct comedi_lrange pci9111_hr_ai_range = {
+#define PCI9111_AI_FIFO_REG            0x00
+#define PCI9111_AO_REG                 0x00
+#define PCI9111_DIO_REG                        0x02
+#define PCI9111_EDIO_REG               0x04
+#define PCI9111_AI_CHANNEL_REG         0x06
+#define PCI9111_AI_RANGE_STAT_REG      0x08
+#define PCI9111_AI_STAT_AD_BUSY                (1 << 7)
+#define PCI9111_AI_STAT_FF_FF          (1 << 6)
+#define PCI9111_AI_STAT_FF_HF          (1 << 5)
+#define PCI9111_AI_STAT_FF_EF          (1 << 4)
+#define PCI9111_AI_RANGE_MASK          (7 << 0)
+#define PCI9111_AI_TRIG_CTRL_REG       0x0a
+#define PCI9111_AI_TRIG_CTRL_TRGEVENT  (1 << 5)
+#define PCI9111_AI_TRIG_CTRL_POTRG     (1 << 4)
+#define PCI9111_AI_TRIG_CTRL_PTRG      (1 << 3)
+#define PCI9111_AI_TRIG_CTRL_ETIS      (1 << 2)
+#define PCI9111_AI_TRIG_CTRL_TPST      (1 << 1)
+#define PCI9111_AI_TRIG_CTRL_ASCAN     (1 << 0)
+#define PCI9111_INT_CTRL_REG           0x0c
+#define PCI9111_INT_CTRL_ISC2          (1 << 3)
+#define PCI9111_INT_CTRL_FFEN          (1 << 2)
+#define PCI9111_INT_CTRL_ISC1          (1 << 1)
+#define PCI9111_INT_CTRL_ISC0          (1 << 0)
+#define PCI9111_SOFT_TRIG_REG          0x0e
+#define PCI9111_8254_BASE_REG          0x40
+#define PCI9111_INT_CLR_REG            0x48
+
+static const struct comedi_lrange pci9111_ai_range = {
        5,
        {
-        BIP_RANGE(10),
-        BIP_RANGE(5),
-        BIP_RANGE(2.5),
-        BIP_RANGE(1.25),
-        BIP_RANGE(0.625)
-        }
+               BIP_RANGE(10),
+               BIP_RANGE(5),
+               BIP_RANGE(2.5),
+               BIP_RANGE(1.25),
+               BIP_RANGE(0.625)
+       }
 };
 
-/*  Private data structure */
-
 struct pci9111_private_data {
-       unsigned long lcr_io_base; /* Local configuration register base
-                                   * address */
+       unsigned long lcr_io_base;
 
        int stop_counter;
        int stop_is_none;
@@ -217,21 +141,14 @@ struct pci9111_private_data {
        unsigned int chunk_counter;
        unsigned int chunk_num_samples;
 
-       int ao_readback;        /*  Last written analog output data */
-
-       unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
-                                      * pacer */
-       unsigned int timer_divisor_2;
+       int ao_readback;
 
-       int is_valid;           /*  Is device valid */
+       unsigned int div1;
+       unsigned int div2;
 
        short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
 };
 
-/*  ------------------------------------------------------------------ */
-/*  PLX9050 SECTION */
-/*  ------------------------------------------------------------------ */
-
 #define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
 
 #define PLX9050_LINTI1_ENABLE          (1 << 0)
@@ -267,12 +184,6 @@ static void plx9050_interrupt_control(unsigned long io_base,
        outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
 }
 
-/*  ------------------------------------------------------------------ */
-/*  MISCELLANEOUS SECTION */
-/*  ------------------------------------------------------------------ */
-
-/*  8254 timer */
-
 static void pci9111_timer_set(struct comedi_device *dev)
 {
        struct pci9111_private_data *dev_private = dev->private;
@@ -284,8 +195,8 @@ static void pci9111_timer_set(struct comedi_device *dev)
 
        udelay(1);
 
-       i8254_write(timer_base, 1, 2, dev_private->timer_divisor_2);
-       i8254_write(timer_base, 1, 1, dev_private->timer_divisor_1);
+       i8254_write(timer_base, 1, 2, dev_private->div2);
+       i8254_write(timer_base, 1, 1, dev_private->div1);
 }
 
 enum pci9111_trigger_sources {
@@ -299,47 +210,55 @@ static void pci9111_trigger_source_set(struct comedi_device *dev,
 {
        int flags;
 
-       flags = pci9111_trigger_and_autoscan_get() & 0x09;
+       /* Read the current trigger mode control bits */
+       flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+       /* Mask off the EITS and TPST bits */
+       flags &= 0x9;
 
        switch (source) {
        case software:
-               flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
                break;
 
        case timer_pacer:
-               flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
+               flags |= PCI9111_AI_TRIG_CTRL_TPST;
                break;
 
        case external:
-               flags |= PCI9111_EITS_EXTERNAL;
+               flags |= PCI9111_AI_TRIG_CTRL_ETIS;
                break;
        }
 
-       pci9111_trigger_and_autoscan_set(flags);
+       outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
 }
 
 static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
 {
        int flags;
 
-       flags = pci9111_trigger_and_autoscan_get() & 0x07;
+       /* Read the current trigger mode control bits */
+       flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+       /* Mask off the PTRG bit */
+       flags &= 0x7;
 
        if (pretrigger)
-               flags |= PCI9111_PTRG_ON;
+               flags |= PCI9111_AI_TRIG_CTRL_PTRG;
 
-       pci9111_trigger_and_autoscan_set(flags);
+       outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
 }
 
 static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
 {
        int flags;
 
-       flags = pci9111_trigger_and_autoscan_get() & 0x0e;
+       /* Read the current trigger mode control bits */
+       flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+       /* Mask off the ASCAN bit */
+       flags &= 0xe;
 
        if (autoscan)
-               flags |= PCI9111_ASCAN_ON;
+               flags |= PCI9111_AI_TRIG_CTRL_ASCAN;
 
-       pci9111_trigger_and_autoscan_set(flags);
+       outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
 }
 
 enum pci9111_ISC0_sources {
@@ -358,24 +277,32 @@ static void pci9111_interrupt_source_set(struct comedi_device *dev,
 {
        int flags;
 
-       flags = pci9111_interrupt_and_fifo_get() & 0x04;
+       /* Read the current interrupt control bits */
+       flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
+       /* Shift the bits so they are compatible with the write register */
+       flags >>= 4;
+       /* Mask off the ISCx bits */
+       flags &= 0xc0;
 
+       /* Now set the new ISCx bits */
        if (irq_0_source == irq_on_fifo_half_full)
-               flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
+               flags |= PCI9111_INT_CTRL_ISC0;
 
        if (irq_1_source == irq_on_external_trigger)
-               flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
+               flags |= PCI9111_INT_CTRL_ISC1;
 
-       pci9111_interrupt_and_fifo_set(flags);
+       outb(flags, dev->iobase + PCI9111_INT_CTRL_REG);
 }
 
-/*  ------------------------------------------------------------------ */
-/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
-/*  ------------------------------------------------------------------ */
-
-/*  Cancel analog input autoscan */
+static void pci9111_fifo_reset(struct comedi_device *dev)
+{
+       unsigned long int_ctrl_reg = dev->iobase + PCI9111_INT_CTRL_REG;
 
-#undef AI_DO_CMD_DEBUG
+       /* To reset the FIFO, set FFEN sequence as 0 -> 1 -> 0 */
+       outb(0, int_ctrl_reg);
+       outb(PCI9111_INT_CTRL_FFEN, int_ctrl_reg);
+       outb(0, int_ctrl_reg);
+}
 
 static int pci9111_ai_cancel(struct comedi_device *dev,
                             struct comedi_subdevice *s)
@@ -383,7 +310,6 @@ static int pci9111_ai_cancel(struct comedi_device *dev,
        struct pci9111_private_data *dev_private = dev->private;
 
        /*  Disable interrupts */
-
        plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
                                  true, false);
 
@@ -391,27 +317,14 @@ static int pci9111_ai_cancel(struct comedi_device *dev,
 
        pci9111_autoscan_set(dev, false);
 
-       pci9111_fifo_reset();
-
-#ifdef AI_DO_CMD_DEBUG
-       printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
-#endif
+       pci9111_fifo_reset(dev);
 
        return 0;
 }
 
-/*  Test analog input command */
-
-#define pci9111_check_trigger_src(src, flags)  do {                    \
-               tmp = src;                                              \
-               src &= flags;                                           \
-               if (!src || tmp != src)                                 \
-                       error++;                                        \
-       } while (false);
-
-static int
-pci9111_ai_do_cmd_test(struct comedi_device *dev,
-                      struct comedi_subdevice *s, struct comedi_cmd *cmd)
+static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
+                                 struct comedi_subdevice *s,
+                                 struct comedi_cmd *cmd)
 {
        struct pci9111_private_data *dev_private = dev->private;
        int tmp;
@@ -419,45 +332,36 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
        int range, reference;
        int i;
 
-       /*  Step 1 : check if trigger are trivialy valid */
+       /* Step 1 : check if triggers are trivially valid */
 
-       pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
-       pci9111_check_trigger_src(cmd->scan_begin_src,
-                                 TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
-       pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
-       pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
-       pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+       error |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       error |= cfc_check_trigger_src(&cmd->scan_begin_src,
+                                       TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
+       error |= cfc_check_trigger_src(&cmd->convert_src,
+                                       TRIG_TIMER | TRIG_EXT);
+       error |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       error |= cfc_check_trigger_src(&cmd->stop_src,
+                                       TRIG_COUNT | TRIG_NONE);
 
        if (error)
                return 1;
 
-       /*  step 2 : make sure trigger sources are unique and mutually
-        *  compatible */
+       /* Step 2a : make sure trigger sources are unique */
 
-       if (cmd->start_src != TRIG_NOW)
-               error++;
+       error |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+       error |= cfc_check_trigger_is_unique(cmd->convert_src);
+       error |= cfc_check_trigger_is_unique(cmd->stop_src);
 
-       if ((cmd->scan_begin_src != TRIG_TIMER) &&
-           (cmd->scan_begin_src != TRIG_FOLLOW) &&
-           (cmd->scan_begin_src != TRIG_EXT))
-               error++;
+       /* Step 2b : and mutually compatible */
 
-       if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
-               error++;
        if ((cmd->convert_src == TRIG_TIMER) &&
            !((cmd->scan_begin_src == TRIG_TIMER) ||
              (cmd->scan_begin_src == TRIG_FOLLOW)))
-               error++;
+               error |= -EINVAL;
        if ((cmd->convert_src == TRIG_EXT) &&
            !((cmd->scan_begin_src == TRIG_EXT) ||
              (cmd->scan_begin_src == TRIG_FOLLOW)))
-               error++;
-
-
-       if (cmd->scan_end_src != TRIG_COUNT)
-               error++;
-       if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
-               error++;
+               error |= -EINVAL;
 
        if (error)
                return 2;
@@ -517,9 +421,9 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
        if (cmd->convert_src == TRIG_TIMER) {
                tmp = cmd->convert_arg;
                i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
-                                              &(dev_private->timer_divisor_1),
-                                              &(dev_private->timer_divisor_2),
-                                              &(cmd->convert_arg),
+                                              &dev_private->div1,
+                                              &dev_private->div2,
+                                              &cmd->convert_arg,
                                               cmd->flags & TRIG_ROUND_MASK);
                if (tmp != cmd->convert_arg)
                        error++;
@@ -590,8 +494,6 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
 
 }
 
-/*  Analog input command */
-
 static int pci9111_ai_do_cmd(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
@@ -608,17 +510,20 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
        /*  TODO: handle the case of an external multiplexer */
 
        if (async_cmd->chanlist_len > 1) {
-               pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
+               outb(async_cmd->chanlist_len - 1,
+                       dev->iobase + PCI9111_AI_CHANNEL_REG);
                pci9111_autoscan_set(dev, true);
        } else {
-               pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
+               outb(CR_CHAN(async_cmd->chanlist[0]),
+                       dev->iobase + PCI9111_AI_CHANNEL_REG);
                pci9111_autoscan_set(dev, false);
        }
 
        /*  Set gain */
        /*  This is the same gain on every channel */
 
-       pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
+       outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK,
+               dev->iobase + PCI9111_AI_RANGE_STAT_REG);
 
        /* Set counter */
 
@@ -644,21 +549,9 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
        dev_private->scan_delay = 0;
        switch (async_cmd->convert_src) {
        case TRIG_TIMER:
-               i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
-                                              &(dev_private->timer_divisor_1),
-                                              &(dev_private->timer_divisor_2),
-                                              &(async_cmd->convert_arg),
-                                              async_cmd->
-                                              flags & TRIG_ROUND_MASK);
-#ifdef AI_DO_CMD_DEBUG
-               printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
-                      dev_private->timer_divisor_1,
-                      dev_private->timer_divisor_2);
-#endif
-
                pci9111_trigger_source_set(dev, software);
                pci9111_timer_set(dev);
-               pci9111_fifo_reset();
+               pci9111_fifo_reset(dev);
                pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
                                             irq_on_timer_tick);
                pci9111_trigger_source_set(dev, timer_pacer);
@@ -677,7 +570,7 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
        case TRIG_EXT:
 
                pci9111_trigger_source_set(dev, external);
-               pci9111_fifo_reset();
+               pci9111_fifo_reset(dev);
                pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
                                             irq_on_timer_tick);
                plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
@@ -696,23 +589,6 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev,
        dev_private->chunk_num_samples =
            dev_private->chanlist_len * (1 + dev_private->scan_delay);
 
-#ifdef AI_DO_CMD_DEBUG
-       printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
-       printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
-              pci9111_trigger_and_autoscan_get());
-       printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
-              pci9111_interrupt_and_fifo_get());
-       printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
-       printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
-              dev_private->stop_counter);
-       printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
-              dev_private->scan_delay);
-       printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
-              dev_private->chanlist_len);
-       printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
-              dev_private->chunk_num_samples);
-#endif
-
        return 0;
 }
 
@@ -732,18 +608,13 @@ static void pci9111_ai_munge(struct comedi_device *dev,
                array[i] = ((array[i] >> shift) & maxdata) ^ invert;
 }
 
-/*  ------------------------------------------------------------------ */
-/*  INTERRUPT SECTION */
-/*  ------------------------------------------------------------------ */
-
-#undef INTERRUPT_DEBUG
-
 static irqreturn_t pci9111_interrupt(int irq, void *p_device)
 {
        struct comedi_device *dev = p_device;
        struct pci9111_private_data *dev_private = dev->private;
        struct comedi_subdevice *s = dev->read_subdev;
        struct comedi_async *async;
+       unsigned int status;
        unsigned long irq_flags;
        unsigned char intcsr;
 
@@ -775,10 +646,13 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
            (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
                /*  Interrupt comes from fifo_half-full signal */
 
-               if (pci9111_is_fifo_full()) {
+               status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+
+               /* '0' means FIFO is full, data may have been lost */
+               if (!(status & PCI9111_AI_STAT_FF_FF)) {
                        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
                        comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
-                       pci9111_interrupt_clear();
+                       outb(0, dev->iobase + PCI9111_INT_CLR_REG);
                        pci9111_ai_cancel(dev, s);
                        async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
                        comedi_event(dev, s);
@@ -786,14 +660,11 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
                        return IRQ_HANDLED;
                }
 
-               if (pci9111_is_fifo_half_full()) {
+               /* '0' means FIFO is half-full */
+               if (!(status & PCI9111_AI_STAT_FF_HF)) {
                        unsigned int num_samples;
                        unsigned int bytes_written = 0;
 
-#ifdef INTERRUPT_DEBUG
-                       printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
-#endif
-
                        num_samples =
                            PCI9111_FIFO_HALF_SIZE >
                            dev_private->stop_counter
@@ -867,10 +738,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
                pci9111_ai_cancel(dev, s);
        }
 
-       /* Very important, otherwise another interrupt request will be inserted
-        * and will cause driver hangs on processing interrupt event. */
-
-       pci9111_interrupt_clear();
+       outb(0, dev->iobase + PCI9111_INT_CLR_REG);
 
        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 
@@ -879,42 +747,45 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device)
        return IRQ_HANDLED;
 }
 
-/*  ------------------------------------------------------------------ */
-/*  INSTANT ANALOG INPUT OUTPUT SECTION */
-/*  ------------------------------------------------------------------ */
-
-/*  analog instant input */
-
 static int pci9111_ai_insn_read(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int range = CR_RANGE(insn->chanspec);
        unsigned int maxdata = s->maxdata;
        unsigned int invert = (maxdata + 1) >> 1;
        unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
+       unsigned int status;
        int timeout;
        int i;
 
-       pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
+       outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG);
 
-       if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
-               pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
+       status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+       if ((status & PCI9111_AI_RANGE_MASK) != range) {
+               outb(range & PCI9111_AI_RANGE_MASK,
+                       dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+       }
 
-       pci9111_fifo_reset();
+       pci9111_fifo_reset(dev);
 
        for (i = 0; i < insn->n; i++) {
-               pci9111_software_trigger();
+               /* Generate a software trigger */
+               outb(0, dev->iobase + PCI9111_SOFT_TRIG_REG);
 
                timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
 
                while (timeout--) {
-                       if (!pci9111_is_fifo_empty())
+                       status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
+                       /* '1' means FIFO is not empty */
+                       if (status & PCI9111_AI_STAT_FF_EF)
                                goto conversion_done;
                }
 
                comedi_error(dev, "A/D read timeout");
                data[i] = 0;
-               pci9111_fifo_reset();
+               pci9111_fifo_reset(dev);
                return -ETIME;
 
 conversion_done:
@@ -988,18 +859,11 @@ static int pci9111_do_insn_bits(struct comedi_device *dev,
        return insn->n;
 }
 
-/*  ------------------------------------------------------------------ */
-/*  INITIALISATION SECTION */
-/*  ------------------------------------------------------------------ */
-
-/*  Reset device */
-
 static int pci9111_reset(struct comedi_device *dev)
 {
        struct pci9111_private_data *dev_private = dev->private;
 
        /*  Set trigger source to software */
-
        plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
                                  true, false);
 
@@ -1007,11 +871,9 @@ static int pci9111_reset(struct comedi_device *dev)
        pci9111_pretrigger_set(dev, false);
        pci9111_autoscan_set(dev, false);
 
-       /*  Reset 8254 chip */
-
-       dev_private->timer_divisor_1 = 0;
-       dev_private->timer_divisor_2 = 0;
-
+       /* Reset 8254 chip */
+       dev_private->div1 = 0;
+       dev_private->div2 = 0;
        pci9111_timer_set(dev);
 
        return 0;
@@ -1059,7 +921,7 @@ static int pci9111_attach_pci(struct comedi_device *dev,
        s->n_chan       = 16;
        s->maxdata      = 0xffff;
        s->len_chanlist = 16;
-       s->range_table  = &pci9111_hr_ai_range;
+       s->range_table  = &pci9111_ai_range;
        s->cancel       = pci9111_ai_cancel;
        s->insn_read    = pci9111_ai_insn_read;
        s->do_cmdtest   = pci9111_ai_do_cmd_test;
@@ -1092,8 +954,6 @@ static int pci9111_attach_pci(struct comedi_device *dev,
        s->range_table  = &range_digital;
        s->insn_bits    = pci9111_do_insn_bits;
 
-       dev_private->is_valid = 1;
-
        dev_info(dev->class_dev, "%s attached\n", dev->board_name);
 
        return 0;
@@ -1102,18 +962,14 @@ static int pci9111_attach_pci(struct comedi_device *dev,
 static void pci9111_detach(struct comedi_device *dev)
 {
        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-       struct pci9111_private_data *dev_private = dev->private;
 
-       if (dev_private) {
-               if (dev_private->is_valid)
-                       pci9111_reset(dev);
-       }
+       if (dev->iobase)
+               pci9111_reset(dev);
        if (dev->irq != 0)
                free_irq(dev->irq, dev);
        if (pcidev) {
                if (dev->iobase)
                        comedi_pci_disable(pcidev);
-               pci_dev_put(pcidev);
        }
 }