linux/drivers/staging/comedi/drivers/dt2817.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/dt2817.c
   3    Hardware driver for Data Translation DT2817
   4
   5    COMEDI - Linux Control and Measurement Device Interface
   6    Copyright (C) 1998 David A. Schleef <ds@schleef.org>
   7
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 2 of the License, or
  11    (at your option) any later version.
  12
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17*/
  18/*
  19Driver: dt2817
  20Description: Data Translation DT2817
  21Author: ds
  22Status: complete
  23Devices: [Data Translation] DT2817 (dt2817)
  24
  25A very simple digital I/O card.  Four banks of 8 lines, each bank
  26is configurable for input or output.  One wonders why it takes a
  2750 page manual to describe this thing.
  28
  29The driver (which, btw, is much less than 50 pages) has 1 subdevice
  30with 32 channels, configurable in groups of 8.
  31
  32Configuration options:
  33  [0] - I/O port base base address
  34*/
  35
  36#include <linux/module.h>
  37#include "../comedidev.h"
  38
  39#define DT2817_CR 0
  40#define DT2817_DATA 1
  41
  42static int dt2817_dio_insn_config(struct comedi_device *dev,
  43                                  struct comedi_subdevice *s,
  44                                  struct comedi_insn *insn,
  45                                  unsigned int *data)
  46{
  47        unsigned int chan = CR_CHAN(insn->chanspec);
  48        unsigned int oe = 0;
  49        unsigned int mask;
  50        int ret;
  51
  52        if (chan < 8)
  53                mask = 0x000000ff;
  54        else if (chan < 16)
  55                mask = 0x0000ff00;
  56        else if (chan < 24)
  57                mask = 0x00ff0000;
  58        else
  59                mask = 0xff000000;
  60
  61        ret = comedi_dio_insn_config(dev, s, insn, data, mask);
  62        if (ret)
  63                return ret;
  64
  65        if (s->io_bits & 0x000000ff)
  66                oe |= 0x1;
  67        if (s->io_bits & 0x0000ff00)
  68                oe |= 0x2;
  69        if (s->io_bits & 0x00ff0000)
  70                oe |= 0x4;
  71        if (s->io_bits & 0xff000000)
  72                oe |= 0x8;
  73
  74        outb(oe, dev->iobase + DT2817_CR);
  75
  76        return insn->n;
  77}
  78
  79static int dt2817_dio_insn_bits(struct comedi_device *dev,
  80                                struct comedi_subdevice *s,
  81                                struct comedi_insn *insn,
  82                                unsigned int *data)
  83{
  84        unsigned long iobase = dev->iobase + DT2817_DATA;
  85        unsigned int mask;
  86        unsigned int val;
  87
  88        mask = comedi_dio_update_state(s, data);
  89        if (mask) {
  90                if (mask & 0x000000ff)
  91                        outb(s->state & 0xff, iobase + 0);
  92                if (mask & 0x0000ff00)
  93                        outb((s->state >> 8) & 0xff, iobase + 1);
  94                if (mask & 0x00ff0000)
  95                        outb((s->state >> 16) & 0xff, iobase + 2);
  96                if (mask & 0xff000000)
  97                        outb((s->state >> 24) & 0xff, iobase + 3);
  98        }
  99
 100        val = inb(iobase + 0);
 101        val |= (inb(iobase + 1) << 8);
 102        val |= (inb(iobase + 2) << 16);
 103        val |= (inb(iobase + 3) << 24);
 104
 105        data[1] = val;
 106
 107        return insn->n;
 108}
 109
 110static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 111{
 112        int ret;
 113        struct comedi_subdevice *s;
 114
 115        ret = comedi_request_region(dev, it->options[0], 0x5);
 116        if (ret)
 117                return ret;
 118
 119        ret = comedi_alloc_subdevices(dev, 1);
 120        if (ret)
 121                return ret;
 122
 123        s = &dev->subdevices[0];
 124
 125        s->n_chan = 32;
 126        s->type = COMEDI_SUBD_DIO;
 127        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 128        s->range_table = &range_digital;
 129        s->maxdata = 1;
 130        s->insn_bits = dt2817_dio_insn_bits;
 131        s->insn_config = dt2817_dio_insn_config;
 132
 133        s->state = 0;
 134        outb(0, dev->iobase + DT2817_CR);
 135
 136        return 0;
 137}
 138
 139static struct comedi_driver dt2817_driver = {
 140        .driver_name    = "dt2817",
 141        .module         = THIS_MODULE,
 142        .attach         = dt2817_attach,
 143        .detach         = comedi_legacy_detach,
 144};
 145module_comedi_driver(dt2817_driver);
 146
 147MODULE_AUTHOR("Comedi http://www.comedi.org");
 148MODULE_DESCRIPTION("Comedi low-level driver");
 149MODULE_LICENSE("GPL");
 150