linux/drivers/staging/comedi/drivers/adl_pci8164.c
<<
>>
Prefs
   1/*
   2 * comedi/drivers/adl_pci8164.c
   3 *
   4 * Hardware comedi driver for PCI-8164 Adlink card
   5 * Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 */
  17
  18/*
  19 * Driver: adl_pci8164
  20 * Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board
  21 * Devices: [ADLink] PCI-8164 (adl_pci8164)
  22 * Author: Michel Lachaine <mike@mikelachaine.ca>
  23 * Status: experimental
  24 * Updated: Mon, 14 Apr 2008 15:10:32 +0100
  25 *
  26 * Configuration Options: not applicable, uses PCI auto config
  27 */
  28
  29#include <linux/kernel.h>
  30#include <linux/module.h>
  31
  32#include "../comedi_pci.h"
  33
  34#define PCI8164_AXIS(x)         ((x) * 0x08)
  35#define PCI8164_CMD_MSTS_REG    0x00
  36#define PCI8164_OTP_SSTS_REG    0x02
  37#define PCI8164_BUF0_REG        0x04
  38#define PCI8164_BUF1_REG        0x06
  39
  40static int adl_pci8164_insn_read(struct comedi_device *dev,
  41                                 struct comedi_subdevice *s,
  42                                 struct comedi_insn *insn,
  43                                 unsigned int *data)
  44{
  45        unsigned long offset = (unsigned long)s->private;
  46        unsigned int chan = CR_CHAN(insn->chanspec);
  47        int i;
  48
  49        for (i = 0; i < insn->n; i++)
  50                data[i] = inw(dev->iobase + PCI8164_AXIS(chan) + offset);
  51
  52        return insn->n;
  53}
  54
  55static int adl_pci8164_insn_write(struct comedi_device *dev,
  56                                  struct comedi_subdevice *s,
  57                                  struct comedi_insn *insn,
  58                                  unsigned int *data)
  59{
  60        unsigned long offset = (unsigned long)s->private;
  61        unsigned int chan = CR_CHAN(insn->chanspec);
  62        int i;
  63
  64        for (i = 0; i < insn->n; i++)
  65                outw(data[i], dev->iobase + PCI8164_AXIS(chan) + offset);
  66
  67        return insn->n;
  68}
  69
  70static int adl_pci8164_auto_attach(struct comedi_device *dev,
  71                                   unsigned long context_unused)
  72{
  73        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
  74        struct comedi_subdevice *s;
  75        int ret;
  76
  77        ret = comedi_pci_enable(dev);
  78        if (ret)
  79                return ret;
  80        dev->iobase = pci_resource_start(pcidev, 2);
  81
  82        ret = comedi_alloc_subdevices(dev, 4);
  83        if (ret)
  84                return ret;
  85
  86        /* read MSTS register / write CMD register for each axis (channel) */
  87        s = &dev->subdevices[0];
  88        s->type         = COMEDI_SUBD_PROC;
  89        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
  90        s->n_chan       = 4;
  91        s->maxdata      = 0xffff;
  92        s->len_chanlist = 4;
  93        s->insn_read    = adl_pci8164_insn_read;
  94        s->insn_write   = adl_pci8164_insn_write;
  95        s->private      = (void *)PCI8164_CMD_MSTS_REG;
  96
  97        /* read SSTS register / write OTP register for each axis (channel) */
  98        s = &dev->subdevices[1];
  99        s->type         = COMEDI_SUBD_PROC;
 100        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 101        s->n_chan       = 4;
 102        s->maxdata      = 0xffff;
 103        s->len_chanlist = 4;
 104        s->insn_read    = adl_pci8164_insn_read;
 105        s->insn_write   = adl_pci8164_insn_write;
 106        s->private      = (void *)PCI8164_OTP_SSTS_REG;
 107
 108        /* read/write BUF0 register for each axis (channel) */
 109        s = &dev->subdevices[2];
 110        s->type         = COMEDI_SUBD_PROC;
 111        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 112        s->n_chan       = 4;
 113        s->maxdata      = 0xffff;
 114        s->len_chanlist = 4;
 115        s->insn_read    = adl_pci8164_insn_read;
 116        s->insn_write   = adl_pci8164_insn_write;
 117        s->private      = (void *)PCI8164_BUF0_REG;
 118
 119        /* read/write BUF1 register for each axis (channel) */
 120        s = &dev->subdevices[3];
 121        s->type         = COMEDI_SUBD_PROC;
 122        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 123        s->n_chan       = 4;
 124        s->maxdata      = 0xffff;
 125        s->len_chanlist = 4;
 126        s->insn_read    = adl_pci8164_insn_read;
 127        s->insn_write   = adl_pci8164_insn_write;
 128        s->private      = (void *)PCI8164_BUF1_REG;
 129
 130        return 0;
 131}
 132
 133static struct comedi_driver adl_pci8164_driver = {
 134        .driver_name    = "adl_pci8164",
 135        .module         = THIS_MODULE,
 136        .auto_attach    = adl_pci8164_auto_attach,
 137        .detach         = comedi_pci_detach,
 138};
 139
 140static int adl_pci8164_pci_probe(struct pci_dev *dev,
 141                                 const struct pci_device_id *id)
 142{
 143        return comedi_pci_auto_config(dev, &adl_pci8164_driver,
 144                                      id->driver_data);
 145}
 146
 147static const struct pci_device_id adl_pci8164_pci_table[] = {
 148        { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x8164) },
 149        { 0 }
 150};
 151MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
 152
 153static struct pci_driver adl_pci8164_pci_driver = {
 154        .name           = "adl_pci8164",
 155        .id_table       = adl_pci8164_pci_table,
 156        .probe          = adl_pci8164_pci_probe,
 157        .remove         = comedi_pci_auto_unconfig,
 158};
 159module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver);
 160
 161MODULE_AUTHOR("Comedi http://www.comedi.org");
 162MODULE_DESCRIPTION("Comedi low-level driver");
 163MODULE_LICENSE("GPL");
 164