18ffdff6aSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
28ffdff6aSGreg Kroah-Hartman /*
38ffdff6aSGreg Kroah-Hartman * pcl724.c
48ffdff6aSGreg Kroah-Hartman * Comedi driver for 8255 based ISA and PC/104 DIO boards
58ffdff6aSGreg Kroah-Hartman *
68ffdff6aSGreg Kroah-Hartman * Michal Dobes <dobes@tesnet.cz>
78ffdff6aSGreg Kroah-Hartman */
88ffdff6aSGreg Kroah-Hartman
98ffdff6aSGreg Kroah-Hartman /*
108ffdff6aSGreg Kroah-Hartman * Driver: pcl724
118ffdff6aSGreg Kroah-Hartman * Description: Comedi driver for 8255 based ISA DIO boards
128ffdff6aSGreg Kroah-Hartman * Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
138ffdff6aSGreg Kroah-Hartman * [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio),
148ffdff6aSGreg Kroah-Hartman * [WinSystems] PCM-IO48 (pcmio48),
158ffdff6aSGreg Kroah-Hartman * [Diamond Systems] ONYX-MM-DIO (onyx-mm-dio)
168ffdff6aSGreg Kroah-Hartman * Author: Michal Dobes <dobes@tesnet.cz>
178ffdff6aSGreg Kroah-Hartman * Status: untested
188ffdff6aSGreg Kroah-Hartman *
198ffdff6aSGreg Kroah-Hartman * Configuration options:
208ffdff6aSGreg Kroah-Hartman * [0] - IO Base
218ffdff6aSGreg Kroah-Hartman * [1] - IRQ (not supported)
228ffdff6aSGreg Kroah-Hartman * [2] - number of DIO (pcl722 and acl7122 boards)
238ffdff6aSGreg Kroah-Hartman * 0, 144: 144 DIO configuration
248ffdff6aSGreg Kroah-Hartman * 1, 96: 96 DIO configuration
258ffdff6aSGreg Kroah-Hartman */
268ffdff6aSGreg Kroah-Hartman
278ffdff6aSGreg Kroah-Hartman #include <linux/module.h>
28df0e68c1SIan Abbott #include <linux/comedi/comedidev.h>
29*631e272bSIan Abbott #include <linux/comedi/comedi_8255.h>
308ffdff6aSGreg Kroah-Hartman
318ffdff6aSGreg Kroah-Hartman struct pcl724_board {
328ffdff6aSGreg Kroah-Hartman const char *name;
338ffdff6aSGreg Kroah-Hartman unsigned int io_range;
348ffdff6aSGreg Kroah-Hartman unsigned int can_have96:1;
358ffdff6aSGreg Kroah-Hartman unsigned int is_pet48:1;
368ffdff6aSGreg Kroah-Hartman int numofports;
378ffdff6aSGreg Kroah-Hartman };
388ffdff6aSGreg Kroah-Hartman
398ffdff6aSGreg Kroah-Hartman static const struct pcl724_board boardtypes[] = {
408ffdff6aSGreg Kroah-Hartman {
418ffdff6aSGreg Kroah-Hartman .name = "pcl724",
428ffdff6aSGreg Kroah-Hartman .io_range = 0x04,
438ffdff6aSGreg Kroah-Hartman .numofports = 1, /* 24 DIO channels */
448ffdff6aSGreg Kroah-Hartman }, {
458ffdff6aSGreg Kroah-Hartman .name = "pcl722",
468ffdff6aSGreg Kroah-Hartman .io_range = 0x20,
478ffdff6aSGreg Kroah-Hartman .can_have96 = 1,
488ffdff6aSGreg Kroah-Hartman .numofports = 6, /* 144 (or 96) DIO channels */
498ffdff6aSGreg Kroah-Hartman }, {
508ffdff6aSGreg Kroah-Hartman .name = "pcl731",
518ffdff6aSGreg Kroah-Hartman .io_range = 0x08,
528ffdff6aSGreg Kroah-Hartman .numofports = 2, /* 48 DIO channels */
538ffdff6aSGreg Kroah-Hartman }, {
548ffdff6aSGreg Kroah-Hartman .name = "acl7122",
558ffdff6aSGreg Kroah-Hartman .io_range = 0x20,
568ffdff6aSGreg Kroah-Hartman .can_have96 = 1,
578ffdff6aSGreg Kroah-Hartman .numofports = 6, /* 144 (or 96) DIO channels */
588ffdff6aSGreg Kroah-Hartman }, {
598ffdff6aSGreg Kroah-Hartman .name = "acl7124",
608ffdff6aSGreg Kroah-Hartman .io_range = 0x04,
618ffdff6aSGreg Kroah-Hartman .numofports = 1, /* 24 DIO channels */
628ffdff6aSGreg Kroah-Hartman }, {
638ffdff6aSGreg Kroah-Hartman .name = "pet48dio",
648ffdff6aSGreg Kroah-Hartman .io_range = 0x02,
658ffdff6aSGreg Kroah-Hartman .is_pet48 = 1,
668ffdff6aSGreg Kroah-Hartman .numofports = 2, /* 48 DIO channels */
678ffdff6aSGreg Kroah-Hartman }, {
688ffdff6aSGreg Kroah-Hartman .name = "pcmio48",
698ffdff6aSGreg Kroah-Hartman .io_range = 0x08,
708ffdff6aSGreg Kroah-Hartman .numofports = 2, /* 48 DIO channels */
718ffdff6aSGreg Kroah-Hartman }, {
728ffdff6aSGreg Kroah-Hartman .name = "onyx-mm-dio",
738ffdff6aSGreg Kroah-Hartman .io_range = 0x10,
748ffdff6aSGreg Kroah-Hartman .numofports = 2, /* 48 DIO channels */
758ffdff6aSGreg Kroah-Hartman },
768ffdff6aSGreg Kroah-Hartman };
778ffdff6aSGreg Kroah-Hartman
pcl724_8255mapped_io(struct comedi_device * dev,int dir,int port,int data,unsigned long iobase)788ffdff6aSGreg Kroah-Hartman static int pcl724_8255mapped_io(struct comedi_device *dev,
798ffdff6aSGreg Kroah-Hartman int dir, int port, int data,
808ffdff6aSGreg Kroah-Hartman unsigned long iobase)
818ffdff6aSGreg Kroah-Hartman {
828ffdff6aSGreg Kroah-Hartman int movport = I8255_SIZE * (iobase >> 12);
838ffdff6aSGreg Kroah-Hartman
848ffdff6aSGreg Kroah-Hartman iobase &= 0x0fff;
858ffdff6aSGreg Kroah-Hartman
868ffdff6aSGreg Kroah-Hartman outb(port + movport, iobase);
878ffdff6aSGreg Kroah-Hartman if (dir) {
888ffdff6aSGreg Kroah-Hartman outb(data, iobase + 1);
898ffdff6aSGreg Kroah-Hartman return 0;
908ffdff6aSGreg Kroah-Hartman }
918ffdff6aSGreg Kroah-Hartman return inb(iobase + 1);
928ffdff6aSGreg Kroah-Hartman }
938ffdff6aSGreg Kroah-Hartman
pcl724_attach(struct comedi_device * dev,struct comedi_devconfig * it)948ffdff6aSGreg Kroah-Hartman static int pcl724_attach(struct comedi_device *dev,
958ffdff6aSGreg Kroah-Hartman struct comedi_devconfig *it)
968ffdff6aSGreg Kroah-Hartman {
978ffdff6aSGreg Kroah-Hartman const struct pcl724_board *board = dev->board_ptr;
988ffdff6aSGreg Kroah-Hartman struct comedi_subdevice *s;
998ffdff6aSGreg Kroah-Hartman unsigned long iobase;
1008ffdff6aSGreg Kroah-Hartman unsigned int iorange;
1018ffdff6aSGreg Kroah-Hartman int n_subdevices;
1028ffdff6aSGreg Kroah-Hartman int ret;
1038ffdff6aSGreg Kroah-Hartman int i;
1048ffdff6aSGreg Kroah-Hartman
1058ffdff6aSGreg Kroah-Hartman iorange = board->io_range;
1068ffdff6aSGreg Kroah-Hartman n_subdevices = board->numofports;
1078ffdff6aSGreg Kroah-Hartman
1088ffdff6aSGreg Kroah-Hartman /* Handle PCL-724 in 96 DIO configuration */
1098ffdff6aSGreg Kroah-Hartman if (board->can_have96 &&
1108ffdff6aSGreg Kroah-Hartman (it->options[2] == 1 || it->options[2] == 96)) {
1118ffdff6aSGreg Kroah-Hartman iorange = 0x10;
1128ffdff6aSGreg Kroah-Hartman n_subdevices = 4;
1138ffdff6aSGreg Kroah-Hartman }
1148ffdff6aSGreg Kroah-Hartman
1158ffdff6aSGreg Kroah-Hartman ret = comedi_request_region(dev, it->options[0], iorange);
1168ffdff6aSGreg Kroah-Hartman if (ret)
1178ffdff6aSGreg Kroah-Hartman return ret;
1188ffdff6aSGreg Kroah-Hartman
1198ffdff6aSGreg Kroah-Hartman ret = comedi_alloc_subdevices(dev, n_subdevices);
1208ffdff6aSGreg Kroah-Hartman if (ret)
1218ffdff6aSGreg Kroah-Hartman return ret;
1228ffdff6aSGreg Kroah-Hartman
1238ffdff6aSGreg Kroah-Hartman for (i = 0; i < dev->n_subdevices; i++) {
1248ffdff6aSGreg Kroah-Hartman s = &dev->subdevices[i];
1258ffdff6aSGreg Kroah-Hartman if (board->is_pet48) {
1268ffdff6aSGreg Kroah-Hartman iobase = dev->iobase + (i * 0x1000);
1278ffdff6aSGreg Kroah-Hartman ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
1288ffdff6aSGreg Kroah-Hartman iobase);
1298ffdff6aSGreg Kroah-Hartman } else {
1308ffdff6aSGreg Kroah-Hartman ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
1318ffdff6aSGreg Kroah-Hartman }
1328ffdff6aSGreg Kroah-Hartman if (ret)
1338ffdff6aSGreg Kroah-Hartman return ret;
1348ffdff6aSGreg Kroah-Hartman }
1358ffdff6aSGreg Kroah-Hartman
1368ffdff6aSGreg Kroah-Hartman return 0;
1378ffdff6aSGreg Kroah-Hartman }
1388ffdff6aSGreg Kroah-Hartman
1398ffdff6aSGreg Kroah-Hartman static struct comedi_driver pcl724_driver = {
1408ffdff6aSGreg Kroah-Hartman .driver_name = "pcl724",
1418ffdff6aSGreg Kroah-Hartman .module = THIS_MODULE,
1428ffdff6aSGreg Kroah-Hartman .attach = pcl724_attach,
1438ffdff6aSGreg Kroah-Hartman .detach = comedi_legacy_detach,
1448ffdff6aSGreg Kroah-Hartman .board_name = &boardtypes[0].name,
1458ffdff6aSGreg Kroah-Hartman .num_names = ARRAY_SIZE(boardtypes),
1468ffdff6aSGreg Kroah-Hartman .offset = sizeof(struct pcl724_board),
1478ffdff6aSGreg Kroah-Hartman };
1488ffdff6aSGreg Kroah-Hartman module_comedi_driver(pcl724_driver);
1498ffdff6aSGreg Kroah-Hartman
1508ffdff6aSGreg Kroah-Hartman MODULE_AUTHOR("Comedi https://www.comedi.org");
1518ffdff6aSGreg Kroah-Hartman MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards");
1528ffdff6aSGreg Kroah-Hartman MODULE_LICENSE("GPL");
153