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