root/drivers/staging/comedi/drivers/addi_apci_3120.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. apci3120_addon_write
  2. apci3120_init_dma
  3. apci3120_setup_dma
  4. apci3120_ns_to_timer
  5. apci3120_clr_timer2_interrupt
  6. apci3120_timer_write
  7. apci3120_timer_read
  8. apci3120_timer_set_mode
  9. apci3120_timer_enable
  10. apci3120_exttrig_enable
  11. apci3120_set_chanlist
  12. apci3120_interrupt_dma
  13. apci3120_interrupt
  14. apci3120_ai_cmd
  15. apci3120_ai_cmdtest
  16. apci3120_cancel
  17. apci3120_ai_eoc
  18. apci3120_ai_insn_read
  19. apci3120_ao_ready
  20. apci3120_ao_insn_write
  21. apci3120_di_insn_bits
  22. apci3120_do_insn_bits
  23. apci3120_timer_insn_config
  24. apci3120_timer_insn_read
  25. apci3120_dma_alloc
  26. apci3120_dma_free
  27. apci3120_reset
  28. apci3120_auto_attach
  29. apci3120_detach
  30. apci3120_pci_probe

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * addi_apci_3120.c
   4  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
   5  *
   6  *      ADDI-DATA GmbH
   7  *      Dieselstrasse 3
   8  *      D-77833 Ottersweier
   9  *      Tel: +19(0)7223/9493-0
  10  *      Fax: +49(0)7223/9493-92
  11  *      http://www.addi-data.com
  12  *      info@addi-data.com
  13  */
  14 
  15 #include <linux/module.h>
  16 #include <linux/interrupt.h>
  17 
  18 #include "../comedi_pci.h"
  19 #include "amcc_s5933.h"
  20 
  21 /*
  22  * PCI BAR 0 register map (devpriv->amcc)
  23  * see amcc_s5933.h for register and bit defines
  24  */
  25 #define APCI3120_FIFO_ADVANCE_ON_BYTE_2         BIT(29)
  26 
  27 /*
  28  * PCI BAR 1 register map (dev->iobase)
  29  */
  30 #define APCI3120_AI_FIFO_REG                    0x00
  31 #define APCI3120_CTRL_REG                       0x00
  32 #define APCI3120_CTRL_EXT_TRIG                  BIT(15)
  33 #define APCI3120_CTRL_GATE(x)                   BIT(12 + (x))
  34 #define APCI3120_CTRL_PR(x)                     (((x) & 0xf) << 8)
  35 #define APCI3120_CTRL_PA(x)                     (((x) & 0xf) << 0)
  36 #define APCI3120_AI_SOFTTRIG_REG                0x02
  37 #define APCI3120_STATUS_REG                     0x02
  38 #define APCI3120_STATUS_EOC_INT                 BIT(15)
  39 #define APCI3120_STATUS_AMCC_INT                BIT(14)
  40 #define APCI3120_STATUS_EOS_INT                 BIT(13)
  41 #define APCI3120_STATUS_TIMER2_INT              BIT(12)
  42 #define APCI3120_STATUS_INT_MASK                (0xf << 12)
  43 #define APCI3120_STATUS_TO_DI_BITS(x)           (((x) >> 8) & 0xf)
  44 #define APCI3120_STATUS_TO_VERSION(x)           (((x) >> 4) & 0xf)
  45 #define APCI3120_STATUS_FIFO_FULL               BIT(2)
  46 #define APCI3120_STATUS_FIFO_EMPTY              BIT(1)
  47 #define APCI3120_STATUS_DA_READY                BIT(0)
  48 #define APCI3120_TIMER_REG                      0x04
  49 #define APCI3120_CHANLIST_REG                   0x06
  50 #define APCI3120_CHANLIST_INDEX(x)              (((x) & 0xf) << 8)
  51 #define APCI3120_CHANLIST_UNIPOLAR              BIT(7)
  52 #define APCI3120_CHANLIST_GAIN(x)               (((x) & 0x3) << 4)
  53 #define APCI3120_CHANLIST_MUX(x)                (((x) & 0xf) << 0)
  54 #define APCI3120_AO_REG(x)                      (0x08 + (((x) / 4) * 2))
  55 #define APCI3120_AO_MUX(x)                      (((x) & 0x3) << 14)
  56 #define APCI3120_AO_DATA(x)                     ((x) << 0)
  57 #define APCI3120_TIMER_MODE_REG                 0x0c
  58 #define APCI3120_TIMER_MODE(_t, _m)             ((_m) << ((_t) * 2))
  59 #define APCI3120_TIMER_MODE0                    0  /* I8254_MODE0 */
  60 #define APCI3120_TIMER_MODE2                    1  /* I8254_MODE2 */
  61 #define APCI3120_TIMER_MODE4                    2  /* I8254_MODE4 */
  62 #define APCI3120_TIMER_MODE5                    3  /* I8254_MODE5 */
  63 #define APCI3120_TIMER_MODE_MASK(_t)            (3 << ((_t) * 2))
  64 #define APCI3120_CTR0_REG                       0x0d
  65 #define APCI3120_CTR0_DO_BITS(x)                ((x) << 4)
  66 #define APCI3120_CTR0_TIMER_SEL(x)              ((x) << 0)
  67 #define APCI3120_MODE_REG                       0x0e
  68 #define APCI3120_MODE_TIMER2_CLK(x)             (((x) & 0x3) << 6)
  69 #define APCI3120_MODE_TIMER2_CLK_OSC            APCI3120_MODE_TIMER2_CLK(0)
  70 #define APCI3120_MODE_TIMER2_CLK_OUT1           APCI3120_MODE_TIMER2_CLK(1)
  71 #define APCI3120_MODE_TIMER2_CLK_EOC            APCI3120_MODE_TIMER2_CLK(2)
  72 #define APCI3120_MODE_TIMER2_CLK_EOS            APCI3120_MODE_TIMER2_CLK(3)
  73 #define APCI3120_MODE_TIMER2_CLK_MASK           APCI3120_MODE_TIMER2_CLK(3)
  74 #define APCI3120_MODE_TIMER2_AS(x)              (((x) & 0x3) << 4)
  75 #define APCI3120_MODE_TIMER2_AS_TIMER           APCI3120_MODE_TIMER2_AS(0)
  76 #define APCI3120_MODE_TIMER2_AS_COUNTER         APCI3120_MODE_TIMER2_AS(1)
  77 #define APCI3120_MODE_TIMER2_AS_WDOG            APCI3120_MODE_TIMER2_AS(2)
  78 #define APCI3120_MODE_TIMER2_AS_MASK            APCI3120_MODE_TIMER2_AS(3)
  79 #define APCI3120_MODE_SCAN_ENA                  BIT(3)
  80 #define APCI3120_MODE_TIMER2_IRQ_ENA            BIT(2)
  81 #define APCI3120_MODE_EOS_IRQ_ENA               BIT(1)
  82 #define APCI3120_MODE_EOC_IRQ_ENA               BIT(0)
  83 
  84 /*
  85  * PCI BAR 2 register map (devpriv->addon)
  86  */
  87 #define APCI3120_ADDON_ADDR_REG                 0x00
  88 #define APCI3120_ADDON_DATA_REG                 0x02
  89 #define APCI3120_ADDON_CTRL_REG                 0x04
  90 #define APCI3120_ADDON_CTRL_AMWEN_ENA           BIT(1)
  91 #define APCI3120_ADDON_CTRL_A2P_FIFO_ENA        BIT(0)
  92 
  93 /*
  94  * Board revisions
  95  */
  96 #define APCI3120_REVA                           0xa
  97 #define APCI3120_REVB                           0xb
  98 #define APCI3120_REVA_OSC_BASE                  70      /* 70ns = 14.29MHz */
  99 #define APCI3120_REVB_OSC_BASE                  50      /* 50ns = 20MHz */
 100 
 101 static const struct comedi_lrange apci3120_ai_range = {
 102         8, {
 103                 BIP_RANGE(10),
 104                 BIP_RANGE(5),
 105                 BIP_RANGE(2),
 106                 BIP_RANGE(1),
 107                 UNI_RANGE(10),
 108                 UNI_RANGE(5),
 109                 UNI_RANGE(2),
 110                 UNI_RANGE(1)
 111         }
 112 };
 113 
 114 enum apci3120_boardid {
 115         BOARD_APCI3120,
 116         BOARD_APCI3001,
 117 };
 118 
 119 struct apci3120_board {
 120         const char *name;
 121         unsigned int ai_is_16bit:1;
 122         unsigned int has_ao:1;
 123 };
 124 
 125 static const struct apci3120_board apci3120_boardtypes[] = {
 126         [BOARD_APCI3120] = {
 127                 .name           = "apci3120",
 128                 .ai_is_16bit    = 1,
 129                 .has_ao         = 1,
 130         },
 131         [BOARD_APCI3001] = {
 132                 .name           = "apci3001",
 133         },
 134 };
 135 
 136 struct apci3120_dmabuf {
 137         unsigned short *virt;
 138         dma_addr_t hw;
 139         unsigned int size;
 140         unsigned int use_size;
 141 };
 142 
 143 struct apci3120_private {
 144         unsigned long amcc;
 145         unsigned long addon;
 146         unsigned int osc_base;
 147         unsigned int use_dma:1;
 148         unsigned int use_double_buffer:1;
 149         unsigned int cur_dmabuf:1;
 150         struct apci3120_dmabuf dmabuf[2];
 151         unsigned char do_bits;
 152         unsigned char timer_mode;
 153         unsigned char mode;
 154         unsigned short ctrl;
 155 };
 156 
 157 static void apci3120_addon_write(struct comedi_device *dev,
 158                                  unsigned int val, unsigned int reg)
 159 {
 160         struct apci3120_private *devpriv = dev->private;
 161 
 162         /* 16-bit interface for AMCC add-on registers */
 163 
 164         outw(reg, devpriv->addon + APCI3120_ADDON_ADDR_REG);
 165         outw(val & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
 166 
 167         outw(reg + 2, devpriv->addon + APCI3120_ADDON_ADDR_REG);
 168         outw((val >> 16) & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
 169 }
 170 
 171 static void apci3120_init_dma(struct comedi_device *dev,
 172                               struct apci3120_dmabuf *dmabuf)
 173 {
 174         struct apci3120_private *devpriv = dev->private;
 175 
 176         /* AMCC - enable transfer count and reset A2P FIFO */
 177         outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
 178              devpriv->amcc + AMCC_OP_REG_AGCSTS);
 179 
 180         /* Add-On - enable transfer count and reset A2P FIFO */
 181         apci3120_addon_write(dev, AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
 182                              AMCC_OP_REG_AGCSTS);
 183 
 184         /* AMCC - enable transfers and reset A2P flags */
 185         outl(RESET_A2P_FLAGS | EN_A2P_TRANSFERS,
 186              devpriv->amcc + AMCC_OP_REG_MCSR);
 187 
 188         /* Add-On - DMA start address */
 189         apci3120_addon_write(dev, dmabuf->hw, AMCC_OP_REG_AMWAR);
 190 
 191         /* Add-On - Number of acquisitions */
 192         apci3120_addon_write(dev, dmabuf->use_size, AMCC_OP_REG_AMWTC);
 193 
 194         /* AMCC - enable write complete (DMA) and set FIFO advance */
 195         outl(APCI3120_FIFO_ADVANCE_ON_BYTE_2 | AINT_WRITE_COMPL,
 196              devpriv->amcc + AMCC_OP_REG_INTCSR);
 197 
 198         /* Add-On - enable DMA */
 199         outw(APCI3120_ADDON_CTRL_AMWEN_ENA | APCI3120_ADDON_CTRL_A2P_FIFO_ENA,
 200              devpriv->addon + APCI3120_ADDON_CTRL_REG);
 201 }
 202 
 203 static void apci3120_setup_dma(struct comedi_device *dev,
 204                                struct comedi_subdevice *s)
 205 {
 206         struct apci3120_private *devpriv = dev->private;
 207         struct comedi_cmd *cmd = &s->async->cmd;
 208         struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
 209         struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
 210         unsigned int dmalen0 = dmabuf0->size;
 211         unsigned int dmalen1 = dmabuf1->size;
 212         unsigned int scan_bytes;
 213 
 214         scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg);
 215 
 216         if (cmd->stop_src == TRIG_COUNT) {
 217                 /*
 218                  * Must we fill full first buffer? And must we fill
 219                  * full second buffer when first is once filled?
 220                  */
 221                 if (dmalen0 > (cmd->stop_arg * scan_bytes))
 222                         dmalen0 = cmd->stop_arg * scan_bytes;
 223                 else if (dmalen1 > (cmd->stop_arg * scan_bytes - dmalen0))
 224                         dmalen1 = cmd->stop_arg * scan_bytes - dmalen0;
 225         }
 226 
 227         if (cmd->flags & CMDF_WAKE_EOS) {
 228                 /* don't we want wake up every scan? */
 229                 if (dmalen0 > scan_bytes) {
 230                         dmalen0 = scan_bytes;
 231                         if (cmd->scan_end_arg & 1)
 232                                 dmalen0 += 2;
 233                 }
 234                 if (dmalen1 > scan_bytes) {
 235                         dmalen1 = scan_bytes;
 236                         if (cmd->scan_end_arg & 1)
 237                                 dmalen1 -= 2;
 238                         if (dmalen1 < 4)
 239                                 dmalen1 = 4;
 240                 }
 241         } else {
 242                 /* isn't output buff smaller that our DMA buff? */
 243                 if (dmalen0 > s->async->prealloc_bufsz)
 244                         dmalen0 = s->async->prealloc_bufsz;
 245                 if (dmalen1 > s->async->prealloc_bufsz)
 246                         dmalen1 = s->async->prealloc_bufsz;
 247         }
 248         dmabuf0->use_size = dmalen0;
 249         dmabuf1->use_size = dmalen1;
 250 
 251         apci3120_init_dma(dev, dmabuf0);
 252 }
 253 
 254 /*
 255  * There are three timers on the board. They all use the same base
 256  * clock with a fixed prescaler for each timer. The base clock used
 257  * depends on the board version and type.
 258  *
 259  * APCI-3120 Rev A boards OSC = 14.29MHz base clock (~70ns)
 260  * APCI-3120 Rev B boards OSC = 20MHz base clock (50ns)
 261  * APCI-3001 boards OSC = 20MHz base clock (50ns)
 262  *
 263  * The prescalers for each timer are:
 264  * Timer 0 CLK = OSC/10
 265  * Timer 1 CLK = OSC/1000
 266  * Timer 2 CLK = OSC/1000
 267  */
 268 static unsigned int apci3120_ns_to_timer(struct comedi_device *dev,
 269                                          unsigned int timer,
 270                                          unsigned int ns,
 271                                          unsigned int flags)
 272 {
 273         struct apci3120_private *devpriv = dev->private;
 274         unsigned int prescale = (timer == 0) ? 10 : 1000;
 275         unsigned int timer_base = devpriv->osc_base * prescale;
 276         unsigned int divisor;
 277 
 278         switch (flags & CMDF_ROUND_MASK) {
 279         case CMDF_ROUND_UP:
 280                 divisor = DIV_ROUND_UP(ns, timer_base);
 281                 break;
 282         case CMDF_ROUND_DOWN:
 283                 divisor = ns / timer_base;
 284                 break;
 285         case CMDF_ROUND_NEAREST:
 286         default:
 287                 divisor = DIV_ROUND_CLOSEST(ns, timer_base);
 288                 break;
 289         }
 290 
 291         if (timer == 2) {
 292                 /* timer 2 is 24-bits */
 293                 if (divisor > 0x00ffffff)
 294                         divisor = 0x00ffffff;
 295         } else {
 296                 /* timers 0 and 1 are 16-bits */
 297                 if (divisor > 0xffff)
 298                         divisor = 0xffff;
 299         }
 300         /* the timers require a minimum divisor of 2 */
 301         if (divisor < 2)
 302                 divisor = 2;
 303 
 304         return divisor;
 305 }
 306 
 307 static void apci3120_clr_timer2_interrupt(struct comedi_device *dev)
 308 {
 309         /* a dummy read of APCI3120_CTR0_REG clears the timer 2 interrupt */
 310         inb(dev->iobase + APCI3120_CTR0_REG);
 311 }
 312 
 313 static void apci3120_timer_write(struct comedi_device *dev,
 314                                  unsigned int timer, unsigned int val)
 315 {
 316         struct apci3120_private *devpriv = dev->private;
 317 
 318         /* write 16-bit value to timer (lower 16-bits of timer 2) */
 319         outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
 320              APCI3120_CTR0_TIMER_SEL(timer),
 321              dev->iobase + APCI3120_CTR0_REG);
 322         outw(val & 0xffff, dev->iobase + APCI3120_TIMER_REG);
 323 
 324         if (timer == 2) {
 325                 /* write upper 16-bits to timer 2 */
 326                 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
 327                      APCI3120_CTR0_TIMER_SEL(timer + 1),
 328                      dev->iobase + APCI3120_CTR0_REG);
 329                 outw((val >> 16) & 0xffff, dev->iobase + APCI3120_TIMER_REG);
 330         }
 331 }
 332 
 333 static unsigned int apci3120_timer_read(struct comedi_device *dev,
 334                                         unsigned int timer)
 335 {
 336         struct apci3120_private *devpriv = dev->private;
 337         unsigned int val;
 338 
 339         /* read 16-bit value from timer (lower 16-bits of timer 2) */
 340         outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
 341              APCI3120_CTR0_TIMER_SEL(timer),
 342              dev->iobase + APCI3120_CTR0_REG);
 343         val = inw(dev->iobase + APCI3120_TIMER_REG);
 344 
 345         if (timer == 2) {
 346                 /* read upper 16-bits from timer 2 */
 347                 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
 348                      APCI3120_CTR0_TIMER_SEL(timer + 1),
 349                      dev->iobase + APCI3120_CTR0_REG);
 350                 val |= (inw(dev->iobase + APCI3120_TIMER_REG) << 16);
 351         }
 352 
 353         return val;
 354 }
 355 
 356 static void apci3120_timer_set_mode(struct comedi_device *dev,
 357                                     unsigned int timer, unsigned int mode)
 358 {
 359         struct apci3120_private *devpriv = dev->private;
 360 
 361         devpriv->timer_mode &= ~APCI3120_TIMER_MODE_MASK(timer);
 362         devpriv->timer_mode |= APCI3120_TIMER_MODE(timer, mode);
 363         outb(devpriv->timer_mode, dev->iobase + APCI3120_TIMER_MODE_REG);
 364 }
 365 
 366 static void apci3120_timer_enable(struct comedi_device *dev,
 367                                   unsigned int timer, bool enable)
 368 {
 369         struct apci3120_private *devpriv = dev->private;
 370 
 371         if (enable)
 372                 devpriv->ctrl |= APCI3120_CTRL_GATE(timer);
 373         else
 374                 devpriv->ctrl &= ~APCI3120_CTRL_GATE(timer);
 375         outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
 376 }
 377 
 378 static void apci3120_exttrig_enable(struct comedi_device *dev, bool enable)
 379 {
 380         struct apci3120_private *devpriv = dev->private;
 381 
 382         if (enable)
 383                 devpriv->ctrl |= APCI3120_CTRL_EXT_TRIG;
 384         else
 385                 devpriv->ctrl &= ~APCI3120_CTRL_EXT_TRIG;
 386         outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
 387 }
 388 
 389 static void apci3120_set_chanlist(struct comedi_device *dev,
 390                                   struct comedi_subdevice *s,
 391                                   int n_chan, unsigned int *chanlist)
 392 {
 393         struct apci3120_private *devpriv = dev->private;
 394         int i;
 395 
 396         /* set chanlist for scan */
 397         for (i = 0; i < n_chan; i++) {
 398                 unsigned int chan = CR_CHAN(chanlist[i]);
 399                 unsigned int range = CR_RANGE(chanlist[i]);
 400                 unsigned int val;
 401 
 402                 val = APCI3120_CHANLIST_MUX(chan) |
 403                       APCI3120_CHANLIST_GAIN(range) |
 404                       APCI3120_CHANLIST_INDEX(i);
 405 
 406                 if (comedi_range_is_unipolar(s, range))
 407                         val |= APCI3120_CHANLIST_UNIPOLAR;
 408 
 409                 outw(val, dev->iobase + APCI3120_CHANLIST_REG);
 410         }
 411 
 412         /* a dummy read of APCI3120_TIMER_MODE_REG resets the ai FIFO */
 413         inw(dev->iobase + APCI3120_TIMER_MODE_REG);
 414 
 415         /* set scan length (PR) and scan start (PA) */
 416         devpriv->ctrl = APCI3120_CTRL_PR(n_chan - 1) | APCI3120_CTRL_PA(0);
 417         outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
 418 
 419         /* enable chanlist scanning if necessary */
 420         if (n_chan > 1)
 421                 devpriv->mode |= APCI3120_MODE_SCAN_ENA;
 422 }
 423 
 424 static void apci3120_interrupt_dma(struct comedi_device *dev,
 425                                    struct comedi_subdevice *s)
 426 {
 427         struct apci3120_private *devpriv = dev->private;
 428         struct comedi_async *async = s->async;
 429         struct comedi_cmd *cmd = &async->cmd;
 430         struct apci3120_dmabuf *dmabuf;
 431         unsigned int nbytes;
 432         unsigned int nsamples;
 433 
 434         dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
 435 
 436         nbytes = dmabuf->use_size - inl(devpriv->amcc + AMCC_OP_REG_MWTC);
 437 
 438         if (nbytes < dmabuf->use_size)
 439                 dev_err(dev->class_dev, "Interrupted DMA transfer!\n");
 440         if (nbytes & 1) {
 441                 dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n");
 442                 async->events |= COMEDI_CB_ERROR;
 443                 return;
 444         }
 445 
 446         nsamples = comedi_bytes_to_samples(s, nbytes);
 447         if (nsamples) {
 448                 comedi_buf_write_samples(s, dmabuf->virt, nsamples);
 449 
 450                 if (!(cmd->flags & CMDF_WAKE_EOS))
 451                         async->events |= COMEDI_CB_EOS;
 452         }
 453 
 454         if ((async->events & COMEDI_CB_CANCEL_MASK) ||
 455             (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg))
 456                 return;
 457 
 458         if (devpriv->use_double_buffer) {
 459                 /* switch DMA buffers for next interrupt */
 460                 devpriv->cur_dmabuf = !devpriv->cur_dmabuf;
 461                 dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
 462                 apci3120_init_dma(dev, dmabuf);
 463         } else {
 464                 /* restart DMA if not using double buffering */
 465                 apci3120_init_dma(dev, dmabuf);
 466         }
 467 }
 468 
 469 static irqreturn_t apci3120_interrupt(int irq, void *d)
 470 {
 471         struct comedi_device *dev = d;
 472         struct apci3120_private *devpriv = dev->private;
 473         struct comedi_subdevice *s = dev->read_subdev;
 474         struct comedi_async *async = s->async;
 475         struct comedi_cmd *cmd = &async->cmd;
 476         unsigned int status;
 477         unsigned int int_amcc;
 478 
 479         status = inw(dev->iobase + APCI3120_STATUS_REG);
 480         int_amcc = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
 481 
 482         if (!(status & APCI3120_STATUS_INT_MASK) &&
 483             !(int_amcc & ANY_S593X_INT)) {
 484                 dev_err(dev->class_dev, "IRQ from unknown source\n");
 485                 return IRQ_NONE;
 486         }
 487 
 488         outl(int_amcc | AINT_INT_MASK, devpriv->amcc + AMCC_OP_REG_INTCSR);
 489 
 490         if (devpriv->ctrl & APCI3120_CTRL_EXT_TRIG)
 491                 apci3120_exttrig_enable(dev, false);
 492 
 493         if (int_amcc & MASTER_ABORT_INT)
 494                 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
 495         if (int_amcc & TARGET_ABORT_INT)
 496                 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
 497 
 498         if ((status & APCI3120_STATUS_EOS_INT) &&
 499             (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) {
 500                 unsigned short val;
 501                 int i;
 502 
 503                 for (i = 0; i < cmd->chanlist_len; i++) {
 504                         val = inw(dev->iobase + APCI3120_AI_FIFO_REG);
 505                         comedi_buf_write_samples(s, &val, 1);
 506                 }
 507 
 508                 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
 509                 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
 510         }
 511 
 512         if (status & APCI3120_STATUS_TIMER2_INT) {
 513                 /*
 514                  * for safety...
 515                  * timer2 interrupts are not enabled in the driver
 516                  */
 517                 apci3120_clr_timer2_interrupt(dev);
 518         }
 519 
 520         if (status & APCI3120_STATUS_AMCC_INT) {
 521                 /* AMCC- Clear write complete interrupt (DMA) */
 522                 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
 523 
 524                 /* do some data transfer */
 525                 apci3120_interrupt_dma(dev, s);
 526         }
 527 
 528         if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
 529                 async->events |= COMEDI_CB_EOA;
 530 
 531         comedi_handle_events(dev, s);
 532 
 533         return IRQ_HANDLED;
 534 }
 535 
 536 static int apci3120_ai_cmd(struct comedi_device *dev,
 537                            struct comedi_subdevice *s)
 538 {
 539         struct apci3120_private *devpriv = dev->private;
 540         struct comedi_cmd *cmd = &s->async->cmd;
 541         unsigned int divisor;
 542 
 543         /* set default mode bits */
 544         devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
 545                         APCI3120_MODE_TIMER2_AS_TIMER;
 546 
 547         /* AMCC- Clear write complete interrupt (DMA) */
 548         outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
 549 
 550         devpriv->cur_dmabuf = 0;
 551 
 552         /* load chanlist for command scan */
 553         apci3120_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist);
 554 
 555         if (cmd->start_src == TRIG_EXT)
 556                 apci3120_exttrig_enable(dev, true);
 557 
 558         if (cmd->scan_begin_src == TRIG_TIMER) {
 559                 /*
 560                  * Timer 1 is used in MODE2 (rate generator) to set the
 561                  * start time for each scan.
 562                  */
 563                 divisor = apci3120_ns_to_timer(dev, 1, cmd->scan_begin_arg,
 564                                                cmd->flags);
 565                 apci3120_timer_set_mode(dev, 1, APCI3120_TIMER_MODE2);
 566                 apci3120_timer_write(dev, 1, divisor);
 567         }
 568 
 569         /*
 570          * Timer 0 is used in MODE2 (rate generator) to set the conversion
 571          * time for each acquisition.
 572          */
 573         divisor = apci3120_ns_to_timer(dev, 0, cmd->convert_arg, cmd->flags);
 574         apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE2);
 575         apci3120_timer_write(dev, 0, divisor);
 576 
 577         if (devpriv->use_dma)
 578                 apci3120_setup_dma(dev, s);
 579         else
 580                 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
 581 
 582         /* set mode to enable acquisition */
 583         outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
 584 
 585         if (cmd->scan_begin_src == TRIG_TIMER)
 586                 apci3120_timer_enable(dev, 1, true);
 587         apci3120_timer_enable(dev, 0, true);
 588 
 589         return 0;
 590 }
 591 
 592 static int apci3120_ai_cmdtest(struct comedi_device *dev,
 593                                struct comedi_subdevice *s,
 594                                struct comedi_cmd *cmd)
 595 {
 596         unsigned int arg;
 597         int err = 0;
 598 
 599         /* Step 1 : check if triggers are trivially valid */
 600 
 601         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 602         err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 603                                         TRIG_TIMER | TRIG_FOLLOW);
 604         err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
 605         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 606         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 607 
 608         if (err)
 609                 return 1;
 610 
 611         /* Step 2a : make sure trigger sources are unique */
 612 
 613         err |= comedi_check_trigger_is_unique(cmd->start_src);
 614         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 615         err |= comedi_check_trigger_is_unique(cmd->stop_src);
 616 
 617         /* Step 2b : and mutually compatible */
 618 
 619         if (err)
 620                 return 2;
 621 
 622         /* Step 3: check if arguments are trivially valid */
 623 
 624         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 625 
 626         if (cmd->scan_begin_src == TRIG_TIMER) {        /* Test Delay timing */
 627                 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 628                                                     100000);
 629         }
 630 
 631         /* minimum conversion time per sample is 10us */
 632         err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
 633 
 634         err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
 635         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 636                                            cmd->chanlist_len);
 637 
 638         if (cmd->stop_src == TRIG_COUNT)
 639                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 640         else    /*  TRIG_NONE */
 641                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 642 
 643         if (err)
 644                 return 3;
 645 
 646         /* Step 4: fix up any arguments */
 647 
 648         if (cmd->scan_begin_src == TRIG_TIMER) {
 649                 /* scan begin must be larger than the scan time */
 650                 arg = cmd->convert_arg * cmd->scan_end_arg;
 651                 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
 652         }
 653 
 654         if (err)
 655                 return 4;
 656 
 657         /* Step 5: check channel list if it exists */
 658 
 659         return 0;
 660 }
 661 
 662 static int apci3120_cancel(struct comedi_device *dev,
 663                            struct comedi_subdevice *s)
 664 {
 665         struct apci3120_private *devpriv = dev->private;
 666 
 667         /* Add-On - disable DMA */
 668         outw(0, devpriv->addon + 4);
 669 
 670         /* Add-On - disable bus master */
 671         apci3120_addon_write(dev, 0, AMCC_OP_REG_AGCSTS);
 672 
 673         /* AMCC - disable bus master */
 674         outl(0, devpriv->amcc + AMCC_OP_REG_MCSR);
 675 
 676         /* disable all counters, ext trigger, and reset scan */
 677         devpriv->ctrl = 0;
 678         outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
 679 
 680         /* DISABLE_ALL_INTERRUPT */
 681         devpriv->mode = 0;
 682         outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
 683 
 684         inw(dev->iobase + APCI3120_STATUS_REG);
 685         devpriv->cur_dmabuf = 0;
 686 
 687         return 0;
 688 }
 689 
 690 static int apci3120_ai_eoc(struct comedi_device *dev,
 691                            struct comedi_subdevice *s,
 692                            struct comedi_insn *insn,
 693                            unsigned long context)
 694 {
 695         unsigned int status;
 696 
 697         status = inw(dev->iobase + APCI3120_STATUS_REG);
 698         if ((status & APCI3120_STATUS_EOC_INT) == 0)
 699                 return 0;
 700         return -EBUSY;
 701 }
 702 
 703 static int apci3120_ai_insn_read(struct comedi_device *dev,
 704                                  struct comedi_subdevice *s,
 705                                  struct comedi_insn *insn,
 706                                  unsigned int *data)
 707 {
 708         struct apci3120_private *devpriv = dev->private;
 709         unsigned int divisor;
 710         int ret;
 711         int i;
 712 
 713         /* set mode for A/D conversions by software trigger with timer 0 */
 714         devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
 715                         APCI3120_MODE_TIMER2_AS_TIMER;
 716         outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
 717 
 718         /* load chanlist for single channel scan */
 719         apci3120_set_chanlist(dev, s, 1, &insn->chanspec);
 720 
 721         /*
 722          * Timer 0 is used in MODE4 (software triggered strobe) to set the
 723          * conversion time for each acquisition. Each conversion is triggered
 724          * when the divisor is written to the timer, The conversion is done
 725          * when the EOC bit in the status register is '0'.
 726          */
 727         apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE4);
 728         apci3120_timer_enable(dev, 0, true);
 729 
 730         /* fixed conversion time of 10 us */
 731         divisor = apci3120_ns_to_timer(dev, 0, 10000, CMDF_ROUND_NEAREST);
 732 
 733         for (i = 0; i < insn->n; i++) {
 734                 /* trigger conversion */
 735                 apci3120_timer_write(dev, 0, divisor);
 736 
 737                 ret = comedi_timeout(dev, s, insn, apci3120_ai_eoc, 0);
 738                 if (ret)
 739                         return ret;
 740 
 741                 data[i] = inw(dev->iobase + APCI3120_AI_FIFO_REG);
 742         }
 743 
 744         return insn->n;
 745 }
 746 
 747 static int apci3120_ao_ready(struct comedi_device *dev,
 748                              struct comedi_subdevice *s,
 749                              struct comedi_insn *insn,
 750                              unsigned long context)
 751 {
 752         unsigned int status;
 753 
 754         status = inw(dev->iobase + APCI3120_STATUS_REG);
 755         if (status & APCI3120_STATUS_DA_READY)
 756                 return 0;
 757         return -EBUSY;
 758 }
 759 
 760 static int apci3120_ao_insn_write(struct comedi_device *dev,
 761                                   struct comedi_subdevice *s,
 762                                   struct comedi_insn *insn,
 763                                   unsigned int *data)
 764 {
 765         unsigned int chan = CR_CHAN(insn->chanspec);
 766         int i;
 767 
 768         for (i = 0; i < insn->n; i++) {
 769                 unsigned int val = data[i];
 770                 int ret;
 771 
 772                 ret = comedi_timeout(dev, s, insn, apci3120_ao_ready, 0);
 773                 if (ret)
 774                         return ret;
 775 
 776                 outw(APCI3120_AO_MUX(chan) | APCI3120_AO_DATA(val),
 777                      dev->iobase + APCI3120_AO_REG(chan));
 778 
 779                 s->readback[chan] = val;
 780         }
 781 
 782         return insn->n;
 783 }
 784 
 785 static int apci3120_di_insn_bits(struct comedi_device *dev,
 786                                  struct comedi_subdevice *s,
 787                                  struct comedi_insn *insn,
 788                                  unsigned int *data)
 789 {
 790         unsigned int status;
 791 
 792         status = inw(dev->iobase + APCI3120_STATUS_REG);
 793         data[1] = APCI3120_STATUS_TO_DI_BITS(status);
 794 
 795         return insn->n;
 796 }
 797 
 798 static int apci3120_do_insn_bits(struct comedi_device *dev,
 799                                  struct comedi_subdevice *s,
 800                                  struct comedi_insn *insn,
 801                                  unsigned int *data)
 802 {
 803         struct apci3120_private *devpriv = dev->private;
 804 
 805         if (comedi_dio_update_state(s, data)) {
 806                 devpriv->do_bits = s->state;
 807                 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits),
 808                      dev->iobase + APCI3120_CTR0_REG);
 809         }
 810 
 811         data[1] = s->state;
 812 
 813         return insn->n;
 814 }
 815 
 816 static int apci3120_timer_insn_config(struct comedi_device *dev,
 817                                       struct comedi_subdevice *s,
 818                                       struct comedi_insn *insn,
 819                                       unsigned int *data)
 820 {
 821         struct apci3120_private *devpriv = dev->private;
 822         unsigned int divisor;
 823         unsigned int status;
 824         unsigned int mode;
 825         unsigned int timer_mode;
 826 
 827         switch (data[0]) {
 828         case INSN_CONFIG_ARM:
 829                 apci3120_clr_timer2_interrupt(dev);
 830                 divisor = apci3120_ns_to_timer(dev, 2, data[1],
 831                                                CMDF_ROUND_DOWN);
 832                 apci3120_timer_write(dev, 2, divisor);
 833                 apci3120_timer_enable(dev, 2, true);
 834                 break;
 835 
 836         case INSN_CONFIG_DISARM:
 837                 apci3120_timer_enable(dev, 2, false);
 838                 apci3120_clr_timer2_interrupt(dev);
 839                 break;
 840 
 841         case INSN_CONFIG_GET_COUNTER_STATUS:
 842                 data[1] = 0;
 843                 data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING |
 844                           COMEDI_COUNTER_TERMINAL_COUNT;
 845 
 846                 if (devpriv->ctrl & APCI3120_CTRL_GATE(2)) {
 847                         data[1] |= COMEDI_COUNTER_ARMED;
 848                         data[1] |= COMEDI_COUNTER_COUNTING;
 849                 }
 850                 status = inw(dev->iobase + APCI3120_STATUS_REG);
 851                 if (status & APCI3120_STATUS_TIMER2_INT) {
 852                         data[1] &= ~COMEDI_COUNTER_COUNTING;
 853                         data[1] |= COMEDI_COUNTER_TERMINAL_COUNT;
 854                 }
 855                 break;
 856 
 857         case INSN_CONFIG_SET_COUNTER_MODE:
 858                 switch (data[1]) {
 859                 case I8254_MODE0:
 860                         mode = APCI3120_MODE_TIMER2_AS_COUNTER;
 861                         timer_mode = APCI3120_TIMER_MODE0;
 862                         break;
 863                 case I8254_MODE2:
 864                         mode = APCI3120_MODE_TIMER2_AS_TIMER;
 865                         timer_mode = APCI3120_TIMER_MODE2;
 866                         break;
 867                 case I8254_MODE4:
 868                         mode = APCI3120_MODE_TIMER2_AS_TIMER;
 869                         timer_mode = APCI3120_TIMER_MODE4;
 870                         break;
 871                 case I8254_MODE5:
 872                         mode = APCI3120_MODE_TIMER2_AS_WDOG;
 873                         timer_mode = APCI3120_TIMER_MODE5;
 874                         break;
 875                 default:
 876                         return -EINVAL;
 877                 }
 878                 apci3120_timer_enable(dev, 2, false);
 879                 apci3120_clr_timer2_interrupt(dev);
 880                 apci3120_timer_set_mode(dev, 2, timer_mode);
 881                 devpriv->mode &= ~APCI3120_MODE_TIMER2_AS_MASK;
 882                 devpriv->mode |= mode;
 883                 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
 884                 break;
 885 
 886         default:
 887                 return -EINVAL;
 888         }
 889 
 890         return insn->n;
 891 }
 892 
 893 static int apci3120_timer_insn_read(struct comedi_device *dev,
 894                                     struct comedi_subdevice *s,
 895                                     struct comedi_insn *insn,
 896                                     unsigned int *data)
 897 {
 898         int i;
 899 
 900         for (i = 0; i < insn->n; i++)
 901                 data[i] = apci3120_timer_read(dev, 2);
 902 
 903         return insn->n;
 904 }
 905 
 906 static void apci3120_dma_alloc(struct comedi_device *dev)
 907 {
 908         struct apci3120_private *devpriv = dev->private;
 909         struct apci3120_dmabuf *dmabuf;
 910         int order;
 911         int i;
 912 
 913         for (i = 0; i < 2; i++) {
 914                 dmabuf = &devpriv->dmabuf[i];
 915                 for (order = 2; order >= 0; order--) {
 916                         dmabuf->virt = dma_alloc_coherent(dev->hw_dev,
 917                                                           PAGE_SIZE << order,
 918                                                           &dmabuf->hw,
 919                                                           GFP_KERNEL);
 920                         if (dmabuf->virt)
 921                                 break;
 922                 }
 923                 if (!dmabuf->virt)
 924                         break;
 925                 dmabuf->size = PAGE_SIZE << order;
 926 
 927                 if (i == 0)
 928                         devpriv->use_dma = 1;
 929                 if (i == 1)
 930                         devpriv->use_double_buffer = 1;
 931         }
 932 }
 933 
 934 static void apci3120_dma_free(struct comedi_device *dev)
 935 {
 936         struct apci3120_private *devpriv = dev->private;
 937         struct apci3120_dmabuf *dmabuf;
 938         int i;
 939 
 940         if (!devpriv)
 941                 return;
 942 
 943         for (i = 0; i < 2; i++) {
 944                 dmabuf = &devpriv->dmabuf[i];
 945                 if (dmabuf->virt) {
 946                         dma_free_coherent(dev->hw_dev, dmabuf->size,
 947                                           dmabuf->virt, dmabuf->hw);
 948                 }
 949         }
 950 }
 951 
 952 static void apci3120_reset(struct comedi_device *dev)
 953 {
 954         /* disable all interrupt sources */
 955         outb(0, dev->iobase + APCI3120_MODE_REG);
 956 
 957         /* disable all counters, ext trigger, and reset scan */
 958         outw(0, dev->iobase + APCI3120_CTRL_REG);
 959 
 960         /* clear interrupt status */
 961         inw(dev->iobase + APCI3120_STATUS_REG);
 962 }
 963 
 964 static int apci3120_auto_attach(struct comedi_device *dev,
 965                                 unsigned long context)
 966 {
 967         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 968         const struct apci3120_board *board = NULL;
 969         struct apci3120_private *devpriv;
 970         struct comedi_subdevice *s;
 971         unsigned int status;
 972         int ret;
 973 
 974         if (context < ARRAY_SIZE(apci3120_boardtypes))
 975                 board = &apci3120_boardtypes[context];
 976         if (!board)
 977                 return -ENODEV;
 978         dev->board_ptr = board;
 979         dev->board_name = board->name;
 980 
 981         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 982         if (!devpriv)
 983                 return -ENOMEM;
 984 
 985         ret = comedi_pci_enable(dev);
 986         if (ret)
 987                 return ret;
 988         pci_set_master(pcidev);
 989 
 990         dev->iobase = pci_resource_start(pcidev, 1);
 991         devpriv->amcc = pci_resource_start(pcidev, 0);
 992         devpriv->addon = pci_resource_start(pcidev, 2);
 993 
 994         apci3120_reset(dev);
 995 
 996         if (pcidev->irq > 0) {
 997                 ret = request_irq(pcidev->irq, apci3120_interrupt, IRQF_SHARED,
 998                                   dev->board_name, dev);
 999                 if (ret == 0) {
1000                         dev->irq = pcidev->irq;
1001 
1002                         apci3120_dma_alloc(dev);
1003                 }
1004         }
1005 
1006         status = inw(dev->iobase + APCI3120_STATUS_REG);
1007         if (APCI3120_STATUS_TO_VERSION(status) == APCI3120_REVB ||
1008             context == BOARD_APCI3001)
1009                 devpriv->osc_base = APCI3120_REVB_OSC_BASE;
1010         else
1011                 devpriv->osc_base = APCI3120_REVA_OSC_BASE;
1012 
1013         ret = comedi_alloc_subdevices(dev, 5);
1014         if (ret)
1015                 return ret;
1016 
1017         /* Analog Input subdevice */
1018         s = &dev->subdevices[0];
1019         s->type         = COMEDI_SUBD_AI;
1020         s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1021         s->n_chan       = 16;
1022         s->maxdata      = board->ai_is_16bit ? 0xffff : 0x0fff;
1023         s->range_table  = &apci3120_ai_range;
1024         s->insn_read    = apci3120_ai_insn_read;
1025         if (dev->irq) {
1026                 dev->read_subdev = s;
1027                 s->subdev_flags |= SDF_CMD_READ;
1028                 s->len_chanlist = s->n_chan;
1029                 s->do_cmdtest   = apci3120_ai_cmdtest;
1030                 s->do_cmd       = apci3120_ai_cmd;
1031                 s->cancel       = apci3120_cancel;
1032         }
1033 
1034         /* Analog Output subdevice */
1035         s = &dev->subdevices[1];
1036         if (board->has_ao) {
1037                 s->type         = COMEDI_SUBD_AO;
1038                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1039                 s->n_chan       = 8;
1040                 s->maxdata      = 0x3fff;
1041                 s->range_table  = &range_bipolar10;
1042                 s->insn_write   = apci3120_ao_insn_write;
1043 
1044                 ret = comedi_alloc_subdev_readback(s);
1045                 if (ret)
1046                         return ret;
1047         } else {
1048                 s->type         = COMEDI_SUBD_UNUSED;
1049         }
1050 
1051         /* Digital Input subdevice */
1052         s = &dev->subdevices[2];
1053         s->type         = COMEDI_SUBD_DI;
1054         s->subdev_flags = SDF_READABLE;
1055         s->n_chan       = 4;
1056         s->maxdata      = 1;
1057         s->range_table  = &range_digital;
1058         s->insn_bits    = apci3120_di_insn_bits;
1059 
1060         /* Digital Output subdevice */
1061         s = &dev->subdevices[3];
1062         s->type         = COMEDI_SUBD_DO;
1063         s->subdev_flags = SDF_WRITABLE;
1064         s->n_chan       = 4;
1065         s->maxdata      = 1;
1066         s->range_table  = &range_digital;
1067         s->insn_bits    = apci3120_do_insn_bits;
1068 
1069         /* Timer subdevice */
1070         s = &dev->subdevices[4];
1071         s->type         = COMEDI_SUBD_TIMER;
1072         s->subdev_flags = SDF_READABLE;
1073         s->n_chan       = 1;
1074         s->maxdata      = 0x00ffffff;
1075         s->insn_config  = apci3120_timer_insn_config;
1076         s->insn_read    = apci3120_timer_insn_read;
1077 
1078         return 0;
1079 }
1080 
1081 static void apci3120_detach(struct comedi_device *dev)
1082 {
1083         comedi_pci_detach(dev);
1084         apci3120_dma_free(dev);
1085 }
1086 
1087 static struct comedi_driver apci3120_driver = {
1088         .driver_name    = "addi_apci_3120",
1089         .module         = THIS_MODULE,
1090         .auto_attach    = apci3120_auto_attach,
1091         .detach         = apci3120_detach,
1092 };
1093 
1094 static int apci3120_pci_probe(struct pci_dev *dev,
1095                               const struct pci_device_id *id)
1096 {
1097         return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data);
1098 }
1099 
1100 static const struct pci_device_id apci3120_pci_table[] = {
1101         { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 },
1102         { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 },
1103         { 0 }
1104 };
1105 MODULE_DEVICE_TABLE(pci, apci3120_pci_table);
1106 
1107 static struct pci_driver apci3120_pci_driver = {
1108         .name           = "addi_apci_3120",
1109         .id_table       = apci3120_pci_table,
1110         .probe          = apci3120_pci_probe,
1111         .remove         = comedi_pci_auto_unconfig,
1112 };
1113 module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
1114 
1115 MODULE_AUTHOR("Comedi http://www.comedi.org");
1116 MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board");
1117 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */