linux/drivers/staging/comedi/drivers/pcl725.c
<<
>>
Prefs
   1/*
   2 * comedi/drivers/pcl725.c
   3 * Driver for PCL725 and clones
   4 * David A. Schleef
   5 */
   6/*
   7Driver: pcl725
   8Description: Advantech PCL-725 (& compatibles)
   9Author: ds
  10Status: unknown
  11Devices: [Advantech] PCL-725 (pcl725)
  12*/
  13
  14#include "../comedidev.h"
  15
  16#include <linux/ioport.h>
  17
  18#define PCL725_SIZE 2
  19
  20#define PCL725_DO 0
  21#define PCL725_DI 1
  22
  23static int pcl725_attach(struct comedi_device *dev,
  24                         struct comedi_devconfig *it);
  25static int pcl725_detach(struct comedi_device *dev);
  26static struct comedi_driver driver_pcl725 = {
  27        .driver_name = "pcl725",
  28        .module = THIS_MODULE,
  29        .attach = pcl725_attach,
  30        .detach = pcl725_detach,
  31};
  32
  33static int __init driver_pcl725_init_module(void)
  34{
  35        return comedi_driver_register(&driver_pcl725);
  36}
  37
  38static void __exit driver_pcl725_cleanup_module(void)
  39{
  40        comedi_driver_unregister(&driver_pcl725);
  41}
  42
  43module_init(driver_pcl725_init_module);
  44module_exit(driver_pcl725_cleanup_module);
  45
  46static int pcl725_do_insn(struct comedi_device *dev, struct comedi_subdevice *s,
  47                          struct comedi_insn *insn, unsigned int *data)
  48{
  49        if (insn->n != 2)
  50                return -EINVAL;
  51
  52        if (data[0]) {
  53                s->state &= ~data[0];
  54                s->state |= (data[0] & data[1]);
  55                outb(s->state, dev->iobase + PCL725_DO);
  56        }
  57
  58        data[1] = s->state;
  59
  60        return 2;
  61}
  62
  63static int pcl725_di_insn(struct comedi_device *dev, struct comedi_subdevice *s,
  64                          struct comedi_insn *insn, unsigned int *data)
  65{
  66        if (insn->n != 2)
  67                return -EINVAL;
  68
  69        data[1] = inb(dev->iobase + PCL725_DI);
  70
  71        return 2;
  72}
  73
  74static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
  75{
  76        struct comedi_subdevice *s;
  77        unsigned long iobase;
  78
  79        iobase = it->options[0];
  80        printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
  81        if (!request_region(iobase, PCL725_SIZE, "pcl725")) {
  82                printk("I/O port conflict\n");
  83                return -EIO;
  84        }
  85        dev->board_name = "pcl725";
  86        dev->iobase = iobase;
  87        dev->irq = 0;
  88
  89        if (alloc_subdevices(dev, 2) < 0)
  90                return -ENOMEM;
  91
  92        s = dev->subdevices + 0;
  93        /* do */
  94        s->type = COMEDI_SUBD_DO;
  95        s->subdev_flags = SDF_WRITABLE;
  96        s->maxdata = 1;
  97        s->n_chan = 8;
  98        s->insn_bits = pcl725_do_insn;
  99        s->range_table = &range_digital;
 100
 101        s = dev->subdevices + 1;
 102        /* di */
 103        s->type = COMEDI_SUBD_DI;
 104        s->subdev_flags = SDF_READABLE;
 105        s->maxdata = 1;
 106        s->n_chan = 8;
 107        s->insn_bits = pcl725_di_insn;
 108        s->range_table = &range_digital;
 109
 110        printk(KERN_INFO "\n");
 111
 112        return 0;
 113}
 114
 115static int pcl725_detach(struct comedi_device *dev)
 116{
 117        printk(KERN_INFO "comedi%d: pcl725: remove\n", dev->minor);
 118
 119        if (dev->iobase)
 120                release_region(dev->iobase, PCL725_SIZE);
 121
 122        return 0;
 123}
 124
 125MODULE_AUTHOR("Comedi http://www.comedi.org");
 126MODULE_DESCRIPTION("Comedi low-level driver");
 127MODULE_LICENSE("GPL");
 128