linux/drivers/staging/comedi/drivers/poc.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/poc.c
   3    Mini-drivers for POC (Piece of Crap) boards
   4    Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
   5    Copyright (C) 2001 David A. Schleef <ds@schleef.org>
   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/*
  18Driver: poc
  19Description: Generic driver for very simple devices
  20Author: ds
  21Devices: [Keithley Metrabyte] DAC-02 (dac02)
  22Updated: Sat, 16 Mar 2002 17:34:48 -0800
  23Status: unknown
  24
  25This driver is indended to support very simple ISA-based devices,
  26including:
  27  dac02 - Keithley DAC-02 analog output board
  28
  29Configuration options:
  30  [0] - I/O port base
  31*/
  32
  33#include <linux/module.h>
  34#include "../comedidev.h"
  35
  36struct boarddef_struct {
  37        const char *name;
  38        unsigned int iosize;
  39        int (*setup) (struct comedi_device *);
  40        int type;
  41        int n_chan;
  42        int n_bits;
  43        int (*winsn) (struct comedi_device *, struct comedi_subdevice *,
  44                      struct comedi_insn *, unsigned int *);
  45        int (*rinsn) (struct comedi_device *, struct comedi_subdevice *,
  46                      struct comedi_insn *, unsigned int *);
  47        int (*insnbits) (struct comedi_device *, struct comedi_subdevice *,
  48                         struct comedi_insn *, unsigned int *);
  49        const struct comedi_lrange *range;
  50};
  51
  52struct poc_private {
  53        unsigned int ao_readback[32];
  54};
  55
  56static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
  57                         struct comedi_insn *insn, unsigned int *data)
  58{
  59        struct poc_private *devpriv = dev->private;
  60        int chan;
  61
  62        chan = CR_CHAN(insn->chanspec);
  63        data[0] = devpriv->ao_readback[chan];
  64
  65        return 1;
  66}
  67
  68/* DAC-02 registers */
  69#define DAC02_LSB(a)    (2 * a)
  70#define DAC02_MSB(a)    (2 * a + 1)
  71
  72static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
  73                          struct comedi_insn *insn, unsigned int *data)
  74{
  75        struct poc_private *devpriv = dev->private;
  76        int temp;
  77        int chan;
  78        int output;
  79
  80        chan = CR_CHAN(insn->chanspec);
  81        devpriv->ao_readback[chan] = data[0];
  82        output = data[0];
  83#ifdef wrong
  84        /*  convert to complementary binary if range is bipolar */
  85        if ((CR_RANGE(insn->chanspec) & 0x2) == 0)
  86                output = ~output;
  87#endif
  88        temp = (output << 4) & 0xf0;
  89        outb(temp, dev->iobase + DAC02_LSB(chan));
  90        temp = (output >> 4) & 0xff;
  91        outb(temp, dev->iobase + DAC02_MSB(chan));
  92
  93        return 1;
  94}
  95
  96static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
  97{
  98        const struct boarddef_struct *board = comedi_board(dev);
  99        struct poc_private *devpriv;
 100        struct comedi_subdevice *s;
 101        int ret;
 102
 103        ret = comedi_request_region(dev, it->options[0], board->iosize);
 104        if (ret)
 105                return ret;
 106
 107        ret = comedi_alloc_subdevices(dev, 1);
 108        if (ret)
 109                return ret;
 110
 111        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 112        if (!devpriv)
 113                return -ENOMEM;
 114
 115        /* analog output subdevice */
 116        s = &dev->subdevices[0];
 117        s->type = board->type;
 118        s->n_chan = board->n_chan;
 119        s->maxdata = (1 << board->n_bits) - 1;
 120        s->range_table = board->range;
 121        s->insn_write = board->winsn;
 122        s->insn_read = board->rinsn;
 123        s->insn_bits = board->insnbits;
 124        if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO)
 125                s->subdev_flags = SDF_WRITABLE;
 126
 127        return 0;
 128}
 129
 130static const struct boarddef_struct boards[] = {
 131        {
 132                .name           = "dac02",
 133                .iosize         = 8,
 134                /* .setup       = dac02_setup, */
 135                .type           = COMEDI_SUBD_AO,
 136                .n_chan         = 2,
 137                .n_bits         = 12,
 138                .winsn          = dac02_ao_winsn,
 139                .rinsn          = readback_insn,
 140                .range          = &range_unknown,
 141        },
 142};
 143
 144static struct comedi_driver poc_driver = {
 145        .driver_name    = "poc",
 146        .module         = THIS_MODULE,
 147        .attach         = poc_attach,
 148        .detach         = comedi_legacy_detach,
 149        .board_name     = &boards[0].name,
 150        .num_names      = ARRAY_SIZE(boards),
 151        .offset         = sizeof(boards[0]),
 152};
 153module_comedi_driver(poc_driver);
 154
 155MODULE_AUTHOR("Comedi http://www.comedi.org");
 156MODULE_DESCRIPTION("Comedi low-level driver");
 157MODULE_LICENSE("GPL");
 158