1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/module.h>
34#include "../comedidev.h"
35
36struct boarddef_struct {
37 const char *name;
38 unsigned int iosize;
39 int (*setup) (struct comedi_device *);
40 int type;
41 int n_chan;
42 int n_bits;
43 int (*winsn) (struct comedi_device *, struct comedi_subdevice *,
44 struct comedi_insn *, unsigned int *);
45 int (*rinsn) (struct comedi_device *, struct comedi_subdevice *,
46 struct comedi_insn *, unsigned int *);
47 int (*insnbits) (struct comedi_device *, struct comedi_subdevice *,
48 struct comedi_insn *, unsigned int *);
49 const struct comedi_lrange *range;
50};
51
52struct poc_private {
53 unsigned int ao_readback[32];
54};
55
56static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
57 struct comedi_insn *insn, unsigned int *data)
58{
59 struct poc_private *devpriv = dev->private;
60 int chan;
61
62 chan = CR_CHAN(insn->chanspec);
63 data[0] = devpriv->ao_readback[chan];
64
65 return 1;
66}
67
68
69#define DAC02_LSB(a) (2 * a)
70#define DAC02_MSB(a) (2 * a + 1)
71
72static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
73 struct comedi_insn *insn, unsigned int *data)
74{
75 struct poc_private *devpriv = dev->private;
76 int temp;
77 int chan;
78 int output;
79
80 chan = CR_CHAN(insn->chanspec);
81 devpriv->ao_readback[chan] = data[0];
82 output = data[0];
83#ifdef wrong
84
85 if ((CR_RANGE(insn->chanspec) & 0x2) == 0)
86 output = ~output;
87#endif
88 temp = (output << 4) & 0xf0;
89 outb(temp, dev->iobase + DAC02_LSB(chan));
90 temp = (output >> 4) & 0xff;
91 outb(temp, dev->iobase + DAC02_MSB(chan));
92
93 return 1;
94}
95
96static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
97{
98 const struct boarddef_struct *board = comedi_board(dev);
99 struct poc_private *devpriv;
100 struct comedi_subdevice *s;
101 int ret;
102
103 ret = comedi_request_region(dev, it->options[0], board->iosize);
104 if (ret)
105 return ret;
106
107 ret = comedi_alloc_subdevices(dev, 1);
108 if (ret)
109 return ret;
110
111 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
112 if (!devpriv)
113 return -ENOMEM;
114
115
116 s = &dev->subdevices[0];
117 s->type = board->type;
118 s->n_chan = board->n_chan;
119 s->maxdata = (1 << board->n_bits) - 1;
120 s->range_table = board->range;
121 s->insn_write = board->winsn;
122 s->insn_read = board->rinsn;
123 s->insn_bits = board->insnbits;
124 if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO)
125 s->subdev_flags = SDF_WRITABLE;
126
127 return 0;
128}
129
130static const struct boarddef_struct boards[] = {
131 {
132 .name = "dac02",
133 .iosize = 8,
134
135 .type = COMEDI_SUBD_AO,
136 .n_chan = 2,
137 .n_bits = 12,
138 .winsn = dac02_ao_winsn,
139 .rinsn = readback_insn,
140 .range = &range_unknown,
141 },
142};
143
144static struct comedi_driver poc_driver = {
145 .driver_name = "poc",
146 .module = THIS_MODULE,
147 .attach = poc_attach,
148 .detach = comedi_legacy_detach,
149 .board_name = &boards[0].name,
150 .num_names = ARRAY_SIZE(boards),
151 .offset = sizeof(boards[0]),
152};
153module_comedi_driver(poc_driver);
154
155MODULE_AUTHOR("Comedi http://www.comedi.org");
156MODULE_DESCRIPTION("Comedi low-level driver");
157MODULE_LICENSE("GPL");
158