linux/drivers/staging/comedi/drivers/adl_pci7x3x.c
<<
>>
Prefs
   1/*
   2 * COMEDI driver for the ADLINK PCI-723x/743x series boards.
   3 * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
   4 *
   5 * Based on the adl_pci7230 driver written by:
   6 *      David Fernandez <dfcastelao@gmail.com>
   7 * and the adl_pci7432 driver written by:
   8 *      Michel Lachaine <mike@mikelachaine.ca>
   9 *
  10 * COMEDI - Linux Control and Measurement Device Interface
  11 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 */
  23
  24/*
  25Driver: adl_pci7x3x
  26Description: 32/64-Channel Isolated Digital I/O Boards
  27Devices: (ADLink) PCI-7230 [adl_pci7230] - 16 input / 16 output
  28         (ADLink) PCI-7233 [adl_pci7233] - 32 input
  29         (ADLink) PCI-7234 [adl_pci7234] - 32 output
  30         (ADLink) PCI-7432 [adl_pci7432] - 32 input / 32 output
  31         (ADLink) PCI-7433 [adl_pci7433] - 64 input
  32         (ADLink) PCI-7434 [adl_pci7434] - 64 output
  33Author: H Hartley Sweeten <hsweeten@visionengravers.com>
  34Updated: Thu, 02 Aug 2012 14:27:46 -0700
  35Status: untested
  36
  37The PCI-7230, PCI-7432 and PCI-7433 boards also support external
  38interrupt signals on digital input channels 0 and 1. The PCI-7233
  39has dual-interrupt sources for change-of-state (COS) on any 16
  40digital input channels of LSB and for COS on any 16 digital input
  41lines of MSB. Interrupts are not currently supported by this
  42driver.
  43
  44Configuration Options: not applicable, uses comedi PCI auto config
  45*/
  46
  47#include <linux/module.h>
  48#include <linux/pci.h>
  49
  50#include "../comedidev.h"
  51
  52/*
  53 * Register I/O map (32-bit access only)
  54 */
  55#define PCI7X3X_DIO_REG         0x00
  56#define PCI743X_DIO_REG         0x04
  57
  58enum apci1516_boardid {
  59        BOARD_PCI7230,
  60        BOARD_PCI7233,
  61        BOARD_PCI7234,
  62        BOARD_PCI7432,
  63        BOARD_PCI7433,
  64        BOARD_PCI7434,
  65};
  66
  67struct adl_pci7x3x_boardinfo {
  68        const char *name;
  69        int nsubdevs;
  70        int di_nchan;
  71        int do_nchan;
  72};
  73
  74static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = {
  75        [BOARD_PCI7230] = {
  76                .name           = "adl_pci7230",
  77                .nsubdevs       = 2,
  78                .di_nchan       = 16,
  79                .do_nchan       = 16,
  80        },
  81        [BOARD_PCI7233] = {
  82                .name           = "adl_pci7233",
  83                .nsubdevs       = 1,
  84                .di_nchan       = 32,
  85        },
  86        [BOARD_PCI7234] = {
  87                .name           = "adl_pci7234",
  88                .nsubdevs       = 1,
  89                .do_nchan       = 32,
  90        },
  91        [BOARD_PCI7432] = {
  92                .name           = "adl_pci7432",
  93                .nsubdevs       = 2,
  94                .di_nchan       = 32,
  95                .do_nchan       = 32,
  96        },
  97        [BOARD_PCI7433] = {
  98                .name           = "adl_pci7433",
  99                .nsubdevs       = 2,
 100                .di_nchan       = 64,
 101        },
 102        [BOARD_PCI7434] = {
 103                .name           = "adl_pci7434",
 104                .nsubdevs       = 2,
 105                .do_nchan       = 64,
 106        }
 107};
 108
 109static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev,
 110                                    struct comedi_subdevice *s,
 111                                    struct comedi_insn *insn,
 112                                    unsigned int *data)
 113{
 114        unsigned long reg = (unsigned long)s->private;
 115
 116        if (comedi_dio_update_state(s, data))
 117                outl(s->state, dev->iobase + reg);
 118
 119        data[1] = s->state;
 120
 121        return insn->n;
 122}
 123
 124static int adl_pci7x3x_di_insn_bits(struct comedi_device *dev,
 125                                    struct comedi_subdevice *s,
 126                                    struct comedi_insn *insn,
 127                                    unsigned int *data)
 128{
 129        unsigned long reg = (unsigned long)s->private;
 130
 131        data[1] = inl(dev->iobase + reg);
 132
 133        return insn->n;
 134}
 135
 136static int adl_pci7x3x_auto_attach(struct comedi_device *dev,
 137                                   unsigned long context)
 138{
 139        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 140        const struct adl_pci7x3x_boardinfo *board = NULL;
 141        struct comedi_subdevice *s;
 142        int subdev;
 143        int nchan;
 144        int ret;
 145
 146        if (context < ARRAY_SIZE(adl_pci7x3x_boards))
 147                board = &adl_pci7x3x_boards[context];
 148        if (!board)
 149                return -ENODEV;
 150        dev->board_ptr = board;
 151        dev->board_name = board->name;
 152
 153        ret = comedi_pci_enable(dev);
 154        if (ret)
 155                return ret;
 156        dev->iobase = pci_resource_start(pcidev, 2);
 157
 158        /*
 159         * One or two subdevices are setup by this driver depending on
 160         * the number of digital inputs and/or outputs provided by the
 161         * board. Each subdevice has a maximum of 32 channels.
 162         *
 163         *      PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output
 164         *      PCI-7233 - 1 subdevice: 0 - 32 input
 165         *      PCI-7234 - 1 subdevice: 0 - 32 output
 166         *      PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output
 167         *      PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input
 168         *      PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output
 169         */
 170        ret = comedi_alloc_subdevices(dev, board->nsubdevs);
 171        if (ret)
 172                return ret;
 173
 174        subdev = 0;
 175
 176        if (board->di_nchan) {
 177                nchan = min(board->di_nchan, 32);
 178
 179                s = &dev->subdevices[subdev];
 180                /* Isolated digital inputs 0 to 15/31 */
 181                s->type         = COMEDI_SUBD_DI;
 182                s->subdev_flags = SDF_READABLE;
 183                s->n_chan       = nchan;
 184                s->maxdata      = 1;
 185                s->insn_bits    = adl_pci7x3x_di_insn_bits;
 186                s->range_table  = &range_digital;
 187
 188                s->private      = (void *)PCI7X3X_DIO_REG;
 189
 190                subdev++;
 191
 192                nchan = board->di_nchan - nchan;
 193                if (nchan) {
 194                        s = &dev->subdevices[subdev];
 195                        /* Isolated digital inputs 32 to 63 */
 196                        s->type         = COMEDI_SUBD_DI;
 197                        s->subdev_flags = SDF_READABLE;
 198                        s->n_chan       = nchan;
 199                        s->maxdata      = 1;
 200                        s->insn_bits    = adl_pci7x3x_di_insn_bits;
 201                        s->range_table  = &range_digital;
 202
 203                        s->private      = (void *)PCI743X_DIO_REG;
 204
 205                        subdev++;
 206                }
 207        }
 208
 209        if (board->do_nchan) {
 210                nchan = min(board->do_nchan, 32);
 211
 212                s = &dev->subdevices[subdev];
 213                /* Isolated digital outputs 0 to 15/31 */
 214                s->type         = COMEDI_SUBD_DO;
 215                s->subdev_flags = SDF_WRITABLE;
 216                s->n_chan       = nchan;
 217                s->maxdata      = 1;
 218                s->insn_bits    = adl_pci7x3x_do_insn_bits;
 219                s->range_table  = &range_digital;
 220
 221                s->private      = (void *)PCI7X3X_DIO_REG;
 222
 223                subdev++;
 224
 225                nchan = board->do_nchan - nchan;
 226                if (nchan) {
 227                        s = &dev->subdevices[subdev];
 228                        /* Isolated digital outputs 32 to 63 */
 229                        s->type         = COMEDI_SUBD_DO;
 230                        s->subdev_flags = SDF_WRITABLE;
 231                        s->n_chan       = nchan;
 232                        s->maxdata      = 1;
 233                        s->insn_bits    = adl_pci7x3x_do_insn_bits;
 234                        s->range_table  = &range_digital;
 235
 236                        s->private      = (void *)PCI743X_DIO_REG;
 237
 238                        subdev++;
 239                }
 240        }
 241
 242        return 0;
 243}
 244
 245static struct comedi_driver adl_pci7x3x_driver = {
 246        .driver_name    = "adl_pci7x3x",
 247        .module         = THIS_MODULE,
 248        .auto_attach    = adl_pci7x3x_auto_attach,
 249        .detach         = comedi_pci_detach,
 250};
 251
 252static int adl_pci7x3x_pci_probe(struct pci_dev *dev,
 253                                 const struct pci_device_id *id)
 254{
 255        return comedi_pci_auto_config(dev, &adl_pci7x3x_driver,
 256                                      id->driver_data);
 257}
 258
 259static const struct pci_device_id adl_pci7x3x_pci_table[] = {
 260        { PCI_VDEVICE(ADLINK, 0x7230), BOARD_PCI7230 },
 261        { PCI_VDEVICE(ADLINK, 0x7233), BOARD_PCI7233 },
 262        { PCI_VDEVICE(ADLINK, 0x7234), BOARD_PCI7234 },
 263        { PCI_VDEVICE(ADLINK, 0x7432), BOARD_PCI7432 },
 264        { PCI_VDEVICE(ADLINK, 0x7433), BOARD_PCI7433 },
 265        { PCI_VDEVICE(ADLINK, 0x7434), BOARD_PCI7434 },
 266        { 0 }
 267};
 268MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table);
 269
 270static struct pci_driver adl_pci7x3x_pci_driver = {
 271        .name           = "adl_pci7x3x",
 272        .id_table       = adl_pci7x3x_pci_table,
 273        .probe          = adl_pci7x3x_pci_probe,
 274        .remove         = comedi_pci_auto_unconfig,
 275};
 276module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
 277
 278MODULE_DESCRIPTION("ADLINK PCI-723x/743x Isolated Digital I/O boards");
 279MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
 280MODULE_LICENSE("GPL");
 281
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.