Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
[linux-2.6.git] / drivers / staging / comedi / drivers / pcl724.c
blobcea657c7801dd49aee659eda220ad50df6be07d7
1 /*
2 * pcl724.c
3 * Comedi driver for 8255 based ISA DIO boards
5 * Michal Dobes <dobes@tesnet.cz>
6 */
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 * Author: Michal Dobes <dobes@tesnet.cz>
18 * Status: untested
20 * Configuration options:
21 * [0] - IO Base
22 * [1] - IRQ (not supported)
23 * [2] - number of DIO (pcl722 and acl7122 boards)
24 * 0, 144: 144 DIO configuration
25 * 1, 96: 96 DIO configuration
28 #include "../comedidev.h"
30 #include <linux/ioport.h>
31 #include <linux/delay.h>
33 #include "8255.h"
35 #define SIZE_8255 4
37 struct pcl724_board {
38 const char *name;
39 unsigned int io_range;
40 unsigned int can_have96:1;
41 unsigned int is_pet48:1;
42 int numofports;
45 static const struct pcl724_board boardtypes[] = {
47 .name = "pcl724",
48 .io_range = 0x04,
49 .numofports = 1, /* 24 DIO channels */
50 }, {
51 .name = "pcl722",
52 .io_range = 0x20,
53 .can_have96 = 1,
54 .numofports = 6, /* 144 (or 96) DIO channels */
55 }, {
56 .name = "pcl731",
57 .io_range = 0x08,
58 .numofports = 2, /* 48 DIO channels */
59 }, {
60 .name = "acl7122",
61 .io_range = 0x20,
62 .can_have96 = 1,
63 .numofports = 6, /* 144 (or 96) DIO channels */
64 }, {
65 .name = "acl7124",
66 .io_range = 0x04,
67 .numofports = 1, /* 24 DIO channels */
68 }, {
69 .name = "pet48dio",
70 .io_range = 0x02,
71 .is_pet48 = 1,
72 .numofports = 2, /* 48 DIO channels */
76 static int pcl724_8255mapped_io(int dir, int port, int data,
77 unsigned long iobase)
79 int movport = SIZE_8255 * (iobase >> 12);
81 iobase &= 0x0fff;
83 if (dir) {
84 outb(port + movport, iobase);
85 outb(data, iobase + 1);
86 return 0;
87 } else {
88 outb(port + movport, iobase);
89 return inb(iobase + 1);
93 static int pcl724_attach(struct comedi_device *dev,
94 struct comedi_devconfig *it)
96 const struct pcl724_board *board = comedi_board(dev);
97 struct comedi_subdevice *s;
98 unsigned long iobase;
99 unsigned int iorange;
100 int n_subdevices;
101 int ret;
102 int i;
104 iorange = board->io_range;
105 n_subdevices = board->numofports;
107 /* Handle PCL-724 in 96 DIO configuration */
108 if (board->can_have96 &&
109 (it->options[2] == 1 || it->options[2] == 96)) {
110 iorange = 0x10;
111 n_subdevices = 4;
114 ret = comedi_request_region(dev, it->options[0], iorange);
115 if (ret)
116 return ret;
118 ret = comedi_alloc_subdevices(dev, n_subdevices);
119 if (ret)
120 return ret;
122 for (i = 0; i < dev->n_subdevices; i++) {
123 s = &dev->subdevices[i];
124 if (board->is_pet48) {
125 iobase = dev->iobase + (i * 0x1000);
126 ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
127 iobase);
128 } else {
129 iobase = dev->iobase + (i * SIZE_8255);
130 ret = subdev_8255_init(dev, s, NULL, iobase);
132 if (ret)
133 return ret;
136 return 0;
139 static 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),
148 module_comedi_driver(pcl724_driver);
150 MODULE_AUTHOR("Comedi http://www.comedi.org");
151 MODULE_DESCRIPTION("Comedi driver for 8255 based ISA DIO boards");
152 MODULE_LICENSE("GPL");