This source file includes following definitions.
- pci_dio_insn_bits_di_b
- pci_dio_insn_bits_di_w
- pci_dio_insn_bits_do_b
- pci_dio_insn_bits_do_w
- pci_dio_reset
- pci_dio_auto_attach
- pci_dio_override_cardtype
- adv_pci_dio_pci_probe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <linux/module.h>
25 #include <linux/delay.h>
26
27 #include "../comedi_pci.h"
28
29 #include "8255.h"
30 #include "comedi_8254.h"
31
32
33
34
35
36
37 #define PCI173X_INT_EN_REG 0x08
38 #define PCI173X_INT_RF_REG 0x0c
39 #define PCI173X_INT_CLR_REG 0x10
40
41
42 #define PCI1750_INT_REG 0x20
43
44
45 #define PCI1753_INT_REG(x) (0x10 + (x))
46 #define PCI1753E_INT_REG(x) (0x30 + (x))
47
48
49 #define PCI1754_INT_REG(x) (0x08 + (x) * 2)
50
51
52 #define PCI1752_CFC_REG 0x12
53
54
55 #define PCI1761_INT_EN_REG 0x03
56 #define PCI1761_INT_RF_REG 0x04
57 #define PCI1761_INT_CLR_REG 0x05
58
59
60 #define PCI1762_INT_REG 0x06
61
62
63 #define PCI_DIO_MAX_DI_SUBDEVS 2
64 #define PCI_DIO_MAX_DO_SUBDEVS 2
65 #define PCI_DIO_MAX_DIO_SUBDEVG 2
66
67 enum pci_dio_boardid {
68 TYPE_PCI1730,
69 TYPE_PCI1733,
70 TYPE_PCI1734,
71 TYPE_PCI1735,
72 TYPE_PCI1736,
73 TYPE_PCI1739,
74 TYPE_PCI1750,
75 TYPE_PCI1751,
76 TYPE_PCI1752,
77 TYPE_PCI1753,
78 TYPE_PCI1753E,
79 TYPE_PCI1754,
80 TYPE_PCI1756,
81 TYPE_PCI1761,
82 TYPE_PCI1762
83 };
84
85 struct diosubd_data {
86 int chans;
87 unsigned long addr;
88 };
89
90 struct dio_boardtype {
91 const char *name;
92 int nsubdevs;
93 struct diosubd_data sdi[PCI_DIO_MAX_DI_SUBDEVS];
94 struct diosubd_data sdo[PCI_DIO_MAX_DO_SUBDEVS];
95 struct diosubd_data sdio[PCI_DIO_MAX_DIO_SUBDEVG];
96 unsigned long id_reg;
97 unsigned long timer_regbase;
98 unsigned int is_16bit:1;
99 };
100
101 static const struct dio_boardtype boardtypes[] = {
102 [TYPE_PCI1730] = {
103 .name = "pci1730",
104 .nsubdevs = 5,
105 .sdi[0] = { 16, 0x02, },
106 .sdi[1] = { 16, 0x00, },
107 .sdo[0] = { 16, 0x02, },
108 .sdo[1] = { 16, 0x00, },
109 .id_reg = 0x04,
110 },
111 [TYPE_PCI1733] = {
112 .name = "pci1733",
113 .nsubdevs = 2,
114 .sdi[1] = { 32, 0x00, },
115 .id_reg = 0x04,
116 },
117 [TYPE_PCI1734] = {
118 .name = "pci1734",
119 .nsubdevs = 2,
120 .sdo[1] = { 32, 0x00, },
121 .id_reg = 0x04,
122 },
123 [TYPE_PCI1735] = {
124 .name = "pci1735",
125 .nsubdevs = 4,
126 .sdi[0] = { 32, 0x00, },
127 .sdo[0] = { 32, 0x00, },
128 .id_reg = 0x08,
129 .timer_regbase = 0x04,
130 },
131 [TYPE_PCI1736] = {
132 .name = "pci1736",
133 .nsubdevs = 3,
134 .sdi[1] = { 16, 0x00, },
135 .sdo[1] = { 16, 0x00, },
136 .id_reg = 0x04,
137 },
138 [TYPE_PCI1739] = {
139 .name = "pci1739",
140 .nsubdevs = 3,
141 .sdio[0] = { 2, 0x00, },
142 .id_reg = 0x08,
143 },
144 [TYPE_PCI1750] = {
145 .name = "pci1750",
146 .nsubdevs = 2,
147 .sdi[1] = { 16, 0x00, },
148 .sdo[1] = { 16, 0x00, },
149 },
150 [TYPE_PCI1751] = {
151 .name = "pci1751",
152 .nsubdevs = 3,
153 .sdio[0] = { 2, 0x00, },
154 .timer_regbase = 0x18,
155 },
156 [TYPE_PCI1752] = {
157 .name = "pci1752",
158 .nsubdevs = 3,
159 .sdo[0] = { 32, 0x00, },
160 .sdo[1] = { 32, 0x04, },
161 .id_reg = 0x10,
162 .is_16bit = 1,
163 },
164 [TYPE_PCI1753] = {
165 .name = "pci1753",
166 .nsubdevs = 4,
167 .sdio[0] = { 4, 0x00, },
168 },
169 [TYPE_PCI1753E] = {
170 .name = "pci1753e",
171 .nsubdevs = 8,
172 .sdio[0] = { 4, 0x00, },
173 .sdio[1] = { 4, 0x20, },
174 },
175 [TYPE_PCI1754] = {
176 .name = "pci1754",
177 .nsubdevs = 3,
178 .sdi[0] = { 32, 0x00, },
179 .sdi[1] = { 32, 0x04, },
180 .id_reg = 0x10,
181 .is_16bit = 1,
182 },
183 [TYPE_PCI1756] = {
184 .name = "pci1756",
185 .nsubdevs = 3,
186 .sdi[1] = { 32, 0x00, },
187 .sdo[1] = { 32, 0x04, },
188 .id_reg = 0x10,
189 .is_16bit = 1,
190 },
191 [TYPE_PCI1761] = {
192 .name = "pci1761",
193 .nsubdevs = 3,
194 .sdi[1] = { 8, 0x01 },
195 .sdo[1] = { 8, 0x00 },
196 .id_reg = 0x02,
197 },
198 [TYPE_PCI1762] = {
199 .name = "pci1762",
200 .nsubdevs = 3,
201 .sdi[1] = { 16, 0x02, },
202 .sdo[1] = { 16, 0x00, },
203 .id_reg = 0x04,
204 .is_16bit = 1,
205 },
206 };
207
208 static int pci_dio_insn_bits_di_b(struct comedi_device *dev,
209 struct comedi_subdevice *s,
210 struct comedi_insn *insn,
211 unsigned int *data)
212 {
213 unsigned long reg = (unsigned long)s->private;
214 unsigned long iobase = dev->iobase + reg;
215
216 data[1] = inb(iobase);
217 if (s->n_chan > 8)
218 data[1] |= (inb(iobase + 1) << 8);
219 if (s->n_chan > 16)
220 data[1] |= (inb(iobase + 2) << 16);
221 if (s->n_chan > 24)
222 data[1] |= (inb(iobase + 3) << 24);
223
224 return insn->n;
225 }
226
227 static int pci_dio_insn_bits_di_w(struct comedi_device *dev,
228 struct comedi_subdevice *s,
229 struct comedi_insn *insn,
230 unsigned int *data)
231 {
232 unsigned long reg = (unsigned long)s->private;
233 unsigned long iobase = dev->iobase + reg;
234
235 data[1] = inw(iobase);
236 if (s->n_chan > 16)
237 data[1] |= (inw(iobase + 2) << 16);
238
239 return insn->n;
240 }
241
242 static int pci_dio_insn_bits_do_b(struct comedi_device *dev,
243 struct comedi_subdevice *s,
244 struct comedi_insn *insn,
245 unsigned int *data)
246 {
247 unsigned long reg = (unsigned long)s->private;
248 unsigned long iobase = dev->iobase + reg;
249
250 if (comedi_dio_update_state(s, data)) {
251 outb(s->state & 0xff, iobase);
252 if (s->n_chan > 8)
253 outb((s->state >> 8) & 0xff, iobase + 1);
254 if (s->n_chan > 16)
255 outb((s->state >> 16) & 0xff, iobase + 2);
256 if (s->n_chan > 24)
257 outb((s->state >> 24) & 0xff, iobase + 3);
258 }
259
260 data[1] = s->state;
261
262 return insn->n;
263 }
264
265 static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
266 struct comedi_subdevice *s,
267 struct comedi_insn *insn,
268 unsigned int *data)
269 {
270 unsigned long reg = (unsigned long)s->private;
271 unsigned long iobase = dev->iobase + reg;
272
273 if (comedi_dio_update_state(s, data)) {
274 outw(s->state & 0xffff, iobase);
275 if (s->n_chan > 16)
276 outw((s->state >> 16) & 0xffff, iobase + 2);
277 }
278
279 data[1] = s->state;
280
281 return insn->n;
282 }
283
284 static int pci_dio_reset(struct comedi_device *dev, unsigned long cardtype)
285 {
286
287 if (cardtype == TYPE_PCI1752 || cardtype == TYPE_PCI1756)
288 outw(0, dev->iobase + PCI1752_CFC_REG);
289
290
291 switch (cardtype) {
292 case TYPE_PCI1730:
293 case TYPE_PCI1733:
294 case TYPE_PCI1736:
295 outb(0, dev->iobase + PCI173X_INT_EN_REG);
296 outb(0x0f, dev->iobase + PCI173X_INT_CLR_REG);
297 outb(0, dev->iobase + PCI173X_INT_RF_REG);
298 break;
299 case TYPE_PCI1739:
300 case TYPE_PCI1750:
301 case TYPE_PCI1751:
302 outb(0x88, dev->iobase + PCI1750_INT_REG);
303 break;
304 case TYPE_PCI1753:
305 case TYPE_PCI1753E:
306 outb(0x88, dev->iobase + PCI1753_INT_REG(0));
307 outb(0x80, dev->iobase + PCI1753_INT_REG(1));
308 outb(0x80, dev->iobase + PCI1753_INT_REG(2));
309 outb(0x80, dev->iobase + PCI1753_INT_REG(3));
310 if (cardtype == TYPE_PCI1753E) {
311 outb(0x88, dev->iobase + PCI1753E_INT_REG(0));
312 outb(0x80, dev->iobase + PCI1753E_INT_REG(1));
313 outb(0x80, dev->iobase + PCI1753E_INT_REG(2));
314 outb(0x80, dev->iobase + PCI1753E_INT_REG(3));
315 }
316 break;
317 case TYPE_PCI1754:
318 case TYPE_PCI1756:
319 outw(0x08, dev->iobase + PCI1754_INT_REG(0));
320 outw(0x08, dev->iobase + PCI1754_INT_REG(1));
321 if (cardtype == TYPE_PCI1754) {
322 outw(0x08, dev->iobase + PCI1754_INT_REG(2));
323 outw(0x08, dev->iobase + PCI1754_INT_REG(3));
324 }
325 break;
326 case TYPE_PCI1761:
327
328 outb(0, dev->iobase + PCI1761_INT_EN_REG);
329
330 outb(0xff, dev->iobase + PCI1761_INT_CLR_REG);
331
332 outb(0, dev->iobase + PCI1761_INT_RF_REG);
333 break;
334 case TYPE_PCI1762:
335 outw(0x0101, dev->iobase + PCI1762_INT_REG);
336 break;
337 default:
338 break;
339 }
340
341 return 0;
342 }
343
344 static int pci_dio_auto_attach(struct comedi_device *dev,
345 unsigned long context)
346 {
347 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
348 const struct dio_boardtype *board = NULL;
349 const struct diosubd_data *d;
350 struct comedi_subdevice *s;
351 int ret, subdev, i, j;
352
353 if (context < ARRAY_SIZE(boardtypes))
354 board = &boardtypes[context];
355 if (!board)
356 return -ENODEV;
357 dev->board_ptr = board;
358 dev->board_name = board->name;
359
360 ret = comedi_pci_enable(dev);
361 if (ret)
362 return ret;
363 if (context == TYPE_PCI1736)
364 dev->iobase = pci_resource_start(pcidev, 0);
365 else
366 dev->iobase = pci_resource_start(pcidev, 2);
367
368 pci_dio_reset(dev, context);
369
370 ret = comedi_alloc_subdevices(dev, board->nsubdevs);
371 if (ret)
372 return ret;
373
374 subdev = 0;
375 for (i = 0; i < PCI_DIO_MAX_DI_SUBDEVS; i++) {
376 d = &board->sdi[i];
377 if (d->chans) {
378 s = &dev->subdevices[subdev++];
379 s->type = COMEDI_SUBD_DI;
380 s->subdev_flags = SDF_READABLE;
381 s->n_chan = d->chans;
382 s->maxdata = 1;
383 s->range_table = &range_digital;
384 s->insn_bits = board->is_16bit
385 ? pci_dio_insn_bits_di_w
386 : pci_dio_insn_bits_di_b;
387 s->private = (void *)d->addr;
388 }
389 }
390
391 for (i = 0; i < PCI_DIO_MAX_DO_SUBDEVS; i++) {
392 d = &board->sdo[i];
393 if (d->chans) {
394 s = &dev->subdevices[subdev++];
395 s->type = COMEDI_SUBD_DO;
396 s->subdev_flags = SDF_WRITABLE;
397 s->n_chan = d->chans;
398 s->maxdata = 1;
399 s->range_table = &range_digital;
400 s->insn_bits = board->is_16bit
401 ? pci_dio_insn_bits_do_w
402 : pci_dio_insn_bits_do_b;
403 s->private = (void *)d->addr;
404
405
406 if (board->is_16bit) {
407 outw(0, dev->iobase + d->addr);
408 if (s->n_chan > 16)
409 outw(0, dev->iobase + d->addr + 2);
410 } else {
411 outb(0, dev->iobase + d->addr);
412 if (s->n_chan > 8)
413 outb(0, dev->iobase + d->addr + 1);
414 if (s->n_chan > 16)
415 outb(0, dev->iobase + d->addr + 2);
416 if (s->n_chan > 24)
417 outb(0, dev->iobase + d->addr + 3);
418 }
419 }
420 }
421
422 for (i = 0; i < PCI_DIO_MAX_DIO_SUBDEVG; i++) {
423 d = &board->sdio[i];
424 for (j = 0; j < d->chans; j++) {
425 s = &dev->subdevices[subdev++];
426 ret = subdev_8255_init(dev, s, NULL,
427 d->addr + j * I8255_SIZE);
428 if (ret)
429 return ret;
430 }
431 }
432
433 if (board->id_reg) {
434 s = &dev->subdevices[subdev++];
435 s->type = COMEDI_SUBD_DI;
436 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
437 s->n_chan = 4;
438 s->maxdata = 1;
439 s->range_table = &range_digital;
440 s->insn_bits = board->is_16bit ? pci_dio_insn_bits_di_w
441 : pci_dio_insn_bits_di_b;
442 s->private = (void *)board->id_reg;
443 }
444
445 if (board->timer_regbase) {
446 s = &dev->subdevices[subdev++];
447
448 dev->pacer = comedi_8254_init(dev->iobase +
449 board->timer_regbase,
450 0, I8254_IO8, 0);
451 if (!dev->pacer)
452 return -ENOMEM;
453
454 comedi_8254_subdevice_init(s, dev->pacer);
455 }
456
457 return 0;
458 }
459
460 static struct comedi_driver adv_pci_dio_driver = {
461 .driver_name = "adv_pci_dio",
462 .module = THIS_MODULE,
463 .auto_attach = pci_dio_auto_attach,
464 .detach = comedi_pci_detach,
465 };
466
467 static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev,
468 unsigned long cardtype)
469 {
470
471
472
473
474
475 if (cardtype != TYPE_PCI1753)
476 return cardtype;
477 if (pci_enable_device(pcidev) < 0)
478 return cardtype;
479 if (pci_request_region(pcidev, 2, "adv_pci_dio") == 0) {
480
481
482
483
484
485 unsigned long reg = pci_resource_start(pcidev, 2) + 53;
486
487 outb(0x05, reg);
488 if ((inb(reg) & 0x07) == 0x02) {
489 outb(0x02, reg);
490 if ((inb(reg) & 0x07) == 0x05)
491 cardtype = TYPE_PCI1753E;
492 }
493 pci_release_region(pcidev, 2);
494 }
495 pci_disable_device(pcidev);
496 return cardtype;
497 }
498
499 static int adv_pci_dio_pci_probe(struct pci_dev *dev,
500 const struct pci_device_id *id)
501 {
502 unsigned long cardtype;
503
504 cardtype = pci_dio_override_cardtype(dev, id->driver_data);
505 return comedi_pci_auto_config(dev, &adv_pci_dio_driver, cardtype);
506 }
507
508 static const struct pci_device_id adv_pci_dio_pci_table[] = {
509 { PCI_VDEVICE(ADVANTECH, 0x1730), TYPE_PCI1730 },
510 { PCI_VDEVICE(ADVANTECH, 0x1733), TYPE_PCI1733 },
511 { PCI_VDEVICE(ADVANTECH, 0x1734), TYPE_PCI1734 },
512 { PCI_VDEVICE(ADVANTECH, 0x1735), TYPE_PCI1735 },
513 { PCI_VDEVICE(ADVANTECH, 0x1736), TYPE_PCI1736 },
514 { PCI_VDEVICE(ADVANTECH, 0x1739), TYPE_PCI1739 },
515 { PCI_VDEVICE(ADVANTECH, 0x1750), TYPE_PCI1750 },
516 { PCI_VDEVICE(ADVANTECH, 0x1751), TYPE_PCI1751 },
517 { PCI_VDEVICE(ADVANTECH, 0x1752), TYPE_PCI1752 },
518 { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 },
519 { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 },
520 { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 },
521 { PCI_VDEVICE(ADVANTECH, 0x1761), TYPE_PCI1761 },
522 { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 },
523 { 0 }
524 };
525 MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
526
527 static struct pci_driver adv_pci_dio_pci_driver = {
528 .name = "adv_pci_dio",
529 .id_table = adv_pci_dio_pci_table,
530 .probe = adv_pci_dio_pci_probe,
531 .remove = comedi_pci_auto_unconfig,
532 };
533 module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
534
535 MODULE_AUTHOR("Comedi http://www.comedi.org");
536 MODULE_DESCRIPTION("Comedi driver for Advantech Digital I/O Cards");
537 MODULE_LICENSE("GPL");