2 * comedi/drivers/pcl730.c
3 * Driver for Advantech PCL-730 and clones
8 Description: Advantech PCL-730 (& compatibles)
9 Author: José Luis Sánchez (jsanchezv@teleline.es)
11 Devices: [Advantech] PCL-730 (pcl730), [ICP] ISO-730 (iso730),
12 [Adlink] ACL-7130 (acl7130)
14 Interrupts are not supported.
15 The ACL-7130 card have an 8254 timer/counter not supported by this driver.
18 #include "../comedidev.h"
20 #include <linux/ioport.h>
23 #define ACL7130_SIZE 8
24 #define PCL730_IDIO_LO 0 /* Isolated Digital I/O low byte (ID0-ID7) */
25 #define PCL730_IDIO_HI 1 /* Isolated Digital I/O high byte (ID8-ID15) */
26 #define PCL730_DIO_LO 2 /* TTL Digital I/O low byte (D0-D7) */
27 #define PCL730_DIO_HI 3 /* TTL Digital I/O high byte (D8-D15) */
29 static int pcl730_attach(struct comedi_device
*dev
,
30 struct comedi_devconfig
*it
);
31 static int pcl730_detach(struct comedi_device
*dev
);
35 const char *name
; /* board name */
36 unsigned int io_range
; /* len of I/O space */
39 static const struct pcl730_board boardtypes
[] = {
40 {"pcl730", PCL730_SIZE
,},
41 {"iso730", PCL730_SIZE
,},
42 {"acl7130", ACL7130_SIZE
,},
45 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl730_board))
46 #define this_board ((const struct pcl730_board *)dev->board_ptr)
48 static struct comedi_driver driver_pcl730
= {
49 .driver_name
= "pcl730",
50 .module
= THIS_MODULE
,
51 .attach
= pcl730_attach
,
52 .detach
= pcl730_detach
,
53 .board_name
= &boardtypes
[0].name
,
54 .num_names
= n_boardtypes
,
55 .offset
= sizeof(struct pcl730_board
),
58 COMEDI_INITCLEANUP(driver_pcl730
);
60 static int pcl730_do_insn(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
61 struct comedi_insn
*insn
, unsigned int *data
)
68 s
->state
|= (data
[0] & data
[1]);
72 dev
->iobase
+ ((unsigned long)s
->private));
75 dev
->iobase
+ ((unsigned long)s
->private) + 1);
82 static int pcl730_di_insn(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
83 struct comedi_insn
*insn
, unsigned int *data
)
88 data
[1] = inb(dev
->iobase
+ ((unsigned long)s
->private)) |
89 (inb(dev
->iobase
+ ((unsigned long)s
->private) + 1) << 8);
94 static int pcl730_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
96 struct comedi_subdevice
*s
;
100 iobase
= it
->options
[0];
101 iorange
= this_board
->io_range
;
102 printk("comedi%d: pcl730: board=%s 0x%04lx ", dev
->minor
,
103 this_board
->name
, iobase
);
104 if (!request_region(iobase
, iorange
, "pcl730")) {
105 printk("I/O port conflict\n");
108 dev
->board_name
= this_board
->name
;
109 dev
->iobase
= iobase
;
112 if (alloc_subdevices(dev
, 4) < 0)
115 s
= dev
->subdevices
+ 0;
117 s
->type
= COMEDI_SUBD_DO
;
118 s
->subdev_flags
= SDF_WRITABLE
;
121 s
->insn_bits
= pcl730_do_insn
;
122 s
->range_table
= &range_digital
;
123 s
->private = (void *)PCL730_IDIO_LO
;
125 s
= dev
->subdevices
+ 1;
127 s
->type
= COMEDI_SUBD_DI
;
128 s
->subdev_flags
= SDF_READABLE
;
131 s
->insn_bits
= pcl730_di_insn
;
132 s
->range_table
= &range_digital
;
133 s
->private = (void *)PCL730_IDIO_LO
;
135 s
= dev
->subdevices
+ 2;
137 s
->type
= COMEDI_SUBD_DO
;
138 s
->subdev_flags
= SDF_WRITABLE
;
141 s
->insn_bits
= pcl730_do_insn
;
142 s
->range_table
= &range_digital
;
143 s
->private = (void *)PCL730_DIO_LO
;
145 s
= dev
->subdevices
+ 3;
147 s
->type
= COMEDI_SUBD_DI
;
148 s
->subdev_flags
= SDF_READABLE
;
151 s
->insn_bits
= pcl730_di_insn
;
152 s
->range_table
= &range_digital
;
153 s
->private = (void *)PCL730_DIO_LO
;
160 static int pcl730_detach(struct comedi_device
*dev
)
162 printk("comedi%d: pcl730: remove\n", dev
->minor
);
165 release_region(dev
->iobase
, this_board
->io_range
);