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
34
35
36
37
38
39
40
41
42
43#include "../comedidev.h"
44#include "comedi_pci.h"
45#include "8255.h"
46
47
48#define PCI_VENDOR_ID_CB 0x1307
49
50
51
52
53
54
55struct pcidio_board {
56 const char *name;
57 int dev_id;
58 int n_8255;
59
60
61 int pcicontroler_badrindex;
62 int dioregs_badrindex;
63};
64
65static const struct pcidio_board pcidio_boards[] = {
66 {
67 .name = "pci-dio24",
68 .dev_id = 0x0028,
69 .n_8255 = 1,
70 .pcicontroler_badrindex = 1,
71 .dioregs_badrindex = 2,
72 },
73 {
74 .name = "pci-dio24h",
75 .dev_id = 0x0014,
76 .n_8255 = 1,
77 .pcicontroler_badrindex = 1,
78 .dioregs_badrindex = 2,
79 },
80 {
81 .name = "pci-dio48h",
82 .dev_id = 0x000b,
83 .n_8255 = 2,
84 .pcicontroler_badrindex = 0,
85 .dioregs_badrindex = 1,
86 },
87};
88
89
90
91
92
93static DEFINE_PCI_DEVICE_TABLE(pcidio_pci_table) = {
94 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0028) },
95 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0014) },
96 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000b) },
97 { 0 }
98};
99
100MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
101
102
103
104
105#define thisboard ((const struct pcidio_board *)dev->board_ptr)
106
107
108
109
110struct pcidio_private {
111 int data;
112
113
114 struct pci_dev *pci_dev;
115
116
117 unsigned int do_readback[4];
118
119 unsigned long dio_reg_base;
120};
121
122
123
124
125
126#define devpriv ((struct pcidio_private *)dev->private)
127
128
129
130
131
132
133
134static int pcidio_attach(struct comedi_device *dev,
135 struct comedi_devconfig *it);
136static int pcidio_detach(struct comedi_device *dev);
137static struct comedi_driver driver_cb_pcidio = {
138 .driver_name = "cb_pcidio",
139 .module = THIS_MODULE,
140 .attach = pcidio_attach,
141 .detach = pcidio_detach,
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171};
172
173
174
175
176
177
178
179
180
181static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
182{
183 struct pci_dev *pcidev = NULL;
184 int index;
185 int i;
186
187 printk("comedi%d: cb_pcidio: \n", dev->minor);
188
189
190
191
192
193 if (alloc_private(dev, sizeof(struct pcidio_private)) < 0)
194 return -ENOMEM;
195
196
197
198
199
200
201
202
203
204 for_each_pci_dev(pcidev) {
205
206 if (pcidev->vendor != PCI_VENDOR_ID_CB)
207 continue;
208
209 for (index = 0; index < ARRAY_SIZE(pcidio_boards); index++) {
210 if (pcidio_boards[index].dev_id != pcidev->device)
211 continue;
212
213
214 if (it->options[0] || it->options[1]) {
215
216 if (pcidev->bus->number != it->options[0] ||
217 PCI_SLOT(pcidev->devfn) != it->options[1]) {
218 continue;
219 }
220 }
221 dev->board_ptr = pcidio_boards + index;
222 goto found;
223 }
224 }
225
226 printk("No supported ComputerBoards/MeasurementComputing card found on "
227 "requested position\n");
228 return -EIO;
229
230found:
231
232
233
234
235
236 dev->board_name = thisboard->name;
237
238 devpriv->pci_dev = pcidev;
239 printk("Found %s on bus %i, slot %i\n", thisboard->name,
240 devpriv->pci_dev->bus->number,
241 PCI_SLOT(devpriv->pci_dev->devfn));
242 if (comedi_pci_enable(pcidev, thisboard->name)) {
243 printk
244 ("cb_pcidio: failed to enable PCI device and request regions\n");
245 return -EIO;
246 }
247 devpriv->dio_reg_base
248 =
249 pci_resource_start(devpriv->pci_dev,
250 pcidio_boards[index].dioregs_badrindex);
251
252
253
254
255
256 if (alloc_subdevices(dev, thisboard->n_8255) < 0)
257 return -ENOMEM;
258
259 for (i = 0; i < thisboard->n_8255; i++) {
260 subdev_8255_init(dev, dev->subdevices + i,
261 NULL, devpriv->dio_reg_base + i * 4);
262 printk(" subdev %d: base = 0x%lx\n", i,
263 devpriv->dio_reg_base + i * 4);
264 }
265
266 printk("attached\n");
267 return 1;
268}
269
270
271
272
273
274
275
276
277
278static int pcidio_detach(struct comedi_device *dev)
279{
280 printk("comedi%d: cb_pcidio: remove\n", dev->minor);
281 if (devpriv) {
282 if (devpriv->pci_dev) {
283 if (devpriv->dio_reg_base)
284 comedi_pci_disable(devpriv->pci_dev);
285 pci_dev_put(devpriv->pci_dev);
286 }
287 }
288 if (dev->subdevices) {
289 int i;
290 for (i = 0; i < thisboard->n_8255; i++)
291 subdev_8255_cleanup(dev, dev->subdevices + i);
292 }
293 return 0;
294}
295
296
297
298
299
300static int __devinit driver_cb_pcidio_pci_probe(struct pci_dev *dev,
301 const struct pci_device_id *ent)
302{
303 return comedi_pci_auto_config(dev, driver_cb_pcidio.driver_name);
304}
305
306static void __devexit driver_cb_pcidio_pci_remove(struct pci_dev *dev)
307{
308 comedi_pci_auto_unconfig(dev);
309}
310
311static struct pci_driver driver_cb_pcidio_pci_driver = {
312 .id_table = pcidio_pci_table,
313 .probe = &driver_cb_pcidio_pci_probe,
314 .remove = __devexit_p(&driver_cb_pcidio_pci_remove)
315};
316
317static int __init driver_cb_pcidio_init_module(void)
318{
319 int retval;
320
321 retval = comedi_driver_register(&driver_cb_pcidio);
322 if (retval < 0)
323 return retval;
324
325 driver_cb_pcidio_pci_driver.name = (char *)driver_cb_pcidio.driver_name;
326 return pci_register_driver(&driver_cb_pcidio_pci_driver);
327}
328
329static void __exit driver_cb_pcidio_cleanup_module(void)
330{
331 pci_unregister_driver(&driver_cb_pcidio_pci_driver);
332 comedi_driver_unregister(&driver_cb_pcidio);
333}
334
335module_init(driver_cb_pcidio_init_module);
336module_exit(driver_cb_pcidio_cleanup_module);
337
338MODULE_AUTHOR("Comedi http://www.comedi.org");
339MODULE_DESCRIPTION("Comedi low-level driver");
340MODULE_LICENSE("GPL");
341