s526: remove data[] from s526_gpct_config_t
[comedi.git] / comedi / drivers / s526.c
1 /*
2     comedi/drivers/s526.c
3     Sensoray s526 Comedi driver
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23 /*
24 Driver: s526
25 Description: Sensoray 526 driver
26 Devices: [Sensoray] 526 (s526)
27 Author: Richie
28         Everett Wang <everett.wang@everteq.com>
29 Updated: Thu, 14 Sep. 2006
30 Status: experimental
31
32 Encoder works
33 Analog input works
34 Analog output works
35 PWM output works
36 Commands are not supported yet.
37
38 Configuration Options:
39
40 comedi_config /dev/comedi0 s526 0x2C0,0x3
41
42 */
43
44 #include <linux/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 /* Ports */
54 #define S526_IOSIZE 0x40
55 #define S526_NUM_PORTS 27
56
57 /* registers */
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
86 static 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
116 typedef struct {
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 } counter_mode_register_t;
145
146 union cmReg {
147         counter_mode_register_t reg;
148         unsigned short value;
149 };
150
151 /* Different Application Classes for GPCT Subdevices */
152 /* The list is not exhaustive and needs discussion! */
153 typedef enum {
154         CountingAndTimeMeasurement,
155         SinglePulseGeneration,
156         PulseTrainGeneration,
157         PositionMeasurement,
158         Miscellaneous
159 } S526_GPCT_APP_CLASS;
160
161 /* Config struct for different GPCT subdevice Application Classes and
162    their options
163 */
164 typedef struct s526GPCTConfig {
165         S526_GPCT_APP_CLASS app;
166 } s526_gpct_config_t;
167
168 /*
169  * Board descriptions for two imaginary boards.  Describing the
170  * boards in this way is optional, and completely driver-dependent.
171  * Some drivers use arrays such as this, other do not.
172  */
173 typedef struct s526_board_struct {
174         const char *name;
175         int gpct_chans;
176         int gpct_bits;
177         int ad_chans;
178         int ad_bits;
179         int da_chans;
180         int da_bits;
181         int have_dio;
182 } s526_board;
183
184 static const s526_board s526_boards[] = {
185         {
186               name:     "s526",
187               gpct_chans:4,
188               gpct_bits:24,
189               ad_chans:8,
190               ad_bits:  16,
191               da_chans:4,
192               da_bits:  16,
193               have_dio:1,
194                 }
195 };
196
197 #define ADDR_REG(reg) (dev->iobase + (reg))
198 #define ADDR_CHAN_REG(reg, chan) (dev->iobase + (reg) + (chan) * 8)
199
200 /*
201  * Useful for shorthand access to the particular board structure
202  */
203 #define thisboard ((const s526_board *)dev->board_ptr)
204
205 /* this structure is for data unique to this hardware driver.  If
206    several hardware drivers keep similar information in this structure,
207    feel free to suggest moving the variable to the comedi_device struct.  */
208 typedef struct {
209         int data;
210
211         /* would be useful for a PCI device */
212         struct pci_dev *pci_dev;
213
214         /* Used for AO readback */
215         lsampl_t ao_readback[2];
216
217         s526_gpct_config_t s526_gpct_config[4];
218         unsigned short s526_ai_config;
219 } s526_private;
220 /*
221  * most drivers define the following macro to make it easy to
222  * access the private structure.
223  */
224 #define devpriv ((s526_private *)dev->private)
225
226 /*
227  * The comedi_driver structure tells the Comedi core module
228  * which functions to call to configure/deconfigure (attach/detach)
229  * the board, and also about the kernel module that contains
230  * the device code.
231  */
232 static int s526_attach(comedi_device * dev, comedi_devconfig * it);
233 static int s526_detach(comedi_device * dev);
234 static comedi_driver driver_s526 = {
235       driver_name:"s526",
236       module:THIS_MODULE,
237       attach:s526_attach,
238       detach:s526_detach,
239 /* It is not necessary to implement the following members if you are
240  * writing a driver for a ISA PnP or PCI card */
241         /* Most drivers will support multiple types of boards by
242          * having an array of board structures.  These were defined
243          * in s526_boards[] above.  Note that the element 'name'
244          * was first in the structure -- Comedi uses this fact to
245          * extract the name of the board without knowing any details
246          * about the structure except for its length.
247          * When a device is attached (by comedi_config), the name
248          * of the device is given to Comedi, and Comedi tries to
249          * match it by going through the list of board names.  If
250          * there is a match, the address of the pointer is put
251          * into dev->board_ptr and driver->attach() is called.
252          *
253          * Note that these are not necessary if you can determine
254          * the type of board in software.  ISA PnP, PCI, and PCMCIA
255          * devices are such boards.
256          */
257       board_name:&s526_boards[0].name,
258       offset:sizeof(s526_board),
259       num_names:sizeof(s526_boards) / sizeof(s526_board),
260 };
261
262 static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
263         comedi_insn * insn, lsampl_t * data);
264 static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
265         comedi_insn * insn, lsampl_t * data);
266 static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
267         comedi_insn * insn, lsampl_t * data);
268 static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
269         comedi_insn * insn, lsampl_t * data);
270 static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
271         comedi_insn * insn, lsampl_t * data);
272 static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
273         comedi_insn * insn, lsampl_t * data);
274 static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
275         comedi_insn * insn, lsampl_t * data);
276 static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
277         comedi_insn * insn, lsampl_t * data);
278 static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
279         comedi_insn * insn, lsampl_t * data);
280
281 /*
282  * Attach is called by the Comedi core to configure the driver
283  * for a particular board.  If you specified a board_name array
284  * in the driver structure, dev->board_ptr contains that
285  * address.
286  */
287 static int s526_attach(comedi_device * dev, comedi_devconfig * it)
288 {
289         comedi_subdevice *s;
290         int iobase;
291         int i, n;
292 //      sampl_t value;
293 //      int subdev_channel = 0;
294         union cmReg cmReg;
295
296         printk("comedi%d: s526: ", dev->minor);
297
298         iobase = it->options[0];
299         if (!iobase || !request_region(iobase, S526_IOSIZE, thisboard->name)) {
300                 comedi_error(dev, "I/O port conflict");
301                 return -EIO;
302         }
303         dev->iobase = iobase;
304
305         printk("iobase=0x%lx\n", dev->iobase);
306
307         /*** make it a little quieter, exw, 8/29/06
308         for (i = 0; i < S526_NUM_PORTS; i++) {
309                 printk("0x%02x: 0x%04x\n", ADDR_REG(s526_ports[i]), inw(ADDR_REG(s526_ports[i])));
310         }
311         ***/
312
313 /*
314  * Initialize dev->board_name.  Note that we can use the "thisboard"
315  * macro now, since we just initialized it in the last line.
316  */
317         dev->board_ptr = &s526_boards[0];
318
319         dev->board_name = thisboard->name;
320
321 /*
322  * Allocate the private structure area.  alloc_private() is a
323  * convenient macro defined in comedidev.h.
324  */
325         if (alloc_private(dev, sizeof(s526_private)) < 0)
326                 return -ENOMEM;
327
328 /*
329  * Allocate the subdevice structures.  alloc_subdevice() is a
330  * convenient macro defined in comedidev.h.
331  */
332         dev->n_subdevices = 4;
333         if (alloc_subdevices(dev, dev->n_subdevices) < 0)
334                 return -ENOMEM;
335
336         s = dev->subdevices + 0;
337         /* GENERAL-PURPOSE COUNTER/TIME (GPCT) */
338         s->type = COMEDI_SUBD_COUNTER;
339         s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
340         /* KG: What does SDF_LSAMPL (see multiq3.c) mean? */
341         s->n_chan = thisboard->gpct_chans;
342         s->maxdata = 0x00ffffff;        /* 24 bit counter */
343         s->insn_read = s526_gpct_rinsn;
344         s->insn_config = s526_gpct_insn_config;
345         s->insn_write = s526_gpct_winsn;
346
347         /* Command are not implemented yet, however they are necessary to
348            allocate the necessary memory for the comedi_async struct (used
349            to trigger the GPCT in case of pulsegenerator function */
350         //s->do_cmd = s526_gpct_cmd;
351         //s->do_cmdtest = s526_gpct_cmdtest;
352         //s->cancel = s526_gpct_cancel;
353
354         s = dev->subdevices + 1;
355         //dev->read_subdev=s;
356         /* analog input subdevice */
357         s->type = COMEDI_SUBD_AI;
358         /* we support differential */
359         s->subdev_flags = SDF_READABLE | SDF_DIFF;
360         /* channels 0 to 7 are the regular differential inputs */
361         /* channel 8 is "reference 0" (+10V), channel 9 is "reference 1" (0V) */
362         s->n_chan = 10;
363         s->maxdata = 0xffff;
364         s->range_table = &range_bipolar10;
365         s->len_chanlist = 16;   /* This is the maximum chanlist length that
366                                    the board can handle */
367         s->insn_read = s526_ai_rinsn;
368         s->insn_config = s526_ai_insn_config;
369
370         s = dev->subdevices + 2;
371         /* analog output subdevice */
372         s->type = COMEDI_SUBD_AO;
373         s->subdev_flags = SDF_WRITABLE;
374         s->n_chan = 4;
375         s->maxdata = 0xffff;
376         s->range_table = &range_bipolar10;
377         s->insn_write = s526_ao_winsn;
378         s->insn_read = s526_ao_rinsn;
379
380         s = dev->subdevices + 3;
381         /* digital i/o subdevice */
382         if (thisboard->have_dio) {
383                 s->type = COMEDI_SUBD_DIO;
384                 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
385                 s->n_chan = 8;
386                 s->maxdata = 1;
387                 s->range_table = &range_digital;
388                 s->insn_bits = s526_dio_insn_bits;
389                 s->insn_config = s526_dio_insn_config;
390         } else {
391                 s->type = COMEDI_SUBD_UNUSED;
392         }
393
394         printk("attached\n");
395
396         return 1;
397
398 #if 0
399         // Example of Counter Application
400         //One-shot (software trigger)
401         cmReg.reg.coutSource = 0;       // out RCAP
402         cmReg.reg.coutPolarity = 1;     // Polarity inverted
403         cmReg.reg.autoLoadResetRcap = 1;        // Auto load 0:disabled, 1:enabled
404         cmReg.reg.hwCtEnableSource = 3; // NOT RCAP
405         cmReg.reg.ctEnableCtrl = 2;     // Hardware
406         cmReg.reg.clockSource = 2;      // Internal
407         cmReg.reg.countDir = 1; // Down
408         cmReg.reg.countDirCtrl = 1;     // Software
409         cmReg.reg.outputRegLatchCtrl = 0;       // latch on read
410         cmReg.reg.preloadRegSel = 0;    // PR0
411         cmReg.reg.reserved = 0;
412
413         outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
414
415         outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
416         outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
417
418         outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Reset the counter
419         outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Load the counter from PR0
420
421         outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Reset RCAP (fires one-shot)
422
423 #else
424
425         // Set Counter Mode Register
426         cmReg.reg.coutSource = 0;       // out RCAP
427         cmReg.reg.coutPolarity = 0;     // Polarity inverted
428         cmReg.reg.autoLoadResetRcap = 0;        // Auto load disabled
429         cmReg.reg.hwCtEnableSource = 2; // NOT RCAP
430         cmReg.reg.ctEnableCtrl = 1;     // 1: Software,  >1 : Hardware
431         cmReg.reg.clockSource = 3;      // x4
432         cmReg.reg.countDir = 0; // up
433         cmReg.reg.countDirCtrl = 0;     // quadrature
434         cmReg.reg.outputRegLatchCtrl = 0;       // latch on read
435         cmReg.reg.preloadRegSel = 0;    // PR0
436         cmReg.reg.reserved = 0;
437
438         n = 0;
439         printk("Mode reg=0x%04x, 0x%04lx\n", cmReg.value, ADDR_CHAN_REG(REG_C0M,
440                         n));
441         outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
442         udelay(1000);
443         printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
444
445         // Load the pre-laod register high word
446 //                      value = (sampl_t) (0x55);
447 //                      outw(value, ADDR_CHAN_REG(REG_C0H, n));
448
449         // Load the pre-laod register low word
450 //                      value = (sampl_t)(0xaa55);
451 //                      outw(value, ADDR_CHAN_REG(REG_C0L, n));
452
453         // Write the Counter Control Register
454 //                      outw(value, ADDR_CHAN_REG(REG_C0C, 0));
455
456         // Reset the counter if it is software preload
457         if (cmReg.reg.autoLoadResetRcap == 0) {
458                 outw(0x8000, ADDR_CHAN_REG(REG_C0C, n));        // Reset the counter
459                 outw(0x4000, ADDR_CHAN_REG(REG_C0C, n));        // Load the counter from PR0
460         }
461
462         outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, n));
463         udelay(1000);
464         printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
465
466 #endif
467         printk("Current registres:\n");
468
469         for (i = 0; i < S526_NUM_PORTS; i++) {
470                 printk("0x%02lx: 0x%04x\n", ADDR_REG(s526_ports[i]),
471                         inw(ADDR_REG(s526_ports[i])));
472         }
473         return 1;
474 }
475
476 /*
477  * _detach is called to deconfigure a device.  It should deallocate
478  * resources.
479  * This function is also called when _attach() fails, so it should be
480  * careful not to release resources that were not necessarily
481  * allocated by _attach().  dev->private and dev->subdevices are
482  * deallocated automatically by the core.
483  */
484 static int s526_detach(comedi_device * dev)
485 {
486         printk("comedi%d: s526: remove\n", dev->minor);
487
488         if (dev->iobase > 0)
489                 release_region(dev->iobase, S526_IOSIZE);
490
491         return 0;
492 }
493
494 static int s526_gpct_rinsn(comedi_device * dev, comedi_subdevice * s,
495         comedi_insn * insn, lsampl_t * data)
496 {
497         int i;                  // counts the Data
498         int counter_channel = CR_CHAN(insn->chanspec);
499         unsigned short datalow;
500         unsigned short datahigh;
501
502         // Check if (n > 0)
503         if (insn->n <= 0) {
504                 printk("s526: INSN_READ: n should be > 0\n");
505                 return -EINVAL;
506         }
507         // Read the low word first
508         for (i = 0; i < insn->n; i++) {
509                 datalow = inw(ADDR_CHAN_REG(REG_C0L, counter_channel));
510                 datahigh = inw(ADDR_CHAN_REG(REG_C0H, counter_channel));
511                 data[i] = (int)(datahigh & 0x00FF);
512                 data[i] = (data[i] << 16) | (datalow & 0xFFFF);
513 //              printk("s526 GPCT[%d]: %x(0x%04x, 0x%04x)\n", counter_channel, data[i], datahigh, datalow);
514         }
515         return i;
516 }
517
518 static int s526_gpct_insn_config(comedi_device * dev, comedi_subdevice * s,
519         comedi_insn * insn, lsampl_t * data)
520 {
521         int subdev_channel = CR_CHAN(insn->chanspec);   // Unpack chanspec
522         sampl_t value;
523         union cmReg cmReg;
524
525 //        printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel);
526
527         // Check what type of Counter the user requested, data[0] contains
528         // the Application type
529         switch (data[0]) {
530         case INSN_CONFIG_GPCT_QUADRATURE_ENCODER:
531                 /*
532                    data[0]: Application Type
533                    data[1]: Counter Mode Register Value
534                    data[2]: Pre-load Register Value
535                    data[3]: Conter Control Register
536                  */
537                 printk("s526: GPCT_INSN_CONFIG: Configuring Encoder\n");
538                 devpriv->s526_gpct_config[subdev_channel].app =
539                         PositionMeasurement;
540
541 /*
542                         // Example of Counter Application
543                         //One-shot (software trigger)
544                         cmReg.reg.coutSource            = 0; // out RCAP
545                         cmReg.reg.coutPolarity          = 1; // Polarity inverted
546                         cmReg.reg.autoLoadResetRcap     = 0; // Auto load disabled
547                         cmReg.reg.hwCtEnableSource      = 3; // NOT RCAP
548                         cmReg.reg.ctEnableCtrl          = 2; // Hardware
549                         cmReg.reg.clockSource           = 2; // Internal
550                         cmReg.reg.countDir              = 1; // Down
551                         cmReg.reg.countDirCtrl          = 1; // Software
552                         cmReg.reg.outputRegLatchCtrl    = 0; // latch on read
553                         cmReg.reg.preloadRegSel         = 0; // PR0
554                         cmReg.reg.reserved              = 0;
555
556                         outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
557
558                         outw(0x0001, ADDR_CHAN_REG(REG_C0H, subdev_channel));
559                         outw(0x3C68, ADDR_CHAN_REG(REG_C0L, subdev_channel));
560
561                         outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Reset the counter
562                         outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Load the counter from PR0
563
564                         outw(0x0008, ADDR_CHAN_REG(REG_C0C, subdev_channel));  // Reset RCAP (fires one-shot)
565
566 */
567
568 #if 1
569                 // Set Counter Mode Register
570                 cmReg.value = data[1] & 0xFFFF;
571
572 //                      printk("s526: Counter Mode register=%x\n", cmReg.value);
573                 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
574
575                 // Reset the counter if it is software preload
576                 if (cmReg.reg.autoLoadResetRcap == 0) {
577                         outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Reset the counter
578 //                              outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Load the counter from PR0
579                 }
580 #else
581                 cmReg.reg.countDirCtrl = 0;     // 0 quadrature, 1 software control
582
583                 // data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4
584                 if (data[1] == GPCT_X2) {
585                         cmReg.reg.clockSource = 1;
586                 } else if (data[1] == GPCT_X4) {
587                         cmReg.reg.clockSource = 2;
588                 } else {
589                         cmReg.reg.clockSource = 0;
590                 }
591
592                 // When to take into account the indexpulse:
593                 if (data[2] == GPCT_IndexPhaseLowLow) {
594                 } else if (data[2] == GPCT_IndexPhaseLowHigh) {
595                 } else if (data[2] == GPCT_IndexPhaseHighLow) {
596                 } else if (data[2] == GPCT_IndexPhaseHighHigh) {
597                 }
598                 // Take into account the index pulse?
599                 if (data[3] == GPCT_RESET_COUNTER_ON_INDEX)
600                         cmReg.reg.autoLoadResetRcap = 4;        // Auto load with INDEX^
601
602                 // Set Counter Mode Register
603                 cmReg.value = (sampl_t) (data[1] & 0xFFFF);
604                 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
605
606                 // Load the pre-laod register high word
607                 value = (sampl_t) ((data[2] >> 16) & 0xFFFF);
608                 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
609
610                 // Load the pre-laod register low word
611                 value = (sampl_t) (data[2] & 0xFFFF);
612                 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
613
614                 // Write the Counter Control Register
615                 if (data[3] != 0) {
616                         value = (sampl_t) (data[3] & 0xFFFF);
617                         outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
618                 }
619                 // Reset the counter if it is software preload
620                 if (cmReg.reg.autoLoadResetRcap == 0) {
621                         outw(0x8000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Reset the counter
622                         outw(0x4000, ADDR_CHAN_REG(REG_C0C, subdev_channel));   // Load the counter from PR0
623                 }
624 #endif
625                 break;
626
627         case INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR:
628                 /*
629                    data[0]: Application Type
630                    data[1]: Counter Mode Register Value
631                    data[2]: Pre-load Register 0 Value
632                    data[3]: Pre-load Register 1 Value
633                    data[4]: Conter Control Register
634                  */
635                 printk("s526: GPCT_INSN_CONFIG: Configuring SPG\n");
636                 devpriv->s526_gpct_config[subdev_channel].app =
637                         SinglePulseGeneration;
638
639                 // Set Counter Mode Register
640                 cmReg.value = (sampl_t) (data[1] & 0xFFFF);
641                 cmReg.reg.preloadRegSel = 0;    // PR0
642                 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
643
644                 // Load the pre-laod register 0 high word
645                 value = (sampl_t) ((data[2] >> 16) & 0xFFFF);
646                 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
647
648                 // Load the pre-laod register 0 low word
649                 value = (sampl_t) (data[2] & 0xFFFF);
650                 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
651
652                 // Set Counter Mode Register
653                 cmReg.value = (sampl_t) (data[1] & 0xFFFF);
654                 cmReg.reg.preloadRegSel = 1;    // PR1
655                 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
656
657                 // Load the pre-laod register 1 high word
658                 value = (sampl_t) ((data[3] >> 16) & 0xFFFF);
659                 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
660
661                 // Load the pre-laod register 1 low word
662                 value = (sampl_t) (data[3] & 0xFFFF);
663                 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
664
665                 // Write the Counter Control Register
666                 if (data[4] != 0) {
667                         value = (sampl_t) (data[4] & 0xFFFF);
668                         outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
669                 }
670                 break;
671
672         case INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR:
673                 /*
674                    data[0]: Application Type
675                    data[1]: Counter Mode Register Value
676                    data[2]: Pre-load Register 0 Value
677                    data[3]: Pre-load Register 1 Value
678                    data[4]: Conter Control Register
679                  */
680                 printk("s526: GPCT_INSN_CONFIG: Configuring PTG\n");
681                 devpriv->s526_gpct_config[subdev_channel].app =
682                         PulseTrainGeneration;
683
684                 // Set Counter Mode Register
685                 cmReg.value = (sampl_t) (data[1] & 0xFFFF);
686                 cmReg.reg.preloadRegSel = 0;    // PR0
687                 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
688
689                 // Load the pre-laod register 0 high word
690                 value = (sampl_t) ((data[2] >> 16) & 0xFFFF);
691                 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
692
693                 // Load the pre-laod register 0 low word
694                 value = (sampl_t) (data[2] & 0xFFFF);
695                 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
696
697                 // Set Counter Mode Register
698                 cmReg.value = (sampl_t) (data[1] & 0xFFFF);
699                 cmReg.reg.preloadRegSel = 1;    // PR1
700                 outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
701
702                 // Load the pre-laod register 1 high word
703                 value = (sampl_t) ((data[3] >> 16) & 0xFFFF);
704                 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
705
706                 // Load the pre-laod register 1 low word
707                 value = (sampl_t) (data[3] & 0xFFFF);
708                 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
709
710                 // Write the Counter Control Register
711                 if (data[4] != 0) {
712                         value = (sampl_t) (data[4] & 0xFFFF);
713                         outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
714                 }
715                 break;
716
717         default:
718                 printk("s526: unsupported GPCT_insn_config\n");
719                 return -EINVAL;
720                 break;
721         }
722
723         return insn->n;
724 }
725
726 static int s526_gpct_winsn(comedi_device * dev, comedi_subdevice * s,
727         comedi_insn * insn, lsampl_t * data)
728 {
729         int subdev_channel = CR_CHAN(insn->chanspec);   // Unpack chanspec
730         sampl_t value;
731         union cmReg cmReg;
732
733         printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel);
734         cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
735         printk("s526: Counter Mode Register: %x\n", cmReg.value);
736         if (insn->n < 1) {
737                 printk("S525: INSN_WRITE: Can't handle data length %u\n",
738                                 insn->n);
739                 return -EINVAL;
740         }
741         // Check what Application of Counter this channel is configured for
742         switch (devpriv->s526_gpct_config[subdev_channel].app) {
743         case PositionMeasurement:
744                 printk("S526: INSN_WRITE: PM\n");
745                 outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H,
746                                 subdev_channel));
747                 outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel));
748                 break;
749
750         case SinglePulseGeneration:
751                 printk("S526: INSN_WRITE: SPG\n");
752                 outw(0xFFFF & ((*data) >> 16), ADDR_CHAN_REG(REG_C0H,
753                                 subdev_channel));
754                 outw(0xFFFF & (*data), ADDR_CHAN_REG(REG_C0L, subdev_channel));
755                 break;
756
757         case PulseTrainGeneration:
758                 /* data[0] contains the PULSE_WIDTH
759                    data[1] contains the PULSE_PERIOD
760                    @pre PULSE_PERIOD > PULSE_WIDTH > 0
761                    The above periods must be expressed as a multiple of the
762                    pulse frequency on the selected source
763                  */
764                 printk("S526: INSN_WRITE: PTG\n");
765                 if (insn->n < 2) {
766                         printk("s526: INSN_WRITE: PTG: Problem with data length -> %u\n",
767                                         insn->n);
768                         return -EINVAL;
769                 } else if ((data[1] <= data[0]) || (data[0] == 0)) {
770                         printk("s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n",
771                                 data[0], data[1]);
772                         return -EINVAL;
773                 }
774
775                 value = (sampl_t) ((*data >> 16) & 0xFFFF);
776                 outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
777                 value = (sampl_t) (*data & 0xFFFF);
778                 outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
779                 break;
780         default:                // Impossible
781                 printk("s526: INSN_WRITE: Functionality %d not implemented yet\n", devpriv->s526_gpct_config[subdev_channel].app);
782                 return -EINVAL;
783                 break;
784         }
785         // return the number of samples written
786         return insn->n;
787 }
788
789 #define ISR_ADC_DONE 0x4
790 static int s526_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
791         comedi_insn * insn, lsampl_t * data)
792 {
793         int result = -EINVAL;
794
795         if (insn->n < 1)
796                 return result;
797
798         result = insn->n;
799
800         /* data[0] : channels was set in relevant bits.
801            data[1] : delay
802          */
803         /* COMMENT: abbotti 2008-07-24: I don't know why you'd want to
804          * enable channels here.  The channel should be enabled in the
805          * INSN_READ handler. */
806
807         // Enable ADC interrupt
808         outw(ISR_ADC_DONE, ADDR_REG(REG_IER));
809 //      printk("s526: ADC current value: 0x%04x\n", inw(ADDR_REG(REG_ADC)));
810         devpriv->s526_ai_config = (data[0] & 0x3FF) << 5;
811         if (data[1] > 0)
812                 devpriv->s526_ai_config |= 0x8000;      //set the delay
813
814         devpriv->s526_ai_config |= 0x0001;      // ADC start bit.
815
816         return result;
817 }
818
819 /*
820  * "instructions" read/write data in "one-shot" or "software-triggered"
821  * mode.
822  */
823 static int s526_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
824         comedi_insn * insn, lsampl_t * data)
825 {
826         int n, i;
827         int chan = CR_CHAN(insn->chanspec);
828         unsigned short value;
829         unsigned int d;
830         unsigned int status;
831
832         /* Set configured delay, enable channel for this channel only,
833          * select "ADC read" channel, set "ADC start" bit. */
834         value = (devpriv->s526_ai_config & 0x8000) |
835                 ((1 << 5) << chan) | (chan << 1) | 0x0001;
836
837         /* convert n samples */
838         for (n = 0; n < insn->n; n++) {
839                 /* trigger conversion */
840                 outw(value, ADDR_REG(REG_ADC));
841 //              printk("s526: Wrote 0x%04x to ADC\n", value);
842 //              printk("s526: ADC reg=0x%04x\n", inw(ADDR_REG(REG_ADC)));
843
844 #define TIMEOUT 100
845                 /* wait for conversion to end */
846                 for (i = 0; i < TIMEOUT; i++) {
847                         status = inw(ADDR_REG(REG_ISR));
848                         if (status & ISR_ADC_DONE) {
849                                 outw(ISR_ADC_DONE, ADDR_REG(REG_ISR));
850                                 break;
851                         }
852                 }
853                 if (i == TIMEOUT) {
854                         /* rt_printk() should be used instead of printk()
855                          * whenever the code can be called from real-time. */
856                         rt_printk("s526: ADC(0x%04x) timeout\n",
857                                 inw(ADDR_REG(REG_ISR)));
858                         return -ETIMEDOUT;
859                 }
860
861                 /* read data */
862                 d = inw(ADDR_REG(REG_ADD));
863 //              printk("AI[%d]=0x%04x\n", n, (unsigned short)(d & 0xFFFF));
864
865                 /* munge data */
866                 data[n] = d ^ 0x8000;
867         }
868
869         /* return the number of samples read/written */
870         return n;
871 }
872
873 static int s526_ao_winsn(comedi_device * dev, comedi_subdevice * s,
874         comedi_insn * insn, lsampl_t * data)
875 {
876         int i;
877         int chan = CR_CHAN(insn->chanspec);
878         unsigned short val;
879
880 //      printk("s526_ao_winsn\n");
881         val = chan << 1;
882 //      outw(val, dev->iobase + REG_DAC);
883         outw(val, ADDR_REG(REG_DAC));
884
885         /* Writing a list of values to an AO channel is probably not
886          * very useful, but that's how the interface is defined. */
887         for (i = 0; i < insn->n; i++) {
888                 /* a typical programming sequence */
889 //              outw(data[i], dev->iobase + REG_ADD);  // write the data to preload register
890                 outw(data[i], ADDR_REG(REG_ADD));       // write the data to preload register
891                 devpriv->ao_readback[chan] = data[i];
892 //              outw(val + 1, dev->iobase + REG_DAC); // starts the D/A conversion.
893                 outw(val + 1, ADDR_REG(REG_DAC));       // starts the D/A conversion.
894         }
895
896         /* return the number of samples read/written */
897         return i;
898 }
899
900 /* AO subdevices should have a read insn as well as a write insn.
901  * Usually this means copying a value stored in devpriv. */
902 static int s526_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
903         comedi_insn * insn, lsampl_t * data)
904 {
905         int i;
906         int chan = CR_CHAN(insn->chanspec);
907
908         for (i = 0; i < insn->n; i++)
909                 data[i] = devpriv->ao_readback[chan];
910
911         return i;
912 }
913
914 /* DIO devices are slightly special.  Although it is possible to
915  * implement the insn_read/insn_write interface, it is much more
916  * useful to applications if you implement the insn_bits interface.
917  * This allows packed reading/writing of the DIO channels.  The
918  * comedi core can convert between insn_bits and insn_read/write */
919 static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
920         comedi_insn * insn, lsampl_t * data)
921 {
922         if (insn->n != 2)
923                 return -EINVAL;
924
925         /* The insn data is a mask in data[0] and the new data
926          * in data[1], each channel cooresponding to a bit. */
927         if (data[0]) {
928                 s->state &= ~data[0];
929                 s->state |= data[0] & data[1];
930                 /* Write out the new digital output lines */
931                 outw(s->state, ADDR_REG(REG_DIO));
932         }
933
934         /* on return, data[1] contains the value of the digital
935          * input and output lines. */
936         data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF;        // low 8 bits are the data
937         /* or we could just return the software copy of the output values if
938          * it was a purely digital output subdevice */
939         //data[1]=s->state & 0xFF;
940
941         return 2;
942 }
943
944 static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
945         comedi_insn * insn, lsampl_t * data)
946 {
947         int chan = CR_CHAN(insn->chanspec);
948         int group, mask;
949
950         printk("S526 DIO insn_config\n");
951
952         /* The input or output configuration of each digital line is
953          * configured by a special insn_config instruction.  chanspec
954          * contains the channel to be changed, and data[0] contains the
955          * value COMEDI_INPUT or COMEDI_OUTPUT. */
956
957         group = chan >> 2;
958         mask = 0xF << (group << 2);
959         switch (data[0]) {
960         case INSN_CONFIG_DIO_OUTPUT:
961                 s->state |= 1 << (group + 10);  // bit 10/11 set the group 1/2's mode
962                 s->io_bits |= mask;
963                 break;
964         case INSN_CONFIG_DIO_INPUT:
965                 s->state &= ~(1 << (group + 10));// 1 is output, 0 is input.
966                 s->io_bits &= ~mask;
967                 break;
968         case INSN_CONFIG_DIO_QUERY:
969                 data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
970                 return insn->n;
971         default:
972                 return -EINVAL;
973         }
974         outw(s->state, ADDR_REG(REG_DIO));
975
976         return 1;
977 }
978
979 /*
980  * A convenient macro that defines init_module() and cleanup_module(),
981  * as necessary.
982  */
983 COMEDI_INITCLEANUP(driver_s526);