1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "../comedidev.h"
15
16#include <linux/ioport.h>
17
18#define ACL7225_SIZE 8
19#define P16R16DIO_SIZE 4
20#define ACL7225_RIO_LO 0
21#define ACL7225_RIO_HI 1
22#define ACL7225_DI_LO 2
23#define ACL7225_DI_HI 3
24
25struct boardtype {
26 const char *name;
27 int io_range;
28};
29
30static int acl7225b_do_insn(struct comedi_device *dev,
31 struct comedi_subdevice *s,
32 struct comedi_insn *insn, unsigned int *data)
33{
34 if (data[0]) {
35 s->state &= ~data[0];
36 s->state |= (data[0] & data[1]);
37 }
38 if (data[0] & 0x00ff)
39 outb(s->state & 0xff, dev->iobase + (unsigned long)s->private);
40 if (data[0] & 0xff00)
41 outb((s->state >> 8),
42 dev->iobase + (unsigned long)s->private + 1);
43
44 data[1] = s->state;
45
46 return insn->n;
47}
48
49static int acl7225b_di_insn(struct comedi_device *dev,
50 struct comedi_subdevice *s,
51 struct comedi_insn *insn, unsigned int *data)
52{
53 data[1] = inb(dev->iobase + (unsigned long)s->private) |
54 (inb(dev->iobase + (unsigned long)s->private + 1) << 8);
55
56 return insn->n;
57}
58
59static int acl7225b_attach(struct comedi_device *dev,
60 struct comedi_devconfig *it)
61{
62 const struct boardtype *board = comedi_board(dev);
63 struct comedi_subdevice *s;
64 int iobase, iorange;
65 int ret;
66
67 iobase = it->options[0];
68 iorange = board->io_range;
69 printk(KERN_INFO "comedi%d: acl7225b: board=%s 0x%04x\n", dev->minor,
70 board->name, iobase);
71 if (!request_region(iobase, iorange, "acl7225b")) {
72 printk(KERN_ERR "comedi%d: request_region failed - I/O port conflict\n",
73 dev->minor);
74 return -EIO;
75 }
76 dev->board_name = board->name;
77 dev->iobase = iobase;
78 dev->irq = 0;
79
80 ret = comedi_alloc_subdevices(dev, 3);
81 if (ret)
82 return ret;
83
84 s = dev->subdevices + 0;
85
86 s->type = COMEDI_SUBD_DO;
87 s->subdev_flags = SDF_WRITABLE;
88 s->maxdata = 1;
89 s->n_chan = 16;
90 s->insn_bits = acl7225b_do_insn;
91 s->range_table = &range_digital;
92 s->private = (void *)ACL7225_RIO_LO;
93
94 s = dev->subdevices + 1;
95
96 s->type = COMEDI_SUBD_DI;
97 s->subdev_flags = SDF_READABLE;
98 s->maxdata = 1;
99 s->n_chan = 16;
100 s->insn_bits = acl7225b_di_insn;
101 s->range_table = &range_digital;
102 s->private = (void *)ACL7225_RIO_LO;
103
104 s = dev->subdevices + 2;
105
106 s->type = COMEDI_SUBD_DI;
107 s->subdev_flags = SDF_READABLE;
108 s->maxdata = 1;
109 s->n_chan = 16;
110 s->insn_bits = acl7225b_di_insn;
111 s->range_table = &range_digital;
112 s->private = (void *)ACL7225_DI_LO;
113
114 return 0;
115}
116
117static void acl7225b_detach(struct comedi_device *dev)
118{
119 const struct boardtype *board = comedi_board(dev);
120
121 if (dev->iobase)
122 release_region(dev->iobase, board->io_range);
123}
124
125static const struct boardtype boardtypes[] = {
126 { "acl7225b", ACL7225_SIZE, },
127 { "p16r16dio", P16R16DIO_SIZE, },
128};
129
130static struct comedi_driver acl7225b_driver = {
131 .driver_name = "acl7225b",
132 .module = THIS_MODULE,
133 .attach = acl7225b_attach,
134 .detach = acl7225b_detach,
135 .board_name = &boardtypes[0].name,
136 .num_names = ARRAY_SIZE(boardtypes),
137 .offset = sizeof(struct boardtype),
138};
139module_comedi_driver(acl7225b_driver);
140
141MODULE_AUTHOR("Comedi http://www.comedi.org");
142MODULE_DESCRIPTION("Comedi low-level driver");
143MODULE_LICENSE("GPL");
144