Staging: comedi: Remove C99 comments
[safe/jmp/linux-2.6] / drivers / staging / comedi / drivers / pcl812.c
1 /*
2  * comedi/drivers/pcl812.c
3  *
4  * Author: Michal Dobes <dobes@tesnet.cz>
5  *
6  * hardware driver for Advantech cards
7  *  card:   PCL-812, PCL-812PG, PCL-813, PCL-813B
8  *  driver: pcl812,  pcl812pg,  pcl813,  pcl813b
9  * and for ADlink cards
10  *  card:   ACL-8112DG, ACL-8112HG, ACL-8112PG, ACL-8113, ACL-8216
11  *  driver: acl8112dg,  acl8112hg,  acl8112pg,  acl8113,  acl8216
12  * and for ICP DAS cards
13  *  card:   ISO-813, A-821PGH, A-821PGL, A-821PGL-NDA, A-822PGH, A-822PGL,
14  *  driver: iso813,  a821pgh,  a-821pgl, a-821pglnda,  a822pgh,  a822pgl,
15  *  card:   A-823PGH, A-823PGL, A-826PG
16  * driver:  a823pgh,  a823pgl,  a826pg
17  */
18 /*
19 Driver: pcl812
20 Description: Advantech PCL-812/PG, PCL-813/B,
21              ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216,
22              ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG,
23              ICP DAS ISO-813
24 Author: Michal Dobes <dobes@tesnet.cz>
25 Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg),
26   PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg),
27   ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216),
28   [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl),
29   A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl),
30   A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg)
31 Updated: Mon, 06 Aug 2007 12:03:15 +0100
32 Status: works (I hope. My board fire up under my hands
33                and I cann't test all features.)
34
35 This driver supports insn and cmd interfaces. Some boards support only insn
36 becouse their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813).
37 Data transfer over DMA is supported only when you measure only one
38 channel, this is too hardware limitation of these boards.
39
40 Options for PCL-812:
41   [0] - IO Base
42   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
43   [2] - DMA  (0=disable, 1, 3)
44   [3] - 0=trigger source is internal 8253 with 2MHz clock
45         1=trigger source is external
46   [4] - 0=A/D input range is +/-10V
47         1=A/D input range is +/-5V
48         2=A/D input range is +/-2.5V
49         3=A/D input range is +/-1.25V
50         4=A/D input range is +/-0.625V
51         5=A/D input range is +/-0.3125V
52   [5] - 0=D/A outputs 0-5V  (internal reference -5V)
53         1=D/A outputs 0-10V (internal reference -10V)
54         2=D/A outputs unknow (external reference)
55
56 Options for PCL-812PG, ACL-8112PG:
57   [0] - IO Base
58   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
59   [2] - DMA  (0=disable, 1, 3)
60   [3] - 0=trigger source is internal 8253 with 2MHz clock
61         1=trigger source is external
62   [4] - 0=A/D have max +/-5V input
63         1=A/D have max +/-10V input
64   [5] - 0=D/A outputs 0-5V  (internal reference -5V)
65         1=D/A outputs 0-10V (internal reference -10V)
66         2=D/A outputs unknow (external reference)
67
68 Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG:
69   [0] - IO Base
70   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
71   [2] - DMA  (0=disable, 1, 3)
72   [3] - 0=trigger source is internal 8253 with 2MHz clock
73         1=trigger source is external
74   [4] - 0=A/D channels are S.E.
75         1=A/D channels are DIFF
76   [5] - 0=D/A outputs 0-5V  (internal reference -5V)
77         1=D/A outputs 0-10V (internal reference -10V)
78         2=D/A outputs unknow (external reference)
79
80 Options for A-821PGL/PGH:
81   [0] - IO Base
82   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7)
83   [2] - 0=A/D channels are S.E.
84         1=A/D channels are DIFF
85   [3] - 0=D/A output 0-5V  (internal reference -5V)
86         1=D/A output 0-10V (internal reference -10V)
87
88 Options for A-821PGL-NDA:
89   [0] - IO Base
90   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7)
91   [2] - 0=A/D channels are S.E.
92         1=A/D channels are DIFF
93
94 Options for PCL-813:
95   [0] - IO Base
96
97 Options for PCL-813B:
98   [0] - IO Base
99   [1] - 0= bipolar inputs
100         1= unipolar inputs
101
102 Options for ACL-8113, ISO-813:
103   [0] - IO Base
104   [1] - 0= 10V bipolar inputs
105         1= 10V unipolar inputs
106         2= 20V bipolar inputs
107         3= 20V unipolar inputs
108 */
109
110 #include "../comedidev.h"
111
112 #include <linux/delay.h>
113 #include <linux/ioport.h>
114 #include <asm/dma.h>
115
116 #include "8253.h"
117
118 #undef PCL812_EXTDEBUG          /* if this is defined then a lot of messages is printed */
119
120 /* hardware types of the cards */
121 #define boardPCL812PG            0      /* and ACL-8112PG */
122 #define boardPCL813B             1
123 #define boardPCL812              2
124 #define boardPCL813              3
125 #define boardISO813              5
126 #define boardACL8113             6
127 #define boardACL8112             7      /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */
128 #define boardACL8216             8      /* and ICP DAS A-826PG */
129 #define boardA821                9      /* PGH, PGL, PGL/NDA versions */
130
131 #define PCLx1x_IORANGE          16
132
133 #define PCL812_CTR0              0
134 #define PCL812_CTR1              1
135 #define PCL812_CTR2              2
136 #define PCL812_CTRCTL            3
137 #define PCL812_AD_LO             4
138 #define PCL812_DA1_LO            4
139 #define PCL812_AD_HI             5
140 #define PCL812_DA1_HI            5
141 #define PCL812_DA2_LO            6
142 #define PCL812_DI_LO             6
143 #define PCL812_DA2_HI            7
144 #define PCL812_DI_HI             7
145 #define PCL812_CLRINT            8
146 #define PCL812_GAIN              9
147 #define PCL812_MUX              10
148 #define PCL812_MODE             11
149 #define PCL812_CNTENABLE        10
150 #define PCL812_SOFTTRIG         12
151 #define PCL812_DO_LO            13
152 #define PCL812_DO_HI            14
153
154 #define PCL812_DRDY             0x10    /* =0 data ready */
155
156 #define ACL8216_STATUS           8      /* 5. bit signalize data ready */
157
158 #define ACL8216_DRDY            0x20    /* =0 data ready */
159
160 #define MAX_CHANLIST_LEN        256     /* length of scan list */
161
162 static const struct comedi_lrange range_pcl812pg_ai = { 5, {
163                         BIP_RANGE(5),
164                         BIP_RANGE(2.5),
165                         BIP_RANGE(1.25),
166                         BIP_RANGE(0.625),
167                         BIP_RANGE(0.3125),
168         }
169 };
170 static const struct comedi_lrange range_pcl812pg2_ai = { 5, {
171                         BIP_RANGE(10),
172                         BIP_RANGE(5),
173                         BIP_RANGE(2.5),
174                         BIP_RANGE(1.25),
175                         BIP_RANGE(0.625),
176         }
177 };
178 static const struct comedi_lrange range812_bipolar1_25 = { 1, {
179                         BIP_RANGE(1.25),
180         }
181 };
182 static const struct comedi_lrange range812_bipolar0_625 = { 1, {
183                         BIP_RANGE(0.625),
184         }
185 };
186 static const struct comedi_lrange range812_bipolar0_3125 = { 1, {
187                         BIP_RANGE(0.3125),
188         }
189 };
190 static const struct comedi_lrange range_pcl813b_ai = { 4, {
191                         BIP_RANGE(5),
192                         BIP_RANGE(2.5),
193                         BIP_RANGE(1.25),
194                         BIP_RANGE(0.625),
195         }
196 };
197 static const struct comedi_lrange range_pcl813b2_ai = { 4, {
198                         UNI_RANGE(10),
199                         UNI_RANGE(5),
200                         UNI_RANGE(2.5),
201                         UNI_RANGE(1.25),
202         }
203 };
204 static const struct comedi_lrange range_iso813_1_ai = { 5, {
205                         BIP_RANGE(5),
206                         BIP_RANGE(2.5),
207                         BIP_RANGE(1.25),
208                         BIP_RANGE(0.625),
209                         BIP_RANGE(0.3125),
210         }
211 };
212 static const struct comedi_lrange range_iso813_1_2_ai = { 5, {
213                         UNI_RANGE(10),
214                         UNI_RANGE(5),
215                         UNI_RANGE(2.5),
216                         UNI_RANGE(1.25),
217                         UNI_RANGE(0.625),
218         }
219 };
220 static const struct comedi_lrange range_iso813_2_ai = { 4, {
221                         BIP_RANGE(5),
222                         BIP_RANGE(2.5),
223                         BIP_RANGE(1.25),
224                         BIP_RANGE(0.625),
225         }
226 };
227 static const struct comedi_lrange range_iso813_2_2_ai = { 4, {
228                         UNI_RANGE(10),
229                         UNI_RANGE(5),
230                         UNI_RANGE(2.5),
231                         UNI_RANGE(1.25),
232         }
233 };
234 static const struct comedi_lrange range_acl8113_1_ai = { 4, {
235                         BIP_RANGE(5),
236                         BIP_RANGE(2.5),
237                         BIP_RANGE(1.25),
238                         BIP_RANGE(0.625),
239         }
240 };
241 static const struct comedi_lrange range_acl8113_1_2_ai = { 4, {
242                         UNI_RANGE(10),
243                         UNI_RANGE(5),
244                         UNI_RANGE(2.5),
245                         UNI_RANGE(1.25),
246         }
247 };
248 static const struct comedi_lrange range_acl8113_2_ai = { 3, {
249                         BIP_RANGE(5),
250                         BIP_RANGE(2.5),
251                         BIP_RANGE(1.25),
252         }
253 };
254 static const struct comedi_lrange range_acl8113_2_2_ai = { 3, {
255                         UNI_RANGE(10),
256                         UNI_RANGE(5),
257                         UNI_RANGE(2.5),
258         }
259 };
260 static const struct comedi_lrange range_acl8112dg_ai = { 9, {
261                         BIP_RANGE(5),
262                         BIP_RANGE(2.5),
263                         BIP_RANGE(1.25),
264                         BIP_RANGE(0.625),
265                         UNI_RANGE(10),
266                         UNI_RANGE(5),
267                         UNI_RANGE(2.5),
268                         UNI_RANGE(1.25),
269                         BIP_RANGE(10),
270         }
271 };
272 static const struct comedi_lrange range_acl8112hg_ai = { 12, {
273                         BIP_RANGE(5),
274                         BIP_RANGE(0.5),
275                         BIP_RANGE(0.05),
276                         BIP_RANGE(0.005),
277                         UNI_RANGE(10),
278                         UNI_RANGE(1),
279                         UNI_RANGE(0.1),
280                         UNI_RANGE(0.01),
281                         BIP_RANGE(10),
282                         BIP_RANGE(1),
283                         BIP_RANGE(0.1),
284                         BIP_RANGE(0.01),
285         }
286 };
287 static const struct comedi_lrange range_a821pgh_ai = { 4, {
288                         BIP_RANGE(5),
289                         BIP_RANGE(0.5),
290                         BIP_RANGE(0.05),
291                         BIP_RANGE(0.005),
292         }
293 };
294
295 static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it);
296 static int pcl812_detach(struct comedi_device * dev);
297
298 struct pcl812_board {
299
300         const char *name;       /*  board name */
301         int board_type;         /*  type of this board */
302         int n_aichan;           /*  num of AI chans in S.E. */
303         int n_aichan_diff;      /*  DIFF num of chans */
304         int n_aochan;           /*  num of DA chans */
305         int n_dichan;           /*  DI and DO chans */
306         int n_dochan;
307         int ai_maxdata;         /*  AI resolution */
308         unsigned int ai_ns_min; /*  max sample speed of card v ns */
309         unsigned int i8254_osc_base;    /*  clock base */
310         const struct comedi_lrange *rangelist_ai;       /*  rangelist for A/D */
311         const struct comedi_lrange *rangelist_ao;       /*  rangelist for D/A */
312         unsigned int IRQbits;   /*  allowed IRQ */
313         unsigned char DMAbits;  /*  allowed DMA chans */
314         unsigned char io_range; /*  iorange for this board */
315         unsigned char haveMPC508;       /*  1=board use MPC508A multiplexor */
316 };
317
318
319 static const struct pcl812_board boardtypes[] = {
320         {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
321                         33000, 500, &range_bipolar10, &range_unipolar5,
322                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
323         {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
324                         33000, 500, &range_pcl812pg_ai, &range_unipolar5,
325                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
326         {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
327                         10000, 500, &range_pcl812pg_ai, &range_unipolar5,
328                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
329         {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
330                         10000, 500, &range_acl8112dg_ai, &range_unipolar5,
331                 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
332         {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
333                         10000, 500, &range_acl8112hg_ai, &range_unipolar5,
334                 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
335         {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
336                         10000, 500, &range_pcl813b_ai, &range_unipolar5,
337                 0x000c, 0x00, PCLx1x_IORANGE, 0},
338         {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
339                         10000, 500, &range_pcl813b_ai, NULL,
340                 0x000c, 0x00, PCLx1x_IORANGE, 0},
341         {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
342                         10000, 500, &range_a821pgh_ai, &range_unipolar5,
343                 0x000c, 0x00, PCLx1x_IORANGE, 0},
344         {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
345                         10000, 500, &range_acl8112dg_ai, &range_unipolar5,
346                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
347         {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
348                         10000, 500, &range_acl8112hg_ai, &range_unipolar5,
349                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
350         {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
351                         8000, 500, &range_acl8112dg_ai, &range_unipolar5,
352                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
353         {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
354                         8000, 500, &range_acl8112hg_ai, &range_unipolar5,
355                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
356         {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
357                         0, 0, &range_pcl813b_ai, NULL,
358                 0x0000, 0x00, PCLx1x_IORANGE, 0},
359         {"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff,
360                         0, 0, &range_pcl813b_ai, NULL,
361                 0x0000, 0x00, PCLx1x_IORANGE, 0},
362         {"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff,
363                         0, 0, &range_acl8113_1_ai, NULL,
364                 0x0000, 0x00, PCLx1x_IORANGE, 0},
365         {"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff,
366                         0, 0, &range_iso813_1_ai, NULL,
367                 0x0000, 0x00, PCLx1x_IORANGE, 0},
368         {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
369                         10000, 500, &range_pcl813b2_ai, &range_unipolar5,
370                 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
371         {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
372                         10000, 500, &range_pcl813b2_ai, &range_unipolar5,
373                 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
374 };
375
376 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl812_board))
377 #define this_board ((const struct pcl812_board *)dev->board_ptr)
378
379 static struct comedi_driver driver_pcl812 = {
380       driver_name:"pcl812",
381       module:THIS_MODULE,
382       attach:pcl812_attach,
383       detach:pcl812_detach,
384       board_name:&boardtypes[0].name,
385       num_names:n_boardtypes,
386       offset:sizeof(struct pcl812_board),
387 };
388
389 COMEDI_INITCLEANUP(driver_pcl812);
390
391 struct pcl812_private {
392
393         unsigned char valid;    /*  =1 device is OK */
394         unsigned char dma;      /*  >0 use dma ( usedDMA channel) */
395         unsigned char use_diff; /*  =1 diff inputs */
396         unsigned char use_MPC;  /*  1=board uses MPC508A multiplexor */
397         unsigned char use_ext_trg;      /*  1=board uses external trigger */
398         unsigned char range_correction; /*  =1 we must add 1 to range number */
399         unsigned char old_chan_reg;     /*  lastly used chan/gain pair */
400         unsigned char old_gain_reg;
401         unsigned char mode_reg_int;     /*  there is stored INT number for some card */
402         unsigned char ai_neverending;   /*  =1 we do unlimited AI */
403         unsigned char ai_eos;   /*  1=EOS wake up */
404         unsigned char ai_dma;   /*  =1 we use DMA */
405         unsigned int ai_poll_ptr;       /*  how many sampes transfer poll */
406         unsigned int ai_scans;  /*  len of scanlist */
407         unsigned int ai_act_scan;       /*  how many scans we finished */
408         unsigned int ai_chanlist[MAX_CHANLIST_LEN];     /*  our copy of channel/range list */
409         unsigned int ai_n_chan; /*  how many channels is measured */
410         unsigned int ai_flags;  /*  flaglist */
411         unsigned int ai_data_len;       /*  len of data buffer */
412         short *ai_data; /*  data buffer */
413         unsigned int ai_is16b;  /*  =1 we have 16 bit card */
414         unsigned long dmabuf[2];        /*  PTR to DMA buf */
415         unsigned int dmapages[2];       /*  how many pages we have allocated */
416         unsigned int hwdmaptr[2];       /*  HW PTR to DMA buf */
417         unsigned int hwdmasize[2];      /*  DMA buf size in bytes */
418         unsigned int dmabytestomove[2]; /*  how many bytes DMA transfer */
419         int next_dma_buf;       /*  which buffer is next to use */
420         unsigned int dma_runs_to_end;   /*  how many times we must switch DMA buffers */
421         unsigned int last_dma_run;      /*  how many bytes to transfer on last DMA buffer */
422         unsigned int max_812_ai_mode0_rangewait;        /*  setling time for gain */
423         unsigned int ao_readback[2];    /*  data for AO readback */
424 };
425
426
427 #define devpriv ((struct pcl812_private *)dev->private)
428
429 /*
430 ==============================================================================
431 */
432 static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
433         unsigned int divisor2);
434 static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s,
435         unsigned int rangechan, char wait);
436 static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
437 /*
438 ==============================================================================
439 */
440 static int pcl812_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
441         struct comedi_insn * insn, unsigned int * data)
442 {
443         int n;
444         int timeout, hi;
445
446         outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE);     /* select software trigger */
447         setup_range_channel(dev, s, insn->chanspec, 1); /*  select channel and renge */
448         for (n = 0; n < insn->n; n++) {
449                 outb(255, dev->iobase + PCL812_SOFTTRIG);       /* start conversion */
450                 comedi_udelay(5);
451                 timeout = 50;   /* wait max 50us, it must finish under 33us */
452                 while (timeout--) {
453                         hi = inb(dev->iobase + PCL812_AD_HI);
454                         if (!(hi & PCL812_DRDY))
455                                 goto conv_finish;
456                         comedi_udelay(1);
457                 }
458                 rt_printk
459                         ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n",
460                         dev->minor, dev->board_name, dev->iobase);
461                 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
462                 return -ETIME;
463
464               conv_finish:
465                 data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO);
466         }
467         outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
468         return n;
469 }
470
471 /*
472 ==============================================================================
473 */
474 static int acl8216_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
475         struct comedi_insn * insn, unsigned int * data)
476 {
477         int n;
478         int timeout;
479
480         outb(1, dev->iobase + PCL812_MODE);     /* select software trigger */
481         setup_range_channel(dev, s, insn->chanspec, 1); /*  select channel and renge */
482         for (n = 0; n < insn->n; n++) {
483                 outb(255, dev->iobase + PCL812_SOFTTRIG);       /* start conversion */
484                 comedi_udelay(5);
485                 timeout = 50;   /* wait max 50us, it must finish under 33us */
486                 while (timeout--) {
487                         if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY))
488                                 goto conv_finish;
489                         comedi_udelay(1);
490                 }
491                 rt_printk
492                         ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n",
493                         dev->minor, dev->board_name, dev->iobase);
494                 outb(0, dev->iobase + PCL812_MODE);
495                 return -ETIME;
496
497               conv_finish:
498                 data[n] =
499                         (inb(dev->iobase +
500                                 PCL812_AD_HI) << 8) | inb(dev->iobase +
501                         PCL812_AD_LO);
502         }
503         outb(0, dev->iobase + PCL812_MODE);
504         return n;
505 }
506
507 /*
508 ==============================================================================
509 */
510 static int pcl812_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
511         struct comedi_insn * insn, unsigned int * data)
512 {
513         int chan = CR_CHAN(insn->chanspec);
514         int i;
515
516         for (i = 0; i < insn->n; i++) {
517                 outb((data[i] & 0xff),
518                         dev->iobase + (chan ? PCL812_DA2_LO : PCL812_DA1_LO));
519                 outb((data[i] >> 8) & 0x0f,
520                         dev->iobase + (chan ? PCL812_DA2_HI : PCL812_DA1_HI));
521                 devpriv->ao_readback[chan] = data[i];
522         }
523
524         return i;
525 }
526
527 /*
528 ==============================================================================
529 */
530 static int pcl812_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
531         struct comedi_insn * insn, unsigned int * data)
532 {
533         int chan = CR_CHAN(insn->chanspec);
534         int i;
535
536         for (i = 0; i < insn->n; i++) {
537                 data[i] = devpriv->ao_readback[chan];
538         }
539
540         return i;
541 }
542
543 /*
544 ==============================================================================
545 */
546 static int pcl812_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
547         struct comedi_insn * insn, unsigned int * data)
548 {
549         if (insn->n != 2)
550                 return -EINVAL;
551
552         data[1] = inb(dev->iobase + PCL812_DI_LO);
553         data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8;
554
555         return 2;
556 }
557
558 /*
559 ==============================================================================
560 */
561 static int pcl812_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
562         struct comedi_insn * insn, unsigned int * data)
563 {
564         if (insn->n != 2)
565                 return -EINVAL;
566
567         if (data[0]) {
568                 s->state &= ~data[0];
569                 s->state |= data[0] & data[1];
570                 outb(s->state & 0xff, dev->iobase + PCL812_DO_LO);
571                 outb((s->state >> 8), dev->iobase + PCL812_DO_HI);
572         }
573         data[1] = s->state;
574
575         return 2;
576 }
577
578 #ifdef PCL812_EXTDEBUG
579 /*
580 ==============================================================================
581 */
582 static void pcl812_cmdtest_out(int e, struct comedi_cmd * cmd)
583 {
584         rt_printk("pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
585                 cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
586         rt_printk("pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n", e,
587                 cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg);
588         rt_printk("pcl812 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src,
589                 cmd->scan_end_src);
590         rt_printk("pcl812 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n", e,
591                 cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len);
592 }
593 #endif
594
595 /*
596 ==============================================================================
597 */
598 static int pcl812_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
599         struct comedi_cmd * cmd)
600 {
601         int err = 0;
602         int tmp, divisor1, divisor2;
603
604 #ifdef PCL812_EXTDEBUG
605         rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...)\n");
606         pcl812_cmdtest_out(-1, cmd);
607 #endif
608         /* step 1: make sure trigger sources are trivially valid */
609
610         tmp = cmd->start_src;
611         cmd->start_src &= TRIG_NOW;
612         if (!cmd->start_src || tmp != cmd->start_src)
613                 err++;
614
615         tmp = cmd->scan_begin_src;
616         cmd->scan_begin_src &= TRIG_FOLLOW;
617         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
618                 err++;
619
620         tmp = cmd->convert_src;
621         if (devpriv->use_ext_trg) {
622                 cmd->convert_src &= TRIG_EXT;
623         } else {
624                 cmd->convert_src &= TRIG_TIMER;
625         }
626         if (!cmd->convert_src || tmp != cmd->convert_src)
627                 err++;
628
629         tmp = cmd->scan_end_src;
630         cmd->scan_end_src &= TRIG_COUNT;
631         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
632                 err++;
633
634         tmp = cmd->stop_src;
635         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
636         if (!cmd->stop_src || tmp != cmd->stop_src)
637                 err++;
638
639         if (err) {
640 #ifdef PCL812_EXTDEBUG
641                 pcl812_cmdtest_out(1, cmd);
642                 rt_printk
643                         ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=1\n",
644                         err);
645 #endif
646                 return 1;
647         }
648
649         /* step 2: make sure trigger sources are unique and mutually compatible */
650
651         if (cmd->start_src != TRIG_NOW) {
652                 cmd->start_src = TRIG_NOW;
653                 err++;
654         }
655
656         if (cmd->scan_begin_src != TRIG_FOLLOW) {
657                 cmd->scan_begin_src = TRIG_FOLLOW;
658                 err++;
659         }
660
661         if (devpriv->use_ext_trg) {
662                 if (cmd->convert_src != TRIG_EXT) {
663                         cmd->convert_src = TRIG_EXT;
664                         err++;
665                 }
666         } else {
667                 if (cmd->convert_src != TRIG_TIMER) {
668                         cmd->convert_src = TRIG_TIMER;
669                         err++;
670                 }
671         }
672
673         if (cmd->scan_end_src != TRIG_COUNT) {
674                 cmd->scan_end_src = TRIG_COUNT;
675                 err++;
676         }
677
678         if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
679                 err++;
680
681         if (err) {
682 #ifdef PCL812_EXTDEBUG
683                 pcl812_cmdtest_out(2, cmd);
684                 rt_printk
685                         ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=2\n",
686                         err);
687 #endif
688                 return 2;
689         }
690
691         /* step 3: make sure arguments are trivially compatible */
692
693         if (cmd->start_arg != 0) {
694                 cmd->start_arg = 0;
695                 err++;
696         }
697
698         if (cmd->scan_begin_arg != 0) {
699                 cmd->scan_begin_arg = 0;
700                 err++;
701         }
702
703         if (cmd->convert_src == TRIG_TIMER) {
704                 if (cmd->convert_arg < this_board->ai_ns_min) {
705                         cmd->convert_arg = this_board->ai_ns_min;
706                         err++;
707                 }
708         } else {                /* TRIG_EXT */
709                 if (cmd->convert_arg != 0) {
710                         cmd->convert_arg = 0;
711                         err++;
712                 }
713         }
714
715         if (!cmd->chanlist_len) {
716                 cmd->chanlist_len = 1;
717                 err++;
718         }
719         if (cmd->chanlist_len > MAX_CHANLIST_LEN) {
720                 cmd->chanlist_len = this_board->n_aichan;
721                 err++;
722         }
723         if (cmd->scan_end_arg != cmd->chanlist_len) {
724                 cmd->scan_end_arg = cmd->chanlist_len;
725                 err++;
726         }
727         if (cmd->stop_src == TRIG_COUNT) {
728                 if (!cmd->stop_arg) {
729                         cmd->stop_arg = 1;
730                         err++;
731                 }
732         } else {                /* TRIG_NONE */
733                 if (cmd->stop_arg != 0) {
734                         cmd->stop_arg = 0;
735                         err++;
736                 }
737         }
738
739         if (err) {
740 #ifdef PCL812_EXTDEBUG
741                 pcl812_cmdtest_out(3, cmd);
742                 rt_printk
743                         ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=3\n",
744                         err);
745 #endif
746                 return 3;
747         }
748
749         /* step 4: fix up any arguments */
750
751         if (cmd->convert_src == TRIG_TIMER) {
752                 tmp = cmd->convert_arg;
753                 i8253_cascade_ns_to_timer(this_board->i8254_osc_base, &divisor1,
754                         &divisor2, &cmd->convert_arg,
755                         cmd->flags & TRIG_ROUND_MASK);
756                 if (cmd->convert_arg < this_board->ai_ns_min)
757                         cmd->convert_arg = this_board->ai_ns_min;
758                 if (tmp != cmd->convert_arg)
759                         err++;
760         }
761
762         if (err) {
763 #ifdef PCL812_EXTDEBUG
764                 rt_printk
765                         ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=4\n",
766                         err);
767 #endif
768                 return 4;
769         }
770
771         return 0;
772 }
773
774 /*
775 ==============================================================================
776 */
777 static int pcl812_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
778 {
779         unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
780         struct comedi_cmd *cmd = &s->async->cmd;
781
782 #ifdef PCL812_EXTDEBUG
783         rt_printk("pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n");
784 #endif
785
786         if (cmd->start_src != TRIG_NOW)
787                 return -EINVAL;
788         if (cmd->scan_begin_src != TRIG_FOLLOW)
789                 return -EINVAL;
790         if (devpriv->use_ext_trg) {
791                 if (cmd->convert_src != TRIG_EXT)
792                         return -EINVAL;
793         } else {
794                 if (cmd->convert_src != TRIG_TIMER)
795                         return -EINVAL;
796         }
797         if (cmd->scan_end_src != TRIG_COUNT)
798                 return -EINVAL;
799         if (cmd->scan_end_arg != cmd->chanlist_len)
800                 return -EINVAL;
801         if (cmd->chanlist_len > MAX_CHANLIST_LEN)
802                 return -EINVAL;
803
804         if (cmd->convert_src == TRIG_TIMER) {
805                 if (cmd->convert_arg < this_board->ai_ns_min)
806                         cmd->convert_arg = this_board->ai_ns_min;
807                 i8253_cascade_ns_to_timer(this_board->i8254_osc_base,
808                         &divisor1, &divisor2, &cmd->convert_arg,
809                         cmd->flags & TRIG_ROUND_MASK);
810         }
811
812         start_pacer(dev, -1, 0, 0);     /*  stop pacer */
813
814         devpriv->ai_n_chan = cmd->chanlist_len;
815         memcpy(devpriv->ai_chanlist, cmd->chanlist,
816                 sizeof(unsigned int) * cmd->scan_end_arg);
817         setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1);        /*  select first channel and range */
818
819         if (devpriv->dma) {     /*  check if we can use DMA transfer */
820                 devpriv->ai_dma = 1;
821                 for (i = 1; i < devpriv->ai_n_chan; i++)
822                         if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) {
823                                 devpriv->ai_dma = 0;    /*  we cann't use DMA :-( */
824                                 break;
825                         }
826         } else
827                 devpriv->ai_dma = 0;
828
829         devpriv->ai_flags = cmd->flags;
830         devpriv->ai_data_len = s->async->prealloc_bufsz;
831         devpriv->ai_data = s->async->prealloc_buf;
832         if (cmd->stop_src == TRIG_COUNT) {
833                 devpriv->ai_scans = cmd->stop_arg;
834                 devpriv->ai_neverending = 0;
835         } else {
836                 devpriv->ai_scans = 0;
837                 devpriv->ai_neverending = 1;
838         }
839
840         devpriv->ai_act_scan = 0;
841         devpriv->ai_poll_ptr = 0;
842         s->async->cur_chan = 0;
843
844         if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {      /*  don't we want wake up every scan? */
845                 devpriv->ai_eos = 1;
846                 if (devpriv->ai_n_chan == 1)
847                         devpriv->ai_dma = 0;    /*  DMA is useless for this situation */
848         }
849
850         if (devpriv->ai_dma) {
851                 if (devpriv->ai_eos) {  /*  we use EOS, so adapt DMA buffer to one scan */
852                         devpriv->dmabytestomove[0] =
853                                 devpriv->ai_n_chan * sizeof(short);
854                         devpriv->dmabytestomove[1] =
855                                 devpriv->ai_n_chan * sizeof(short);
856                         devpriv->dma_runs_to_end = 1;
857                 } else {
858                         devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
859                         devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
860                         if (devpriv->ai_data_len < devpriv->hwdmasize[0])
861                                 devpriv->dmabytestomove[0] =
862                                         devpriv->ai_data_len;
863                         if (devpriv->ai_data_len < devpriv->hwdmasize[1])
864                                 devpriv->dmabytestomove[1] =
865                                         devpriv->ai_data_len;
866                         if (devpriv->ai_neverending) {
867                                 devpriv->dma_runs_to_end = 1;
868                         } else {
869                                 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /*  how many samples we must transfer? */
870                                 devpriv->dma_runs_to_end = bytes / devpriv->dmabytestomove[0];  /*  how many DMA pages we must fill */
871                                 devpriv->last_dma_run = bytes % devpriv->dmabytestomove[0];     /* on last dma transfer must be moved */
872                                 if (devpriv->dma_runs_to_end == 0)
873                                         devpriv->dmabytestomove[0] =
874                                                 devpriv->last_dma_run;
875                                 devpriv->dma_runs_to_end--;
876                         }
877                 }
878                 if (devpriv->dmabytestomove[0] > devpriv->hwdmasize[0]) {
879                         devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
880                         devpriv->ai_eos = 0;
881                 }
882                 if (devpriv->dmabytestomove[1] > devpriv->hwdmasize[1]) {
883                         devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
884                         devpriv->ai_eos = 0;
885                 }
886                 devpriv->next_dma_buf = 0;
887                 set_dma_mode(devpriv->dma, DMA_MODE_READ);
888                 dma_flags = claim_dma_lock();
889                 clear_dma_ff(devpriv->dma);
890                 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
891                 set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]);
892                 release_dma_lock(dma_flags);
893                 enable_dma(devpriv->dma);
894 #ifdef PCL812_EXTDEBUG
895                 rt_printk
896                         ("pcl812 EDBG:   DMA %d PTR 0x%0x/0x%0x LEN %u/%u EOS %d\n",
897                         devpriv->dma, devpriv->hwdmaptr[0],
898                         devpriv->hwdmaptr[1], devpriv->dmabytestomove[0],
899                         devpriv->dmabytestomove[1], devpriv->ai_eos);
900 #endif
901         }
902
903         switch (cmd->convert_src) {
904         case TRIG_TIMER:
905                 start_pacer(dev, 1, divisor1, divisor2);
906                 break;
907         }
908
909         if (devpriv->ai_dma) {
910                 outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE);     /*  let's go! */
911         } else {
912                 outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE);     /*  let's go! */
913         }
914
915 #ifdef PCL812_EXTDEBUG
916         rt_printk("pcl812 EDBG: END: pcl812_ai_cmd(...)\n");
917 #endif
918
919         return 0;
920 }
921
922 /*
923 ==============================================================================
924 */
925 static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
926 {
927         char err = 1;
928         unsigned int mask, timeout;
929         struct comedi_device *dev = d;
930         struct comedi_subdevice *s = dev->subdevices + 0;
931
932         s->async->events = 0;
933
934         timeout = 50;           /* wait max 50us, it must finish under 33us */
935         if (devpriv->ai_is16b) {
936                 mask = 0xffff;
937                 while (timeout--) {
938                         if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) {
939                                 err = 0;
940                                 break;
941                         }
942                         comedi_udelay(1);
943                 }
944         } else {
945                 mask = 0x0fff;
946                 while (timeout--) {
947                         if (!(inb(dev->iobase + PCL812_AD_HI) & PCL812_DRDY)) {
948                                 err = 0;
949                                 break;
950                         }
951                         comedi_udelay(1);
952                 }
953         }
954
955         if (err) {
956                 rt_printk
957                         ("comedi%d: pcl812: (%s at 0x%lx) A/D cmd IRQ without DRDY!\n",
958                         dev->minor, dev->board_name, dev->iobase);
959                 pcl812_ai_cancel(dev, s);
960                 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
961                 comedi_event(dev, s);
962                 return IRQ_HANDLED;
963         }
964
965         comedi_buf_put(s->async,
966                 ((inb(dev->iobase + PCL812_AD_HI) << 8) | inb(dev->iobase +
967                                 PCL812_AD_LO)) & mask);
968
969         outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
970
971         if (s->async->cur_chan == 0) {  /* one scan done */
972                 devpriv->ai_act_scan++;
973                 if (!(devpriv->ai_neverending))
974                         if (devpriv->ai_act_scan >= devpriv->ai_scans) {        /* all data sampled */
975                                 pcl812_ai_cancel(dev, s);
976                                 s->async->events |= COMEDI_CB_EOA;
977                         }
978         }
979
980         comedi_event(dev, s);
981         return IRQ_HANDLED;
982 }
983
984 /*
985 ==============================================================================
986 */
987 static void transfer_from_dma_buf(struct comedi_device * dev, struct comedi_subdevice * s,
988         short * ptr, unsigned int bufptr, unsigned int len)
989 {
990         unsigned int i;
991
992         s->async->events = 0;
993         for (i = len; i; i--) {
994                 comedi_buf_put(s->async, ptr[bufptr++]);        /*  get one sample */
995
996                 if (s->async->cur_chan == 0) {
997                         devpriv->ai_act_scan++;
998                         if (!devpriv->ai_neverending)
999                                 if (devpriv->ai_act_scan >= devpriv->ai_scans) {        /* all data sampled */
1000                                         pcl812_ai_cancel(dev, s);
1001                                         s->async->events |= COMEDI_CB_EOA;
1002                                         break;
1003                                 }
1004                 }
1005         }
1006
1007         comedi_event(dev, s);
1008 }
1009
1010 /*
1011 ==============================================================================
1012 */
1013 static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
1014 {
1015         struct comedi_device *dev = d;
1016         struct comedi_subdevice *s = dev->subdevices + 0;
1017         unsigned long dma_flags;
1018         int len, bufptr;
1019         short *ptr;
1020
1021 #ifdef PCL812_EXTDEBUG
1022         rt_printk("pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n");
1023 #endif
1024         ptr = (short *) devpriv->dmabuf[devpriv->next_dma_buf];
1025         len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) -
1026                 devpriv->ai_poll_ptr;
1027
1028         devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
1029         disable_dma(devpriv->dma);
1030         set_dma_mode(devpriv->dma, DMA_MODE_READ);
1031         dma_flags = claim_dma_lock();
1032         set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]);
1033         if (devpriv->ai_eos) {
1034                 set_dma_count(devpriv->dma,
1035                         devpriv->dmabytestomove[devpriv->next_dma_buf]);
1036         } else {
1037                 if (devpriv->dma_runs_to_end) {
1038                         set_dma_count(devpriv->dma,
1039                                 devpriv->dmabytestomove[devpriv->next_dma_buf]);
1040                 } else {
1041                         set_dma_count(devpriv->dma, devpriv->last_dma_run);
1042                 }
1043                 devpriv->dma_runs_to_end--;
1044         }
1045         release_dma_lock(dma_flags);
1046         enable_dma(devpriv->dma);
1047
1048         outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
1049
1050         bufptr = devpriv->ai_poll_ptr;
1051         devpriv->ai_poll_ptr = 0;
1052
1053         transfer_from_dma_buf(dev, s, ptr, bufptr, len);
1054
1055 #ifdef PCL812_EXTDEBUG
1056         rt_printk("pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n");
1057 #endif
1058         return IRQ_HANDLED;
1059 }
1060
1061 /*
1062 ==============================================================================
1063 */
1064 static irqreturn_t interrupt_pcl812(int irq, void *d)
1065 {
1066         struct comedi_device *dev = d;
1067
1068         if (!dev->attached) {
1069                 comedi_error(dev, "spurious interrupt");
1070                 return IRQ_HANDLED;
1071         }
1072         if (devpriv->ai_dma) {
1073                 return interrupt_pcl812_ai_dma(irq, d);
1074         } else {
1075                 return interrupt_pcl812_ai_int(irq, d);
1076         };
1077 }
1078
1079 /*
1080 ==============================================================================
1081 */
1082 static int pcl812_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
1083 {
1084         unsigned long flags;
1085         unsigned int top1, top2, i;
1086
1087         if (!devpriv->ai_dma)
1088                 return 0;       /*  poll is valid only for DMA transfer */
1089
1090         comedi_spin_lock_irqsave(&dev->spinlock, flags);
1091
1092         for (i = 0; i < 10; i++) {
1093                 top1 = get_dma_residue(devpriv->ai_dma);        /*  where is now DMA */
1094                 top2 = get_dma_residue(devpriv->ai_dma);
1095                 if (top1 == top2)
1096                         break;
1097         }
1098
1099         if (top1 != top2) {
1100                 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
1101                 return 0;
1102         }
1103
1104         top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1;       /*  where is now DMA in buffer */
1105         top1 >>= 1;             /*  sample position */
1106         top2 = top1 - devpriv->ai_poll_ptr;
1107         if (top2 < 1) {         /*  no new samples */
1108                 comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
1109                 return 0;
1110         }
1111
1112         transfer_from_dma_buf(dev, s,
1113                 (void *)devpriv->dmabuf[1 - devpriv->next_dma_buf],
1114                 devpriv->ai_poll_ptr, top2);
1115
1116         devpriv->ai_poll_ptr = top1;    /*  new buffer position */
1117
1118         comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
1119
1120         return s->async->buf_write_count - s->async->buf_read_count;
1121 }
1122
1123 /*
1124 ==============================================================================
1125 */
1126 static void setup_range_channel(struct comedi_device * dev, struct comedi_subdevice * s,
1127         unsigned int rangechan, char wait)
1128 {
1129         unsigned char chan_reg = CR_CHAN(rangechan);    /*  normal board */
1130         unsigned char gain_reg = CR_RANGE(rangechan) + devpriv->range_correction;       /*  gain index */
1131
1132         if ((chan_reg == devpriv->old_chan_reg)
1133                 && (gain_reg == devpriv->old_gain_reg))
1134                 return;         /*  we can return, no change */
1135
1136         devpriv->old_chan_reg = chan_reg;
1137         devpriv->old_gain_reg = gain_reg;
1138
1139         if (devpriv->use_MPC) {
1140                 if (devpriv->use_diff) {
1141                         chan_reg = chan_reg | 0x30;     /*  DIFF inputs */
1142                 } else {
1143                         if (chan_reg & 0x80) {
1144                                 chan_reg = chan_reg | 0x20;     /*  SE inputs 8-15 */
1145                         } else {
1146                                 chan_reg = chan_reg | 0x10;     /*  SE inputs 0-7 */
1147                         }
1148                 }
1149         }
1150
1151         outb(chan_reg, dev->iobase + PCL812_MUX);       /* select channel */
1152         outb(gain_reg, dev->iobase + PCL812_GAIN);      /* select gain */
1153
1154         if (wait) {
1155                 comedi_udelay(devpriv->max_812_ai_mode0_rangewait);     /*  XXX this depends on selected range and can be very long for some high gain ranges! */
1156         }
1157 }
1158
1159 /*
1160 ==============================================================================
1161 */
1162 static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
1163         unsigned int divisor2)
1164 {
1165 #ifdef PCL812_EXTDEBUG
1166         rt_printk("pcl812 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode, divisor1,
1167                 divisor2);
1168 #endif
1169         outb(0xb4, dev->iobase + PCL812_CTRCTL);
1170         outb(0x74, dev->iobase + PCL812_CTRCTL);
1171         comedi_udelay(1);
1172
1173         if (mode == 1) {
1174                 outb(divisor2 & 0xff, dev->iobase + PCL812_CTR2);
1175                 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL812_CTR2);
1176                 outb(divisor1 & 0xff, dev->iobase + PCL812_CTR1);
1177                 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1);
1178         }
1179 #ifdef PCL812_EXTDEBUG
1180         rt_printk("pcl812 EDBG: END: start_pacer(...)\n");
1181 #endif
1182 }
1183
1184 /*
1185 ==============================================================================
1186 */
1187 static void free_resources(struct comedi_device * dev)
1188 {
1189
1190         if (dev->private) {
1191                 if (devpriv->dmabuf[0])
1192                         free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1193                 if (devpriv->dmabuf[1])
1194                         free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1195                 if (devpriv->dma)
1196                         free_dma(devpriv->dma);
1197         }
1198         if (dev->irq)
1199                 comedi_free_irq(dev->irq, dev);
1200         if (dev->iobase)
1201                 release_region(dev->iobase, this_board->io_range);
1202 }
1203
1204 /*
1205 ==============================================================================
1206 */
1207 static int pcl812_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
1208 {
1209 #ifdef PCL812_EXTDEBUG
1210         rt_printk("pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n");
1211 #endif
1212         if (devpriv->ai_dma)
1213                 disable_dma(devpriv->dma);
1214         outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
1215         outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);     /* Stop A/D */
1216         start_pacer(dev, -1, 0, 0);     /*  stop 8254 */
1217         outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
1218 #ifdef PCL812_EXTDEBUG
1219         rt_printk("pcl812 EDBG: END: pcl812_ai_cancel(...)\n");
1220 #endif
1221         return 0;
1222 }
1223
1224 /*
1225 ==============================================================================
1226 */
1227 static void pcl812_reset(struct comedi_device * dev)
1228 {
1229 #ifdef PCL812_EXTDEBUG
1230         rt_printk("pcl812 EDBG: BGN: pcl812_reset(...)\n");
1231 #endif
1232         outb(0, dev->iobase + PCL812_MUX);
1233         outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN);
1234         devpriv->old_chan_reg = -1;     /*  invalidate chain/gain memory */
1235         devpriv->old_gain_reg = -1;
1236
1237         switch (this_board->board_type) {
1238         case boardPCL812PG:
1239         case boardPCL812:
1240         case boardACL8112:
1241         case boardACL8216:
1242                 outb(0, dev->iobase + PCL812_DA2_LO);
1243                 outb(0, dev->iobase + PCL812_DA2_HI);
1244         case boardA821:
1245                 outb(0, dev->iobase + PCL812_DA1_LO);
1246                 outb(0, dev->iobase + PCL812_DA1_HI);
1247                 start_pacer(dev, -1, 0, 0);     /*  stop 8254 */
1248                 outb(0, dev->iobase + PCL812_DO_HI);
1249                 outb(0, dev->iobase + PCL812_DO_LO);
1250                 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
1251                 outb(0, dev->iobase + PCL812_CLRINT);
1252                 break;
1253         case boardPCL813B:
1254         case boardPCL813:
1255         case boardISO813:
1256         case boardACL8113:
1257                 comedi_udelay(5);
1258                 break;
1259         }
1260         comedi_udelay(5);
1261 #ifdef PCL812_EXTDEBUG
1262         rt_printk("pcl812 EDBG: END: pcl812_reset(...)\n");
1263 #endif
1264 }
1265
1266 /*
1267 ==============================================================================
1268 */
1269 static int pcl812_attach(struct comedi_device * dev, struct comedi_devconfig * it)
1270 {
1271         int ret, subdev;
1272         unsigned long iobase;
1273         unsigned int irq;
1274         unsigned int dma;
1275         unsigned long pages;
1276         struct comedi_subdevice *s;
1277         int n_subdevices;
1278
1279         iobase = it->options[0];
1280         printk("comedi%d: pcl812:  board=%s, ioport=0x%03lx", dev->minor,
1281                 this_board->name, iobase);
1282
1283         if (!request_region(iobase, this_board->io_range, "pcl812")) {
1284                 printk("I/O port conflict\n");
1285                 return -EIO;
1286         }
1287         dev->iobase = iobase;
1288
1289         if ((ret = alloc_private(dev, sizeof(struct pcl812_private))) < 0) {
1290                 free_resources(dev);
1291                 return ret;     /* Can't alloc mem */
1292         }
1293
1294         dev->board_name = this_board->name;
1295
1296         irq = 0;
1297         if (this_board->IRQbits != 0) { /* board support IRQ */
1298                 irq = it->options[1];
1299                 if (irq) {      /* we want to use IRQ */
1300                         if (((1 << irq) & this_board->IRQbits) == 0) {
1301                                 printk(", IRQ %u is out of allowed range, DISABLING IT", irq);
1302                                 irq = 0;        /* Bad IRQ */
1303                         } else {
1304                                 if (comedi_request_irq(irq, interrupt_pcl812, 0,
1305                                                 "pcl812", dev)) {
1306                                         printk(", unable to allocate IRQ %u, DISABLING IT", irq);
1307                                         irq = 0;        /* Can't use IRQ */
1308                                 } else {
1309                                         printk(", irq=%u", irq);
1310                                 }
1311                         }
1312                 }
1313         }
1314
1315         dev->irq = irq;
1316
1317         dma = 0;
1318         devpriv->dma = dma;
1319         if (!dev->irq)
1320                 goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1321         if (this_board->DMAbits != 0) { /* board support DMA */
1322                 dma = it->options[2];
1323                 if (((1 << dma) & this_board->DMAbits) == 0) {
1324                         printk(", DMA is out of allowed range, FAIL!\n");
1325                         return -EINVAL; /* Bad DMA */
1326                 }
1327                 ret = request_dma(dma, "pcl812");
1328                 if (ret) {
1329                         printk(", unable to allocate DMA %u, FAIL!\n", dma);
1330                         return -EBUSY;  /* DMA isn't free */
1331                 }
1332                 devpriv->dma = dma;
1333                 printk(", dma=%u", dma);
1334                 pages = 1;      /* we want 8KB */
1335                 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1336                 if (!devpriv->dmabuf[0]) {
1337                         printk(", unable to allocate DMA buffer, FAIL!\n");
1338                         /* maybe experiment with try_to_free_pages() will help .... */
1339                         free_resources(dev);
1340                         return -EBUSY;  /* no buffer :-( */
1341                 }
1342                 devpriv->dmapages[0] = pages;
1343                 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1344                 devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages);
1345                 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1346                 if (!devpriv->dmabuf[1]) {
1347                         printk(", unable to allocate DMA buffer, FAIL!\n");
1348                         free_resources(dev);
1349                         return -EBUSY;
1350                 }
1351                 devpriv->dmapages[1] = pages;
1352                 devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
1353                 devpriv->hwdmasize[1] = PAGE_SIZE * (1 << pages);
1354         }
1355       no_dma:
1356
1357         n_subdevices = 0;
1358         if (this_board->n_aichan > 0)
1359                 n_subdevices++;
1360         if (this_board->n_aochan > 0)
1361                 n_subdevices++;
1362         if (this_board->n_dichan > 0)
1363                 n_subdevices++;
1364         if (this_board->n_dochan > 0)
1365                 n_subdevices++;
1366
1367         if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) {
1368                 free_resources(dev);
1369                 return ret;
1370         }
1371
1372         subdev = 0;
1373
1374         /* analog input */
1375         if (this_board->n_aichan > 0) {
1376                 s = dev->subdevices + subdev;
1377                 s->type = COMEDI_SUBD_AI;
1378                 s->subdev_flags = SDF_READABLE;
1379                 switch (this_board->board_type) {
1380                 case boardA821:
1381                         if (it->options[2] == 1) {
1382                                 s->n_chan = this_board->n_aichan_diff;
1383                                 s->subdev_flags |= SDF_DIFF;
1384                                 devpriv->use_diff = 1;
1385                         } else {
1386                                 s->n_chan = this_board->n_aichan;
1387                                 s->subdev_flags |= SDF_GROUND;
1388                         }
1389                         break;
1390                 case boardACL8112:
1391                 case boardACL8216:
1392                         if (it->options[4] == 1) {
1393                                 s->n_chan = this_board->n_aichan_diff;
1394                                 s->subdev_flags |= SDF_DIFF;
1395                                 devpriv->use_diff = 1;
1396                         } else {
1397                                 s->n_chan = this_board->n_aichan;
1398                                 s->subdev_flags |= SDF_GROUND;
1399                         }
1400                         break;
1401                 default:
1402                         s->n_chan = this_board->n_aichan;
1403                         s->subdev_flags |= SDF_GROUND;
1404                         break;
1405                 }
1406                 s->maxdata = this_board->ai_maxdata;
1407                 s->len_chanlist = MAX_CHANLIST_LEN;
1408                 s->range_table = this_board->rangelist_ai;
1409                 if (this_board->board_type == boardACL8216) {
1410                         s->insn_read = acl8216_ai_insn_read;
1411                 } else {
1412                         s->insn_read = pcl812_ai_insn_read;
1413                 }
1414                 devpriv->use_MPC = this_board->haveMPC508;
1415                 s->cancel = pcl812_ai_cancel;
1416                 if (dev->irq) {
1417                         dev->read_subdev = s;
1418                         s->subdev_flags |= SDF_CMD_READ;
1419                         s->do_cmdtest = pcl812_ai_cmdtest;
1420                         s->do_cmd = pcl812_ai_cmd;
1421                         s->poll = pcl812_ai_poll;
1422                 }
1423                 switch (this_board->board_type) {
1424                 case boardPCL812PG:
1425                         if (it->options[4] == 1)
1426                                 s->range_table = &range_pcl812pg2_ai;
1427                         break;
1428                 case boardPCL812:
1429                         switch (it->options[4]) {
1430                         case 0:
1431                                 s->range_table = &range_bipolar10;
1432                                 break;
1433                         case 1:
1434                                 s->range_table = &range_bipolar5;
1435                                 break;
1436                         case 2:
1437                                 s->range_table = &range_bipolar2_5;
1438                                 break;
1439                         case 3:
1440                                 s->range_table = &range812_bipolar1_25;
1441                                 break;
1442                         case 4:
1443                                 s->range_table = &range812_bipolar0_625;
1444                                 break;
1445                         case 5:
1446                                 s->range_table = &range812_bipolar0_3125;
1447                                 break;
1448                         default:
1449                                 s->range_table = &range_bipolar10;
1450                                 break;
1451                                 printk(", incorrect range number %d, changing to 0 (+/-10V)", it->options[4]);
1452                                 break;
1453                         }
1454                         break;
1455                         break;
1456                 case boardPCL813B:
1457                         if (it->options[1] == 1)
1458                                 s->range_table = &range_pcl813b2_ai;
1459                         break;
1460                 case boardISO813:
1461                         switch (it->options[1]) {
1462                         case 0:
1463                                 s->range_table = &range_iso813_1_ai;
1464                                 break;
1465                         case 1:
1466                                 s->range_table = &range_iso813_1_2_ai;
1467                                 break;
1468                         case 2:
1469                                 s->range_table = &range_iso813_2_ai;
1470                                 devpriv->range_correction = 1;
1471                                 break;
1472                         case 3:
1473                                 s->range_table = &range_iso813_2_2_ai;
1474                                 devpriv->range_correction = 1;
1475                                 break;
1476                         default:
1477                                 s->range_table = &range_iso813_1_ai;
1478                                 break;
1479                                 printk(", incorrect range number %d, changing to 0 ", it->options[1]);
1480                                 break;
1481                         }
1482                         break;
1483                 case boardACL8113:
1484                         switch (it->options[1]) {
1485                         case 0:
1486                                 s->range_table = &range_acl8113_1_ai;
1487                                 break;
1488                         case 1:
1489                                 s->range_table = &range_acl8113_1_2_ai;
1490                                 break;
1491                         case 2:
1492                                 s->range_table = &range_acl8113_2_ai;
1493                                 devpriv->range_correction = 1;
1494                                 break;
1495                         case 3:
1496                                 s->range_table = &range_acl8113_2_2_ai;
1497                                 devpriv->range_correction = 1;
1498                                 break;
1499                         default:
1500                                 s->range_table = &range_acl8113_1_ai;
1501                                 break;
1502                                 printk(", incorrect range number %d, changing to 0 ", it->options[1]);
1503                                 break;
1504                         }
1505                         break;
1506                 }
1507                 subdev++;
1508         }
1509
1510         /* analog output */
1511         if (this_board->n_aochan > 0) {
1512                 s = dev->subdevices + subdev;
1513                 s->type = COMEDI_SUBD_AO;
1514                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1515                 s->n_chan = this_board->n_aochan;
1516                 s->maxdata = 0xfff;
1517                 s->len_chanlist = 1;
1518                 s->range_table = this_board->rangelist_ao;
1519                 s->insn_read = pcl812_ao_insn_read;
1520                 s->insn_write = pcl812_ao_insn_write;
1521                 switch (this_board->board_type) {
1522                 case boardA821:
1523                         if (it->options[3] == 1)
1524                                 s->range_table = &range_unipolar10;
1525                         break;
1526                 case boardPCL812:
1527                 case boardACL8112:
1528                 case boardPCL812PG:
1529                 case boardACL8216:
1530                         if (it->options[5] == 1)
1531                                 s->range_table = &range_unipolar10;
1532                         if (it->options[5] == 2)
1533                                 s->range_table = &range_unknown;
1534                         break;
1535                 }
1536                 subdev++;
1537         }
1538
1539         /* digital input */
1540         if (this_board->n_dichan > 0) {
1541                 s = dev->subdevices + subdev;
1542                 s->type = COMEDI_SUBD_DI;
1543                 s->subdev_flags = SDF_READABLE;
1544                 s->n_chan = this_board->n_dichan;
1545                 s->maxdata = 1;
1546                 s->len_chanlist = this_board->n_dichan;
1547                 s->range_table = &range_digital;
1548                 s->insn_bits = pcl812_di_insn_bits;
1549                 subdev++;
1550         }
1551
1552         /* digital output */
1553         if (this_board->n_dochan > 0) {
1554                 s = dev->subdevices + subdev;
1555                 s->type = COMEDI_SUBD_DO;
1556                 s->subdev_flags = SDF_WRITABLE;
1557                 s->n_chan = this_board->n_dochan;
1558                 s->maxdata = 1;
1559                 s->len_chanlist = this_board->n_dochan;
1560                 s->range_table = &range_digital;
1561                 s->insn_bits = pcl812_do_insn_bits;
1562                 subdev++;
1563         }
1564
1565         switch (this_board->board_type) {
1566         case boardACL8216:
1567                 devpriv->ai_is16b = 1;
1568         case boardPCL812PG:
1569         case boardPCL812:
1570         case boardACL8112:
1571                 devpriv->max_812_ai_mode0_rangewait = 1;
1572                 if (it->options[3] > 0)
1573                         devpriv->use_ext_trg = 1;       /*  we use external trigger */
1574         case boardA821:
1575                 devpriv->max_812_ai_mode0_rangewait = 1;
1576                 devpriv->mode_reg_int = (irq << 4) & 0xf0;
1577                 break;
1578         case boardPCL813B:
1579         case boardPCL813:
1580         case boardISO813:
1581         case boardACL8113:
1582                 devpriv->max_812_ai_mode0_rangewait = 5;        /* maybe there must by greatest timeout */
1583                 break;
1584         }
1585
1586         printk("\n");
1587         devpriv->valid = 1;
1588
1589         pcl812_reset(dev);
1590
1591         return 0;
1592 }
1593
1594 /*
1595 ==============================================================================
1596  */
1597 static int pcl812_detach(struct comedi_device * dev)
1598 {
1599
1600 #ifdef PCL812_EXTDEBUG
1601         rt_printk("comedi%d: pcl812: remove\n", dev->minor);
1602 #endif
1603         free_resources(dev);
1604         return 0;
1605 }