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