152 lines
3.5 KiB
C
152 lines
3.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* pcl724.c
|
|
* Comedi driver for 8255 based ISA and PC/104 DIO boards
|
|
*
|
|
* Michal Dobes <dobes@tesnet.cz>
|
|
*/
|
|
|
|
/*
|
|
* Driver: pcl724
|
|
* Description: Comedi driver for 8255 based ISA DIO boards
|
|
* Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
|
|
* [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio),
|
|
* [WinSystems] PCM-IO48 (pcmio48),
|
|
* [Diamond Systems] ONYX-MM-DIO (onyx-mm-dio)
|
|
* Author: Michal Dobes <dobes@tesnet.cz>
|
|
* Status: untested
|
|
*
|
|
* Configuration options:
|
|
* [0] - IO Base
|
|
* [1] - IRQ (not supported)
|
|
* [2] - number of DIO (pcl722 and acl7122 boards)
|
|
* 0, 144: 144 DIO configuration
|
|
* 1, 96: 96 DIO configuration
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/comedi/comedidev.h>
|
|
#include <linux/comedi/comedi_8255.h>
|
|
|
|
struct pcl724_board {
|
|
const char *name;
|
|
unsigned int io_range;
|
|
unsigned int can_have96:1;
|
|
unsigned int is_pet48:1;
|
|
int numofports;
|
|
};
|
|
|
|
static const struct pcl724_board boardtypes[] = {
|
|
{
|
|
.name = "pcl724",
|
|
.io_range = 0x04,
|
|
.numofports = 1, /* 24 DIO channels */
|
|
}, {
|
|
.name = "pcl722",
|
|
.io_range = 0x20,
|
|
.can_have96 = 1,
|
|
.numofports = 6, /* 144 (or 96) DIO channels */
|
|
}, {
|
|
.name = "pcl731",
|
|
.io_range = 0x08,
|
|
.numofports = 2, /* 48 DIO channels */
|
|
}, {
|
|
.name = "acl7122",
|
|
.io_range = 0x20,
|
|
.can_have96 = 1,
|
|
.numofports = 6, /* 144 (or 96) DIO channels */
|
|
}, {
|
|
.name = "acl7124",
|
|
.io_range = 0x04,
|
|
.numofports = 1, /* 24 DIO channels */
|
|
}, {
|
|
.name = "pet48dio",
|
|
.io_range = 0x02,
|
|
.is_pet48 = 1,
|
|
.numofports = 2, /* 48 DIO channels */
|
|
}, {
|
|
.name = "pcmio48",
|
|
.io_range = 0x08,
|
|
.numofports = 2, /* 48 DIO channels */
|
|
}, {
|
|
.name = "onyx-mm-dio",
|
|
.io_range = 0x10,
|
|
.numofports = 2, /* 48 DIO channels */
|
|
},
|
|
};
|
|
|
|
static int pcl724_8255mapped_io(struct comedi_device *dev,
|
|
int dir, int port, int data,
|
|
unsigned long iobase)
|
|
{
|
|
int movport = I8255_SIZE * (iobase >> 12);
|
|
|
|
iobase &= 0x0fff;
|
|
|
|
outb(port + movport, iobase);
|
|
if (dir) {
|
|
outb(data, iobase + 1);
|
|
return 0;
|
|
}
|
|
return inb(iobase + 1);
|
|
}
|
|
|
|
static int pcl724_attach(struct comedi_device *dev,
|
|
struct comedi_devconfig *it)
|
|
{
|
|
const struct pcl724_board *board = dev->board_ptr;
|
|
struct comedi_subdevice *s;
|
|
unsigned long iobase;
|
|
unsigned int iorange;
|
|
int n_subdevices;
|
|
int ret;
|
|
int i;
|
|
|
|
iorange = board->io_range;
|
|
n_subdevices = board->numofports;
|
|
|
|
/* Handle PCL-724 in 96 DIO configuration */
|
|
if (board->can_have96 &&
|
|
(it->options[2] == 1 || it->options[2] == 96)) {
|
|
iorange = 0x10;
|
|
n_subdevices = 4;
|
|
}
|
|
|
|
ret = comedi_request_region(dev, it->options[0], iorange);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = comedi_alloc_subdevices(dev, n_subdevices);
|
|
if (ret)
|
|
return ret;
|
|
|
|
for (i = 0; i < dev->n_subdevices; i++) {
|
|
s = &dev->subdevices[i];
|
|
if (board->is_pet48) {
|
|
iobase = dev->iobase + (i * 0x1000);
|
|
ret = subdev_8255_cb_init(dev, s, pcl724_8255mapped_io,
|
|
iobase);
|
|
} else {
|
|
ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
|
|
}
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct comedi_driver pcl724_driver = {
|
|
.driver_name = "pcl724",
|
|
.module = THIS_MODULE,
|
|
.attach = pcl724_attach,
|
|
.detach = comedi_legacy_detach,
|
|
.board_name = &boardtypes[0].name,
|
|
.num_names = ARRAY_SIZE(boardtypes),
|
|
.offset = sizeof(struct pcl724_board),
|
|
};
|
|
module_comedi_driver(pcl724_driver);
|
|
|
|
MODULE_AUTHOR("Comedi https://www.comedi.org");
|
|
MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards");
|
|
MODULE_LICENSE("GPL");
|