linux/drivers/staging/comedi/drivers/pcl724.c
<<
>>
Prefs
   1/*
   2 * pcl724.c
   3 * Comedi driver for 8255 based ISA and PC/104 DIO boards
   4 *
   5 * Michal Dobes <dobes@tesnet.cz>
   6 */
   7
   8/*
   9 * Driver: pcl724
  10 * Description: Comedi driver for 8255 based ISA DIO boards
  11 * Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
  12 *  [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio),
  13 *  [WinSystems] PCM-IO48 (pcmio48),
  14 *  [Diamond Systems] ONYX-MM-DIO (onyx-mm-dio)
  15 * Author: Michal Dobes <dobes@tesnet.cz>
  16 * Status: untested
  17 *
  18 * Configuration options:
  19 *   [0] - IO Base
  20 *   [1] - IRQ (not supported)
  21 *   [2] - number of DIO (pcl722 and acl7122 boards)
  22 *         0, 144: 144 DIO configuration
  23 *         1,  96:  96 DIO configuration
  24 */
  25
  26#include <linux/module.h>
  27#include "../comedidev.h"
  28
  29#include "8255.h"
  30
  31struct pcl724_board {
  32        const char *name;
  33        unsigned int io_range;
  34        unsigned int can_have96:1;
  35        unsigned int is_pet48:1;
  36        int numofports;
  37};
  38
  39static const struct pcl724_board boardtypes[] = {
  40        {
  41                .name           = "pcl724",
  42                .io_range       = 0x04,
  43                .numofports     = 1,    /* 24 DIO channels */
  44        }, {
  45                .name           = "pcl722",
  46                .io_range       = 0x20,
  47                .can_have96     = 1,
  48                .numofports     = 6,    /* 144 (or 96) DIO channels */
  49        }, {
  50                .name           = "pcl731",
  51                .io_range       = 0x08,
  52                .numofports     = 2,    /* 48 DIO channels */
  53        }, {
  54                .name           = "acl7122",
  55                .io_range       = 0x20,
  56                .can_have96     = 1,
  57                .numofports     = 6,    /* 144 (or 96) DIO channels */
  58        }, {
  59                .name           = "acl7124",
  60                .io_range       = 0x04,
  61                .numofports     = 1,    /* 24 DIO channels */
  62        }, {
  63                .name           = "pet48dio",
  64                .io_range       = 0x02,
  65                .is_pet48       = 1,
  66                .numofports     = 2,    /* 48 DIO channels */
  67        }, {
  68                .name           = "pcmio48",
  69                .io_range       = 0x08,
  70                .numofports     = 2,    /* 48 DIO channels */
  71        }, {
  72                .name           = "onyx-mm-dio",
  73                .io_range       = 0x10,
  74                .numofports     = 2,    /* 48 DIO channels */
  75        },
  76};
  77
  78static int pcl724_8255mapped_io(struct comedi_device *dev,
  79                                int dir, int port, int data,
  80                                unsigned long iobase)
  81{
  82        int movport = I8255_SIZE * (iobase >> 12);
  83
  84        iobase &= 0x0fff;
  85
  86        outb(port + movport, iobase);
  87        if (dir) {
  88                outb(data, iobase + 1);
  89                return 0;
  90        }
  91        return inb(iobase + 1);
  92}
  93
  94static int pcl724_attach(struct comedi_device *dev,
  95                         struct comedi_devconfig *it)
  96{
  97        const struct pcl724_board *board = dev->board_ptr;
  98        struct comedi_subdevice *s;
  99        unsigned long iobase;
 100        unsigned int iorange;
 101        int n_subdevices;
 102        int ret;
 103        int i;
 104
 105        iorange = board->io_range;
 106        n_subdevices = board->numofports;
 107
 108        /* Handle PCL-724 in 96 DIO configuration */
 109        if (board->can_have96 &&
 110            (it->options[2] == 1 || it->options[2] == 96)) {
 111                iorange = 0x10;
 112                n_subdevices = 4;
 113        }
 114
 115        ret = comedi_request_region(dev, it->options[0], iorange);
 116        if (ret)
 117                return ret;
 118
 119        ret = comedi_alloc_subdevices(dev, n_subdevices);
 120        if (ret)
 121                return ret;
 122
 123        for (i = 0; i < dev->n_subdevices; i++) {
 124                s = &dev->subdevices[i];
 125                if (board->is_pet48) {
 126                        iobase = dev->iobase + (i * 0x1000);
 127                        ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
 128                                               iobase);
 129                } else {
 130                        ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
 131                }
 132                if (ret)
 133                        return ret;
 134        }
 135
 136        return 0;
 137}
 138
 139static struct comedi_driver pcl724_driver = {
 140        .driver_name    = "pcl724",
 141        .module         = THIS_MODULE,
 142        .attach         = pcl724_attach,
 143        .detach         = comedi_legacy_detach,
 144        .board_name     = &boardtypes[0].name,
 145        .num_names      = ARRAY_SIZE(boardtypes),
 146        .offset         = sizeof(struct pcl724_board),
 147};
 148module_comedi_driver(pcl724_driver);
 149
 150MODULE_AUTHOR("Comedi http://www.comedi.org");
 151MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards");
 152MODULE_LICENSE("GPL");
 153