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#include <linux/slab.h>
 210
 211#include "../comedidev.h"
 212
 213#include "comedi_pci.h"
 214
 215#include "8255.h"
 216#include "8253.h"
 217
 218#define DIO200_DRIVER_NAME      "amplc_dio200"
 219
 220/* PCI IDs */
 221#define PCI_VENDOR_ID_AMPLICON 0x14dc
 222#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
 223#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
 224#define PCI_DEVICE_ID_INVALID 0xffff
 225
 226/* 200 series registers */
 227#define DIO200_IO_SIZE          0x20
 228#define DIO200_XCLK_SCE         0x18    /* Group X clock selection register */
 229#define DIO200_YCLK_SCE         0x19    /* Group Y clock selection register */
 230#define DIO200_ZCLK_SCE         0x1a    /* Group Z clock selection register */
 231#define DIO200_XGAT_SCE         0x1b    /* Group X gate selection register */
 232#define DIO200_YGAT_SCE         0x1c    /* Group Y gate selection register */
 233#define DIO200_ZGAT_SCE         0x1d    /* Group Z gate selection register */
 234#define DIO200_INT_SCE          0x1e    /* Interrupt enable/status register */
 235
 236/*
 237 * Macros for constructing value for DIO_200_?CLK_SCE and
 238 * DIO_200_?GAT_SCE registers:
 239 *
 240 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
 241 * 'chan' is the channel: 0, 1 or 2.
 242 * 'source' is the signal source: 0 to 7.
 243 */
 244#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
 245#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
 246
 247/*
 248 * Periods of the internal clock sources in nanoseconds.
 249 */
 250static const unsigned clock_period[8] = {
 251        0,                      /* dedicated clock input/output pin */
 252        100,                    /* 10 MHz */
 253        1000,                   /* 1 MHz */
 254        10000,                  /* 100 kHz */
 255        100000,                 /* 10 kHz */
 256        1000000,                /* 1 kHz */
 257        0,                      /* OUT N-1 */
 258        0                       /* group clock input pin */
 259};
 260
 261/*
 262 * Board descriptions.
 263 */
 264
 265enum dio200_bustype { isa_bustype, pci_bustype };
 266
 267enum dio200_model {
 268        pc212e_model,
 269        pc214e_model,
 270        pc215e_model, pci215_model,
 271        pc218e_model,
 272        pc272e_model, pci272_model,
 273        anypci_model
 274};
 275
 276enum dio200_layout {
 277        pc212_layout,
 278        pc214_layout,
 279        pc215_layout,
 280        pc218_layout,
 281        pc272_layout
 282};
 283
 284struct dio200_board {
 285        const char *name;
 286        unsigned short devid;
 287        enum dio200_bustype bustype;
 288        enum dio200_model model;
 289        enum dio200_layout layout;
 290};
 291
 292static const struct dio200_board dio200_boards[] = {
 293        {
 294         .name = "pc212e",
 295         .bustype = isa_bustype,
 296         .model = pc212e_model,
 297         .layout = pc212_layout,
 298         },
 299        {
 300         .name = "pc214e",
 301         .bustype = isa_bustype,
 302         .model = pc214e_model,
 303         .layout = pc214_layout,
 304         },
 305        {
 306         .name = "pc215e",
 307         .bustype = isa_bustype,
 308         .model = pc215e_model,
 309         .layout = pc215_layout,
 310         },
 311#ifdef CONFIG_COMEDI_PCI
 312        {
 313         .name = "pci215",
 314         .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
 315         .bustype = pci_bustype,
 316         .model = pci215_model,
 317         .layout = pc215_layout,
 318         },
 319#endif
 320        {
 321         .name = "pc218e",
 322         .bustype = isa_bustype,
 323         .model = pc218e_model,
 324         .layout = pc218_layout,
 325         },
 326        {
 327         .name = "pc272e",
 328         .bustype = isa_bustype,
 329         .model = pc272e_model,
 330         .layout = pc272_layout,
 331         },
 332#ifdef CONFIG_COMEDI_PCI
 333        {
 334         .name = "pci272",
 335         .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
 336         .bustype = pci_bustype,
 337         .model = pci272_model,
 338         .layout = pc272_layout,
 339         },
 340#endif
 341#ifdef CONFIG_COMEDI_PCI
 342        {
 343         .name = DIO200_DRIVER_NAME,
 344         .devid = PCI_DEVICE_ID_INVALID,
 345         .bustype = pci_bustype,
 346         .model = anypci_model, /* wildcard */
 347         },
 348#endif
 349};
 350
 351/*
 352 * Layout descriptions - some ISA and PCI board descriptions share the same
 353 * layout.
 354 */
 355
 356enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
 357
 358#define DIO200_MAX_SUBDEVS      7
 359#define DIO200_MAX_ISNS         6
 360
 361struct dio200_layout_struct {
 362        unsigned short n_subdevs;       /* number of subdevices */
 363        unsigned char sdtype[DIO200_MAX_SUBDEVS];       /* enum dio200_sdtype */
 364        unsigned char sdinfo[DIO200_MAX_SUBDEVS];       /* depends on sdtype */
 365        char has_int_sce;       /* has interrupt enable/status register */
 366        char has_clk_gat_sce;   /* has clock/gate selection registers */
 367};
 368
 369static const struct dio200_layout_struct dio200_layouts[] = {
 370        [pc212_layout] = {
 371                          .n_subdevs = 6,
 372                          .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
 373                                     sd_8254,
 374                                     sd_intr},
 375                          .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
 376                                     0x3F},
 377                          .has_int_sce = 1,
 378                          .has_clk_gat_sce = 1,
 379                          },
 380        [pc214_layout] = {
 381                          .n_subdevs = 4,
 382                          .sdtype = {sd_8255, sd_8255, sd_8254,
 383                                     sd_intr},
 384                          .sdinfo = {0x00, 0x08, 0x10, 0x01},
 385                          .has_int_sce = 0,
 386                          .has_clk_gat_sce = 0,
 387                          },
 388        [pc215_layout] = {
 389                          .n_subdevs = 5,
 390                          .sdtype = {sd_8255, sd_8255, sd_8254,
 391                                     sd_8254,
 392                                     sd_intr},
 393                          .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
 394                          .has_int_sce = 1,
 395                          .has_clk_gat_sce = 1,
 396                          },
 397        [pc218_layout] = {
 398                          .n_subdevs = 7,
 399                          .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
 400                                     sd_8254,
 401                                     sd_intr},
 402                          .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
 403                                     0x14,
 404                                     0x3F},
 405                          .has_int_sce = 1,
 406                          .has_clk_gat_sce = 1,
 407                          },
 408        [pc272_layout] = {
 409                          .n_subdevs = 4,
 410                          .sdtype = {sd_8255, sd_8255, sd_8255,
 411                                     sd_intr},
 412                          .sdinfo = {0x00, 0x08, 0x10, 0x3F},
 413                          .has_int_sce = 1,
 414                          .has_clk_gat_sce = 0,
 415                          },
 416};
 417
 418/*
 419 * PCI driver table.
 420 */
 421
 422#ifdef CONFIG_COMEDI_PCI
 423static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
 424        {
 425        PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215,
 426                    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 427        PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272,
 428                    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 429        0}
 430};
 431
 432MODULE_DEVICE_TABLE(pci, dio200_pci_table);
 433#endif /* CONFIG_COMEDI_PCI */
 434
 435/*
 436 * Useful for shorthand access to the particular board structure
 437 */
 438#define thisboard ((const struct dio200_board *)dev->board_ptr)
 439#define thislayout (&dio200_layouts[((struct dio200_board *) \
 440                    dev->board_ptr)->layout])
 441
 442/* this structure is for data unique to this hardware driver.  If
 443   several hardware drivers keep similar information in this structure,
 444   feel free to suggest moving the variable to the struct comedi_device struct.
 445 */
 446struct dio200_private {
 447#ifdef CONFIG_COMEDI_PCI
 448        struct pci_dev *pci_dev;        /* PCI device */
 449#endif
 450        int intr_sd;
 451};
 452
 453#define devpriv ((struct dio200_private *)dev->private)
 454
 455struct dio200_subdev_8254 {
 456        unsigned long iobase;   /* Counter base address */
 457        unsigned long clk_sce_iobase;   /* CLK_SCE base address */
 458        unsigned long gat_sce_iobase;   /* GAT_SCE base address */
 459        int which;              /* Bit 5 of CLK_SCE or GAT_SCE */
 460        int has_clk_gat_sce;
 461        unsigned clock_src[3];  /* Current clock sources */
 462        unsigned gate_src[3];   /* Current gate sources */
 463        spinlock_t spinlock;
 464};
 465
 466struct dio200_subdev_intr {
 467        unsigned long iobase;
 468        spinlock_t spinlock;
 469        int active;
 470        int has_int_sce;
 471        unsigned int valid_isns;
 472        unsigned int enabled_isns;
 473        unsigned int stopcount;
 474        int continuous;
 475};
 476
 477/*
 478 * The struct comedi_driver structure tells the Comedi core module
 479 * which functions to call to configure/deconfigure (attach/detach)
 480 * the board, and also about the kernel module that contains
 481 * the device code.
 482 */
 483static int dio200_attach(struct comedi_device *dev,
 484                         struct comedi_devconfig *it);
 485static int dio200_detach(struct comedi_device *dev);
 486static struct comedi_driver driver_amplc_dio200 = {
 487        .driver_name = DIO200_DRIVER_NAME,
 488        .module = THIS_MODULE,
 489        .attach = dio200_attach,
 490        .detach = dio200_detach,
 491        .board_name = &dio200_boards[0].name,
 492        .offset = sizeof(struct dio200_board),
 493        .num_names = ARRAY_SIZE(dio200_boards),
 494};
 495
 496#ifdef CONFIG_COMEDI_PCI
 497static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev,
 498                                                   const struct pci_device_id
 499                                                   *ent)
 500{
 501        return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name);
 502}
 503
 504static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev)
 505{
 506        comedi_pci_auto_unconfig(dev);
 507}
 508
 509static struct pci_driver driver_amplc_dio200_pci_driver = {
 510        .id_table = dio200_pci_table,
 511        .probe = &driver_amplc_dio200_pci_probe,
 512        .remove = __devexit_p(&driver_amplc_dio200_pci_remove)
 513};
 514
 515static int __init driver_amplc_dio200_init_module(void)
 516{
 517        int retval;
 518
 519        retval = comedi_driver_register(&driver_amplc_dio200);
 520        if (retval < 0)
 521                return retval;
 522
 523        driver_amplc_dio200_pci_driver.name =
 524            (char *)driver_amplc_dio200.driver_name;
 525        return pci_register_driver(&driver_amplc_dio200_pci_driver);
 526}
 527
 528static void __exit driver_amplc_dio200_cleanup_module(void)
 529{
 530        pci_unregister_driver(&driver_amplc_dio200_pci_driver);
 531        comedi_driver_unregister(&driver_amplc_dio200);
 532}
 533
 534module_init(driver_amplc_dio200_init_module);
 535module_exit(driver_amplc_dio200_cleanup_module);
 536#else
 537static int __init driver_amplc_dio200_init_module(void)
 538{
 539        return comedi_driver_register(&driver_amplc_dio200);
 540}
 541
 542static void __exit driver_amplc_dio200_cleanup_module(void)
 543{
 544        comedi_driver_unregister(&driver_amplc_dio200);
 545}
 546
 547module_init(driver_amplc_dio200_init_module);
 548module_exit(driver_amplc_dio200_cleanup_module);
 549#endif
 550
 551/*
 552 * This function looks for a PCI device matching the requested board name,
 553 * bus and slot.
 554 */
 555#ifdef CONFIG_COMEDI_PCI
 556static int
 557dio200_find_pci(struct comedi_device *dev, int bus, int slot,
 558                struct pci_dev **pci_dev_p)
 559{
 560        struct pci_dev *pci_dev = NULL;
 561
 562        *pci_dev_p = NULL;
 563
 564        /* Look for matching PCI device. */
 565        for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
 566             pci_dev != NULL;
 567             pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
 568                                      PCI_ANY_ID, pci_dev)) {
 569                /* If bus/slot specified, check them. */
 570                if (bus || slot) {
 571                        if (bus != pci_dev->bus->number
 572                            || slot != PCI_SLOT(pci_dev->devfn))
 573                                continue;
 574                }
 575                if (thisboard->model == anypci_model) {
 576                        /* Match any supported model. */
 577                        int i;
 578
 579                        for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
 580                                if (dio200_boards[i].bustype != pci_bustype)
 581                                        continue;
 582                                if (pci_dev->device == dio200_boards[i].devid) {
 583                                        /* Change board_ptr to matched board. */
 584                                        dev->board_ptr = &dio200_boards[i];
 585                                        break;
 586                                }
 587                        }
 588                        if (i == ARRAY_SIZE(dio200_boards))
 589                                continue;
 590                } else {
 591                        /* Match specific model name. */
 592                        if (pci_dev->device != thisboard->devid)
 593                                continue;
 594                }
 595
 596                /* Found a match. */
 597                *pci_dev_p = pci_dev;
 598                return 0;
 599        }
 600        /* No match found. */
 601        if (bus || slot) {
 602                printk(KERN_ERR
 603                       "comedi%d: error! no %s found at pci %02x:%02x!\n",
 604                       dev->minor, thisboard->name, bus, slot);
 605        } else {
 606                printk(KERN_ERR "comedi%d: error! no %s found!\n",
 607                       dev->minor, thisboard->name);
 608        }
 609        return -EIO;
 610}
 611#endif
 612
 613/*
 614 * This function checks and requests an I/O region, reporting an error
 615 * if there is a conflict.
 616 */
 617static int
 618dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
 619{
 620        if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
 621                printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
 622                       minor, from, extent);
 623                return -EIO;
 624        }
 625        return 0;
 626}
 627
 628/*
 629 * 'insn_bits' function for an 'INTERRUPT' subdevice.
 630 */
 631static int
 632dio200_subdev_intr_insn_bits(struct comedi_device *dev,
 633                             struct comedi_subdevice *s,
 634                             struct comedi_insn *insn, unsigned int *data)
 635{
 636        struct dio200_subdev_intr *subpriv = s->private;
 637
 638        if (subpriv->has_int_sce) {
 639                /* Just read the interrupt status register.  */
 640                data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
 641        } else {
 642                /* No interrupt status register. */
 643                data[0] = 0;
 644        }
 645
 646        return 2;
 647}
 648
 649/*
 650 * Called to stop acquisition for an 'INTERRUPT' subdevice.
 651 */
 652static void dio200_stop_intr(struct comedi_device *dev,
 653                             struct comedi_subdevice *s)
 654{
 655        struct dio200_subdev_intr *subpriv = s->private;
 656
 657        subpriv->active = 0;
 658        subpriv->enabled_isns = 0;
 659        if (subpriv->has_int_sce)
 660                outb(0, subpriv->iobase);
 661}
 662
 663/*
 664 * Called to start acquisition for an 'INTERRUPT' subdevice.
 665 */
 666static int dio200_start_intr(struct comedi_device *dev,
 667                             struct comedi_subdevice *s)
 668{
 669        unsigned int n;
 670        unsigned isn_bits;
 671        struct dio200_subdev_intr *subpriv = s->private;
 672        struct comedi_cmd *cmd = &s->async->cmd;
 673        int retval = 0;
 674
 675        if (!subpriv->continuous && subpriv->stopcount == 0) {
 676                /* An empty acquisition! */
 677                s->async->events |= COMEDI_CB_EOA;
 678                subpriv->active = 0;
 679                retval = 1;
 680        } else {
 681                /* Determine interrupt sources to enable. */
 682                isn_bits = 0;
 683                if (cmd->chanlist) {
 684                        for (n = 0; n < cmd->chanlist_len; n++)
 685                                isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
 686                }
 687                isn_bits &= subpriv->valid_isns;
 688                /* Enable interrupt sources. */
 689                subpriv->enabled_isns = isn_bits;
 690                if (subpriv->has_int_sce)
 691                        outb(isn_bits, subpriv->iobase);
 692        }
 693
 694        return retval;
 695}
 696
 697/*
 698 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
 699 */
 700static int
 701dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
 702                          unsigned int trignum)
 703{
 704        struct dio200_subdev_intr *subpriv;
 705        unsigned long flags;
 706        int event = 0;
 707
 708        if (trignum != 0)
 709                return -EINVAL;
 710
 711        subpriv = s->private;
 712
 713        spin_lock_irqsave(&subpriv->spinlock, flags);
 714        s->async->inttrig = NULL;
 715        if (subpriv->active)
 716                event = dio200_start_intr(dev, s);
 717
 718        spin_unlock_irqrestore(&subpriv->spinlock, flags);
 719
 720        if (event)
 721                comedi_event(dev, s);
 722
 723        return 1;
 724}
 725
 726/*
 727 * This is called from the interrupt service routine to handle a read
 728 * scan on an 'INTERRUPT' subdevice.
 729 */
 730static int dio200_handle_read_intr(struct comedi_device *dev,
 731                                   struct comedi_subdevice *s)
 732{
 733        struct dio200_subdev_intr *subpriv = s->private;
 734        unsigned triggered;
 735        unsigned intstat;
 736        unsigned cur_enabled;
 737        unsigned int oldevents;
 738        unsigned long flags;
 739
 740        triggered = 0;
 741
 742        spin_lock_irqsave(&subpriv->spinlock, flags);
 743        oldevents = s->async->events;
 744        if (subpriv->has_int_sce) {
 745                /*
 746                 * Collect interrupt sources that have triggered and disable
 747                 * them temporarily.  Loop around until no extra interrupt
 748                 * sources have triggered, at which point, the valid part of
 749                 * the interrupt status register will read zero, clearing the
 750                 * cause of the interrupt.
 751                 *
 752                 * Mask off interrupt sources already seen to avoid infinite
 753                 * loop in case of misconfiguration.
 754                 */
 755                cur_enabled = subpriv->enabled_isns;
 756                while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
 757                                   & ~triggered)) != 0) {
 758                        triggered |= intstat;
 759                        cur_enabled &= ~triggered;
 760                        outb(cur_enabled, subpriv->iobase);
 761                }
 762        } else {
 763                /*
 764                 * No interrupt status register.  Assume the single interrupt
 765                 * source has triggered.
 766                 */
 767                triggered = subpriv->enabled_isns;
 768        }
 769
 770        if (triggered) {
 771                /*
 772                 * Some interrupt sources have triggered and have been
 773                 * temporarily disabled to clear the cause of the interrupt.
 774                 *
 775                 * Reenable them NOW to minimize the time they are disabled.
 776                 */
 777                cur_enabled = subpriv->enabled_isns;
 778                if (subpriv->has_int_sce)
 779                        outb(cur_enabled, subpriv->iobase);
 780
 781                if (subpriv->active) {
 782                        /*
 783                         * The command is still active.
 784                         *
 785                         * Ignore interrupt sources that the command isn't
 786                         * interested in (just in case there's a race
 787                         * condition).
 788                         */
 789                        if (triggered & subpriv->enabled_isns) {
 790                                /* Collect scan data. */
 791                                short val;
 792                                unsigned int n, ch, len;
 793
 794                                val = 0;
 795                                len = s->async->cmd.chanlist_len;
 796                                for (n = 0; n < len; n++) {
 797                                        ch = CR_CHAN(s->async->cmd.chanlist[n]);
 798                                        if (triggered & (1U << ch))
 799                                                val |= (1U << n);
 800                                }
 801                                /* Write the scan to the buffer. */
 802                                if (comedi_buf_put(s->async, val)) {
 803                                        s->async->events |= (COMEDI_CB_BLOCK |
 804                                                             COMEDI_CB_EOS);
 805                                } else {
 806                                        /* Error!  Stop acquisition.  */
 807                                        dio200_stop_intr(dev, s);
 808                                        s->async->events |= COMEDI_CB_ERROR
 809                                            | COMEDI_CB_OVERFLOW;
 810                                        comedi_error(dev, "buffer overflow");
 811                                }
 812
 813                                /* Check for end of acquisition. */
 814                                if (!subpriv->continuous) {
 815                                        /* stop_src == TRIG_COUNT */
 816                                        if (subpriv->stopcount > 0) {
 817                                                subpriv->stopcount--;
 818                                                if (subpriv->stopcount == 0) {
 819                                                        s->async->events |=
 820                                                            COMEDI_CB_EOA;
 821                                                        dio200_stop_intr(dev,
 822                                                                         s);
 823                                                }
 824                                        }
 825                                }
 826                        }
 827                }
 828        }
 829        spin_unlock_irqrestore(&subpriv->spinlock, flags);
 830
 831        if (oldevents != s->async->events)
 832                comedi_event(dev, s);
 833
 834        return (triggered != 0);
 835}
 836
 837/*
 838 * 'cancel' function for an 'INTERRUPT' subdevice.
 839 */
 840static int dio200_subdev_intr_cancel(struct comedi_device *dev,
 841                                     struct comedi_subdevice *s)
 842{
 843        struct dio200_subdev_intr *subpriv = s->private;
 844        unsigned long flags;
 845
 846        spin_lock_irqsave(&subpriv->spinlock, flags);
 847        if (subpriv->active)
 848                dio200_stop_intr(dev, s);
 849
 850        spin_unlock_irqrestore(&subpriv->spinlock, flags);
 851
 852        return 0;
 853}
 854
 855/*
 856 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
 857 */
 858static int
 859dio200_subdev_intr_cmdtest(struct comedi_device *dev,
 860                           struct comedi_subdevice *s, struct comedi_cmd *cmd)
 861{
 862        int err = 0;
 863        unsigned int tmp;
 864
 865        /* step 1: make sure trigger sources are trivially valid */
 866
 867        tmp = cmd->start_src;
 868        cmd->start_src &= (TRIG_NOW | TRIG_INT);
 869        if (!cmd->start_src || tmp != cmd->start_src)
 870                err++;
 871
 872        tmp = cmd->scan_begin_src;
 873        cmd->scan_begin_src &= TRIG_EXT;
 874        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
 875                err++;
 876
 877        tmp = cmd->convert_src;
 878        cmd->convert_src &= TRIG_NOW;
 879        if (!cmd->convert_src || tmp != cmd->convert_src)
 880                err++;
 881
 882        tmp = cmd->scan_end_src;
 883        cmd->scan_end_src &= TRIG_COUNT;
 884        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
 885                err++;
 886
 887        tmp = cmd->stop_src;
 888        cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
 889        if (!cmd->stop_src || tmp != cmd->stop_src)
 890                err++;
 891
 892        if (err)
 893                return 1;
 894
 895        /* step 2: make sure trigger sources are unique and mutually
 896                   compatible */
 897
 898        /* these tests are true if more than one _src bit is set */
 899        if ((cmd->start_src & (cmd->start_src - 1)) != 0)
 900                err++;
 901        if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
 902                err++;
 903        if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
 904                err++;
 905        if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
 906                err++;
 907        if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
 908                err++;
 909
 910        if (err)
 911                return 2;
 912
 913        /* step 3: make sure arguments are trivially compatible */
 914
 915        /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
 916        if (cmd->start_arg != 0) {
 917                cmd->start_arg = 0;
 918                err++;
 919        }
 920
 921        /* cmd->scan_begin_src == TRIG_EXT */
 922        if (cmd->scan_begin_arg != 0) {
 923                cmd->scan_begin_arg = 0;
 924                err++;
 925        }
 926
 927        /* cmd->convert_src == TRIG_NOW */
 928        if (cmd->convert_arg != 0) {
 929                cmd->convert_arg = 0;
 930                err++;
 931        }
 932
 933        /* cmd->scan_end_src == TRIG_COUNT */
 934        if (cmd->scan_end_arg != cmd->chanlist_len) {
 935                cmd->scan_end_arg = cmd->chanlist_len;
 936                err++;
 937        }
 938
 939        switch (cmd->stop_src) {
 940        case TRIG_COUNT:
 941                /* any count allowed */
 942                break;
 943        case TRIG_NONE:
 944                if (cmd->stop_arg != 0) {
 945                        cmd->stop_arg = 0;
 946                        err++;
 947                }
 948                break;
 949        default:
 950                break;
 951        }
 952
 953        if (err)
 954                return 3;
 955
 956        /* step 4: fix up any arguments */
 957
 958        /* if (err) return 4; */
 959
 960        return 0;
 961}
 962
 963/*
 964 * 'do_cmd' function for an 'INTERRUPT' subdevice.
 965 */
 966static int dio200_subdev_intr_cmd(struct comedi_device *dev,
 967                                  struct comedi_subdevice *s)
 968{
 969        struct comedi_cmd *cmd = &s->async->cmd;
 970        struct dio200_subdev_intr *subpriv = s->private;
 971        unsigned long flags;
 972        int event = 0;
 973
 974        spin_lock_irqsave(&subpriv->spinlock, flags);
 975        subpriv->active = 1;
 976
 977        /* Set up end of acquisition. */
 978        switch (cmd->stop_src) {
 979        case TRIG_COUNT:
 980                subpriv->continuous = 0;
 981                subpriv->stopcount = cmd->stop_arg;
 982                break;
 983        default:
 984                /* TRIG_NONE */
 985                subpriv->continuous = 1;
 986                subpriv->stopcount = 0;
 987                break;
 988        }
 989
 990        /* Set up start of acquisition. */
 991        switch (cmd->start_src) {
 992        case TRIG_INT:
 993                s->async->inttrig = dio200_inttrig_start_intr;
 994                break;
 995        default:
 996                /* TRIG_NOW */
 997                event = dio200_start_intr(dev, s);
 998                break;
 999        }
1000        spin_unlock_irqrestore(&subpriv->spinlock, flags);
1001
1002        if (event)
1003                comedi_event(dev, s);
1004
1005        return 0;
1006}
1007
1008/*
1009 * This function initializes an 'INTERRUPT' subdevice.
1010 */
1011static int
1012dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
1013                        unsigned long iobase, unsigned valid_isns,
1014                        int has_int_sce)
1015{
1016        struct dio200_subdev_intr *subpriv;
1017
1018        subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1019        if (!subpriv) {
1020                printk(KERN_ERR "comedi%d: error! out of memory!\n",
1021                       dev->minor);
1022                return -ENOMEM;
1023        }
1024        subpriv->iobase = iobase;
1025        subpriv->has_int_sce = has_int_sce;
1026        subpriv->valid_isns = valid_isns;
1027        spin_lock_init(&subpriv->spinlock);
1028
1029        if (has_int_sce)
1030                outb(0, subpriv->iobase);       /* Disable interrupt sources. */
1031
1032        s->private = subpriv;
1033        s->type = COMEDI_SUBD_DI;
1034        s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1035        if (has_int_sce) {
1036                s->n_chan = DIO200_MAX_ISNS;
1037                s->len_chanlist = DIO200_MAX_ISNS;
1038        } else {
1039                /* No interrupt source register.  Support single channel. */
1040                s->n_chan = 1;
1041                s->len_chanlist = 1;
1042        }
1043        s->range_table = &range_digital;
1044        s->maxdata = 1;
1045        s->insn_bits = dio200_subdev_intr_insn_bits;
1046        s->do_cmdtest = dio200_subdev_intr_cmdtest;
1047        s->do_cmd = dio200_subdev_intr_cmd;
1048        s->cancel = dio200_subdev_intr_cancel;
1049
1050        return 0;
1051}
1052
1053/*
1054 * This function cleans up an 'INTERRUPT' subdevice.
1055 */
1056static void
1057dio200_subdev_intr_cleanup(struct comedi_device *dev,
1058                           struct comedi_subdevice *s)
1059{
1060        struct dio200_subdev_intr *subpriv = s->private;
1061        kfree(subpriv);
1062}
1063
1064/*
1065 * Interrupt service routine.
1066 */
1067static irqreturn_t dio200_interrupt(int irq, void *d)
1068{
1069        struct comedi_device *dev = d;
1070        int handled;
1071
1072        if (!dev->attached)
1073                return IRQ_NONE;
1074
1075        if (devpriv->intr_sd >= 0) {
1076                handled = dio200_handle_read_intr(dev,
1077                                                  dev->subdevices +
1078                                                  devpriv->intr_sd);
1079        } else {
1080                handled = 0;
1081        }
1082
1083        return IRQ_RETVAL(handled);
1084}
1085
1086/*
1087 * Handle 'insn_read' for an '8254' counter subdevice.
1088 */
1089static int
1090dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
1091                        struct comedi_insn *insn, unsigned int *data)
1092{
1093        struct dio200_subdev_8254 *subpriv = s->private;
1094        int chan = CR_CHAN(insn->chanspec);
1095        unsigned long flags;
1096
1097        spin_lock_irqsave(&subpriv->spinlock, flags);
1098        data[0] = i8254_read(subpriv->iobase, 0, chan);
1099        spin_unlock_irqrestore(&subpriv->spinlock, flags);
1100
1101        return 1;
1102}
1103
1104/*
1105 * Handle 'insn_write' for an '8254' counter subdevice.
1106 */
1107static int
1108dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
1109                         struct comedi_insn *insn, unsigned int *data)
1110{
1111        struct dio200_subdev_8254 *subpriv = s->private;
1112        int chan = CR_CHAN(insn->chanspec);
1113        unsigned long flags;
1114
1115        spin_lock_irqsave(&subpriv->spinlock, flags);
1116        i8254_write(subpriv->iobase, 0, chan, data[0]);
1117        spin_unlock_irqrestore(&subpriv->spinlock, flags);
1118
1119        return 1;
1120}
1121
1122/*
1123 * Set gate source for an '8254' counter subdevice channel.
1124 */
1125static int
1126dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1127                    unsigned int counter_number, unsigned int gate_src)
1128{
1129        unsigned char byte;
1130
1131        if (!subpriv->has_clk_gat_sce)
1132                return -1;
1133        if (counter_number > 2)
1134                return -1;
1135        if (gate_src > 7)
1136                return -1;
1137
1138        subpriv->gate_src[counter_number] = gate_src;
1139        byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1140        outb(byte, subpriv->gat_sce_iobase);
1141
1142        return 0;
1143}
1144
1145/*
1146 * Get gate source for an '8254' counter subdevice channel.
1147 */
1148static int
1149dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1150                    unsigned int counter_number)
1151{
1152        if (!subpriv->has_clk_gat_sce)
1153                return -1;
1154        if (counter_number > 2)
1155                return -1;
1156
1157        return subpriv->gate_src[counter_number];
1158}
1159
1160/*
1161 * Set clock source for an '8254' counter subdevice channel.
1162 */
1163static int
1164dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1165                     unsigned int counter_number, unsigned int clock_src)
1166{
1167        unsigned char byte;
1168
1169        if (!subpriv->has_clk_gat_sce)
1170                return -1;
1171        if (counter_number > 2)
1172                return -1;
1173        if (clock_src > 7)
1174                return -1;
1175
1176        subpriv->clock_src[counter_number] = clock_src;
1177        byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1178        outb(byte, subpriv->clk_sce_iobase);
1179
1180        return 0;
1181}
1182
1183/*
1184 * Get clock source for an '8254' counter subdevice channel.
1185 */
1186static int
1187dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1188                     unsigned int counter_number, unsigned int *period_ns)
1189{
1190        unsigned clock_src;
1191
1192        if (!subpriv->has_clk_gat_sce)
1193                return -1;
1194        if (counter_number > 2)
1195                return -1;
1196
1197        clock_src = subpriv->clock_src[counter_number];
1198        *period_ns = clock_period[clock_src];
1199        return clock_src;
1200}
1201
1202/*
1203 * Handle 'insn_config' for an '8254' counter subdevice.
1204 */
1205static int
1206dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1207                          struct comedi_insn *insn, unsigned int *data)
1208{
1209        struct dio200_subdev_8254 *subpriv = s->private;
1210        int ret = 0;
1211        int chan = CR_CHAN(insn->chanspec);
1212        unsigned long flags;
1213
1214        spin_lock_irqsave(&subpriv->spinlock, flags);
1215        switch (data[0]) {
1216        case INSN_CONFIG_SET_COUNTER_MODE:
1217                ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1218                if (ret < 0)
1219                        ret = -EINVAL;
1220                break;
1221        case INSN_CONFIG_8254_READ_STATUS:
1222                data[1] = i8254_status(subpriv->iobase, 0, chan);
1223                break;
1224        case INSN_CONFIG_SET_GATE_SRC:
1225                ret = dio200_set_gate_src(subpriv, chan, data[2]);
1226                if (ret < 0)
1227                        ret = -EINVAL;
1228                break;
1229        case INSN_CONFIG_GET_GATE_SRC:
1230                ret = dio200_get_gate_src(subpriv, chan);
1231                if (ret < 0) {
1232                        ret = -EINVAL;
1233                        break;
1234                }
1235                data[2] = ret;
1236                break;
1237        case INSN_CONFIG_SET_CLOCK_SRC:
1238                ret = dio200_set_clock_src(subpriv, chan, data[1]);
1239                if (ret < 0)
1240                        ret = -EINVAL;
1241                break;
1242        case INSN_CONFIG_GET_CLOCK_SRC:
1243                ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1244                if (ret < 0) {
1245                        ret = -EINVAL;
1246                        break;
1247                }
1248                data[1] = ret;
1249                break;
1250        default:
1251                ret = -EINVAL;
1252                break;
1253        }
1254        spin_unlock_irqrestore(&subpriv->spinlock, flags);
1255        return ret < 0 ? ret : insn->n;
1256}
1257
1258/*
1259 * This function initializes an '8254' counter subdevice.
1260 *
1261 * Note: iobase is the base address of the board, not the subdevice;
1262 * offset is the offset to the 8254 chip.
1263 */
1264static int
1265dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
1266                        unsigned long iobase, unsigned offset,
1267                        int has_clk_gat_sce)
1268{
1269        struct dio200_subdev_8254 *subpriv;
1270        unsigned int chan;
1271
1272        subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1273        if (!subpriv) {
1274                printk(KERN_ERR "comedi%d: error! out of memory!\n",
1275                       dev->minor);
1276                return -ENOMEM;
1277        }
1278
1279        s->private = subpriv;
1280        s->type = COMEDI_SUBD_COUNTER;
1281        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1282        s->n_chan = 3;
1283        s->maxdata = 0xFFFF;
1284        s->insn_read = dio200_subdev_8254_read;
1285        s->insn_write = dio200_subdev_8254_write;
1286        s->insn_config = dio200_subdev_8254_config;
1287
1288        spin_lock_init(&subpriv->spinlock);
1289        subpriv->iobase = offset + iobase;
1290        subpriv->has_clk_gat_sce = has_clk_gat_sce;
1291        if (has_clk_gat_sce) {
1292                /* Derive CLK_SCE and GAT_SCE register offsets from
1293                 * 8254 offset. */
1294                subpriv->clk_sce_iobase =
1295                    DIO200_XCLK_SCE + (offset >> 3) + iobase;
1296                subpriv->gat_sce_iobase =
1297                    DIO200_XGAT_SCE + (offset >> 3) + iobase;
1298                subpriv->which = (offset >> 2) & 1;
1299        }
1300
1301        /* Initialize channels. */
1302        for (chan = 0; chan < 3; chan++) {
1303                i8254_set_mode(subpriv->iobase, 0, chan,
1304                               I8254_MODE0 | I8254_BINARY);
1305                if (subpriv->has_clk_gat_sce) {
1306                        /* Gate source 0 is VCC (logic 1). */
1307                        dio200_set_gate_src(subpriv, chan, 0);
1308                        /* Clock source 0 is the dedicated clock input. */
1309                        dio200_set_clock_src(subpriv, chan, 0);
1310                }
1311        }
1312
1313        return 0;
1314}
1315
1316/*
1317 * This function cleans up an '8254' counter subdevice.
1318 */
1319static void
1320dio200_subdev_8254_cleanup(struct comedi_device *dev,
1321                           struct comedi_subdevice *s)
1322{
1323        struct dio200_subdev_intr *subpriv = s->private;
1324        kfree(subpriv);
1325}
1326
1327/*
1328 * Attach is called by the Comedi core to configure the driver
1329 * for a particular board.  If you specified a board_name array
1330 * in the driver structure, dev->board_ptr contains that
1331 * address.
1332 */
1333static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1334{
1335        struct comedi_subdevice *s;
1336        unsigned long iobase = 0;
1337        unsigned int irq = 0;
1338#ifdef CONFIG_COMEDI_PCI
1339        struct pci_dev *pci_dev = NULL;
1340        int bus = 0, slot = 0;
1341#endif
1342        const struct dio200_layout_struct *layout;
1343        int share_irq = 0;
1344        int sdx;
1345        unsigned n;
1346        int ret;
1347
1348        printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1349               DIO200_DRIVER_NAME);
1350
1351        ret = alloc_private(dev, sizeof(struct dio200_private));
1352        if (ret < 0) {
1353                printk(KERN_ERR "comedi%d: error! out of memory!\n",
1354                       dev->minor);
1355                return ret;
1356        }
1357
1358        /* Process options. */
1359        switch (thisboard->bustype) {
1360        case isa_bustype:
1361                iobase = it->options[0];
1362                irq = it->options[1];
1363                share_irq = 0;
1364                break;
1365#ifdef CONFIG_COMEDI_PCI
1366        case pci_bustype:
1367                bus = it->options[0];
1368                slot = it->options[1];
1369                share_irq = 1;
1370
1371                ret = dio200_find_pci(dev, bus, slot, &pci_dev);
1372                if (ret < 0)
1373                        return ret;
1374                devpriv->pci_dev = pci_dev;
1375                break;
1376#endif
1377        default:
1378                printk(KERN_ERR
1379                       "comedi%d: %s: BUG! cannot determine board type!\n",
1380                       dev->minor, DIO200_DRIVER_NAME);
1381                return -EINVAL;
1382                break;
1383        }
1384
1385        devpriv->intr_sd = -1;
1386
1387        /* Enable device and reserve I/O spaces. */
1388#ifdef CONFIG_COMEDI_PCI
1389        if (pci_dev) {
1390                ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1391                if (ret < 0) {
1392                        printk(KERN_ERR
1393                               "comedi%d: error! cannot enable PCI device and request regions!\n",
1394                               dev->minor);
1395                        return ret;
1396                }
1397                iobase = pci_resource_start(pci_dev, 2);
1398                irq = pci_dev->irq;
1399        } else
1400#endif
1401        {
1402                ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
1403                if (ret < 0)
1404                        return ret;
1405        }
1406        dev->iobase = iobase;
1407
1408        layout = thislayout;
1409
1410        ret = alloc_subdevices(dev, layout->n_subdevs);
1411        if (ret < 0) {
1412                printk(KERN_ERR "comedi%d: error! out of memory!\n",
1413                       dev->minor);
1414                return ret;
1415        }
1416
1417        for (n = 0; n < dev->n_subdevices; n++) {
1418                s = &dev->subdevices[n];
1419                switch (layout->sdtype[n]) {
1420                case sd_8254:
1421                        /* counter subdevice (8254) */
1422                        ret = dio200_subdev_8254_init(dev, s, iobase,
1423                                                      layout->sdinfo[n],
1424                                                      layout->has_clk_gat_sce);
1425                        if (ret < 0)
1426                                return ret;
1427
1428                        break;
1429                case sd_8255:
1430                        /* digital i/o subdevice (8255) */
1431                        ret = subdev_8255_init(dev, s, NULL,
1432                                               iobase + layout->sdinfo[n]);
1433                        if (ret < 0)
1434                                return ret;
1435
1436                        break;
1437                case sd_intr:
1438                        /* 'INTERRUPT' subdevice */
1439                        if (irq) {
1440                                ret = dio200_subdev_intr_init(dev, s,
1441                                                              iobase +
1442                                                              DIO200_INT_SCE,
1443                                                              layout->sdinfo[n],
1444                                                              layout->
1445                                                              has_int_sce);
1446                                if (ret < 0)
1447                                        return ret;
1448
1449                                devpriv->intr_sd = n;
1450                        } else {
1451                                s->type = COMEDI_SUBD_UNUSED;
1452                        }
1453                        break;
1454                default:
1455                        s->type = COMEDI_SUBD_UNUSED;
1456                        break;
1457                }
1458        }
1459
1460        sdx = devpriv->intr_sd;
1461        if (sdx >= 0 && sdx < dev->n_subdevices)
1462                dev->read_subdev = &dev->subdevices[sdx];
1463
1464        dev->board_name = thisboard->name;
1465
1466        if (irq) {
1467                unsigned long flags = share_irq ? IRQF_SHARED : 0;
1468
1469                if (request_irq(irq, dio200_interrupt, flags,
1470                                DIO200_DRIVER_NAME, dev) >= 0) {
1471                        dev->irq = irq;
1472                } else {
1473                        printk(KERN_WARNING
1474                               "comedi%d: warning! irq %u unavailable!\n",
1475                               dev->minor, irq);
1476                }
1477        }
1478
1479        printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1480        if (thisboard->bustype == isa_bustype) {
1481                printk("(base %#lx) ", iobase);
1482        } else {
1483#ifdef CONFIG_COMEDI_PCI
1484                printk("(pci %s) ", pci_name(pci_dev));
1485#endif
1486        }
1487        if (irq)
1488                printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1489        else
1490                printk("(no irq) ");
1491
1492        printk("attached\n");
1493
1494        return 1;
1495}
1496
1497/*
1498 * _detach is called to deconfigure a device.  It should deallocate
1499 * resources.
1500 * This function is also called when _attach() fails, so it should be
1501 * careful not to release resources that were not necessarily
1502 * allocated by _attach().  dev->private and dev->subdevices are
1503 * deallocated automatically by the core.
1504 */
1505static int dio200_detach(struct comedi_device *dev)
1506{
1507        const struct dio200_layout_struct *layout;
1508        unsigned n;
1509
1510        printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1511               DIO200_DRIVER_NAME);
1512
1513        if (dev->irq)
1514                free_irq(dev->irq, dev);
1515        if (dev->subdevices) {
1516                layout = thislayout;
1517                for (n = 0; n < dev->n_subdevices; n++) {
1518                        struct comedi_subdevice *s = &dev->subdevices[n];
1519                        switch (layout->sdtype[n]) {
1520                        case sd_8254:
1521                                dio200_subdev_8254_cleanup(dev, s);
1522                                break;
1523                        case sd_8255:
1524                                subdev_8255_cleanup(dev, s);
1525                                break;
1526                        case sd_intr:
1527                                dio200_subdev_intr_cleanup(dev, s);
1528                                break;
1529                        default:
1530                                break;
1531                        }
1532                }
1533        }
1534        if (devpriv) {
1535#ifdef CONFIG_COMEDI_PCI
1536                if (devpriv->pci_dev) {
1537                        if (dev->iobase)
1538                                comedi_pci_disable(devpriv->pci_dev);
1539                        pci_dev_put(devpriv->pci_dev);
1540                } else
1541#endif
1542                {
1543                        if (dev->iobase)
1544                                release_region(dev->iobase, DIO200_IO_SIZE);
1545                }
1546        }
1547        if (dev->board_name)
1548                printk(KERN_INFO "comedi%d: %s removed\n",
1549                       dev->minor, dev->board_name);
1550
1551        return 0;
1552}
1553
1554MODULE_AUTHOR("Comedi http://www.comedi.org");
1555MODULE_DESCRIPTION("Comedi low-level driver");
1556MODULE_LICENSE("GPL");
1557
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.