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
44
45
46
47
48
49
50
51#include "../comedidev.h"
52
53#include "comedi_pci.h"
54
55#define PCI_VENDOR_ID_ADVANTECH 0x13fe
56
57
58#define TYPE_PCI1723 0
59
60#define IORANGE_1723 0x2A
61
62
63#define PCI1723_DA(N) ((N)<<1)
64
65#define PCI1723_SYN_SET 0x12
66#define PCI1723_ALL_CHNNELE_SYN_STROBE 0x12
67
68
69#define PCI1723_RANGE_CALIBRATION_MODE 0x14
70
71#define PCI1723_RANGE_CALIBRATION_STATUS 0x14
72
73
74#define PCI1723_CONTROL_CMD_CALIBRATION_FUN 0x16
75
76
77
78
79#define PCI1723_STATUS_CMD_CALIBRATION_FUN 0x16
80
81
82
83
84
85#define PCI1723_CALIBRATION_PARA_STROBE 0x18
86
87
88#define PCI1723_DIGITAL_IO_PORT_SET 0x1A
89#define PCI1723_DIGITAL_IO_PORT_MODE 0x1A
90
91#define PCI1723_WRITE_DIGITAL_OUTPUT_CMD 0x1C
92
93#define PCI1723_READ_DIGITAL_INPUT_DATA 0x1C
94
95#define PCI1723_WRITE_CAL_CMD 0x1E
96#define PCI1723_READ_CAL_STATUS 0x1E
97
98#define PCI1723_SYN_STROBE 0x20
99
100#define PCI1723_RESET_ALL_CHN_STROBE 0x22
101
102
103#define PCI1723_RESET_CAL_CONTROL_STROBE 0x24
104
105
106
107
108
109#define PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE 0x26
110
111
112
113
114
115#define PCI1723_SELECT_CALIBRATION 0x28
116
117
118
119static const struct comedi_lrange range_pci1723 = { 1, {
120 BIP_RANGE(10)
121 }
122};
123
124
125
126
127struct pci1723_board {
128 const char *name;
129 int vendor_id;
130 int device_id;
131 int iorange;
132 char cardtype;
133 int n_aochan;
134 int n_diochan;
135 int ao_maxdata;
136 const struct comedi_lrange *rangelist_ao;
137};
138
139static const struct pci1723_board boardtypes[] = {
140 {
141 .name = "pci1723",
142 .vendor_id = PCI_VENDOR_ID_ADVANTECH,
143 .device_id = 0x1723,
144 .iorange = IORANGE_1723,
145 .cardtype = TYPE_PCI1723,
146 .n_aochan = 8,
147 .n_diochan = 16,
148 .ao_maxdata = 0xffff,
149 .rangelist_ao = &range_pci1723,
150 },
151};
152
153
154
155
156
157static DEFINE_PCI_DEVICE_TABLE(pci1723_pci_table) = {
158 { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) },
159 { 0 }
160};
161
162MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
163
164
165
166
167
168
169
170static int pci1723_attach(struct comedi_device *dev,
171 struct comedi_devconfig *it);
172static int pci1723_detach(struct comedi_device *dev);
173
174#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pci1723_board))
175
176static struct comedi_driver driver_pci1723 = {
177 .driver_name = "adv_pci1723",
178 .module = THIS_MODULE,
179 .attach = pci1723_attach,
180 .detach = pci1723_detach,
181};
182
183
184struct pci1723_private {
185 int valid;
186
187 struct pci_dev *pcidev;
188 unsigned char da_range[8];
189
190 short ao_data[8];
191};
192
193
194#define devpriv ((struct pci1723_private *)dev->private)
195
196#define this_board boardtypes
197
198
199
200
201static int pci1723_reset(struct comedi_device *dev)
202{
203 int i;
204 DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n");
205
206 outw(0x01, dev->iobase + PCI1723_SYN_SET);
207
208
209 for (i = 0; i < 8; i++) {
210
211 devpriv->ao_data[i] = 0x8000;
212 outw(devpriv->ao_data[i], dev->iobase + PCI1723_DA(i));
213
214 devpriv->da_range[i] = 0;
215 outw(((devpriv->da_range[i] << 4) | i),
216 PCI1723_RANGE_CALIBRATION_MODE);
217 }
218
219 outw(0, dev->iobase + PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE);
220
221 outw(0, dev->iobase + PCI1723_SYN_STROBE);
222
223
224 outw(0, dev->iobase + PCI1723_SYN_SET);
225
226 DPRINTK("adv_pci1723 EDBG: END: pci1723_reset(...)\n");
227 return 0;
228}
229
230static int pci1723_insn_read_ao(struct comedi_device *dev,
231 struct comedi_subdevice *s,
232 struct comedi_insn *insn, unsigned int *data)
233{
234 int n, chan;
235
236 chan = CR_CHAN(insn->chanspec);
237 DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() -----\n");
238 for (n = 0; n < insn->n; n++)
239 data[n] = devpriv->ao_data[chan];
240
241 return n;
242}
243
244
245
246
247static int pci1723_ao_write_winsn(struct comedi_device *dev,
248 struct comedi_subdevice *s,
249 struct comedi_insn *insn, unsigned int *data)
250{
251 int n, chan;
252 chan = CR_CHAN(insn->chanspec);
253
254 DPRINTK("PCI1723: the pci1723_ao_write_winsn() ------\n");
255
256 for (n = 0; n < insn->n; n++) {
257
258 devpriv->ao_data[chan] = data[n];
259 outw(data[n], dev->iobase + PCI1723_DA(chan));
260 }
261
262 return n;
263}
264
265
266
267
268static int pci1723_dio_insn_config(struct comedi_device *dev,
269 struct comedi_subdevice *s,
270 struct comedi_insn *insn, unsigned int *data)
271{
272 unsigned int mask;
273 unsigned int bits;
274 unsigned short dio_mode;
275
276 mask = 1 << CR_CHAN(insn->chanspec);
277 if (mask & 0x00FF)
278 bits = 0x00FF;
279 else
280 bits = 0xFF00;
281
282 switch (data[0]) {
283 case INSN_CONFIG_DIO_INPUT:
284 s->io_bits &= ~bits;
285 break;
286 case INSN_CONFIG_DIO_OUTPUT:
287 s->io_bits |= bits;
288 break;
289 case INSN_CONFIG_DIO_QUERY:
290 data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
291 return insn->n;
292 default:
293 return -EINVAL;
294 }
295
296
297 dio_mode = 0x0000;
298 if ((s->io_bits & 0x00FF) == 0)
299 dio_mode |= 0x0001;
300 if ((s->io_bits & 0xFF00) == 0)
301 dio_mode |= 0x0002;
302 outw(dio_mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET);
303 return 1;
304}
305
306
307
308
309static int pci1723_dio_insn_bits(struct comedi_device *dev,
310 struct comedi_subdevice *s,
311 struct comedi_insn *insn, unsigned int *data)
312{
313 if (data[0]) {
314 s->state &= ~data[0];
315 s->state |= (data[0] & data[1]);
316 outw(s->state, dev->iobase + PCI1723_WRITE_DIGITAL_OUTPUT_CMD);
317 }
318 data[1] = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
319 return 2;
320}
321
322
323
324
325
326static int pci1723_attach(struct comedi_device *dev,
327 struct comedi_devconfig *it)
328{
329 struct comedi_subdevice *s;
330 int ret, subdev, n_subdevices;
331 struct pci_dev *pcidev;
332 unsigned int iobase;
333 unsigned char pci_bus, pci_slot, pci_func;
334 int opt_bus, opt_slot;
335 const char *errstr;
336
337 printk(KERN_ERR "comedi%d: adv_pci1723: board=%s",
338 dev->minor, this_board->name);
339
340 opt_bus = it->options[0];
341 opt_slot = it->options[1];
342
343 ret = alloc_private(dev, sizeof(struct pci1723_private));
344 if (ret < 0) {
345 printk(" - Allocation failed!\n");
346 return -ENOMEM;
347 }
348
349
350 errstr = "not found!";
351 pcidev = NULL;
352 while (NULL != (pcidev =
353 pci_get_device(PCI_VENDOR_ID_ADVANTECH,
354 this_board->device_id, pcidev))) {
355
356 if (opt_bus || opt_slot) {
357
358 if (opt_bus != pcidev->bus->number
359 || opt_slot != PCI_SLOT(pcidev->devfn))
360 continue;
361 }
362
363
364
365
366 if (comedi_pci_enable(pcidev, "adv_pci1723")) {
367 errstr =
368 "failed to enable PCI device and request regions!";
369 continue;
370 }
371 break;
372 }
373
374 if (!pcidev) {
375 if (opt_bus || opt_slot) {
376 printk(KERN_ERR " - Card at b:s %d:%d %s\n",
377 opt_bus, opt_slot, errstr);
378 } else {
379 printk(KERN_ERR " - Card %s\n", errstr);
380 }
381 return -EIO;
382 }
383
384 pci_bus = pcidev->bus->number;
385 pci_slot = PCI_SLOT(pcidev->devfn);
386 pci_func = PCI_FUNC(pcidev->devfn);
387 iobase = pci_resource_start(pcidev, 2);
388
389 printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4x",
390 pci_bus, pci_slot, pci_func, iobase);
391
392 dev->iobase = iobase;
393
394 dev->board_name = this_board->name;
395 devpriv->pcidev = pcidev;
396
397 n_subdevices = 0;
398
399 if (this_board->n_aochan)
400 n_subdevices++;
401 if (this_board->n_diochan)
402 n_subdevices++;
403
404 ret = alloc_subdevices(dev, n_subdevices);
405 if (ret < 0) {
406 printk(" - Allocation failed!\n");
407 return ret;
408 }
409
410 pci1723_reset(dev);
411 subdev = 0;
412 if (this_board->n_aochan) {
413 s = dev->subdevices + subdev;
414 dev->write_subdev = s;
415 s->type = COMEDI_SUBD_AO;
416 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
417 s->n_chan = this_board->n_aochan;
418 s->maxdata = this_board->ao_maxdata;
419 s->len_chanlist = this_board->n_aochan;
420 s->range_table = this_board->rangelist_ao;
421
422 s->insn_write = pci1723_ao_write_winsn;
423 s->insn_read = pci1723_insn_read_ao;
424
425
426 switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE)
427 & 0x03) {
428 case 0x00:
429 s->io_bits = 0xFFFF;
430 break;
431 case 0x01:
432 s->io_bits = 0xFF00;
433 break;
434 case 0x02:
435 s->io_bits = 0x00FF;
436 break;
437 case 0x03:
438 s->io_bits = 0x0000;
439 break;
440 }
441
442 s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
443
444 subdev++;
445 }
446
447 if (this_board->n_diochan) {
448 s = dev->subdevices + subdev;
449 s->type = COMEDI_SUBD_DIO;
450 s->subdev_flags =
451 SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
452 s->n_chan = this_board->n_diochan;
453 s->maxdata = 1;
454 s->len_chanlist = this_board->n_diochan;
455 s->range_table = &range_digital;
456 s->insn_config = pci1723_dio_insn_config;
457 s->insn_bits = pci1723_dio_insn_bits;
458 subdev++;
459 }
460
461 devpriv->valid = 1;
462
463 pci1723_reset(dev);
464
465 return 0;
466}
467
468
469
470
471
472
473
474
475
476static int pci1723_detach(struct comedi_device *dev)
477{
478 printk(KERN_ERR "comedi%d: pci1723: remove\n", dev->minor);
479
480 if (dev->private) {
481 if (devpriv->valid)
482 pci1723_reset(dev);
483
484 if (devpriv->pcidev) {
485 if (dev->iobase)
486 comedi_pci_disable(devpriv->pcidev);
487 pci_dev_put(devpriv->pcidev);
488 }
489 }
490
491 return 0;
492}
493
494
495
496
497
498static int __devinit driver_pci1723_pci_probe(struct pci_dev *dev,
499 const struct pci_device_id *ent)
500{
501 return comedi_pci_auto_config(dev, driver_pci1723.driver_name);
502}
503
504static void __devexit driver_pci1723_pci_remove(struct pci_dev *dev)
505{
506 comedi_pci_auto_unconfig(dev);
507}
508
509static struct pci_driver driver_pci1723_pci_driver = {
510 .id_table = pci1723_pci_table,
511 .probe = &driver_pci1723_pci_probe,
512 .remove = __devexit_p(&driver_pci1723_pci_remove)
513};
514
515static int __init driver_pci1723_init_module(void)
516{
517 int retval;
518
519 retval = comedi_driver_register(&driver_pci1723);
520 if (retval < 0)
521 return retval;
522
523 driver_pci1723_pci_driver.name = (char *)driver_pci1723.driver_name;
524 return pci_register_driver(&driver_pci1723_pci_driver);
525}
526
527static void __exit driver_pci1723_cleanup_module(void)
528{
529 pci_unregister_driver(&driver_pci1723_pci_driver);
530 comedi_driver_unregister(&driver_pci1723);
531}
532
533module_init(driver_pci1723_init_module);
534module_exit(driver_pci1723_cleanup_module);
535
536MODULE_AUTHOR("Comedi http://www.comedi.org");
537MODULE_DESCRIPTION("Comedi low-level driver");
538MODULE_LICENSE("GPL");
539