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