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#include "../comedidev.h"
45#include <linux/ioport.h>
46#include <asm/byteorder.h>
47
48#define S526_SIZE 64
49
50#define S526_START_AI_CONV 0
51#define S526_AI_READ 0
52
53
54#define S526_IOSIZE 0x40
55#define S526_NUM_PORTS 27
56
57
58#define REG_TCR 0x00
59#define REG_WDC 0x02
60#define REG_DAC 0x04
61#define REG_ADC 0x06
62#define REG_ADD 0x08
63#define REG_DIO 0x0A
64#define REG_IER 0x0C
65#define REG_ISR 0x0E
66#define REG_MSC 0x10
67#define REG_C0L 0x12
68#define REG_C0H 0x14
69#define REG_C0M 0x16
70#define REG_C0C 0x18
71#define REG_C1L 0x1A
72#define REG_C1H 0x1C
73#define REG_C1M 0x1E
74#define REG_C1C 0x20
75#define REG_C2L 0x22
76#define REG_C2H 0x24
77#define REG_C2M 0x26
78#define REG_C2C 0x28
79#define REG_C3L 0x2A
80#define REG_C3H 0x2C
81#define REG_C3M 0x2E
82#define REG_C3C 0x30
83#define REG_EED 0x32
84#define REG_EEC 0x34
85
86static const int s526_ports[] = {
87 REG_TCR,
88 REG_WDC,
89 REG_DAC,
90 REG_ADC,
91 REG_ADD,
92 REG_DIO,
93 REG_IER,
94 REG_ISR,
95 REG_MSC,
96 REG_C0L,
97 REG_C0H,
98 REG_C0M,
99 REG_C0C,
100 REG_C1L,
101 REG_C1H,
102 REG_C1M,
103 REG_C1C,
104 REG_C2L,
105 REG_C2H,
106 REG_C2M,
107 REG_C2C,
108 REG_C3L,
109 REG_C3H,
110 REG_C3M,
111 REG_C3C,
112 REG_EED,
113 REG_EEC
114};
115
116struct counter_mode_register_t {
117#if defined(__LITTLE_ENDIAN_BITFIELD)
118 unsigned short coutSource:1;
119 unsigned short coutPolarity:1;
120 unsigned short autoLoadResetRcap:3;
121 unsigned short hwCtEnableSource:2;
122 unsigned short ctEnableCtrl:2;
123 unsigned short clockSource:2;
124 unsigned short countDir:1;
125 unsigned short countDirCtrl:1;
126 unsigned short outputRegLatchCtrl:1;
127 unsigned short preloadRegSel:1;
128 unsigned short reserved:1;
129 #elif defined(__BIG_ENDIAN_BITFIELD)
130 unsigned short reserved:1;
131 unsigned short preloadRegSel:1;
132 unsigned short outputRegLatchCtrl:1;
133 unsigned short countDirCtrl:1;
134 unsigned short countDir:1;
135 unsigned short clockSource:2;
136 unsigned short ctEnableCtrl:2;
137 unsigned short hwCtEnableSource:2;
138 unsigned short autoLoadResetRcap:3;
139 unsigned short coutPolarity:1;
140 unsigned short coutSource:1;
141#else
142#error Unknown bit field order
143#endif
144};
145
146union cmReg {
147 struct counter_mode_register_t reg;
148 unsigned short value;
149};
150
151#define MAX_GPCT_CONFIG_DATA 6
152
153
154
155enum S526_GPCT_APP_CLASS {
156 CountingAndTimeMeasurement,
157 SinglePulseGeneration,
158 PulseTrainGeneration,
159 PositionMeasurement,
160 Miscellaneous
161};
162
163
164
165
166struct s526GPCTConfig {
167 enum S526_GPCT_APP_CLASS app;
168 int data[MAX_GPCT_CONFIG_DATA];
169};
170
171
172
173
174
175
176struct s526_board {
177 const char *name;
178 int gpct_chans;
179 int gpct_bits;
180 int ad_chans;
181 int ad_bits;
182 int da_chans;
183 int da_bits;
184 int have_dio;
185};
186
187static const struct s526_board s526_boards[] = {
188 {
189 .name = "s526",
190 .gpct_chans = 4,
191 .gpct_bits = 24,
192 .ad_chans = 8,
193 .ad_bits = 16,
194 .da_chans = 4,
195 .da_bits = 16,
196 .have_dio = 1,
197 }
198};
199
200#define ADDR_REG(reg) (dev->iobase + (reg))
201#define ADDR_CHAN_REG(reg, chan) (dev->iobase + (reg) + (chan) * 8)
202
203
204
205
206
207
208struct s526_private {
209 unsigned int ao_readback[2];
210 struct s526GPCTConfig s526_gpct_config[4];
211 unsigned short s526_ai_config;
212};
213
214
215
216
217
218#define devpriv ((struct s526_private *)dev->private)
219
220static int s526_gpct_rinsn(struct comedi_device *dev,
221 struct comedi_subdevice *s, struct comedi_insn *insn,
222 unsigned int *data)
223{
224 int i;
225 int counter_channel = CR_CHAN(insn->chanspec);
226 unsigned short datalow;
227 unsigned short datahigh;
228
229
230 if (insn->n <= 0) {
231 printk(KERN_ERR "s526: INSN_READ: n should be > 0\n");
232 return -EINVAL;
233 }
234
235 for (i = 0; i < insn->n; i++) {
236 datalow = inw(ADDR_CHAN_REG(REG_C0L, counter_channel));
237 datahigh = inw(ADDR_CHAN_REG(REG_C0H, counter_channel));
238 data[i] = (int)(datahigh & 0x00FF);
239 data[i] = (data[i] << 16) | (datalow & 0xFFFF);
240
241
242 }
243 return i;
244}
245
246static int s526_gpct_insn_config(struct comedi_device *dev,
247 struct comedi_subdevice *s,
248 struct comedi_insn *insn, unsigned int *data)
249{
250 int subdev_channel = CR_CHAN(insn->chanspec);
251 int i;
252 short value;
253 union cmReg cmReg;
254
255
256
257
258 for (i = 0; i < MAX_GPCT_CONFIG_DATA; i++) {
259 devpriv->s526_gpct_config[subdev_channel].data[i] =
260 insn->data[i];
261
262 }
263
264
265
266 switch (insn->data[0]) {
267 case INSN_CONFIG_GPCT_QUADRATURE_ENCODER:
268
269
270
271
272
273
274 printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring Encoder\n");
275 devpriv->s526_gpct_config[subdev_channel].app =
276 PositionMeasurement;
277
278#if 0
279
280
281 cmReg.reg.coutSource = 0;
282 cmReg.reg.coutPolarity = 1;
283 cmReg.reg.autoLoadResetRcap = 0;
284 cmReg.reg.hwCtEnableSource = 3;
285 cmReg.reg.ctEnableCtrl = 2;
286 cmReg.reg.clockSource = 2;
287 cmReg.reg.countDir = 1;
288 cmReg.reg.countDirCtrl = 1;
289 cmReg.reg.outputRegLatchCtrl = 0;
290 cmReg.reg.preloadRegSel = 0;
291 cmReg.reg.reserved = 0;
292
293 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
294
295 outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
296 outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
297
298
299 outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
300
301 outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
302
303
304 outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));
305
306#endif
307
308#if 1
309
310 cmReg.value = insn->data[1] & 0xFFFF;
311
312
313 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
314
315
316 if (cmReg.reg.autoLoadResetRcap == 0) {
317
318 outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
319
320
321
322 }
323#else
324
325 cmReg.reg.countDirCtrl = 0;
326
327
328 if (insn->data[1] == GPCT_X2)
329 cmReg.reg.clockSource = 1;
330 else if (insn->data[1] == GPCT_X4)
331 cmReg.reg.clockSource = 2;
332 else
333 cmReg.reg.clockSource = 0;
334
335
336
337
338
339
340
341
342 if (insn->data[3] == GPCT_RESET_COUNTER_ON_INDEX)
343
344 cmReg.reg.autoLoadResetRcap = 4;
345
346
347 cmReg.value = (short)(insn->data[1] & 0xFFFF);
348 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
349
350
351 value = (short)((insn->data[2] >> 16) & 0xFFFF);
352 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
353
354
355 value = (short)(insn->data[2] & 0xFFFF);
356 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
357
358
359 if (insn->data[3] != 0) {
360 value = (short)(insn->data[3] & 0xFFFF);
361 outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
362 }
363
364 if (cmReg.reg.autoLoadResetRcap == 0) {
365
366 outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
367
368 outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
369 }
370#endif
371 break;
372
373 case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR:
374
375
376
377
378
379
380
381 printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring SPG\n");
382 devpriv->s526_gpct_config[subdev_channel].app =
383 SinglePulseGeneration;
384
385
386 cmReg.value = (short)(insn->data[1] & 0xFFFF);
387 cmReg.reg.preloadRegSel = 0;
388 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
389
390
391 value = (short)((insn->data[2] >> 16) & 0xFFFF);
392 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
393
394
395 value = (short)(insn->data[2] & 0xFFFF);
396 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
397
398
399 cmReg.value = (short)(insn->data[1] & 0xFFFF);
400 cmReg.reg.preloadRegSel = 1;
401 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
402
403
404 value = (short)((insn->data[3] >> 16) & 0xFFFF);
405 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
406
407
408 value = (short)(insn->data[3] & 0xFFFF);
409 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
410
411
412 if (insn->data[4] != 0) {
413 value = (short)(insn->data[4] & 0xFFFF);
414 outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
415 }
416 break;
417
418 case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR:
419
420
421
422
423
424
425
426 printk(KERN_INFO "s526: GPCT_INSN_CONFIG: Configuring PTG\n");
427 devpriv->s526_gpct_config[subdev_channel].app =
428 PulseTrainGeneration;
429
430
431 cmReg.value = (short)(insn->data[1] & 0xFFFF);
432 cmReg.reg.preloadRegSel = 0;
433 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
434
435
436 value = (short)((insn->data[2] >> 16) & 0xFFFF);
437 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
438
439
440 value = (short)(insn->data[2] & 0xFFFF);
441 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
442
443
444 cmReg.value = (short)(insn->data[1] & 0xFFFF);
445 cmReg.reg.preloadRegSel = 1;
446 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
447
448
449 value = (short)((insn->data[3] >> 16) & 0xFFFF);
450 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
451
452
453 value = (short)(insn->data[3] & 0xFFFF);
454 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
455
456
457 if (insn->data[4] != 0) {
458 value = (short)(insn->data[4] & 0xFFFF);
459 outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
460 }
461 break;
462
463 default:
464 printk(KERN_ERR "s526: unsupported GPCT_insn_config\n");
465 return -EINVAL;
466 break;
467 }
468
469 return insn->n;
470}
471
472static int s526_gpct_winsn(struct comedi_device *dev,
473 struct comedi_subdevice *s, struct comedi_insn *insn,
474 unsigned int *data)
475{
476 int subdev_channel = CR_CHAN(insn->chanspec);
477 short value;
478 union cmReg cmReg;
479
480 printk(KERN_INFO "s526: GPCT_INSN_WRITE on channel %d\n",
481 subdev_channel);
482 cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
483 printk(KERN_INFO "s526: Counter Mode Register: %x\n", cmReg.value);
484
485 switch (devpriv->s526_gpct_config[subdev_channel].app) {
486 case PositionMeasurement:
487 printk(KERN_INFO "S526: INSN_WRITE: PM\n");
488 outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H,
489 subdev_channel));
490 outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel));
491 break;
492
493 case SinglePulseGeneration:
494 printk(KERN_INFO "S526: INSN_WRITE: SPG\n");
495 outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H,
496 subdev_channel));
497 outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel));
498 break;
499
500 case PulseTrainGeneration:
501
502
503
504
505
506
507 printk(KERN_INFO "S526: INSN_WRITE: PTG\n");
508 if ((insn->data[1] > insn->data[0]) && (insn->data[0] > 0)) {
509 (devpriv->s526_gpct_config[subdev_channel]).data[0] =
510 insn->data[0];
511 (devpriv->s526_gpct_config[subdev_channel]).data[1] =
512 insn->data[1];
513 } else {
514 printk(KERN_ERR "s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n",
515 insn->data[0], insn->data[1]);
516 return -EINVAL;
517 }
518
519 value = (short)((*data >> 16) & 0xFFFF);
520 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
521 value = (short)(*data & 0xFFFF);
522 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
523 break;
524 default:
525 printk
526 ("s526: INSN_WRITE: Functionality %d not implemented yet\n",
527 devpriv->s526_gpct_config[subdev_channel].app);
528 return -EINVAL;
529 break;
530 }
531
532 return insn->n;
533}
534
535#define ISR_ADC_DONE 0x4
536static int s526_ai_insn_config(struct comedi_device *dev,
537 struct comedi_subdevice *s,
538 struct comedi_insn *insn, unsigned int *data)
539{
540 int result = -EINVAL;
541
542 if (insn->n < 1)
543 return result;
544
545 result = insn->n;
546
547
548
549
550
551
552
553
554
555 outw(ISR_ADC_DONE, ADDR_REG(REG_IER));
556
557 devpriv->s526_ai_config = (data[0] & 0x3FF) << 5;
558 if (data[1] > 0)
559 devpriv->s526_ai_config |= 0x8000;
560
561 devpriv->s526_ai_config |= 0x0001;
562
563 return result;
564}
565
566
567
568
569
570static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
571 struct comedi_insn *insn, unsigned int *data)
572{
573 int n, i;
574 int chan = CR_CHAN(insn->chanspec);
575 unsigned short value;
576 unsigned int d;
577 unsigned int status;
578
579
580
581 value = (devpriv->s526_ai_config & 0x8000) |
582 ((1 << 5) << chan) | (chan << 1) | 0x0001;
583
584
585 for (n = 0; n < insn->n; n++) {
586
587 outw(value, ADDR_REG(REG_ADC));
588
589
590
591#define TIMEOUT 100
592
593 for (i = 0; i < TIMEOUT; i++) {
594 status = inw(ADDR_REG(REG_ISR));
595 if (status & ISR_ADC_DONE) {
596 outw(ISR_ADC_DONE, ADDR_REG(REG_ISR));
597 break;
598 }
599 }
600 if (i == TIMEOUT) {
601
602
603 printk(KERN_ERR "s526: ADC(0x%04x) timeout\n",
604 inw(ADDR_REG(REG_ISR)));
605 return -ETIMEDOUT;
606 }
607
608
609 d = inw(ADDR_REG(REG_ADD));
610
611
612
613 data[n] = d ^ 0x8000;
614 }
615
616
617 return n;
618}
619
620static int s526_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
621 struct comedi_insn *insn, unsigned int *data)
622{
623 int i;
624 int chan = CR_CHAN(insn->chanspec);
625 unsigned short val;
626
627
628 val = chan << 1;
629
630 outw(val, ADDR_REG(REG_DAC));
631
632
633
634 for (i = 0; i < insn->n; i++) {
635
636
637
638
639
640 outw(data[i], ADDR_REG(REG_ADD));
641 devpriv->ao_readback[chan] = data[i];
642
643 outw(val + 1, ADDR_REG(REG_DAC));
644 }
645
646
647 return i;
648}
649
650
651
652static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
653 struct comedi_insn *insn, unsigned int *data)
654{
655 int i;
656 int chan = CR_CHAN(insn->chanspec);
657
658 for (i = 0; i < insn->n; i++)
659 data[i] = devpriv->ao_readback[chan];
660
661 return i;
662}
663
664
665
666
667
668
669static int s526_dio_insn_bits(struct comedi_device *dev,
670 struct comedi_subdevice *s,
671 struct comedi_insn *insn, unsigned int *data)
672{
673
674
675 if (data[0]) {
676 s->state &= ~data[0];
677 s->state |= data[0] & data[1];
678
679 outw(s->state, ADDR_REG(REG_DIO));
680 }
681
682
683
684 data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF;
685
686
687
688
689 return insn->n;
690}
691
692static int s526_dio_insn_config(struct comedi_device *dev,
693 struct comedi_subdevice *s,
694 struct comedi_insn *insn, unsigned int *data)
695{
696 int chan = CR_CHAN(insn->chanspec);
697 int group, mask;
698
699 printk(KERN_INFO "S526 DIO insn_config\n");
700
701
702
703
704
705
706 group = chan >> 2;
707 mask = 0xF << (group << 2);
708 switch (data[0]) {
709 case INSN_CONFIG_DIO_OUTPUT:
710
711 s->state |= 1 << (group + 10);
712 s->io_bits |= mask;
713 break;
714 case INSN_CONFIG_DIO_INPUT:
715 s->state &= ~(1 << (group + 10));
716 s->io_bits &= ~mask;
717 break;
718 case INSN_CONFIG_DIO_QUERY:
719 data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
720 return insn->n;
721 default:
722 return -EINVAL;
723 }
724 outw(s->state, ADDR_REG(REG_DIO));
725
726 return 1;
727}
728
729static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
730{
731 const struct s526_board *board = comedi_board(dev);
732 struct comedi_subdevice *s;
733 int iobase;
734 int i, n;
735 int ret;
736
737
738 union cmReg cmReg;
739
740 printk(KERN_INFO "comedi%d: s526: ", dev->minor);
741
742 iobase = it->options[0];
743 if (!iobase || !request_region(iobase, S526_IOSIZE, board->name)) {
744 comedi_error(dev, "I/O port conflict");
745 return -EIO;
746 }
747 dev->iobase = iobase;
748
749 printk("iobase=0x%lx\n", dev->iobase);
750
751
752
753
754
755
756
757
758 dev->board_name = board->name;
759
760
761
762
763
764 if (alloc_private(dev, sizeof(struct s526_private)) < 0)
765 return -ENOMEM;
766
767 ret = comedi_alloc_subdevices(dev, 4);
768 if (ret)
769 return ret;
770
771 s = dev->subdevices + 0;
772
773 s->type = COMEDI_SUBD_COUNTER;
774 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
775
776 s->n_chan = board->gpct_chans;
777 s->maxdata = 0x00ffffff;
778 s->insn_read = s526_gpct_rinsn;
779 s->insn_config = s526_gpct_insn_config;
780 s->insn_write = s526_gpct_winsn;
781
782
783
784
785
786
787
788
789 s = dev->subdevices + 1;
790
791
792 s->type = COMEDI_SUBD_AI;
793
794 s->subdev_flags = SDF_READABLE | SDF_DIFF;
795
796
797 s->n_chan = 10;
798 s->maxdata = 0xffff;
799 s->range_table = &range_bipolar10;
800 s->len_chanlist = 16;
801
802 s->insn_read = s526_ai_rinsn;
803 s->insn_config = s526_ai_insn_config;
804
805 s = dev->subdevices + 2;
806
807 s->type = COMEDI_SUBD_AO;
808 s->subdev_flags = SDF_WRITABLE;
809 s->n_chan = 4;
810 s->maxdata = 0xffff;
811 s->range_table = &range_bipolar10;
812 s->insn_write = s526_ao_winsn;
813 s->insn_read = s526_ao_rinsn;
814
815 s = dev->subdevices + 3;
816
817 if (board->have_dio) {
818 s->type = COMEDI_SUBD_DIO;
819 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
820 s->n_chan = 8;
821 s->maxdata = 1;
822 s->range_table = &range_digital;
823 s->insn_bits = s526_dio_insn_bits;
824 s->insn_config = s526_dio_insn_config;
825 } else {
826 s->type = COMEDI_SUBD_UNUSED;
827 }
828
829 printk(KERN_INFO "attached\n");
830
831 return 1;
832
833#if 0
834
835
836 cmReg.reg.coutSource = 0;
837 cmReg.reg.coutPolarity = 1;
838 cmReg.reg.autoLoadResetRcap = 1;
839 cmReg.reg.hwCtEnableSource = 3;
840 cmReg.reg.ctEnableCtrl = 2;
841 cmReg.reg.clockSource = 2;
842 cmReg.reg.countDir = 1;
843 cmReg.reg.countDirCtrl = 1;
844 cmReg.reg.outputRegLatchCtrl = 0;
845 cmReg.reg.preloadRegSel = 0;
846 cmReg.reg.reserved = 0;
847
848 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
849
850 outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
851 outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
852
853
854 outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
855
856 outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));
857
858 outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));
859
860#else
861
862
863 cmReg.reg.coutSource = 0;
864 cmReg.reg.coutPolarity = 0;
865 cmReg.reg.autoLoadResetRcap = 0;
866 cmReg.reg.hwCtEnableSource = 2;
867 cmReg.reg.ctEnableCtrl = 1;
868 cmReg.reg.clockSource = 3;
869 cmReg.reg.countDir = 0;
870 cmReg.reg.countDirCtrl = 0;
871 cmReg.reg.outputRegLatchCtrl = 0;
872 cmReg.reg.preloadRegSel = 0;
873 cmReg.reg.reserved = 0;
874
875 n = 0;
876 printk(KERN_INFO "Mode reg=0x%04x, 0x%04lx\n",
877 cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
878 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
879 udelay(1000);
880 printk(KERN_INFO "Read back mode reg=0x%04x\n",
881 inw(ADDR_CHAN_REG(REG_C0M, n)));
882
883
884
885
886
887
888
889
890
891
892
893
894
895 if (cmReg.reg.autoLoadResetRcap == 0) {
896
897 outw(0x8000, ADDR_CHAN_REG(REG_C0C, n));
898
899 outw(0x4000, ADDR_CHAN_REG(REG_C0C, n));
900 }
901
902 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
903 udelay(1000);
904 printk(KERN_INFO "Read back mode reg=0x%04x\n",
905 inw(ADDR_CHAN_REG(REG_C0M, n)));
906
907#endif
908 printk(KERN_INFO "Current registres:\n");
909
910 for (i = 0; i < S526_NUM_PORTS; i++) {
911 printk(KERN_INFO "0x%02lx: 0x%04x\n",
912 ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i])));
913 }
914 return 1;
915}
916
917static void s526_detach(struct comedi_device *dev)
918{
919 if (dev->iobase > 0)
920 release_region(dev->iobase, S526_IOSIZE);
921}
922
923static struct comedi_driver s526_driver = {
924 .driver_name = "s526",
925 .module = THIS_MODULE,
926 .attach = s526_attach,
927 .detach = s526_detach,
928 .board_name = &s526_boards[0].name,
929 .offset = sizeof(struct s526_board),
930 .num_names = ARRAY_SIZE(s526_boards),
931};
932module_comedi_driver(s526_driver);
933
934MODULE_AUTHOR("Comedi http://www.comedi.org");
935MODULE_DESCRIPTION("Comedi low-level driver");
936MODULE_LICENSE("GPL");
937