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