]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/cx/csigma.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / cx / csigma.c
1 /*-
2  * Low-level subroutines for Cronyx-Sigma adapter.
3  *
4  * Copyright (C) 1994-2000 Cronyx Engineering.
5  * Author: Serge Vakulenko, <vak@cronyx.ru>
6  *
7  * This software is distributed with NO WARRANTIES, not even the implied
8  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9  *
10  * Authors grant any other persons or organisations permission to use
11  * or modify this software as long as this message is kept with the software,
12  * all derivative works or modified versions.
13  *
14  * Cronyx Id: csigma.c,v 1.1.2.1 2003/11/12 17:13:41 rik Exp $
15  * $FreeBSD$
16  */
17 #include <dev/cx/machdep.h>
18 #include <dev/cx/cxddk.h>
19 #include <dev/cx/cxreg.h>
20 #include <dev/cx/cronyxfw.h>
21
22 #define DMA_MASK        0xd4    /* DMA mask register */
23 #define DMA_MASK_CLEAR  0x04    /* DMA clear mask */
24 #define DMA_MODE        0xd6    /* DMA mode register */
25 #define DMA_MODE_MASTER 0xc0    /* DMA master mode */
26
27 #define BYTE *(unsigned char*)&
28
29 static unsigned char irqmask [] = {
30         BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_3,
31         BCR0_IRQ_DIS,   BCR0_IRQ_5,     BCR0_IRQ_DIS,   BCR0_IRQ_7,
32         BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_10,    BCR0_IRQ_11,
33         BCR0_IRQ_12,    BCR0_IRQ_DIS,   BCR0_IRQ_DIS,   BCR0_IRQ_15,
34 };
35
36 static unsigned char dmamask [] = {
37         BCR0_DMA_DIS,   BCR0_DMA_DIS,   BCR0_DMA_DIS,   BCR0_DMA_DIS,
38         BCR0_DMA_DIS,   BCR0_DMA_5,     BCR0_DMA_6,     BCR0_DMA_7,
39 };
40
41 /* standard base port set */
42 static short porttab [] = {
43         0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
44         0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0
45 };
46
47 /* valid IRQs and DRQs */
48 static short irqtab [] = { 3, 5, 7, 10, 11, 12, 15, 0 };
49 static short dmatab [] = { 5, 6, 7, 0 };
50
51 static int valid (short value, short *list)
52 {
53         while (*list)
54                 if (value == *list++)
55                         return 1;
56         return 0;
57 }
58
59 long cx_rxbaud = 9600;          /* receiver baud rate */
60 long cx_txbaud = 9600;          /* transmitter baud rate */
61
62 int cx_univ_mode = M_HDLC;      /* univ. chan. mode: async or sync */
63 int cx_sync_mode = M_HDLC;      /* sync. chan. mode: HDLC, Bisync or X.21 */
64 int cx_iftype = 0;              /* univ. chan. interface: upper/lower */
65
66 static int cx_probe_chip (port_t base);
67 static void cx_setup_chip (cx_chan_t *c);
68
69 /*
70  * Wait for CCR to clear.
71  */
72 void cx_cmd (port_t base, int cmd)
73 {
74         port_t port = CCR(base);
75         int count;
76
77         /* Wait 10 msec for the previous command to complete. */
78         for (count=0; inb(port) && count<20000; ++count)
79                 continue;
80
81         /* Issue the command. */
82         outb (port, cmd);
83
84         /* Wait 10 msec for the command to complete. */
85         for (count=0; inb(port) && count<20000; ++count)
86                 continue;
87 }
88
89 /*
90  * Reset the chip.
91  */
92 static int cx_reset (port_t port)
93 {
94         int count;
95
96         /* Wait up to 10 msec for revision code to appear after reset. */
97         for (count=0; count<20000; ++count)
98                 if (inb(GFRCR(port)) != 0)
99                         break;
100
101         cx_cmd (port, CCR_RSTALL);
102
103         /* Firmware revision code should clear imediately. */
104         /* Wait up to 10 msec for revision code to appear again. */
105         for (count=0; count<20000; ++count)
106                 if (inb(GFRCR(port)) != 0)
107                         return (1);
108
109         /* Reset failed. */
110         return (0);
111 }
112
113 int cx_download (port_t port, const unsigned char *firmware, long bits,
114         const cr_dat_tst_t *tst)
115 {
116         unsigned char cr2, sr;
117         long i, n, maxn = (bits + 7) / 8;
118         int v, b;
119
120         inb (BDET(port));
121         for (i=n=0; n<maxn; ++n) {
122                 v = ((firmware[n] ^ ' ') << 1) | (firmware[n] >> 7 & 1);
123                 for (b=0; b<7; b+=2, i+=2) {
124                         if (i >= bits)
125                                 break;
126                         cr2 = 0;
127                         if (v >> b & 1) cr2 |= BCR2_TMS;
128                         if (v >> b & 2) cr2 |= BCR2_TDI;
129                         outb (BCR2(port), cr2);
130                         sr = inb (BSR(port));
131                         outb (BCR0(port), BCR0800_TCK);
132                         outb (BCR0(port), 0);
133                         if (i >= tst->end)
134                                 ++tst;
135                         if (i >= tst->start && (sr & BSR800_LERR))
136                                 return (0);
137                 }
138         }
139         return (1);
140 }
141
142 /*
143  * Check if the Sigma-XXX board is present at the given base port.
144  */
145 static int cx_probe_chained_board (port_t port, int *c0, int *c1)
146 {
147         int rev, i;
148
149         /* Read and check the board revision code. */
150         rev = inb (BSR(port));
151         *c0 = *c1 = 0;
152         switch (rev & BSR_VAR_MASK) {
153         case CRONYX_100:        *c0 = 1;        break;
154         case CRONYX_400:        *c1 = 1;        break;
155         case CRONYX_500:        *c0 = *c1 = 1;  break;
156         case CRONYX_410:        *c0 = 1;        break;
157         case CRONYX_810:        *c0 = *c1 = 1;  break;
158         case CRONYX_410s:       *c0 = 1;        break;
159         case CRONYX_810s:       *c0 = *c1 = 1;  break;
160         case CRONYX_440:        *c0 = 1;        break;
161         case CRONYX_840:        *c0 = *c1 = 1;  break;
162         case CRONYX_401:        *c0 = 1;        break;
163         case CRONYX_801:        *c0 = *c1 = 1;  break;
164         case CRONYX_401s:       *c0 = 1;        break;
165         case CRONYX_801s:       *c0 = *c1 = 1;  break;
166         case CRONYX_404:        *c0 = 1;        break;
167         case CRONYX_703:        *c0 = *c1 = 1;  break;
168         default:                return (0);     /* invalid variant code */
169         }
170
171         switch (rev & BSR_OSC_MASK) {
172         case BSR_OSC_20:        /* 20 MHz */
173         case BSR_OSC_18432:     /* 18.432 MHz */
174                 break;
175         default:
176                 return (0);     /* oscillator frequency does not match */
177         }
178
179         for (i=2; i<0x10; i+=2)
180                 if ((inb (BSR(port)+i) & BSR_REV_MASK) != (rev & BSR_REV_MASK))
181                         return (0);     /* status changed? */
182         return (1);
183 }
184
185 /*
186  * Check if the Sigma-800 board is present at the given base port.
187  * Read board status register 1 and check identification bits
188  * which should invert every next read.
189  */
190 static int cx_probe_800_chained_board (port_t port)
191 {
192         unsigned char det, odet;
193         int i;
194
195         odet = inb (BDET(port));
196         if ((odet & (BDET_IB | BDET_IB_NEG)) != BDET_IB &&
197             (odet & (BDET_IB | BDET_IB_NEG)) != BDET_IB_NEG)
198                 return (0);
199         for (i=0; i<100; ++i) {
200                 det = inb (BDET(port));
201                 if (((det ^ odet) & (BDET_IB | BDET_IB_NEG)) !=
202                     (BDET_IB | BDET_IB_NEG))
203                         return (0);
204                 odet = det;
205         }
206         /* Reset the controller. */
207         outb (BCR0(port), 0);
208         outb (BCR1(port), 0);
209         outb (BCR2(port), 0);
210         return (1);
211 }
212
213 /*
214  * Check if the Sigma-2x board is present at the given base port.
215  */
216 static int cx_probe_2x_board (port_t port)
217 {
218         int rev, i;
219
220         /* Read and check the board revision code. */
221         rev = inb (BSR(port));
222         if ((rev & BSR2X_VAR_MASK) != CRONYX_22 &&
223             (rev & BSR2X_VAR_MASK) != CRONYX_24)
224                 return (0);             /* invalid variant code */
225
226         for (i=2; i<0x10; i+=2)
227                 if ((inb (BSR(port)+i) & BSR2X_REV_MASK) !=
228                     (rev & BSR2X_REV_MASK))
229                         return (0);     /* status changed? */
230         return (1);
231 }
232
233 /*
234  * Check if the Cronyx-Sigma board is present at the given base port.
235  */
236 int cx_probe_board (port_t port, int irq, int dma)
237 {
238         int c0, c1, c2=0, c3=0, result;
239
240         if (! valid (port, porttab))
241                 return 0;
242
243         if (irq > 0 && ! valid (irq, irqtab))
244                 return 0;
245
246         if (dma > 0 && ! valid (dma, dmatab))
247                 return 0;
248
249         if (cx_probe_800_chained_board (port)) {
250                 /* Sigma-800 detected. */
251                 if (! (inb (BSR(port)) & BSR_NOCHAIN)) {
252                         /* chained board attached */
253                         if (! cx_probe_800_chained_board (port+0x10))
254                                 /* invalid chained board? */
255                                 return (0);
256                         if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))
257                                 /* invalid chained board flag? */
258                                 return (0);
259                 }
260                 return 1;
261         }
262         if (cx_probe_chained_board (port, &c0, &c1)) {
263                 /* Sigma-XXX detected. */
264                 if (! (inb (BSR(port)) & BSR_NOCHAIN)) {
265                         /* chained board attached */
266                         if (! cx_probe_chained_board (port+0x10, &c2, &c3))
267                                 /* invalid chained board? */
268                                 return (0);
269                         if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))
270                                 /* invalid chained board flag? */
271                                 return (0);
272                 }
273         } else if (cx_probe_2x_board (port)) {
274                 c0 = 1;         /* Sigma-2x detected. */
275                 c1 = 0;
276         } else
277                 return (0);     /* no board detected */
278
279         /* Turn off the reset bit. */
280         outb (BCR0(port), BCR0_NORESET);
281         if (c2 || c3)
282                 outb (BCR0(port + 0x10), BCR0_NORESET);
283
284         result = 1;
285         if (c0 && ! cx_probe_chip (CS0(port)))
286                 result = 0;     /* no CD2400 chip here */
287         else if (c1 && ! cx_probe_chip (CS1A(port)) &&
288             ! cx_probe_chip (CS1(port)))
289                 result = 0;     /* no second CD2400 chip */
290         else if (c2 && ! cx_probe_chip (CS0(port + 0x10)))
291                 result = 0;     /* no CD2400 chip on the slave board */
292         else if (c3 && ! cx_probe_chip (CS1(port + 0x10)))
293                 result = 0;     /* no second CD2400 chip on the slave board */
294
295         /* Reset the controller. */
296         outb (BCR0(port), 0);
297         if (c2 || c3)
298                 outb (BCR0(port + 0x10), 0);
299
300         /* Yes, we really have valid Sigma board. */
301         return (result);
302 }
303
304 /*
305  * Check if the CD2400 chip is present at the given base port.
306  */
307 static int cx_probe_chip (port_t base)
308 {
309         int rev, newrev, count;
310
311         /* Wait up to 10 msec for revision code to appear after reset. */
312         rev = 0;
313         for (count=0; rev==0; ++count) {
314                 if (count >= 20000)
315                         return (0); /* reset failed */
316                 rev = inb (GFRCR(base));
317         }
318
319         /* Read and check the global firmware revision code. */
320         if (! (rev>=REVCL_MIN && rev<=REVCL_MAX) &&
321             ! (rev>=REVCL31_MIN && rev<=REVCL31_MAX))
322                 return (0);     /* CD2400/2431 revision does not match */
323
324         /* Reset the chip. */
325         if (! cx_reset (base))
326                 return (0);
327
328         /* Read and check the new global firmware revision code. */
329         newrev = inb (GFRCR(base));
330         if (newrev != rev)
331                 return (0);     /* revision changed */
332
333         /* Yes, we really have CD2400/2431 chip here. */
334         return (1);
335 }
336
337 /*
338  * Check that the irq is functional.
339  * irq>0  - activate the interrupt from the adapter (irq=on)
340  * irq<0  - deactivate the interrupt (irq=off)
341  * irq==0 - free the interrupt line (irq=tri-state)
342  * Return the interrupt mask _before_ activating irq.
343  */
344 int cx_probe_irq (cx_board_t *b, int irq)
345 {
346         int mask, rev;
347         port_t port;
348
349         rev = inb (BSR(b->port));
350         port = ((rev & BSR_VAR_MASK) != CRONYX_400) ? CS0(b->port) : CS1(b->port);
351
352         outb (0x20, 0x0a);
353         mask = inb (0x20);
354         outb (0xa0, 0x0a);
355         mask |= inb (0xa0) << 8;
356
357         if (irq > 0) {
358                 outb (BCR0(b->port), BCR0_NORESET | irqmask[irq]);
359                 outb (CAR(port), 0);
360                 cx_cmd (port, CCR_CLRCH);
361                 outb (CMR(port), CMR_HDLC);
362                 outb (TCOR(port), 0);
363                 outb (TBPR(port), 1);
364                 cx_cmd (port, CCR_INITCH | CCR_ENTX);
365                 outb (IER(port), IER_TXMPTY);
366         } else if (irq < 0) {
367                 cx_reset (port);
368                 if (-irq > 7) {
369                         outb (0xa0, 0x60 | ((-irq) & 7));
370                         outb (0x20, 0x62);
371                 } else
372                         outb (0x20, 0x60 | (-irq));
373         } else
374                 outb (BCR0(b->port), 0);
375         return mask;
376 }
377
378 static int cx_chip_revision (port_t port, int rev)
379 {
380         int count;
381
382         /* Model 400 has no first chip. */
383         port = ((rev & BSR_VAR_MASK) != CRONYX_400) ? CS0(port) : CS1(port);
384
385         /* Wait up to 10 msec for revision code to appear after reset. */
386         for (count=0; inb(GFRCR(port))==0; ++count)
387                 if (count >= 20000)
388                         return (0); /* reset failed */
389
390         return inb (GFRCR (port));
391 }
392
393 /*
394  * Probe and initialize the board structure.
395  */
396 void cx_init (cx_board_t *b, int num, port_t port, int irq, int dma)
397 {
398         int gfrcr, rev, chain, mod = 0, rev2 = 0, mod2 = 0;
399
400         rev = inb (BSR(port));
401         chain = ! (rev & BSR_NOCHAIN);
402         if (cx_probe_800_chained_board (port)) {
403                 cx_init_800 (b, num, port, irq, dma, chain);
404                 return;
405         }
406         if ((rev & BSR2X_VAR_MASK) == CRONYX_22 ||
407             (rev & BSR2X_VAR_MASK) == CRONYX_24) {
408                 cx_init_2x (b, num, port, irq, dma,
409                         (rev & BSR2X_VAR_MASK), (rev & BSR2X_OSC_33));
410                 return;
411         }
412
413         outb (BCR0(port), BCR0_NORESET);
414         if (chain)
415                 outb (BCR0(port+0x10), BCR0_NORESET);
416         gfrcr = cx_chip_revision (port, rev);
417         if (gfrcr >= REVCL31_MIN && gfrcr <= REVCL31_MAX)
418                 mod = 1;
419         if (chain) {
420                 rev2 = inb (BSR(port+0x10));
421                 gfrcr = cx_chip_revision (port+0x10, rev2);
422                 if (gfrcr >= REVCL31_MIN && gfrcr <= REVCL31_MAX)
423                         mod2 = 1;
424                 outb (BCR0(port+0x10), 0);
425         }
426         outb (BCR0(port), 0);
427
428         cx_init_board (b, num, port, irq, dma, chain,
429                 (rev & BSR_VAR_MASK), (rev & BSR_OSC_MASK), mod,
430                 (rev2 & BSR_VAR_MASK), (rev2 & BSR_OSC_MASK), mod2);
431 }
432
433 /*
434  * Initialize the board structure, given the type of the board.
435  */
436 void cx_init_board (cx_board_t *b, int num, port_t port, int irq, int dma,
437         int chain, int rev, int osc, int mod, int rev2, int osc2, int mod2)
438 {
439         cx_chan_t *c;
440         char *type;
441         int i;
442
443         /* Initialize board structure. */
444         b->port = port;
445         b->num = num;
446         b->irq = irq;
447         b->dma = dma;
448         b->opt = board_opt_dflt;
449
450         b->type = B_SIGMA_XXX;
451         b->if0type = b->if8type = cx_iftype;
452
453         /* Set channels 0 and 8 mode, set DMA and IRQ. */
454         b->bcr0 = b->bcr0b = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];
455
456         /* Clear DTR[0..3] and DTR[8..12]. */
457         b->bcr1 = b->bcr1b = 0;
458
459         /*------------------ Master board -------------------*/
460
461         /* Read and check the board revision code. */
462         strcpy (b->name, mod ? "m" : "");
463         switch (rev) {
464         default:          type = "";     break;
465         case CRONYX_100:  type = "100";  break;
466         case CRONYX_400:  type = "400";  break;
467         case CRONYX_500:  type = "500";  break;
468         case CRONYX_410:  type = "410";  break;
469         case CRONYX_810:  type = "810";  break;
470         case CRONYX_410s: type = "410s"; break;
471         case CRONYX_810s: type = "810s"; break;
472         case CRONYX_440:  type = "440";  break;
473         case CRONYX_840:  type = "840";  break;
474         case CRONYX_401:  type = "401";  break;
475         case CRONYX_801:  type = "801";  break;
476         case CRONYX_401s: type = "401s"; break;
477         case CRONYX_801s: type = "801s"; break;
478         case CRONYX_404:  type = "404";  break;
479         case CRONYX_703:  type = "703";  break;
480         }
481         strcat (b->name, type);
482
483         switch (osc) {
484         default:
485         case BSR_OSC_20: /* 20 MHz */
486                 b->chan[0].oscfreq = b->chan[1].oscfreq =
487                 b->chan[2].oscfreq = b->chan[3].oscfreq =
488                 b->chan[4].oscfreq = b->chan[5].oscfreq =
489                 b->chan[6].oscfreq = b->chan[7].oscfreq =
490                         mod ? 33000000L : 20000000L;
491                 strcat (b->name, "a");
492                 break;
493         case BSR_OSC_18432: /* 18.432 MHz */
494                 b->chan[0].oscfreq = b->chan[1].oscfreq =
495                 b->chan[2].oscfreq = b->chan[3].oscfreq =
496                 b->chan[4].oscfreq = b->chan[5].oscfreq =
497                 b->chan[6].oscfreq = b->chan[7].oscfreq =
498                         mod ? 20000000L : 18432000L;
499                 strcat (b->name, "b");
500                 break;
501         }
502
503         /*------------------ Slave board -------------------*/
504
505         if (chain) {
506                 /* Read and check the board revision code. */
507                 strcat (b->name, mod2 ? "/m" : "/");
508                 switch (rev2) {
509                 default:          type = "";     break;
510                 case CRONYX_100:  type = "100";  break;
511                 case CRONYX_400:  type = "400";  break;
512                 case CRONYX_500:  type = "500";  break;
513                 case CRONYX_410:  type = "410";  break;
514                 case CRONYX_810:  type = "810";  break;
515                 case CRONYX_410s: type = "410s"; break;
516                 case CRONYX_810s: type = "810s"; break;
517                 case CRONYX_440:  type = "440";  break;
518                 case CRONYX_840:  type = "840";  break;
519                 case CRONYX_401:  type = "401";  break;
520                 case CRONYX_801:  type = "801";  break;
521                 case CRONYX_401s: type = "401s"; break;
522                 case CRONYX_801s: type = "801s"; break;
523                 case CRONYX_404:  type = "404";  break;
524                 case CRONYX_703:  type = "703";  break;
525                 }
526                 strcat (b->name, type);
527
528                 switch (osc2) {
529                 default:
530                 case BSR_OSC_20: /* 20 MHz */
531                         b->chan[8].oscfreq = b->chan[9].oscfreq =
532                         b->chan[10].oscfreq = b->chan[11].oscfreq =
533                         b->chan[12].oscfreq = b->chan[13].oscfreq =
534                         b->chan[14].oscfreq = b->chan[15].oscfreq =
535                                 mod2 ? 33000000L : 20000000L;
536                         strcat (b->name, "a");
537                         break;
538                 case BSR_OSC_18432: /* 18.432 MHz */
539                         b->chan[8].oscfreq = b->chan[9].oscfreq =
540                         b->chan[10].oscfreq = b->chan[11].oscfreq =
541                         b->chan[12].oscfreq = b->chan[13].oscfreq =
542                         b->chan[14].oscfreq = b->chan[15].oscfreq =
543                                 mod2 ? 20000000L : 18432000L;
544                         strcat (b->name, "b");
545                         break;
546                 }
547         }
548
549         /* Initialize channel structures. */
550         for (i=0; i<4; ++i) {
551                 b->chan[i+0].port  = CS0(port);
552                 b->chan[i+4].port  = cx_probe_chip (CS1A(port)) ?
553                         CS1A(port) : CS1(port);
554                 b->chan[i+8].port  = CS0(port+0x10);
555                 b->chan[i+12].port = CS1(port+0x10);
556         }
557         for (c=b->chan; c<b->chan+NCHAN; ++c) {
558                 c->board = b;
559                 c->num = c - b->chan;
560                 c->type = T_NONE;
561         }
562
563         /*------------------ Master board -------------------*/
564
565         switch (rev) {
566         case CRONYX_400:
567                 for (i=4; i<8; ++i)
568                         b->chan[i].type = T_UNIV_RS232;
569                 break;
570         case CRONYX_100:
571                 b->chan[0].type = T_UNIV_RS232;
572                 break;
573         case CRONYX_500:
574                 b->chan[0].type = T_UNIV_RS232;
575                 for (i=4; i<8; ++i)
576                         b->chan[i].type = T_UNIV_RS232;
577                 break;
578         case CRONYX_410:
579                 b->chan[0].type = T_UNIV_V35;
580                 for (i=1; i<4; ++i)
581                         b->chan[i].type = T_UNIV_RS232;
582                 break;
583         case CRONYX_810:
584                 b->chan[0].type = T_UNIV_V35;
585                 for (i=1; i<8; ++i)
586                         b->chan[i].type = T_UNIV_RS232;
587                 break;
588         case CRONYX_410s:
589                 b->chan[0].type = T_UNIV_V35;
590                 for (i=1; i<4; ++i)
591                         b->chan[i].type = T_SYNC_RS232;
592                 break;
593         case CRONYX_810s:
594                 b->chan[0].type = T_UNIV_V35;
595                 for (i=1; i<4; ++i)
596                         b->chan[i].type = T_SYNC_RS232;
597                 for (i=4; i<8; ++i)
598                         b->chan[i].type = T_UNIV_RS232;
599                 break;
600         case CRONYX_440:
601                 b->chan[0].type = T_UNIV_V35;
602                 for (i=1; i<4; ++i)
603                         b->chan[i].type = T_SYNC_V35;
604                 break;
605         case CRONYX_840:
606                 b->chan[0].type = T_UNIV_V35;
607                 for (i=1; i<4; ++i)
608                         b->chan[i].type = T_SYNC_V35;
609                 for (i=4; i<8; ++i)
610                         b->chan[i].type = T_UNIV_RS232;
611                 break;
612         case CRONYX_401:
613                 b->chan[0].type = T_UNIV_RS449;
614                 for (i=1; i<4; ++i)
615                         b->chan[i].type = T_UNIV_RS232;
616                 break;
617         case CRONYX_801:
618                 b->chan[0].type = T_UNIV_RS449;
619                 for (i=1; i<8; ++i)
620                         b->chan[i].type = T_UNIV_RS232;
621                 break;
622         case CRONYX_401s:
623                 b->chan[0].type = T_UNIV_RS449;
624                 for (i=1; i<4; ++i)
625                         b->chan[i].type = T_SYNC_RS232;
626                 break;
627         case CRONYX_801s:
628                 b->chan[0].type = T_UNIV_RS449;
629                 for (i=1; i<4; ++i)
630                         b->chan[i].type = T_SYNC_RS232;
631                 for (i=4; i<8; ++i)
632                         b->chan[i].type = T_UNIV_RS232;
633                 break;
634         case CRONYX_404:
635                 b->chan[0].type = T_UNIV_RS449;
636                 for (i=1; i<4; ++i)
637                         b->chan[i].type = T_SYNC_RS449;
638                 break;
639         case CRONYX_703:
640                 b->chan[0].type = T_UNIV_RS449;
641                 for (i=1; i<3; ++i)
642                         b->chan[i].type = T_SYNC_RS449;
643                 for (i=4; i<8; ++i)
644                         b->chan[i].type = T_UNIV_RS232;
645                 break;
646         }
647
648         /*------------------ Slave board -------------------*/
649
650         if (chain) {
651                 switch (rev2) {
652                 case CRONYX_400:
653                         break;
654                 case CRONYX_100:
655                         b->chan[8].type = T_UNIV_RS232;
656                         break;
657                 case CRONYX_500:
658                         b->chan[8].type = T_UNIV_RS232;
659                         for (i=12; i<16; ++i)
660                                 b->chan[i].type = T_UNIV_RS232;
661                         break;
662                 case CRONYX_410:
663                         b->chan[8].type = T_UNIV_V35;
664                         for (i=9; i<12; ++i)
665                                 b->chan[i].type = T_UNIV_RS232;
666                         break;
667                 case CRONYX_810:
668                         b->chan[8].type = T_UNIV_V35;
669                         for (i=9; i<16; ++i)
670                                 b->chan[i].type = T_UNIV_RS232;
671                         break;
672                 case CRONYX_410s:
673                         b->chan[8].type = T_UNIV_V35;
674                         for (i=9; i<12; ++i)
675                                 b->chan[i].type = T_SYNC_RS232;
676                         break;
677                 case CRONYX_810s:
678                         b->chan[8].type = T_UNIV_V35;
679                         for (i=9; i<12; ++i)
680                                 b->chan[i].type = T_SYNC_RS232;
681                         for (i=12; i<16; ++i)
682                                 b->chan[i].type = T_UNIV_RS232;
683                         break;
684                 case CRONYX_440:
685                         b->chan[8].type = T_UNIV_V35;
686                         for (i=9; i<12; ++i)
687                                 b->chan[i].type = T_SYNC_V35;
688                         break;
689                 case CRONYX_840:
690                         b->chan[8].type = T_UNIV_V35;
691                         for (i=9; i<12; ++i)
692                                 b->chan[i].type = T_SYNC_V35;
693                         for (i=12; i<16; ++i)
694                                 b->chan[i].type = T_UNIV_RS232;
695                         break;
696                 case CRONYX_401:
697                         b->chan[8].type = T_UNIV_RS449;
698                         for (i=9; i<12; ++i)
699                                 b->chan[i].type = T_UNIV_RS232;
700                         break;
701                 case CRONYX_801:
702                         b->chan[8].type = T_UNIV_RS449;
703                         for (i=9; i<16; ++i)
704                                 b->chan[i].type = T_UNIV_RS232;
705                         break;
706                 case CRONYX_401s:
707                         b->chan[8].type = T_UNIV_RS449;
708                         for (i=9; i<12; ++i)
709                                 b->chan[i].type = T_UNIV_RS232;
710                         break;
711                 case CRONYX_801s:
712                         b->chan[8].type = T_UNIV_RS449;
713                         for (i=9; i<12; ++i)
714                                 b->chan[i].type = T_SYNC_RS232;
715                         for (i=12; i<16; ++i)
716                                 b->chan[i].type = T_UNIV_RS232;
717                         break;
718                 case CRONYX_404:
719                         b->chan[8].type = T_UNIV_RS449;
720                         for (i=9; i<12; ++i)
721                                 b->chan[i].type = T_SYNC_RS449;
722                         break;
723                 case CRONYX_703:
724                         b->chan[8].type = T_UNIV_RS449;
725                         for (i=9; i<11; ++i)
726                                 b->chan[i].type = T_SYNC_RS449;
727                         for (i=12; i<16; ++i)
728                                 b->chan[i].type = T_UNIV_RS232;
729                         break;
730                 }
731         }
732
733         b->nuniv = b->nsync = b->nasync = 0;
734         for (c=b->chan; c<b->chan+NCHAN; ++c)
735                 switch (c->type) {
736                 case T_ASYNC:      ++b->nasync; break;
737                 case T_UNIV:
738                 case T_UNIV_RS232:
739                 case T_UNIV_RS449:
740                 case T_UNIV_V35:   ++b->nuniv;  break;
741                 case T_SYNC_RS232:
742                 case T_SYNC_V35:
743                 case T_SYNC_RS449: ++b->nsync;  break;
744                 }
745
746         cx_reinit_board (b);
747 }
748
749 /*
750  * Initialize the Sigma-800 board structure.
751  */
752 void cx_init_800 (cx_board_t *b, int num, port_t port, int irq, int dma,
753         int chain)
754 {
755         cx_chan_t *c;
756         int i;
757
758         /* Initialize board structure. */
759         b->port = port;
760         b->num = num;
761         b->irq = irq;
762         b->dma = dma;
763         b->opt = board_opt_dflt;
764         b->type = B_SIGMA_800;
765
766         /* Set channels 0 and 8 mode, set DMA and IRQ. */
767         b->bcr0 = b->bcr0b = dmamask[b->dma] | irqmask[b->irq];
768
769         /* Clear DTR[0..7] and DTR[8..15]. */
770         b->bcr1 = b->bcr1b = 0;
771
772         strcpy (b->name, "800");
773         if (chain)
774                 strcat (b->name, "/800");
775
776         /* Initialize channel structures. */
777         for (i=0; i<4; ++i) {
778                 b->chan[i+0].port  = CS0(port);
779                 b->chan[i+4].port  = cx_probe_chip (CS1A(port)) ?
780                         CS1A(port) : CS1(port);
781                 b->chan[i+8].port  = CS0(port+0x10);
782                 b->chan[i+12].port = CS1(port+0x10);
783         }
784         for (c=b->chan; c<b->chan+NCHAN; ++c) {
785                 c->board = b;
786                 c->num = c - b->chan;
787                 c->oscfreq = 33000000L;
788                 c->type = (c->num < 8 || chain) ? T_UNIV_RS232 : T_NONE;
789         }
790
791         b->nuniv = b->nsync = b->nasync = 0;
792         for (c=b->chan; c<b->chan+NCHAN; ++c)
793                 switch (c->type) {
794                 case T_ASYNC:      ++b->nasync; break;
795                 case T_UNIV:
796                 case T_UNIV_RS232:
797                 case T_UNIV_RS449:
798                 case T_UNIV_V35:   ++b->nuniv;  break;
799                 case T_SYNC_RS232:
800                 case T_SYNC_V35:
801                 case T_SYNC_RS449: ++b->nsync;  break;
802                 }
803
804         cx_reinit_board (b);
805 }
806
807 /*
808  * Initialize the Sigma-2x board structure.
809  */
810 void cx_init_2x (cx_board_t *b, int num, port_t port, int irq, int dma,
811         int rev, int osc)
812 {
813         cx_chan_t *c;
814         int i;
815
816         /* Initialize board structure. */
817         b->port = port;
818         b->num = num;
819         b->irq = irq;
820         b->dma = dma;
821         b->opt = board_opt_dflt;
822
823         b->type = B_SIGMA_2X;
824
825         /* Set channels 0 and 8 mode, set DMA and IRQ. */
826         b->bcr0 = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];
827         if (b->type == B_SIGMA_2X && b->opt.fast)
828                 b->bcr0 |= BCR02X_FAST;
829
830         /* Clear DTR[0..3] and DTR[8..12]. */
831         b->bcr1 = 0;
832
833         /* Initialize channel structures. */
834         for (i=0; i<4; ++i) {
835                 b->chan[i+0].port  = CS0(port);
836                 b->chan[i+4].port  = CS1(port);
837                 b->chan[i+8].port  = CS0(port+0x10);
838                 b->chan[i+12].port = CS1(port+0x10);
839         }
840         for (c=b->chan; c<b->chan+NCHAN; ++c) {
841                 c->board = b;
842                 c->num = c - b->chan;
843                 c->type = T_NONE;
844                 c->oscfreq = (osc & BSR2X_OSC_33) ? 33000000L : 20000000L;
845         }
846
847         /* Check the board revision code. */
848         strcpy (b->name, "22");
849         b->chan[0].type = T_UNIV;
850         b->chan[1].type = T_UNIV;
851         b->nsync = b->nasync = 0;
852         b->nuniv = 2;
853         if (rev == CRONYX_24) {
854                 strcpy (b->name, "24");
855                 b->chan[2].type = T_UNIV;
856                 b->chan[3].type = T_UNIV;
857                 b->nuniv += 2;
858         }
859         strcat (b->name, (osc & BSR2X_OSC_33) ? "c" : "a");
860         cx_reinit_board (b);
861 }
862
863 /*
864  * Reinitialize all channels, using new options and baud rate.
865  */
866 void cx_reinit_board (cx_board_t *b)
867 {
868         cx_chan_t *c;
869
870         b->opt = board_opt_dflt;
871         if (b->type == B_SIGMA_2X) {
872                 b->bcr0 &= ~BCR02X_FAST;
873                 if (b->opt.fast)
874                         b->bcr0 |= BCR02X_FAST;
875         } else
876                 b->if0type = b->if8type = cx_iftype;
877         for (c=b->chan; c<b->chan+NCHAN; ++c) {
878                 switch (c->type) {
879                 default:
880                 case T_NONE:
881                         continue;
882                 case T_UNIV:
883                 case T_UNIV_RS232:
884                 case T_UNIV_RS449:
885                 case T_UNIV_V35:
886                         c->mode = (cx_univ_mode == M_ASYNC) ?
887                                 M_ASYNC : cx_sync_mode;
888                         break;
889                 case T_SYNC_RS232:
890                 case T_SYNC_V35:
891                 case T_SYNC_RS449:
892                         c->mode = cx_sync_mode;
893                         break;
894                 case T_ASYNC:
895                         c->mode = M_ASYNC;
896                         break;
897                 }
898                 c->rxbaud = cx_rxbaud;
899                 c->txbaud = cx_txbaud;
900                 c->opt = chan_opt_dflt;
901                 c->aopt = opt_async_dflt;
902                 c->hopt = opt_hdlc_dflt;
903         }
904 }
905
906 /*
907  * Set up the board.
908  */
909 int cx_setup_board (cx_board_t *b, const unsigned char *firmware,
910         long bits, const cr_dat_tst_t *tst)
911 {
912         int i;
913 #ifndef NDIS_MINIPORT_DRIVER
914         /* Disable DMA channel. */
915         outb (DMA_MASK, (b->dma & 3) | DMA_MASK_CLEAR);
916 #endif
917         /* Reset the controller. */
918         outb (BCR0(b->port), 0);
919         if (b->chan[8].type || b->chan[12].type)
920                 outb (BCR0(b->port+0x10), 0);
921
922         /* Load the firmware. */
923         if (b->type == B_SIGMA_800) {
924                 /* Reset the controllers. */
925                 outb (BCR2(b->port), BCR2_TMS);
926                 if (b->chan[8].type || b->chan[12].type)
927                         outb (BCR2(b->port+0x10), BCR2_TMS);
928                 outb (BCR2(b->port), 0);
929                 if (b->chan[8].type || b->chan[12].type)
930                         outb (BCR2(b->port+0x10), 0);
931
932                 if (firmware &&
933                     (! cx_download (b->port, firmware, bits, tst) ||
934                     ((b->chan[8].type || b->chan[12].type) &&
935                     ! cx_download (b->port+0x10, firmware, bits, tst))))
936                         return (0);
937         }
938
939         /*
940          * Set channels 0 and 8 to RS232 async. mode.
941          * Enable DMA and IRQ.
942          */
943         outb (BCR0(b->port), b->bcr0);
944         if (b->chan[8].type || b->chan[12].type)
945                 outb (BCR0(b->port+0x10), b->bcr0b);
946
947         /* Clear DTR[0..3] and DTR[8..12]. */
948         outw (BCR1(b->port), b->bcr1);
949         if (b->chan[8].type || b->chan[12].type)
950                 outw (BCR1(b->port+0x10), b->bcr1b);
951
952         if (b->type == B_SIGMA_800)
953                 outb (BCR2(b->port), b->opt.fast &
954                         (BCR2_BUS0 | BCR2_BUS1));
955
956         /* Initialize all controllers. */
957         for (i=0; i<NCHAN; i+=4)
958                 if (b->chan[i].type != T_NONE)
959                         cx_setup_chip (b->chan + i);
960 #ifndef NDIS_MINIPORT_DRIVER
961         /* Set up DMA channel to master mode. */
962         outb (DMA_MODE, (b->dma & 3) | DMA_MODE_MASTER);
963
964         /* Enable DMA channel. */
965         outb (DMA_MASK, b->dma & 3);
966 #endif
967         /* Initialize all channels. */
968         for (i=0; i<NCHAN; ++i)
969                 if (b->chan[i].type != T_NONE)
970                         cx_setup_chan (b->chan + i);
971         return (1);
972 }
973
974 /*
975  * Initialize the board.
976  */
977 static void cx_setup_chip (cx_chan_t *c)
978 {
979         /* Reset the chip. */
980         cx_reset (c->port);
981
982         /*
983          * Set all interrupt level registers to the same value.
984          * This enables the internal CD2400 priority scheme.
985          */
986         outb (RPILR(c->port), BRD_INTR_LEVEL);
987         outb (TPILR(c->port), BRD_INTR_LEVEL);
988         outb (MPILR(c->port), BRD_INTR_LEVEL);
989
990         /* Set bus error count to zero. */
991         outb (BERCNT(c->port), 0);
992
993         /* Set 16-bit DMA mode. */
994         outb (DMR(c->port), 0);
995
996         /* Set timer period register to 1 msec (approximately). */
997         outb (TPR(c->port), 10);
998 }
999
1000 /*
1001  * Initialize the CD2400 channel.
1002  */
1003 void cx_update_chan (cx_chan_t *c)
1004 {
1005         int clock, period;
1006
1007         if (c->board->type == B_SIGMA_XXX)
1008                 switch (c->num) {
1009                 case 0:
1010                         c->board->bcr0 &= ~BCR0_UMASK;
1011                         if (c->mode != M_ASYNC)
1012                                 c->board->bcr0 |= BCR0_UM_SYNC;
1013                         if (c->board->if0type &&
1014                             (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
1015                                 c->board->bcr0 |= BCR0_UI_RS449;
1016                         outb (BCR0(c->board->port), c->board->bcr0);
1017                         break;
1018                 case 8:
1019                         c->board->bcr0b &= ~BCR0_UMASK;
1020                         if (c->mode != M_ASYNC)
1021                                 c->board->bcr0b |= BCR0_UM_SYNC;
1022                         if (c->board->if8type &&
1023                             (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
1024                                 c->board->bcr0b |= BCR0_UI_RS449;
1025                         outb (BCR0(c->board->port+0x10), c->board->bcr0b);
1026                         break;
1027                 }
1028
1029         /* set current channel number */
1030         outb (CAR(c->port), c->num & 3);
1031
1032         switch (c->mode) {      /* initialize the channel mode */
1033         case M_ASYNC:
1034                 /* set receiver timeout register */
1035                 outw (RTPR(c->port), 10);          /* 10 msec, see TPR */
1036                 c->opt.rcor.encod = ENCOD_NRZ;
1037
1038                 outb (CMR(c->port), CMR_RXDMA | CMR_TXDMA | CMR_ASYNC);
1039                 outb (COR1(c->port), BYTE c->aopt.cor1);
1040                 outb (COR2(c->port), BYTE c->aopt.cor2);
1041                 outb (COR3(c->port), BYTE c->aopt.cor3);
1042                 outb (COR6(c->port), BYTE c->aopt.cor6);
1043                 outb (COR7(c->port), BYTE c->aopt.cor7);
1044                 outb (SCHR1(c->port), c->aopt.schr1);
1045                 outb (SCHR2(c->port), c->aopt.schr2);
1046                 outb (SCHR3(c->port), c->aopt.schr3);
1047                 outb (SCHR4(c->port), c->aopt.schr4);
1048                 outb (SCRL(c->port), c->aopt.scrl);
1049                 outb (SCRH(c->port), c->aopt.scrh);
1050                 outb (LNXT(c->port), c->aopt.lnxt);
1051                 break;
1052         case M_HDLC:
1053                 outb (CMR(c->port), CMR_RXDMA | CMR_TXDMA | CMR_HDLC);
1054                 outb (COR1(c->port), BYTE c->hopt.cor1);
1055                 outb (COR2(c->port), BYTE c->hopt.cor2);
1056                 outb (COR3(c->port), BYTE c->hopt.cor3);
1057                 outb (RFAR1(c->port), c->hopt.rfar1);
1058                 outb (RFAR2(c->port), c->hopt.rfar2);
1059                 outb (RFAR3(c->port), c->hopt.rfar3);
1060                 outb (RFAR4(c->port), c->hopt.rfar4);
1061                 outb (CPSR(c->port), c->hopt.cpsr);
1062                 break;
1063         }
1064
1065         /* set mode-independent options */
1066         outb (COR4(c->port), BYTE c->opt.cor4);
1067         outb (COR5(c->port), BYTE c->opt.cor5);
1068
1069         /* set up receiver clock values */
1070         if (c->mode == M_ASYNC || c->opt.rcor.dpll || c->opt.tcor.llm) {
1071                 cx_clock (c->oscfreq, c->rxbaud, &clock, &period);
1072                 c->opt.rcor.clk = clock;
1073         } else {
1074                 c->opt.rcor.clk = CLK_EXT;
1075                 period = 1;
1076         }
1077         outb (RCOR(c->port), BYTE c->opt.rcor);
1078         outb (RBPR(c->port), period);
1079
1080         /* set up transmitter clock values */
1081         if (c->mode == M_ASYNC || !c->opt.tcor.ext1x) {
1082                 unsigned ext1x = c->opt.tcor.ext1x;
1083                 c->opt.tcor.ext1x = 0;
1084                 cx_clock (c->oscfreq, c->txbaud, &clock, &period);
1085                 c->opt.tcor.clk = clock;
1086                 c->opt.tcor.ext1x = ext1x;
1087         } else {
1088                 c->opt.tcor.clk = CLK_EXT;
1089                 period = 1;
1090         }
1091         outb (TCOR(c->port), BYTE c->opt.tcor);
1092         outb (TBPR(c->port), period);
1093 }
1094
1095 /*
1096  * Initialize the CD2400 channel.
1097  */
1098 void cx_setup_chan (cx_chan_t *c)
1099 {
1100         /* set current channel number */
1101         outb (CAR(c->port), c->num & 3);
1102
1103         /* reset the channel */
1104         cx_cmd (c->port, CCR_CLRCH);
1105
1106         /* set LIVR to contain the board and channel numbers */
1107         outb (LIVR(c->port), c->board->num << 6 | c->num << 2);
1108
1109         /* clear DTR, RTS, set TXCout/DTR pin */
1110         outb (MSVR_RTS(c->port), 0);
1111         outb (MSVR_DTR(c->port), c->mode==M_ASYNC ? 0 : MSV_TXCOUT);
1112
1113         /* set receiver A buffer physical address */
1114         outw (ARBADRU(c->port), (unsigned short) (c->arphys>>16));
1115         outw (ARBADRL(c->port), (unsigned short) c->arphys);
1116
1117         /* set receiver B buffer physical address */
1118         outw (BRBADRU(c->port), (unsigned short) (c->brphys>>16));
1119         outw (BRBADRL(c->port), (unsigned short) c->brphys);
1120
1121         /* set transmitter A buffer physical address */
1122         outw (ATBADRU(c->port), (unsigned short) (c->atphys>>16));
1123         outw (ATBADRL(c->port), (unsigned short) c->atphys);
1124
1125         /* set transmitter B buffer physical address */
1126         outw (BTBADRU(c->port), (unsigned short) (c->btphys>>16));
1127         outw (BTBADRL(c->port), (unsigned short) c->btphys);
1128
1129         c->dtr = 0;
1130         c->rts = 0;
1131
1132         cx_update_chan (c);
1133 }
1134
1135 /*
1136  * Control DTR signal for the channel.
1137  * Turn it on/off.
1138  */
1139 void cx_set_dtr (cx_chan_t *c, int on)
1140 {
1141         cx_board_t *b = c->board;
1142
1143         c->dtr = on ? 1 : 0;
1144
1145         if (b->type == B_SIGMA_2X) {
1146                 if (on) b->bcr1 |= BCR1_DTR(c->num);
1147                 else    b->bcr1 &= ~BCR1_DTR(c->num);
1148                 outw (BCR1(b->port), b->bcr1);
1149                 return;
1150         }
1151         if (b->type == B_SIGMA_800) {
1152                 if (c->num >= 8) {
1153                         if (on) b->bcr1b |= BCR1800_DTR(c->num);
1154                         else    b->bcr1b &= ~BCR1800_DTR(c->num);
1155                         outb (BCR1(b->port+0x10), b->bcr1b);
1156                 } else {
1157                         if (on) b->bcr1 |= BCR1800_DTR(c->num);
1158                         else    b->bcr1 &= ~BCR1800_DTR(c->num);
1159                         outb (BCR1(b->port), b->bcr1);
1160                 }
1161                 return;
1162         }
1163         if (c->mode == M_ASYNC) {
1164                 outb (CAR(c->port), c->num & 3);
1165                 outb (MSVR_DTR(c->port), on ? MSV_DTR : 0);
1166                 return;
1167         }
1168
1169         switch (c->num) {
1170         default:
1171                 /* Channels 4..7 and 12..15 in synchronous mode
1172                  * have no DTR signal. */
1173                 break;
1174
1175         case 1: case 2:  case 3:
1176                 if (c->type == T_UNIV_RS232)
1177                         break;
1178         case 0:
1179                 if (on) b->bcr1 |= BCR1_DTR(c->num);
1180                 else    b->bcr1 &= ~BCR1_DTR(c->num);
1181                 outw (BCR1(b->port), b->bcr1);
1182                 break;
1183
1184         case 9: case 10: case 11:
1185                 if (c->type == T_UNIV_RS232)
1186                         break;
1187         case 8:
1188                 if (on) b->bcr1b |= BCR1_DTR(c->num & 3);
1189                 else    b->bcr1b &= ~BCR1_DTR(c->num & 3);
1190                 outw (BCR1(b->port+0x10), b->bcr1b);
1191                 break;
1192         }
1193 }
1194
1195 /*
1196  * Control RTS signal for the channel.
1197  * Turn it on/off.
1198  */
1199 void cx_set_rts (cx_chan_t *c, int on)
1200 {
1201         c->rts = on ? 1 : 0;
1202         outb (CAR(c->port), c->num & 3);
1203         outb (MSVR_RTS(c->port), on ? MSV_RTS : 0);
1204 }
1205
1206 /*
1207  * Get the state of DSR signal of the channel.
1208  */
1209 int cx_get_dsr (cx_chan_t *c)
1210 {
1211         unsigned char sigval;
1212
1213         if (c->board->type == B_SIGMA_2X ||
1214             c->board->type == B_SIGMA_800 ||
1215             c->mode == M_ASYNC) {
1216                 outb (CAR(c->port), c->num & 3);
1217                 return (inb (MSVR(c->port)) & MSV_DSR ? 1 : 0);
1218         }
1219
1220         /*
1221          * Channels 4..7 and 12..15 don't have DSR signal available.
1222          */
1223         switch (c->num) {
1224         default:
1225                 return (1);
1226
1227         case 1: case 2:  case 3:
1228                 if (c->type == T_UNIV_RS232)
1229                         return (1);
1230         case 0:
1231                 sigval = inw (BSR(c->board->port)) >> 8;
1232                 break;
1233
1234         case 9: case 10: case 11:
1235                 if (c->type == T_UNIV_RS232)
1236                         return (1);
1237         case 8:
1238                 sigval = inw (BSR(c->board->port+0x10)) >> 8;
1239                 break;
1240         }
1241         return (~sigval >> (c->num & 3) & 1);
1242 }
1243
1244 /*
1245  * Get the state of CARRIER signal of the channel.
1246  */
1247 int cx_get_cd (cx_chan_t *c)
1248 {
1249         unsigned char sigval;
1250
1251         if (c->board->type == B_SIGMA_2X ||
1252             c->board->type == B_SIGMA_800 ||
1253             c->mode == M_ASYNC) {
1254                 outb (CAR(c->port), c->num & 3);
1255                 return (inb (MSVR(c->port)) & MSV_CD ? 1 : 0);
1256         }
1257
1258         /*
1259          * Channels 4..7 and 12..15 don't have CD signal available.
1260          */
1261         switch (c->num) {
1262         default:
1263                 return (1);
1264
1265         case 1: case 2:  case 3:
1266                 if (c->type == T_UNIV_RS232)
1267                         return (1);
1268         case 0:
1269                 sigval = inw (BSR(c->board->port)) >> 8;
1270                 break;
1271
1272         case 9: case 10: case 11:
1273                 if (c->type == T_UNIV_RS232)
1274                         return (1);
1275         case 8:
1276                 sigval = inw (BSR(c->board->port+0x10)) >> 8;
1277                 break;
1278         }
1279         return (~sigval >> 4 >> (c->num & 3) & 1);
1280 }
1281
1282 /*
1283  * Get the state of CTS signal of the channel.
1284  */
1285 int cx_get_cts (cx_chan_t *c)
1286 {
1287         outb (CAR(c->port), c->num & 3);
1288         return (inb (MSVR(c->port)) & MSV_CTS ? 1 : 0);
1289 }
1290
1291 /*
1292  * Compute CD2400 clock values.
1293  */
1294 void cx_clock (long hz, long ba, int *clk, int *div)
1295 {
1296         static short clocktab[] = { 8, 32, 128, 512, 2048, 0 };
1297
1298         for (*clk=0; clocktab[*clk]; ++*clk) {
1299                 long c = ba * clocktab[*clk];
1300                 if (hz <= c*256) {
1301                         *div = (2 * hz + c) / (2 * c) - 1;
1302                         return;
1303                 }
1304         }
1305         /* Incorrect baud rate.  Return some meaningful values. */
1306         *clk = 0;
1307         *div = 255;
1308 }
1309
1310 /*
1311  * Turn LED on/off.
1312  */
1313 void cx_led (cx_board_t *b, int on)
1314 {
1315         switch (b->type) {
1316         case B_SIGMA_2X:
1317                 if (on) b->bcr0 |= BCR02X_LED;
1318                 else    b->bcr0 &= ~BCR02X_LED;
1319                 outb (BCR0(b->port), b->bcr0);
1320                 break;
1321         }
1322 }
1323
1324 void cx_disable_dma (cx_board_t *b)
1325 {
1326 #ifndef NDIS_MINIPORT_DRIVER
1327         /* Disable DMA channel. */
1328         outb (DMA_MASK, (b->dma & 3) | DMA_MASK_CLEAR);
1329 #endif
1330 }
1331
1332 cx_board_opt_t board_opt_dflt = { /* board options */
1333         BUS_NORMAL,             /* normal bus master timing */
1334 };
1335
1336 cx_chan_opt_t chan_opt_dflt = { /* mode-independent options */
1337         {                       /* cor4 */
1338                 7,              /* FIFO threshold, odd is better */
1339                 0,
1340                 0,              /* don't detect 1 to 0 on CTS */
1341                 1,              /* detect 1 to 0 on CD */
1342                 0,              /* detect 1 to 0 on DSR */
1343         },
1344         {                       /* cor5 */
1345                 0,              /* receive flow control FIFO threshold */
1346                 0,
1347                 0,              /* don't detect 0 to 1 on CTS */
1348                 1,              /* detect 0 to 1 on CD */
1349                 0,              /* detect 0 to 1 on DSR */
1350         },
1351         {                       /* rcor */
1352                 0,              /* dummy clock source */
1353                 ENCOD_NRZ,      /* NRZ mode */
1354                 0,              /* disable DPLL */
1355                 0,
1356                 0,              /* transmit line value */
1357         },
1358         {                       /* tcor */
1359                 0,
1360                 0,              /* local loopback mode */
1361                 0,
1362                 1,              /* external 1x clock mode */
1363                 0,
1364                 0,              /* dummy transmit clock source */
1365         },
1366 };
1367
1368 cx_opt_async_t opt_async_dflt = { /* default async options */
1369         {                       /* cor1 */
1370                 8-1,            /* 8-bit char length */
1371                 0,              /* don't ignore parity */
1372                 PARM_NOPAR,     /* no parity */
1373                 PAR_EVEN,       /* even parity */
1374         },
1375         {                       /* cor2 */
1376                 0,              /* disable automatic DSR */
1377                 1,              /* enable automatic CTS */
1378                 0,              /* disable automatic RTS */
1379                 0,              /* no remote loopback */
1380                 0,
1381                 0,              /* disable embedded cmds */
1382                 0,              /* disable XON/XOFF */
1383                 0,              /* disable XANY */
1384         },
1385         {                       /* cor3 */
1386                 STOPB_1,        /* 1 stop bit */
1387                 0,
1388                 0,              /* disable special char detection */
1389                 FLOWCC_PASS,    /* pass flow ctl chars to the host */
1390                 0,              /* range detect disable */
1391                 0,              /* disable extended spec. char detect */
1392         },
1393         {                       /* cor6 */
1394                 PERR_INTR,      /* generate exception on parity errors */
1395                 BRK_INTR,       /* generate exception on break condition */
1396                 0,              /* don't translate NL to CR on input */
1397                 0,              /* don't translate CR to NL on input */
1398                 0,              /* don't discard CR on input */
1399         },
1400         {                       /* cor7 */
1401                 0,              /* don't translate CR to NL on output */
1402                 0,              /* don't translate NL to CR on output */
1403                 0,
1404                 0,              /* don't process flow ctl err chars */
1405                 0,              /* disable LNext option */
1406                 0,              /* don't strip 8 bit on input */
1407         },
1408         0, 0, 0, 0, 0, 0, 0,    /* clear schr1-4, scrl, scrh, lnxt */
1409 };
1410
1411 cx_opt_hdlc_t opt_hdlc_dflt = { /* default hdlc options */
1412         {                       /* cor1 */
1413                 2,              /* 2 inter-frame flags */
1414                 0,              /* no-address mode */
1415                 CLRDET_DISABLE, /* disable clear detect */
1416                 AFLO_1OCT,      /* 1-byte address field length */
1417         },
1418         {                       /* cor2 */
1419                 0,              /* disable automatic DSR */
1420                 0,              /* disable automatic CTS */
1421                 0,              /* disable automatic RTS */
1422                 0,
1423                 CRC_INVERT,     /* use CRC V.41 */
1424                 0,
1425                 FCS_NOTPASS,    /* don't pass received CRC to the host */
1426                 0,
1427         },
1428         {                       /* cor3 */
1429                 0,              /* 0 pad characters sent */
1430                 IDLE_FLAG,      /* idle in flag */
1431                 0,              /* enable FCS */
1432                 FCSP_ONES,      /* FCS preset to all ones (V.41) */
1433                 SYNC_AA,        /* use AAh as sync char */
1434                 0,              /* disable pad characters */
1435         },
1436         0, 0, 0, 0,             /* clear rfar1-4 */
1437         POLY_V41,               /* use V.41 CRC polynomial */
1438 };