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