linux/drivers/staging/comedi/drivers/amplc_dio200.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/amplc_dio200.c
   3    Driver for Amplicon PC272E and PCI272 DIO boards.
   4    (Support for other boards in Amplicon 200 series may be added at
   5    a later date, e.g. PCI215.)
   6
   7    Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/>
   8
   9    COMEDI - Linux Control and Measurement Device Interface
  10    Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
  11
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 2 of the License, or
  15    (at your option) any later version.
  16
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21
  22    You should have received a copy of the GNU General Public License
  23    along with this program; if not, write to the Free Software
  24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25
  26*/
  27/*
  28Driver: amplc_dio200
  29Description: Amplicon 200 Series Digital I/O
  30Author: Ian Abbott <abbotti@mev.co.uk>
  31Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
  32  PCI215 (pci215 or amplc_dio200), PC218E (pc218e), PC272E (pc272e),
  33  PCI272 (pci272 or amplc_dio200)
  34Updated: Wed, 22 Oct 2008 13:36:02 +0100
  35Status: works
  36
  37Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
  38  [0] - I/O port base address
  39  [1] - IRQ (optional, but commands won't work without it)
  40
  41Configuration options - PCI215, PCI272:
  42  [0] - PCI bus of device (optional)
  43  [1] - PCI slot of device (optional)
  44  If bus/slot is not specified, the first available PCI device will
  45  be used.
  46
  47Passing a zero for an option is the same as leaving it unspecified.
  48
  49SUBDEVICES
  50
  51                    PC218E         PC212E      PC215E/PCI215
  52                 -------------  -------------  -------------
  53  Subdevices           7              6              5
  54   0                 CTR-X1         PPI-X          PPI-X
  55   1                 CTR-X2         CTR-Y1         PPI-Y
  56   2                 CTR-Y1         CTR-Y2         CTR-Z1
  57   3                 CTR-Y2         CTR-Z1         CTR-Z2
  58   4                 CTR-Z1         CTR-Z2       INTERRUPT
  59   5                 CTR-Z2       INTERRUPT
  60   6               INTERRUPT
  61
  62                    PC214E      PC272E/PCI272
  63                 -------------  -------------
  64  Subdevices           4              4
  65   0                 PPI-X          PPI-X
  66   1                 PPI-Y          PPI-Y
  67   2                 CTR-Z1*        PPI-Z
  68   3               INTERRUPT*     INTERRUPT
  69
  70Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
  71are configurable as inputs or outputs in four groups:
  72
  73  Port A  - channels  0 to  7
  74  Port B  - channels  8 to 15
  75  Port CL - channels 16 to 19
  76  Port CH - channels 20 to 23
  77
  78Only mode 0 of the 8255 chips is supported.
  79
  80Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
  81channel is configured individually with INSN_CONFIG instructions.  The
  82specific type of configuration instruction is specified in data[0].
  83Some configuration instructions expect an additional parameter in
  84data[1]; others return a value in data[1].  The following configuration
  85instructions are supported:
  86
  87  INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
  88    BCD/binary setting specified in data[1].
  89
  90  INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
  91    counter channel into data[1].
  92
  93  INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
  94    specified in data[1] (this is a hardware-specific value).  Not
  95    supported on PC214E.  For the other boards, valid clock sources are
  96    0 to 7 as follows:
  97
  98      0.  CLK n, the counter channel's dedicated CLK input from the SK1
  99        connector.  (N.B. for other values, the counter channel's CLKn
 100        pin on the SK1 connector is an output!)
 101      1.  Internal 10 MHz clock.
 102      2.  Internal 1 MHz clock.
 103      3.  Internal 100 kHz clock.
 104      4.  Internal 10 kHz clock.
 105      5.  Internal 1 kHz clock.
 106      6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
 107      7.  Ext Clock, the counter chip's dedicated Ext Clock input from
 108        the SK1 connector.  This pin is shared by all three counter
 109        channels on the chip.
 110
 111  INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
 112    clock source in data[1].  For internal clock sources, data[2] is set
 113    to the period in ns.
 114
 115  INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
 116    specified in data[2] (this is a hardware-specific value).  Not
 117    supported on PC214E.  For the other boards, valid gate sources are 0
 118    to 7 as follows:
 119
 120      0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
 121      1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
 122      2.  GAT n, the counter channel's dedicated GAT input from the SK1
 123        connector.  (N.B. for other values, the counter channel's GATn
 124        pin on the SK1 connector is an output!)
 125      3.  /OUT n-2, the inverted output of counter channel n-2 (see note
 126        2 below).
 127      4.  Reserved.
 128      5.  Reserved.
 129      6.  Reserved.
 130      7.  Reserved.
 131
 132  INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
 133    source in data[2].
 134
 135Clock and gate interconnection notes:
 136
 137  1.  Clock source OUT n-1 is the output of the preceding channel on the
 138  same counter subdevice if n > 0, or the output of channel 2 on the
 139  preceding counter subdevice (see note 3) if n = 0.
 140
 141  2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
 142  same counter subdevice if n = 2, or the inverted output of channel n+1
 143  on the preceding counter subdevice (see note 3) if n < 2.
 144
 145  3.  The counter subdevices are connected in a ring, so the highest
 146  counter subdevice precedes the lowest.
 147
 148The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
 149digital inputs come from the interrupt status register.  The number of
 150channels matches the number of interrupt sources.  The PC214E does not
 151have an interrupt status register; see notes on 'INTERRUPT SOURCES'
 152below.
 153
 154INTERRUPT SOURCES
 155
 156                    PC218E         PC212E      PC215E/PCI215
 157                 -------------  -------------  -------------
 158  Sources              6              6              6
 159   0              CTR-X1-OUT      PPI-X-C0       PPI-X-C0
 160   1              CTR-X2-OUT      PPI-X-C3       PPI-X-C3
 161   2              CTR-Y1-OUT     CTR-Y1-OUT      PPI-Y-C0
 162   3              CTR-Y2-OUT     CTR-Y2-OUT      PPI-Y-C3
 163   4              CTR-Z1-OUT     CTR-Z1-OUT     CTR-Z1-OUT
 164   5              CTR-Z2-OUT     CTR-Z2-OUT     CTR-Z2-OUT
 165
 166                    PC214E      PC272E/PCI272
 167                 -------------  -------------
 168  Sources              1              6
 169   0               JUMPER-J5      PPI-X-C0
 170   1                              PPI-X-C3
 171   2                              PPI-Y-C0
 172   3                              PPI-Y-C3
 173   4                              PPI-Z-C0
 174   5                              PPI-Z-C3
 175
 176When an interrupt source is enabled in the interrupt source enable
 177register, a rising edge on the source signal latches the corresponding
 178bit to 1 in the interrupt status register.
 179
 180When the interrupt status register value as a whole (actually, just the
 1816 least significant bits) goes from zero to non-zero, the board will
 182generate an interrupt.  For level-triggered hardware interrupts (PCI
 183card), the interrupt will remain asserted until the interrupt status
 184register is cleared to zero.  For edge-triggered hardware interrupts
 185(ISA card), no further interrupts will occur until the interrupt status
 186register is cleared to zero.  To clear a bit to zero in the interrupt
 187status register, the corresponding interrupt source must be disabled
 188in the interrupt source enable register (there is no separate interrupt
 189clear register).
 190
 191The PC214E does not have an interrupt source enable register or an
 192interrupt status register; its 'INTERRUPT' subdevice has a single
 193channel and its interrupt source is selected by the position of jumper
 194J5.
 195
 196COMMANDS
 197
 198The driver supports a read streaming acquisition command on the
 199'INTERRUPT' subdevice.  The channel list selects the interrupt sources
 200to be enabled.  All channels will be sampled together (convert_src ==
 201TRIG_NOW).  The scan begins a short time after the hardware interrupt
 202occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
 203scan_begin_arg == 0).  The value read from the interrupt status register
 204is packed into a short value, one bit per requested channel, in the
 205order they appear in the channel list.
 206*/
 207
 208#include <linux/interrupt.h>
 209
 210#include "../comedidev.h"
 211
 212#include "comedi_pci.h"
 213
 214#include "8255.h"
 215#include "8253.h"
 216
 217#define DIO200_DRIVER_NAME      "amplc_dio200"
 218
 219/* PCI IDs */
 220/* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
 221#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
 222#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
 223#define PCI_DEVICE_ID_INVALID 0xffff
 224
 225/* 200 series registers */
 226#define DIO200_IO_SIZE          0x20
 227#define DIO200_XCLK_SCE         0x18    /* Group X clock selection register */
 228#define DIO200_YCLK_SCE         0x19    /* Group Y clock selection register */
 229#define DIO200_ZCLK_SCE         0x1a    /* Group Z clock selection register */
 230#define DIO200_XGAT_SCE         0x1b    /* Group X gate selection register */
 231#define DIO200_YGAT_SCE         0x1c    /* Group Y gate selection register */
 232#define DIO200_ZGAT_SCE         0x1d    /* Group Z gate selection register */
 233#define DIO200_INT_SCE          0x1e    /* Interrupt enable/status register */
 234
 235/*
 236 * Macros for constructing value for DIO_200_?CLK_SCE and
 237 * DIO_200_?GAT_SCE registers:
 238 *
 239 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
 240 * 'chan' is the channel: 0, 1 or 2.
 241 * 'source' is the signal source: 0 to 7.
 242 */
 243#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
 244#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
 245
 246/*
 247 * Periods of the internal clock sources in nanoseconds.
 248 */
 249static const unsigned clock_period[8] = {
 250        0,                      /* dedicated clock input/output pin */
 251        100,                    /* 10 MHz */
 252        1000,                   /* 1 MHz */
 253        10000,                  /* 100 kHz */
 254        100000,                 /* 10 kHz */
 255        1000000,                /* 1 kHz */
 256        0,                      /* OUT N-1 */
 257        0                       /* group clock input pin */
 258};
 259
 260/*
 261 * Board descriptions.
 262 */
 263
 264enum dio200_bustype { isa_bustype, pci_bustype };
 265
 266enum dio200_model {
 267        pc212e_model,
 268        pc214e_model,
 269        pc215e_model, pci215_model,
 270        pc218e_model,
 271        pc272e_model, pci272_model,
 272        anypci_model
 273};
 274
 275enum dio200_layout {
 276        pc212_layout,
 277        pc214_layout,
 278        pc215_layout,
 279        pc218_layout,
 280        pc272_layout
 281};
 282
 283struct dio200_board {
 284        const char *name;
 285        unsigned short devid;
 286        enum dio200_bustype bustype;
 287        enum dio200_model model;
 288        enum dio200_layout layout;
 289};
 290
 291static const struct dio200_board dio200_boards[] = {
 292        {
 293         .name = "pc212e",
 294         .bustype = isa_bustype,
 295         .model = pc212e_model,
 296         .layout = pc212_layout,
 297         },
 298        {
 299         .name = "pc214e",
 300         .bustype = isa_bustype,
 301         .model = pc214e_model,
 302         .layout = pc214_layout,
 303         },
 304        {
 305         .name = "pc215e",
 306         .bustype = isa_bustype,
 307         .model = pc215e_model,
 308         .layout = pc215_layout,
 309         },
 310#ifdef CONFIG_COMEDI_PCI
 311        {
 312         .name = "pci215",
 313         .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
 314         .bustype = pci_bustype,
 315         .model = pci215_model,
 316         .layout = pc215_layout,
 317         },
 318#endif
 319        {
 320         .name = "pc218e",
 321         .bustype = isa_bustype,
 322         .model = pc218e_model,
 323         .layout = pc218_layout,
 324         },
 325        {
 326         .name = "pc272e",
 327         .bustype = isa_bustype,
 328         .model = pc272e_model,
 329         .layout = pc272_layout,
 330         },
 331#ifdef CONFIG_COMEDI_PCI
 332        {
 333         .name = "pci272",
 334         .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
 335         .bustype = pci_bustype,
 336         .model = pci272_model,
 337         .layout = pc272_layout,
 338         },
 339#endif
 340#ifdef CONFIG_COMEDI_PCI
 341        {
 342         .name = DIO200_DRIVER_NAME,
 343         .devid = PCI_DEVICE_ID_INVALID,
 344         .bustype = pci_bustype,
 345         .model = anypci_model, /* wildcard */
 346         },
 347#endif
 348};
 349
 350/*
 351 * Layout descriptions - some ISA and PCI board descriptions share the same
 352 * layout.
 353 */
 354
 355enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
 356
 357#define DIO200_MAX_SUBDEVS      7
 358#define DIO200_MAX_ISNS         6
 359
 360struct dio200_layout_struct {
 361        unsigned short n_subdevs;       /* number of subdevices */
 362        unsigned char sdtype[DIO200_MAX_SUBDEVS];       /* enum dio200_sdtype */
 363        unsigned char sdinfo[DIO200_MAX_SUBDEVS];       /* depends on sdtype */
 364        char has_int_sce;       /* has interrupt enable/status register */
 365        char has_clk_gat_sce;   /* has clock/gate selection registers */
 366};
 367
 368static const struct dio200_layout_struct dio200_layouts[] = {
 369        [pc212_layout] = {
 370                          .n_subdevs = 6,
 371                          .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
 372                                     sd_8254,
 373                                     sd_intr},
 374                          .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
 375                                     0x3F},
 376                          .has_int_sce = 1,
 377                          .has_clk_gat_sce = 1,
 378                          },
 379        [pc214_layout] = {
 380                          .n_subdevs = 4,
 381                          .sdtype = {sd_8255, sd_8255, sd_8254,
 382                                     sd_intr},
 383                          .sdinfo = {0x00, 0x08, 0x10, 0x01},
 384                          .has_int_sce = 0,
 385                          .has_clk_gat_sce = 0,
 386                          },
 387        [pc215_layout] = {
 388                          .n_subdevs = 5,
 389                          .sdtype = {sd_8255, sd_8255, sd_8254,
 390                                     sd_8254,
 391                                     sd_intr},
 392                          .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
 393                          .has_int_sce = 1,
 394                          .has_clk_gat_sce = 1,
 395                          },
 396        [pc218_layout] = {
 397                          .n_subdevs = 7,
 398                          .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
 399                                     sd_8254,
 400                                     sd_intr},
 401                          .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
 402                                     0x14,
 403                                     0x3F},
 404                          .has_int_sce = 1,
 405                          .has_clk_gat_sce = 1,
 406                          },
 407        [pc272_layout] = {
 408                          .n_subdevs = 4,
 409                          .sdtype = {sd_8255, sd_8255, sd_8255,
 410                                     sd_intr},
 411                          .sdinfo = {0x00, 0x08, 0x10, 0x3F},
 412                          .has_int_sce = 1,
 413                          .has_clk_gat_sce = 0,
 414                          },
 415};
 416
 417/*
 418 * PCI driver table.
 419 */
 420
 421#ifdef CONFIG_COMEDI_PCI
 422static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
 423        {
 424        PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215,
 425                    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 426        PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272,
 427                    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 428        0}
 429};
 430
 431MODULE_DEVICE_TABLE(pci, dio200_pci_table);
 432#endif /* CONFIG_COMEDI_PCI */
 433
 434/*
 435 * Useful for shorthand access to the particular board structure
 436 */
 437#define thisboard ((const struct dio200_board *)dev->board_ptr)
 438#define thislayout (&dio200_layouts[((struct dio200_board *)dev->board_ptr)->layout])
 439
 440/* this structure is for data unique to this hardware driver.  If
 441   several hardware drivers keep similar information in this structure,
 442   feel free to suggest moving the variable to the struct comedi_device struct.  */
 443struct dio200_private {
 444#ifdef CONFIG_COMEDI_PCI
 445        struct pci_dev *pci_dev;        /* PCI device */
 446#endif
 447        int intr_sd;
 448};
 449
 450#define devpriv ((struct dio200_private *)dev->private)
 451
 452struct dio200_subdev_8254 {
 453        unsigned long iobase;   /* Counter base address */
 454        unsigned long clk_sce_iobase;   /* CLK_SCE base address */
 455        unsigned long gat_sce_iobase;   /* GAT_SCE base address */
 456        int which;              /* Bit 5 of CLK_SCE or GAT_SCE */
 457        int has_clk_gat_sce;
 458        unsigned clock_src[3];  /* Current clock sources */
 459        unsigned gate_src[3];   /* Current gate sources */
 460};
 461
 462struct dio200_subdev_intr {
 463        unsigned long iobase;
 464        spinlock_t spinlock;
 465        int active;
 466        int has_int_sce;
 467        unsigned int valid_isns;
 468        unsigned int enabled_isns;
 469        unsigned int stopcount;
 470        int continuous;
 471};
 472
 473/*
 474 * The struct comedi_driver structure tells the Comedi core module
 475 * which functions to call to configure/deconfigure (attach/detach)
 476 * the board, and also about the kernel module that contains
 477 * the device code.
 478 */
 479static int dio200_attach(struct comedi_device *dev,
 480                         struct comedi_devconfig *it);
 481static int dio200_detach(struct comedi_device *dev);
 482static struct comedi_driver driver_amplc_dio200 = {
 483        .driver_name = DIO200_DRIVER_NAME,
 484        .module = THIS_MODULE,
 485        .attach = dio200_attach,
 486        .detach = dio200_detach,
 487        .board_name = &dio200_boards[0].name,
 488        .offset = sizeof(struct dio200_board),
 489        .num_names = ARRAY_SIZE(dio200_boards),
 490};
 491
 492#ifdef CONFIG_COMEDI_PCI
 493COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table);
 494#else
 495COMEDI_INITCLEANUP(driver_amplc_dio200);
 496#endif
 497
 498/*
 499 * This function looks for a PCI device matching the requested board name,
 500 * bus and slot.
 501 */
 502#ifdef CONFIG_COMEDI_PCI
 503static int
 504dio200_find_pci(struct comedi_device *dev, int bus, int slot,
 505                struct pci_dev **pci_dev_p)
 506{
 507        struct pci_dev *pci_dev = NULL;
 508
 509        *pci_dev_p = NULL;
 510
 511        /* Look for matching PCI device. */
 512        for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
 513             pci_dev != NULL;
 514             pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
 515                                      PCI_ANY_ID, pci_dev)) {
 516                /* If bus/slot specified, check them. */
 517                if (bus || slot) {
 518                        if (bus != pci_dev->bus->number
 519                            || slot != PCI_SLOT(pci_dev->devfn))
 520                                continue;
 521                }
 522                if (thisboard->model == anypci_model) {
 523                        /* Match any supported model. */
 524                        int i;
 525
 526                        for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
 527                                if (dio200_boards[i].bustype != pci_bustype)
 528                                        continue;
 529                                if (pci_dev->device == dio200_boards[i].devid) {
 530                                        /* Change board_ptr to matched board. */
 531                                        dev->board_ptr = &dio200_boards[i];
 532                                        break;
 533                                }
 534                        }
 535                        if (i == ARRAY_SIZE(dio200_boards))
 536                                continue;
 537                } else {
 538                        /* Match specific model name. */
 539                        if (pci_dev->device != thisboard->devid)
 540                                continue;
 541                }
 542
 543                /* Found a match. */
 544                *pci_dev_p = pci_dev;
 545                return 0;
 546        }
 547        /* No match found. */
 548        if (bus || slot) {
 549                printk(KERN_ERR
 550                       "comedi%d: error! no %s found at pci %02x:%02x!\n",
 551                       dev->minor, thisboard->name, bus, slot);
 552        } else {
 553                printk(KERN_ERR "comedi%d: error! no %s found!\n",
 554                       dev->minor, thisboard->name);
 555        }
 556        return -EIO;
 557}
 558#endif
 559
 560/*
 561 * This function checks and requests an I/O region, reporting an error
 562 * if there is a conflict.
 563 */
 564static int
 565dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
 566{
 567        if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
 568                printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
 569                       minor, from, extent);
 570                return -EIO;
 571        }
 572        return 0;
 573}
 574
 575/*
 576 * 'insn_bits' function for an 'INTERRUPT' subdevice.
 577 */
 578static int
 579dio200_subdev_intr_insn_bits(struct comedi_device *dev,
 580                             struct comedi_subdevice *s,
 581                             struct comedi_insn *insn, unsigned int *data)
 582{
 583        struct dio200_subdev_intr *subpriv = s->private;
 584
 585        if (subpriv->has_int_sce) {
 586                /* Just read the interrupt status register.  */
 587                data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
 588        } else {
 589                /* No interrupt status register. */
 590                data[0] = 0;
 591        }
 592
 593        return 2;
 594}
 595
 596/*
 597 * Called to stop acquisition for an 'INTERRUPT' subdevice.
 598 */
 599static void dio200_stop_intr(struct comedi_device *dev,
 600                             struct comedi_subdevice *s)
 601{
 602        struct dio200_subdev_intr *subpriv = s->private;
 603
 604        subpriv->active = 0;
 605        subpriv->enabled_isns = 0;
 606        if (subpriv->has_int_sce) {
 607                outb(0, subpriv->iobase);
 608        }
 609}
 610
 611/*
 612 * Called to start acquisition for an 'INTERRUPT' subdevice.
 613 */
 614static int dio200_start_intr(struct comedi_device *dev,
 615                             struct comedi_subdevice *s)
 616{
 617        unsigned int n;
 618        unsigned isn_bits;
 619        struct dio200_subdev_intr *subpriv = s->private;
 620        struct comedi_cmd *cmd = &s->async->cmd;
 621        int retval = 0;
 622
 623        if (!subpriv->continuous && subpriv->stopcount == 0) {
 624                /* An empty acquisition! */
 625                s->async->events |= COMEDI_CB_EOA;
 626                subpriv->active = 0;
 627                retval = 1;
 628        } else {
 629                /* Determine interrupt sources to enable. */
 630                isn_bits = 0;
 631                if (cmd->chanlist) {
 632                        for (n = 0; n < cmd->chanlist_len; n++) {
 633                                isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
 634                        }
 635                }
 636                isn_bits &= subpriv->valid_isns;
 637                /* Enable interrupt sources. */
 638                subpriv->enabled_isns = isn_bits;
 639                if (subpriv->has_int_sce) {
 640                        outb(isn_bits, subpriv->iobase);
 641                }
 642        }
 643
 644        return retval;
 645}
 646
 647/*
 648 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
 649 */
 650static int
 651dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
 652                          unsigned int trignum)
 653{
 654        struct dio200_subdev_intr *subpriv;
 655        unsigned long flags;
 656        int event = 0;
 657
 658        if (trignum != 0)
 659                return -EINVAL;
 660
 661        subpriv = s->private;
 662
 663        spin_lock_irqsave(&subpriv->spinlock, flags);
 664        s->async->inttrig = 0;
 665        if (subpriv->active) {
 666                event = dio200_start_intr(dev, s);
 667        }
 668        spin_unlock_irqrestore(&subpriv->spinlock, flags);
 669
 670        if (event) {
 671                comedi_event(dev, s);
 672        }
 673
 674        return 1;
 675}
 676
 677/*
 678 * This is called from the interrupt service routine to handle a read
 679 * scan on an 'INTERRUPT' subdevice.
 680 */
 681static int dio200_handle_read_intr(struct comedi_device *dev,
 682                                   struct comedi_subdevice *s)
 683{
 684        struct dio200_subdev_intr *subpriv = s->private;
 685        unsigned triggered;
 686        unsigned intstat;
 687        unsigned cur_enabled;
 688        unsigned int oldevents;
 689        unsigned long flags;
 690
 691        triggered = 0;
 692
 693        spin_lock_irqsave(&subpriv->spinlock, flags);
 694        oldevents = s->async->events;
 695        if (subpriv->has_int_sce) {
 696                /*
 697                 * Collect interrupt sources that have triggered and disable
 698                 * them temporarily.  Loop around until no extra interrupt
 699                 * sources have triggered, at which point, the valid part of
 700                 * the interrupt status register will read zero, clearing the
 701                 * cause of the interrupt.
 702                 *
 703                 * Mask off interrupt sources already seen to avoid infinite
 704                 * loop in case of misconfiguration.
 705                 */
 706                cur_enabled = subpriv->enabled_isns;
 707                while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
 708                                   & ~triggered)) != 0) {
 709                        triggered |= intstat;
 710                        cur_enabled &= ~triggered;
 711                        outb(cur_enabled, subpriv->iobase);
 712                }
 713        } else {
 714                /*
 715                 * No interrupt status register.  Assume the single interrupt
 716                 * source has triggered.
 717                 */
 718                triggered = subpriv->enabled_isns;
 719        }
 720
 721        if (triggered) {
 722                /*
 723                 * Some interrupt sources have triggered and have been
 724                 * temporarily disabled to clear the cause of the interrupt.
 725                 *
 726                 * Reenable them NOW to minimize the time they are disabled.
 727                 */
 728                cur_enabled = subpriv->enabled_isns;
 729                if (subpriv->has_int_sce) {
 730                        outb(cur_enabled, subpriv->iobase);
 731                }
 732
 733                if (subpriv->active) {
 734                        /*
 735                         * The command is still active.
 736                         *
 737                         * Ignore interrupt sources that the command isn't
 738                         * interested in (just in case there's a race
 739                         * condition).
 740                         */
 741                        if (triggered & subpriv->enabled_isns) {
 742                                /* Collect scan data. */
 743                                short val;
 744                                unsigned int n, ch, len;
 745
 746                                val = 0;
 747                                len = s->async->cmd.chanlist_len;
 748                                for (n = 0; n < len; n++) {
 749                                        ch = CR_CHAN(s->async->cmd.chanlist[n]);
 750                                        if (triggered & (1U << ch)) {
 751                                                val |= (1U << n);
 752                                        }
 753                                }
 754                                /* Write the scan to the buffer. */
 755                                if (comedi_buf_put(s->async, val)) {
 756                                        s->async->events |= (COMEDI_CB_BLOCK |
 757                                                             COMEDI_CB_EOS);
 758                                } else {
 759                                        /* Error!  Stop acquisition.  */
 760                                        dio200_stop_intr(dev, s);
 761                                        s->async->events |= COMEDI_CB_ERROR
 762                                            | COMEDI_CB_OVERFLOW;
 763                                        comedi_error(dev, "buffer overflow");
 764                                }
 765
 766                                /* Check for end of acquisition. */
 767                                if (!subpriv->continuous) {
 768                                        /* stop_src == TRIG_COUNT */
 769                                        if (subpriv->stopcount > 0) {
 770                                                subpriv->stopcount--;
 771                                                if (subpriv->stopcount == 0) {
 772                                                        s->async->events |=
 773                                                            COMEDI_CB_EOA;
 774                                                        dio200_stop_intr(dev,
 775                                                                         s);
 776                                                }
 777                                        }
 778                                }
 779                        }
 780                }
 781        }
 782        spin_unlock_irqrestore(&subpriv->spinlock, flags);
 783
 784        if (oldevents != s->async->events) {
 785                comedi_event(dev, s);
 786        }
 787
 788        return (triggered != 0);
 789}
 790
 791/*
 792 * 'cancel' function for an 'INTERRUPT' subdevice.
 793 */
 794static int dio200_subdev_intr_cancel(struct comedi_device *dev,
 795                                     struct comedi_subdevice *s)
 796{
 797        struct dio200_subdev_intr *subpriv = s->private;
 798        unsigned long flags;
 799
 800        spin_lock_irqsave(&subpriv->spinlock, flags);
 801        if (subpriv->active) {
 802                dio200_stop_intr(dev, s);
 803        }
 804        spin_unlock_irqrestore(&subpriv->spinlock, flags);
 805
 806        return 0;
 807}
 808
 809/*
 810 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
 811 */
 812static int
 813dio200_subdev_intr_cmdtest(struct comedi_device *dev,
 814                           struct comedi_subdevice *s, struct comedi_cmd *cmd)
 815{
 816        int err = 0;
 817        unsigned int tmp;
 818
 819        /* step 1: make sure trigger sources are trivially valid */
 820
 821        tmp = cmd->start_src;
 822        cmd->start_src &= (TRIG_NOW | TRIG_INT);
 823        if (!cmd->start_src || tmp != cmd->start_src)
 824                err++;
 825
 826        tmp = cmd->scan_begin_src;
 827        cmd->scan_begin_src &= TRIG_EXT;
 828        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
 829                err++;
 830
 831        tmp = cmd->convert_src;
 832        cmd->convert_src &= TRIG_NOW;
 833        if (!cmd->convert_src || tmp != cmd->convert_src)
 834                err++;
 835
 836        tmp = cmd->scan_end_src;
 837        cmd->scan_end_src &= TRIG_COUNT;
 838        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
 839                err++;
 840
 841        tmp = cmd->stop_src;
 842        cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
 843        if (!cmd->stop_src || tmp != cmd->stop_src)
 844                err++;
 845
 846        if (err)
 847                return 1;
 848
 849        /* step 2: make sure trigger sources are unique and mutually compatible */
 850
 851        /* these tests are true if more than one _src bit is set */
 852        if ((cmd->start_src & (cmd->start_src - 1)) != 0)
 853                err++;
 854        if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
 855                err++;
 856        if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
 857                err++;
 858        if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
 859                err++;
 860        if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
 861                err++;
 862
 863        if (err)
 864                return 2;
 865
 866        /* step 3: make sure arguments are trivially compatible */
 867
 868        /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
 869        if (cmd->start_arg != 0) {
 870                cmd->start_arg = 0;
 871                err++;
 872        }
 873
 874        /* cmd->scan_begin_src == TRIG_EXT */
 875        if (cmd->scan_begin_arg != 0) {
 876                cmd->scan_begin_arg = 0;
 877                err++;
 878        }
 879
 880        /* cmd->convert_src == TRIG_NOW */
 881        if (cmd->convert_arg != 0) {
 882                cmd->convert_arg = 0;
 883                err++;
 884        }
 885
 886        /* cmd->scan_end_src == TRIG_COUNT */
 887        if (cmd->scan_end_arg != cmd->chanlist_len) {
 888                cmd->scan_end_arg = cmd->chanlist_len;
 889                err++;
 890        }
 891
 892        switch (cmd->stop_src) {
 893        case TRIG_COUNT:
 894                /* any count allowed */
 895                break;
 896        case TRIG_NONE:
 897                if (cmd->stop_arg != 0) {
 898                        cmd->stop_arg = 0;
 899                        err++;
 900                }
 901                break;
 902        default:
 903                break;
 904        }
 905
 906        if (err)
 907                return 3;
 908
 909        /* step 4: fix up any arguments */
 910
 911        /* if (err) return 4; */
 912
 913        return 0;
 914}
 915
 916/*
 917 * 'do_cmd' function for an 'INTERRUPT' subdevice.
 918 */
 919static int dio200_subdev_intr_cmd(struct comedi_device *dev,
 920                                  struct comedi_subdevice *s)
 921{
 922        struct comedi_cmd *cmd = &s->async->cmd;
 923        struct dio200_subdev_intr *subpriv = s->private;
 924        unsigned long flags;
 925        int event = 0;
 926
 927        spin_lock_irqsave(&subpriv->spinlock, flags);
 928        subpriv->active = 1;
 929
 930        /* Set up end of acquisition. */
 931        switch (cmd->stop_src) {
 932        case TRIG_COUNT:
 933                subpriv->continuous = 0;
 934                subpriv->stopcount = cmd->stop_arg;
 935                break;
 936        default:
 937                /* TRIG_NONE */
 938                subpriv->continuous = 1;
 939                subpriv->stopcount = 0;
 940                break;
 941        }
 942
 943        /* Set up start of acquisition. */
 944        switch (cmd->start_src) {
 945        case TRIG_INT:
 946                s->async->inttrig = dio200_inttrig_start_intr;
 947                break;
 948        default:
 949                /* TRIG_NOW */
 950                event = dio200_start_intr(dev, s);
 951                break;
 952        }
 953        spin_unlock_irqrestore(&subpriv->spinlock, flags);
 954
 955        if (event) {
 956                comedi_event(dev, s);
 957        }
 958
 959        return 0;
 960}
 961
 962/*
 963 * This function initializes an 'INTERRUPT' subdevice.
 964 */
 965static int
 966dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
 967                        unsigned long iobase, unsigned valid_isns,
 968                        int has_int_sce)
 969{
 970        struct dio200_subdev_intr *subpriv;
 971
 972        subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
 973        if (!subpriv) {
 974                printk(KERN_ERR "comedi%d: error! out of memory!\n",
 975                       dev->minor);
 976                return -ENOMEM;
 977        }
 978        subpriv->iobase = iobase;
 979        subpriv->has_int_sce = has_int_sce;
 980        subpriv->valid_isns = valid_isns;
 981        spin_lock_init(&subpriv->spinlock);
 982
 983        if (has_int_sce) {
 984                outb(0, subpriv->iobase);       /* Disable interrupt sources. */
 985        }
 986
 987        s->private = subpriv;
 988        s->type = COMEDI_SUBD_DI;
 989        s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
 990        if (has_int_sce) {
 991                s->n_chan = DIO200_MAX_ISNS;
 992                s->len_chanlist = DIO200_MAX_ISNS;
 993        } else {
 994                /* No interrupt source register.  Support single channel. */
 995                s->n_chan = 1;
 996                s->len_chanlist = 1;
 997        }
 998        s->range_table = &range_digital;
 999        s->maxdata = 1;
1000        s->insn_bits = dio200_subdev_intr_insn_bits;
1001        s->do_cmdtest = dio200_subdev_intr_cmdtest;
1002        s->do_cmd = dio200_subdev_intr_cmd;
1003        s->cancel = dio200_subdev_intr_cancel;
1004
1005        return 0;
1006}
1007
1008/*
1009 * This function cleans up an 'INTERRUPT' subdevice.
1010 */
1011static void
1012dio200_subdev_intr_cleanup(struct comedi_device *dev,
1013                           struct comedi_subdevice *s)
1014{
1015        struct dio200_subdev_intr *subpriv = s->private;
1016
1017        if (subpriv) {
1018                kfree(subpriv);
1019        }
1020}
1021
1022/*
1023 * Interrupt service routine.
1024 */
1025static irqreturn_t dio200_interrupt(int irq, void *d)
1026{
1027        struct comedi_device *dev = d;
1028        int handled;
1029
1030        if (!dev->attached) {
1031                return IRQ_NONE;
1032        }
1033
1034        if (devpriv->intr_sd >= 0) {
1035                handled = dio200_handle_read_intr(dev,
1036                                                  dev->subdevices +
1037                                                  devpriv->intr_sd);
1038        } else {
1039                handled = 0;
1040        }
1041
1042        return IRQ_RETVAL(handled);
1043}
1044
1045/*
1046 * Handle 'insn_read' for an '8254' counter subdevice.
1047 */
1048static int
1049dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
1050                        struct comedi_insn *insn, unsigned int *data)
1051{
1052        struct dio200_subdev_8254 *subpriv = s->private;
1053        int chan = CR_CHAN(insn->chanspec);
1054
1055        data[0] = i8254_read(subpriv->iobase, 0, chan);
1056
1057        return 1;
1058}
1059
1060/*
1061 * Handle 'insn_write' for an '8254' counter subdevice.
1062 */
1063static int
1064dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
1065                         struct comedi_insn *insn, unsigned int *data)
1066{
1067        struct dio200_subdev_8254 *subpriv = s->private;
1068        int chan = CR_CHAN(insn->chanspec);
1069
1070        i8254_write(subpriv->iobase, 0, chan, data[0]);
1071
1072        return 1;
1073}
1074
1075/*
1076 * Set gate source for an '8254' counter subdevice channel.
1077 */
1078static int
1079dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1080                    unsigned int counter_number, unsigned int gate_src)
1081{
1082        unsigned char byte;
1083
1084        if (!subpriv->has_clk_gat_sce)
1085                return -1;
1086        if (counter_number > 2)
1087                return -1;
1088        if (gate_src > 7)
1089                return -1;
1090
1091        subpriv->gate_src[counter_number] = gate_src;
1092        byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1093        outb(byte, subpriv->gat_sce_iobase);
1094
1095        return 0;
1096}
1097
1098/*
1099 * Get gate source for an '8254' counter subdevice channel.
1100 */
1101static int
1102dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1103                    unsigned int counter_number)
1104{
1105        if (!subpriv->has_clk_gat_sce)
1106                return -1;
1107        if (counter_number > 2)
1108                return -1;
1109
1110        return subpriv->gate_src[counter_number];
1111}
1112
1113/*
1114 * Set clock source for an '8254' counter subdevice channel.
1115 */
1116static int
1117dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1118                     unsigned int counter_number, unsigned int clock_src)
1119{
1120        unsigned char byte;
1121
1122        if (!subpriv->has_clk_gat_sce)
1123                return -1;
1124        if (counter_number > 2)
1125                return -1;
1126        if (clock_src > 7)
1127                return -1;
1128
1129        subpriv->clock_src[counter_number] = clock_src;
1130        byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1131        outb(byte, subpriv->clk_sce_iobase);
1132
1133        return 0;
1134}
1135
1136/*
1137 * Get clock source for an '8254' counter subdevice channel.
1138 */
1139static int
1140dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1141                     unsigned int counter_number, unsigned int *period_ns)
1142{
1143        unsigned clock_src;
1144
1145        if (!subpriv->has_clk_gat_sce)
1146                return -1;
1147        if (counter_number > 2)
1148                return -1;
1149
1150        clock_src = subpriv->clock_src[counter_number];
1151        *period_ns = clock_period[clock_src];
1152        return clock_src;
1153}
1154
1155/*
1156 * Handle 'insn_config' for an '8254' counter subdevice.
1157 */
1158static int
1159dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1160                          struct comedi_insn *insn, unsigned int *data)
1161{
1162        struct dio200_subdev_8254 *subpriv = s->private;
1163        int ret;
1164        int chan = CR_CHAN(insn->chanspec);
1165
1166        switch (data[0]) {
1167        case INSN_CONFIG_SET_COUNTER_MODE:
1168                ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1169                if (ret < 0)
1170                        return -EINVAL;
1171                break;
1172        case INSN_CONFIG_8254_READ_STATUS:
1173                data[1] = i8254_status(subpriv->iobase, 0, chan);
1174                break;
1175        case INSN_CONFIG_SET_GATE_SRC:
1176                ret = dio200_set_gate_src(subpriv, chan, data[2]);
1177                if (ret < 0)
1178                        return -EINVAL;
1179                break;
1180        case INSN_CONFIG_GET_GATE_SRC:
1181                ret = dio200_get_gate_src(subpriv, chan);
1182                if (ret < 0)
1183                        return -EINVAL;
1184                data[2] = ret;
1185                break;
1186        case INSN_CONFIG_SET_CLOCK_SRC:
1187                ret = dio200_set_clock_src(subpriv, chan, data[1]);
1188                if (ret < 0)
1189                        return -EINVAL;
1190                break;
1191        case INSN_CONFIG_GET_CLOCK_SRC:
1192                ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1193                if (ret < 0)
1194                        return -EINVAL;
1195                data[1] = ret;
1196                break;
1197        default:
1198                return -EINVAL;
1199                break;
1200        }
1201        return insn->n;
1202}
1203
1204/*
1205 * This function initializes an '8254' counter subdevice.
1206 *
1207 * Note: iobase is the base address of the board, not the subdevice;
1208 * offset is the offset to the 8254 chip.
1209 */
1210static int
1211dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
1212                        unsigned long iobase, unsigned offset,
1213                        int has_clk_gat_sce)
1214{
1215        struct dio200_subdev_8254 *subpriv;
1216        unsigned int chan;
1217
1218        subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1219        if (!subpriv) {
1220                printk(KERN_ERR "comedi%d: error! out of memory!\n",
1221                       dev->minor);
1222                return -ENOMEM;
1223        }
1224
1225        s->private = subpriv;
1226        s->type = COMEDI_SUBD_COUNTER;
1227        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1228        s->n_chan = 3;
1229        s->maxdata = 0xFFFF;
1230        s->insn_read = dio200_subdev_8254_read;
1231        s->insn_write = dio200_subdev_8254_write;
1232        s->insn_config = dio200_subdev_8254_config;
1233
1234        subpriv->iobase = offset + iobase;
1235        subpriv->has_clk_gat_sce = has_clk_gat_sce;
1236        if (has_clk_gat_sce) {
1237                /* Derive CLK_SCE and GAT_SCE register offsets from
1238                 * 8254 offset. */
1239                subpriv->clk_sce_iobase =
1240                    DIO200_XCLK_SCE + (offset >> 3) + iobase;
1241                subpriv->gat_sce_iobase =
1242                    DIO200_XGAT_SCE + (offset >> 3) + iobase;
1243                subpriv->which = (offset >> 2) & 1;
1244        }
1245
1246        /* Initialize channels. */
1247        for (chan = 0; chan < 3; chan++) {
1248                i8254_set_mode(subpriv->iobase, 0, chan,
1249                               I8254_MODE0 | I8254_BINARY);
1250                if (subpriv->has_clk_gat_sce) {
1251                        /* Gate source 0 is VCC (logic 1). */
1252                        dio200_set_gate_src(subpriv, chan, 0);
1253                        /* Clock source 0 is the dedicated clock input. */
1254                        dio200_set_clock_src(subpriv, chan, 0);
1255                }
1256        }
1257
1258        return 0;
1259}
1260
1261/*
1262 * This function cleans up an '8254' counter subdevice.
1263 */
1264static void
1265dio200_subdev_8254_cleanup(struct comedi_device *dev,
1266                           struct comedi_subdevice *s)
1267{
1268        struct dio200_subdev_intr *subpriv = s->private;
1269
1270        if (subpriv) {
1271                kfree(subpriv);
1272        }
1273}
1274
1275/*
1276 * Attach is called by the Comedi core to configure the driver
1277 * for a particular board.  If you specified a board_name array
1278 * in the driver structure, dev->board_ptr contains that
1279 * address.
1280 */
1281static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1282{
1283        struct comedi_subdevice *s;
1284        unsigned long iobase = 0;
1285        unsigned int irq = 0;
1286#ifdef CONFIG_COMEDI_PCI
1287        struct pci_dev *pci_dev = NULL;
1288        int bus = 0, slot = 0;
1289#endif
1290        const struct dio200_layout_struct *layout;
1291        int share_irq = 0;
1292        int sdx;
1293        unsigned n;
1294        int ret;
1295
1296        printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1297               DIO200_DRIVER_NAME);
1298
1299        ret = alloc_private(dev, sizeof(struct dio200_private));
1300        if (ret < 0) {
1301                printk(KERN_ERR "comedi%d: error! out of memory!\n",
1302                       dev->minor);
1303                return ret;
1304        }
1305
1306        /* Process options. */
1307        switch (thisboard->bustype) {
1308        case isa_bustype:
1309                iobase = it->options[0];
1310                irq = it->options[1];
1311                share_irq = 0;
1312                break;
1313#ifdef CONFIG_COMEDI_PCI
1314        case pci_bustype:
1315                bus = it->options[0];
1316                slot = it->options[1];
1317                share_irq = 1;
1318
1319                ret = dio200_find_pci(dev, bus, slot, &pci_dev);
1320                if (ret < 0)
1321                        return ret;
1322                devpriv->pci_dev = pci_dev;
1323                break;
1324#endif
1325        default:
1326                printk(KERN_ERR
1327                       "comedi%d: %s: BUG! cannot determine board type!\n",
1328                       dev->minor, DIO200_DRIVER_NAME);
1329                return -EINVAL;
1330                break;
1331        }
1332
1333        devpriv->intr_sd = -1;
1334
1335        /* Enable device and reserve I/O spaces. */
1336#ifdef CONFIG_COMEDI_PCI
1337        if (pci_dev) {
1338                ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1339                if (ret < 0) {
1340                        printk(KERN_ERR
1341                               "comedi%d: error! cannot enable PCI device and request regions!\n",
1342                               dev->minor);
1343                        return ret;
1344                }
1345                iobase = pci_resource_start(pci_dev, 2);
1346                irq = pci_dev->irq;
1347        } else
1348#endif
1349        {
1350                ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
1351                if (ret < 0) {
1352                        return ret;
1353                }
1354        }
1355        dev->iobase = iobase;
1356
1357        layout = thislayout;
1358
1359        ret = alloc_subdevices(dev, layout->n_subdevs);
1360        if (ret < 0) {
1361                printk(KERN_ERR "comedi%d: error! out of memory!\n",
1362                       dev->minor);
1363                return ret;
1364        }
1365
1366        for (n = 0; n < dev->n_subdevices; n++) {
1367                s = &dev->subdevices[n];
1368                switch (layout->sdtype[n]) {
1369                case sd_8254:
1370                        /* counter subdevice (8254) */
1371                        ret = dio200_subdev_8254_init(dev, s, iobase,
1372                                                      layout->sdinfo[n],
1373                                                      layout->has_clk_gat_sce);
1374                        if (ret < 0) {
1375                                return ret;
1376                        }
1377                        break;
1378                case sd_8255:
1379                        /* digital i/o subdevice (8255) */
1380                        ret = subdev_8255_init(dev, s, 0,
1381                                               iobase + layout->sdinfo[n]);
1382                        if (ret < 0) {
1383                                return ret;
1384                        }
1385                        break;
1386                case sd_intr:
1387                        /* 'INTERRUPT' subdevice */
1388                        if (irq) {
1389                                ret = dio200_subdev_intr_init(dev, s,
1390                                                              iobase +
1391                                                              DIO200_INT_SCE,
1392                                                              layout->sdinfo[n],
1393                                                              layout->
1394                                                              has_int_sce);
1395                                if (ret < 0) {
1396                                        return ret;
1397                                }
1398                                devpriv->intr_sd = n;
1399                        } else {
1400                                s->type = COMEDI_SUBD_UNUSED;
1401                        }
1402                        break;
1403                default:
1404                        s->type = COMEDI_SUBD_UNUSED;
1405                        break;
1406                }
1407        }
1408
1409        sdx = devpriv->intr_sd;
1410        if (sdx >= 0 && sdx < dev->n_subdevices) {
1411                dev->read_subdev = &dev->subdevices[sdx];
1412        }
1413
1414        dev->board_name = thisboard->name;
1415
1416        if (irq) {
1417                unsigned long flags = share_irq ? IRQF_SHARED : 0;
1418
1419                if (request_irq(irq, dio200_interrupt, flags,
1420                                DIO200_DRIVER_NAME, dev) >= 0) {
1421                        dev->irq = irq;
1422                } else {
1423                        printk(KERN_WARNING
1424                               "comedi%d: warning! irq %u unavailable!\n",
1425                               dev->minor, irq);
1426                }
1427        }
1428
1429        printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1430        if (thisboard->bustype == isa_bustype) {
1431                printk("(base %#lx) ", iobase);
1432        } else {
1433#ifdef CONFIG_COMEDI_PCI
1434                printk("(pci %s) ", pci_name(pci_dev));
1435#endif
1436        }
1437        if (irq) {
1438                printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1439        } else {
1440                printk("(no irq) ");
1441        }
1442
1443        printk("attached\n");
1444
1445        return 1;
1446}
1447
1448/*
1449 * _detach is called to deconfigure a device.  It should deallocate
1450 * resources.
1451 * This function is also called when _attach() fails, so it should be
1452 * careful not to release resources that were not necessarily
1453 * allocated by _attach().  dev->private and dev->subdevices are
1454 * deallocated automatically by the core.
1455 */
1456static int dio200_detach(struct comedi_device *dev)
1457{
1458        const struct dio200_layout_struct *layout;
1459        unsigned n;
1460
1461        printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1462               DIO200_DRIVER_NAME);
1463
1464        if (dev->irq) {
1465                free_irq(dev->irq, dev);
1466        }
1467        if (dev->subdevices) {
1468                layout = thislayout;
1469                for (n = 0; n < dev->n_subdevices; n++) {
1470                        struct comedi_subdevice *s = &dev->subdevices[n];
1471                        switch (layout->sdtype[n]) {
1472                        case sd_8254:
1473                                dio200_subdev_8254_cleanup(dev, s);
1474                                break;
1475                        case sd_8255:
1476                                subdev_8255_cleanup(dev, s);
1477                                break;
1478                        case sd_intr:
1479                                dio200_subdev_intr_cleanup(dev, s);
1480                                break;
1481                        default:
1482                                break;
1483                        }
1484                }
1485        }
1486        if (devpriv) {
1487#ifdef CONFIG_COMEDI_PCI
1488                if (devpriv->pci_dev) {
1489                        if (dev->iobase) {
1490                                comedi_pci_disable(devpriv->pci_dev);
1491                        }
1492                        pci_dev_put(devpriv->pci_dev);
1493                } else
1494#endif
1495                {
1496                        if (dev->iobase) {
1497                                release_region(dev->iobase, DIO200_IO_SIZE);
1498                        }
1499                }
1500        }
1501        if (dev->board_name) {
1502                printk(KERN_INFO "comedi%d: %s removed\n",
1503                       dev->minor, dev->board_name);
1504        }
1505
1506        return 0;
1507}
1508
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.