2 comedi/drivers/pcl724.c
4 Michal Dobes <dobes@tesnet.cz>
6 hardware driver for Advantech cards:
7 card: PCL-724, PCL-722, PCL-731
8 driver: pcl724, pcl722, pcl731
10 card: ACL-7122, ACL-7124, PET-48DIO
11 driver: acl7122, acl7124, pet48dio
13 Options for PCL-724, PCL-731, ACL-7124 and PET-48DIO:
16 Options for PCL-722 and ACL-7122:
18 [1] - IRQ (0=disable IRQ) IRQ isn't supported at this time!
20 0, 144: 144 DIO configuration
21 1, 96: 96 DIO configuration
25 Description: Advantech PCL-724, PCL-722, PCL-731 ADLink ACL-7122, ACL-7124,
27 Author: Michal Dobes <dobes@tesnet.cz>
28 Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
29 [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio)
32 This is driver for digital I/O boards PCL-722/724/731 with 144/24/48 DIO
33 and for digital I/O boards ACL-7122/7124/PET-48DIO with 144/24/48 DIO.
34 It need 8255.o for operations and only immediate mode is supported.
35 See the source for configuration details.
38 * check_driver overrides:
42 #include "../comedidev.h"
44 #include <linux/ioport.h>
45 #include <linux/delay.h>
49 #define PCL722_SIZE 32
50 #define PCL722_96_SIZE 16
57 /* #define PCL724_IRQ 1 no IRQ support now */
59 static int pcl724_attach(struct comedi_device
*dev
,
60 struct comedi_devconfig
*it
);
61 static int pcl724_detach(struct comedi_device
*dev
);
65 const char *name
; /* board name */
66 int dio
; /* num of DIO */
67 int numofports
; /* num of 8255 subdevices */
68 unsigned int IRQbits
; /* allowed interrupts */
69 unsigned int io_range
; /* len of IO space */
74 static const struct pcl724_board boardtypes
[] = {
75 {"pcl724", 24, 1, 0x00fc, PCL724_SIZE
, 0, 0,},
76 {"pcl722", 144, 6, 0x00fc, PCL722_SIZE
, 1, 0,},
77 {"pcl731", 48, 2, 0x9cfc, PCL731_SIZE
, 0, 0,},
78 {"acl7122", 144, 6, 0x9ee8, PCL722_SIZE
, 1, 0,},
79 {"acl7124", 24, 1, 0x00fc, PCL724_SIZE
, 0, 0,},
80 {"pet48dio", 48, 2, 0x9eb8, PET48_SIZE
, 0, 1,},
83 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl724_board))
84 #define this_board ((const struct pcl724_board *)dev->board_ptr)
86 static struct comedi_driver driver_pcl724
= {
87 .driver_name
= "pcl724",
88 .module
= THIS_MODULE
,
89 .attach
= pcl724_attach
,
90 .detach
= pcl724_detach
,
91 .board_name
= &boardtypes
[0].name
,
92 .num_names
= n_boardtypes
,
93 .offset
= sizeof(struct pcl724_board
),
96 static int __init
driver_pcl724_init_module(void)
98 return comedi_driver_register(&driver_pcl724
);
101 static void __exit
driver_pcl724_cleanup_module(void)
103 comedi_driver_unregister(&driver_pcl724
);
106 module_init(driver_pcl724_init_module
);
107 module_exit(driver_pcl724_cleanup_module
);
109 static int subdev_8255_cb(int dir
, int port
, int data
, unsigned long arg
)
111 unsigned long iobase
= arg
;
114 outb(data
, iobase
+ port
);
117 return inb(iobase
+ port
);
121 static int subdev_8255mapped_cb(int dir
, int port
, int data
,
122 unsigned long iobase
)
124 int movport
= SIZE_8255
* (iobase
>> 12);
129 outb(port
+ movport
, iobase
);
130 outb(data
, iobase
+ 1);
133 outb(port
+ movport
, iobase
);
134 return inb(iobase
+ 1);
138 static int pcl724_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
140 unsigned long iobase
;
141 unsigned int iorange
;
142 int ret
, i
, n_subdevices
;
147 iobase
= it
->options
[0];
148 iorange
= this_board
->io_range
;
149 if ((this_board
->can_have96
) && ((it
->options
[1] == 1)
150 || (it
->options
[1] == 96)))
151 iorange
= PCL722_96_SIZE
; /* PCL-724 in 96 DIO configuration */
152 printk(KERN_INFO
"comedi%d: pcl724: board=%s, 0x%03lx ", dev
->minor
,
153 this_board
->name
, iobase
);
154 if (!request_region(iobase
, iorange
, "pcl724")) {
155 printk("I/O port conflict\n");
159 dev
->iobase
= iobase
;
161 dev
->board_name
= this_board
->name
;
165 if (this_board
->IRQbits
!= 0) { /* board support IRQ */
166 irq
= it
->options
[1];
167 if (irq
) { /* we want to use IRQ */
168 if (((1 << irq
) & this_board
->IRQbits
) == 0) {
170 ", IRQ %u is out of allowed range, "
171 "DISABLING IT", irq
);
172 irq
= 0; /* Bad IRQ */
175 (irq
, interrupt_pcl724
, 0, "pcl724", dev
)) {
177 ", unable to allocate IRQ %u, "
178 "DISABLING IT", irq
);
179 irq
= 0; /* Can't use IRQ */
181 printk(", irq=%u", irq
);
192 n_subdevices
= this_board
->numofports
;
193 if ((this_board
->can_have96
) && ((it
->options
[1] == 1)
194 || (it
->options
[1] == 96)))
195 n_subdevices
= 4; /* PCL-724 in 96 DIO configuration */
197 ret
= alloc_subdevices(dev
, n_subdevices
);
201 for (i
= 0; i
< dev
->n_subdevices
; i
++) {
202 if (this_board
->is_pet48
) {
203 subdev_8255_init(dev
, dev
->subdevices
+ i
,
204 subdev_8255mapped_cb
,
205 (unsigned long)(dev
->iobase
+
208 subdev_8255_init(dev
, dev
->subdevices
+ i
,
210 (unsigned long)(dev
->iobase
+
217 static int pcl724_detach(struct comedi_device
*dev
)
221 /* printk("comedi%d: pcl724: remove\n",dev->minor); */
223 for (i
= 0; i
< dev
->n_subdevices
; i
++)
224 subdev_8255_cleanup(dev
, dev
->subdevices
+ i
);
228 free_irq(dev
->irq
, dev
);
231 release_region(dev
->iobase
, this_board
->io_range
);
236 MODULE_AUTHOR("Comedi http://www.comedi.org");
237 MODULE_DESCRIPTION("Comedi low-level driver");
238 MODULE_LICENSE("GPL");