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: head/sys/dev/cx/csigma.c 250460 2013-05-10 16:41:26Z eadler $
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
29static 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
36static 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 */
42static 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 */
48static short irqtab [] = { 3, 5, 7, 10, 11, 12, 15, 0 };
49static short dmatab [] = { 5, 6, 7, 0 };
50
51static int valid (short value, short *list)
52{
53 while (*list)
54 if (value == *list++)
55 return 1;
56 return 0;
57}
58
59long cx_rxbaud = 9600; /* receiver baud rate */
60long cx_txbaud = 9600; /* transmitter baud rate */
61
62int cx_univ_mode = M_HDLC; /* univ. chan. mode: async or sync */
63int cx_sync_mode = M_HDLC; /* sync. chan. mode: HDLC, Bisync or X.21 */
64int cx_iftype = 0; /* univ. chan. interface: upper/lower */
65
66static int cx_probe_chip (port_t base);
67static void cx_setup_chip (cx_chan_t *c);
68
69/*
70 * Wait for CCR to clear.
71 */
72void 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 */
92static 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
113int 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 */
145static 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 */
190static 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 */
216static 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 */
236int 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 */
307static 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 */
344int 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
378static 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 */
396void 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 */
436void 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 */
752void 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 */
810void 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 */
866void 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 */
909int 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 */
977static 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 */
1003void 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 */
1098void 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 */
1139void 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 */
1199void 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 */
1209int 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 */
1247int 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 */
1285int 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 */
1294void 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 */
1313void 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
1324void 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
1332cx_board_opt_t board_opt_dflt = { /* board options */
1333 BUS_NORMAL, /* normal bus master timing */
1334};
1335
1336cx_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
1368cx_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
1411cx_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};
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: head/sys/dev/cx/csigma.c 250460 2013-05-10 16:41:26Z eadler $
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
29static 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
36static 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 */
42static 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 */
48static short irqtab [] = { 3, 5, 7, 10, 11, 12, 15, 0 };
49static short dmatab [] = { 5, 6, 7, 0 };
50
51static int valid (short value, short *list)
52{
53 while (*list)
54 if (value == *list++)
55 return 1;
56 return 0;
57}
58
59long cx_rxbaud = 9600; /* receiver baud rate */
60long cx_txbaud = 9600; /* transmitter baud rate */
61
62int cx_univ_mode = M_HDLC; /* univ. chan. mode: async or sync */
63int cx_sync_mode = M_HDLC; /* sync. chan. mode: HDLC, Bisync or X.21 */
64int cx_iftype = 0; /* univ. chan. interface: upper/lower */
65
66static int cx_probe_chip (port_t base);
67static void cx_setup_chip (cx_chan_t *c);
68
69/*
70 * Wait for CCR to clear.
71 */
72void 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 */
92static 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
113int 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 */
145static 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 */
190static 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 */
216static 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 */
236int 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 */
307static 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 */
344int 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
378static 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 */
396void 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 */
436void 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 */
752void 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 */
810void 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 */
866void 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 */
909int 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 */
977static 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 */
1003void 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 */
1098void 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 */
1139void 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 */
1199void 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 */
1209int 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 */
1247int 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 */
1285int 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 */
1294void 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 */
1313void 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
1324void 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
1332cx_board_opt_t board_opt_dflt = { /* board options */
1333 BUS_NORMAL, /* normal bus master timing */
1334};
1335
1336cx_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
1368cx_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
1411cx_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};