FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/cronyx.c
1 /*
2 * Low-level subroutines for Cronyx-Sigma adapter.
3 *
4 * Copyright (C) 1994-95 Cronyx Ltd.
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 * Version 1.6, Wed May 31 16:03:20 MSD 1995
15 */
16 #if defined (MSDOS) || defined (__MSDOS__)
17 # include <string.h>
18 # include <dos.h>
19 # define inb(port) inportb(port)
20 # define inw(port) inport(port)
21 # define outb(port,b) outportb(port,b)
22 # define outw(port,w) outport(port,w)
23 # define vtophys(a) (((unsigned long)(a)>>12 & 0xffff0) +\
24 ((unsigned)(a) & 0xffff))
25 # include "cronyx.h"
26 # include "cxreg.h"
27 #else
28 # include <sys/param.h>
29 # include <sys/systm.h>
30 # include <sys/socket.h>
31 # include <net/if.h>
32 # include <vm/vm.h>
33 # include <vm/vm_param.h>
34 # include <vm/pmap.h>
35 # ifndef __FreeBSD__
36 # include <machine/inline.h>
37 # endif
38 # include <machine/cronyx.h>
39 # include <i386/isa/cxreg.h>
40 #endif
41
42 #define DMA_MASK 0xd4 /* DMA mask register */
43 #define DMA_MASK_CLEAR 0x04 /* DMA clear mask */
44 #define DMA_MODE 0xd6 /* DMA mode register */
45 #define DMA_MODE_MASTER 0xc0 /* DMA master mode */
46
47 #define BYTE *(unsigned char*)&
48
49 static unsigned char irqmask [] = {
50 BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_3,
51 BCR0_IRQ_DIS, BCR0_IRQ_5, BCR0_IRQ_DIS, BCR0_IRQ_7,
52 BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_10, BCR0_IRQ_11,
53 BCR0_IRQ_12, BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_15,
54 };
55
56 static unsigned char dmamask [] = {
57 BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_DIS,
58 BCR0_DMA_DIS, BCR0_DMA_5, BCR0_DMA_6, BCR0_DMA_7,
59 };
60
61 static long cx_rxbaud = CX_SPEED_DFLT; /* receiver baud rate */
62 static long cx_txbaud = CX_SPEED_DFLT; /* transmitter baud rate */
63
64 static int cx_univ_mode = M_ASYNC; /* univ. chan. mode: async or sync */
65 static int cx_sync_mode = M_HDLC; /* sync. chan. mode: HDLC, Bisync or X.21 */
66 static int cx_iftype = 0; /* univ. chan. interface: upper/lower */
67
68 static int cx_probe_chip (int base);
69 static void cx_setup_chip (cx_chip_t *c);
70 static void cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,
71 int chain, int rev, int osc, int rev2, int osc2);
72 static void cx_reinit_board (cx_board_t *b);
73
74 /*
75 * Wait for CCR to clear.
76 */
77 void cx_cmd (int base, int cmd)
78 {
79 unsigned short port = CCR(base);
80 unsigned short count;
81
82 /* Wait 10 msec for the previous command to complete. */
83 for (count=0; inb(port) && count<20000; ++count)
84 continue;
85
86 /* Issue the command. */
87 outb (port, cmd);
88
89 /* Wait 10 msec for the command to complete. */
90 for (count=0; inb(port) && count<20000; ++count)
91 continue;
92 }
93
94 /*
95 * Reset the chip.
96 */
97 static int cx_reset (unsigned short port)
98 {
99 int count;
100
101 /* Wait up to 10 msec for revision code to appear after reset. */
102 for (count=0; count<20000; ++count)
103 if (inb(GFRCR(port)) != 0)
104 break;
105
106 cx_cmd (port, CCR_RSTALL);
107
108 /* Firmware revision code should clear imediately. */
109 /* Wait up to 10 msec for revision code to appear again. */
110 for (count=0; count<20000; ++count)
111 if (inb(GFRCR(port)) != 0)
112 return (1);
113
114 /* Reset failed. */
115 return (0);
116 }
117
118 /*
119 * Check if the CD2400 board is present at the given base port.
120 */
121 static int cx_probe_chained_board (int port, int *c0, int *c1)
122 {
123 int rev, i;
124
125 /* Read and check the board revision code. */
126 rev = inb (BSR(port));
127 *c0 = *c1 = 0;
128 switch (rev & BSR_VAR_MASK) {
129 case CRONYX_100: *c0 = 1; break;
130 case CRONYX_400: *c1 = 1; break;
131 case CRONYX_500: *c0 = *c1 = 1; break;
132 case CRONYX_410: *c0 = 1; break;
133 case CRONYX_810: *c0 = *c1 = 1; break;
134 case CRONYX_410s: *c0 = 1; break;
135 case CRONYX_810s: *c0 = *c1 = 1; break;
136 case CRONYX_440: *c0 = 1; break;
137 case CRONYX_840: *c0 = *c1 = 1; break;
138 case CRONYX_401: *c0 = 1; break;
139 case CRONYX_801: *c0 = *c1 = 1; break;
140 case CRONYX_401s: *c0 = 1; break;
141 case CRONYX_801s: *c0 = *c1 = 1; break;
142 case CRONYX_404: *c0 = 1; break;
143 case CRONYX_703: *c0 = *c1 = 1; break;
144 default: return (0); /* invalid variant code */
145 }
146
147 switch (rev & BSR_OSC_MASK) {
148 case BSR_OSC_20: /* 20 MHz */
149 case BSR_OSC_18432: /* 18.432 MHz */
150 break;
151 default:
152 return (0); /* oscillator frequency does not match */
153 }
154
155 for (i=2; i<0x10; i+=2)
156 if ((inb (BSR(port)+i) & BSR_REV_MASK) != (rev & BSR_REV_MASK))
157 return (0); /* status changed? */
158 return (1);
159 }
160
161 /*
162 * Check if the CD2400 board is present at the given base port.
163 */
164 int
165 cx_probe_board (int port)
166 {
167 int c0, c1, c2=0, c3=0, result;
168
169 if (! cx_probe_chained_board (port, &c0, &c1))
170 return (0); /* no board detected */
171
172 if (! (inb (BSR(port)) & BSR_NOCHAIN)) { /* chained board attached */
173 if (! cx_probe_chained_board (port + 0x10, &c2, &c3))
174 return (0); /* invalid chained board? */
175
176 if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))
177 return (0); /* invalid chained board flag? */
178 }
179
180 /* Turn off the reset bit. */
181 outb (BCR0(port), BCR0_NORESET);
182 if (c2 || c3)
183 outb (BCR0(port + 0x10), BCR0_NORESET);
184
185 result = 1;
186 if (c0 && ! cx_probe_chip (CS0(port)))
187 result = 0; /* no CD2400 chip here */
188 else if (c1 && ! cx_probe_chip (CS1(port)))
189 result = 0; /* no second CD2400 chip */
190 else if (c2 && ! cx_probe_chip (CS0(port + 0x10)))
191 result = 0; /* no CD2400 chip on the slave board */
192 else if (c3 && ! cx_probe_chip (CS1(port + 0x10)))
193 result = 0; /* no second CD2400 chip on the slave board */
194
195 /* Reset the controller. */
196 outb (BCR0(port), 0);
197 if (c2 || c3)
198 outb (BCR0(port + 0x10), 0);
199
200 /* Yes, we really have valid CD2400 board. */
201 return (result);
202 }
203
204 /*
205 * Check if the CD2400 chip is present at the given base port.
206 */
207 static int cx_probe_chip (int base)
208 {
209 int rev, newrev, count;
210
211 /* Wait up to 10 msec for revision code to appear after reset. */
212 for (count=0; inb(GFRCR(base))==0; ++count)
213 if (count >= 20000)
214 return (0); /* reset failed */
215
216 /* Read and check the global firmware revision code. */
217 rev = inb (GFRCR(base));
218 if (rev<REVCL_MIN || rev>REVCL_MAX)
219 return (0); /* CD2400 revision does not match */
220
221 /* Reset the chip. */
222 if (! cx_reset (base))
223 return (0);
224
225 /* Read and check the new global firmware revision code. */
226 newrev = inb (GFRCR(base));
227 if (newrev != rev)
228 return (0); /* revision changed */
229
230 /* Yes, we really have CD2400 chip here. */
231 return (1);
232 }
233
234 /*
235 * Probe and initialize the board structure.
236 */
237 void cx_init (cx_board_t *b, int num, int port, int irq, int dma)
238 {
239 int rev, chain, rev2;
240
241 rev = inb (BSR(port));
242 chain = !(rev & BSR_NOCHAIN);
243 rev2 = chain ? inb (BSR(port+0x10)) : 0;
244 cx_init_board (b, num, port, irq, dma, chain,
245 (rev & BSR_VAR_MASK), (rev & BSR_OSC_MASK),
246 (rev2 & BSR_VAR_MASK), (rev2 & BSR_OSC_MASK));
247 }
248
249 /*
250 * Initialize the board structure, given the type of the board.
251 */
252 static void
253 cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,
254 int chain, int rev, int osc, int rev2, int osc2)
255 {
256 cx_chan_t *c;
257 int i, c0, c1;
258
259 /* Initialize board structure. */
260 b->port = port;
261 b->num = num;
262 b->irq = irq;
263 b->dma = dma;
264 b->if0type = b->if8type = cx_iftype;
265
266 /* Set channels 0 and 8 mode, set DMA and IRQ. */
267 b->bcr0 = b->bcr0b = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];
268
269 /* Clear DTR[0..3] and DTR[8..12]. */
270 b->bcr1 = b->bcr1b = 0;
271
272 /* Initialize chip structures. */
273 for (i=0; i<NCHIP; ++i) {
274 b->chip[i].num = i;
275 b->chip[i].board = b;
276 }
277 b->chip[0].port = CS0(port);
278 b->chip[1].port = CS1(port);
279 b->chip[2].port = CS0(port+0x10);
280 b->chip[3].port = CS1(port+0x10);
281
282 /*------------------ Master board -------------------*/
283
284 /* Read and check the board revision code. */
285 c0 = c1 = 0;
286 b->name[0] = 0;
287 switch (rev) {
288 case CRONYX_100: strcpy (b->name, "100"); c0 = 1; break;
289 case CRONYX_400: strcpy (b->name, "400"); c1 = 1; break;
290 case CRONYX_500: strcpy (b->name, "500"); c0 = c1 = 1; break;
291 case CRONYX_410: strcpy (b->name, "410"); c0 = 1; break;
292 case CRONYX_810: strcpy (b->name, "810"); c0 = c1 = 1; break;
293 case CRONYX_410s: strcpy (b->name, "410s"); c0 = 1; break;
294 case CRONYX_810s: strcpy (b->name, "810s"); c0 = c1 = 1; break;
295 case CRONYX_440: strcpy (b->name, "440"); c0 = 1; break;
296 case CRONYX_840: strcpy (b->name, "840"); c0 = c1 = 1; break;
297 case CRONYX_401: strcpy (b->name, "401"); c0 = 1; break;
298 case CRONYX_801: strcpy (b->name, "801"); c0 = c1 = 1; break;
299 case CRONYX_401s: strcpy (b->name, "401s"); c0 = 1; break;
300 case CRONYX_801s: strcpy (b->name, "801s"); c0 = c1 = 1; break;
301 case CRONYX_404: strcpy (b->name, "404"); c0 = 1; break;
302 case CRONYX_703: strcpy (b->name, "703"); c0 = c1 = 1; break;
303 }
304
305 switch (osc) {
306 default:
307 case BSR_OSC_20: /* 20 MHz */
308 b->chip[0].oscfreq = b->chip[1].oscfreq = 20000000L;
309 strcat (b->name, "a");
310 break;
311 case BSR_OSC_18432: /* 18.432 MHz */
312 b->chip[0].oscfreq = b->chip[1].oscfreq = 18432000L;
313 strcat (b->name, "b");
314 break;
315 }
316
317 if (! c0)
318 b->chip[0].port = 0;
319 if (! c1)
320 b->chip[1].port = 0;
321
322 /*------------------ Slave board -------------------*/
323
324 if (! chain) {
325 b->chip[2].oscfreq = b->chip[3].oscfreq = 0L;
326 b->chip[2].port = b->chip[3].port = 0;
327 } else {
328 /* Read and check the board revision code. */
329 c0 = c1 = 0;
330 strcat (b->name, "/");
331 switch (rev2) {
332 case CRONYX_100: strcat(b->name,"100"); c0=1; break;
333 case CRONYX_400: strcat(b->name,"400"); c1=1; break;
334 case CRONYX_500: strcat(b->name,"500"); c0=c1=1; break;
335 case CRONYX_410: strcat(b->name,"410"); c0=1; break;
336 case CRONYX_810: strcat(b->name,"810"); c0=c1=1; break;
337 case CRONYX_410s: strcat(b->name,"410s"); c0=1; break;
338 case CRONYX_810s: strcat(b->name,"810s"); c0=c1=1; break;
339 case CRONYX_440: strcat(b->name,"440"); c0=1; break;
340 case CRONYX_840: strcat(b->name,"840"); c0=c1=1; break;
341 case CRONYX_401: strcat(b->name,"401"); c0=1; break;
342 case CRONYX_801: strcat(b->name,"801"); c0=c1=1; break;
343 case CRONYX_401s: strcat(b->name,"401s"); c0=1; break;
344 case CRONYX_801s: strcat(b->name,"801s"); c0=c1=1; break;
345 case CRONYX_404: strcat(b->name,"404"); c0=1; break;
346 case CRONYX_703: strcat(b->name,"703"); c0=c1=1; break;
347 }
348
349 switch (osc2) {
350 default:
351 case BSR_OSC_20: /* 20 MHz */
352 b->chip[2].oscfreq = b->chip[3].oscfreq = 20000000L;
353 strcat (b->name, "a");
354 break;
355 case BSR_OSC_18432: /* 18.432 MHz */
356 b->chip[2].oscfreq = b->chip[3].oscfreq = 18432000L;
357 strcat (b->name, "b");
358 break;
359 }
360
361 if (! c0)
362 b->chip[2].port = 0;
363 if (! c1)
364 b->chip[3].port = 0;
365 }
366
367 /* Initialize channel structures. */
368 for (i=0; i<NCHAN; ++i) {
369 cx_chan_t *c = b->chan + i;
370
371 c->num = i;
372 c->board = b;
373 c->chip = b->chip + i*NCHIP/NCHAN;
374 c->stat = b->stat + i;
375 c->type = T_NONE;
376 }
377
378 /*------------------ Master board -------------------*/
379
380 switch (rev) {
381 case CRONYX_400:
382 break;
383 case CRONYX_100:
384 case CRONYX_500:
385 b->chan[0].type = T_UNIV_RS232;
386 break;
387 case CRONYX_410:
388 case CRONYX_810:
389 b->chan[0].type = T_UNIV_V35;
390 for (i=1; i<4; ++i)
391 b->chan[i].type = T_UNIV_RS232;
392 break;
393 case CRONYX_410s:
394 case CRONYX_810s:
395 b->chan[0].type = T_UNIV_V35;
396 for (i=1; i<4; ++i)
397 b->chan[i].type = T_SYNC_RS232;
398 break;
399 case CRONYX_440:
400 case CRONYX_840:
401 b->chan[0].type = T_UNIV_V35;
402 for (i=1; i<4; ++i)
403 b->chan[i].type = T_SYNC_V35;
404 break;
405 case CRONYX_401:
406 case CRONYX_801:
407 b->chan[0].type = T_UNIV_RS449;
408 for (i=1; i<4; ++i)
409 b->chan[i].type = T_UNIV_RS232;
410 break;
411 case CRONYX_401s:
412 case CRONYX_801s:
413 b->chan[0].type = T_UNIV_RS449;
414 for (i=1; i<4; ++i)
415 b->chan[i].type = T_SYNC_RS232;
416 break;
417 case CRONYX_404:
418 b->chan[0].type = T_UNIV_RS449;
419 for (i=1; i<4; ++i)
420 b->chan[i].type = T_SYNC_RS449;
421 break;
422 case CRONYX_703:
423 b->chan[0].type = T_UNIV_RS449;
424 for (i=1; i<3; ++i)
425 b->chan[i].type = T_SYNC_RS449;
426 break;
427 }
428
429 /* If the second controller is present,
430 * then we have 4..7 channels in async. mode */
431 if (b->chip[1].port)
432 for (i=4; i<8; ++i)
433 b->chan[i].type = T_UNIV_RS232;
434
435 /*------------------ Slave board -------------------*/
436
437 if (chain) {
438 switch (rev2) {
439 case CRONYX_400:
440 break;
441 case CRONYX_100:
442 case CRONYX_500:
443 b->chan[8].type = T_UNIV_RS232;
444 break;
445 case CRONYX_410:
446 case CRONYX_810:
447 b->chan[8].type = T_UNIV_V35;
448 for (i=9; i<12; ++i)
449 b->chan[i].type = T_UNIV_RS232;
450 break;
451 case CRONYX_410s:
452 case CRONYX_810s:
453 b->chan[8].type = T_UNIV_V35;
454 for (i=9; i<12; ++i)
455 b->chan[i].type = T_SYNC_RS232;
456 break;
457 case CRONYX_440:
458 case CRONYX_840:
459 b->chan[8].type = T_UNIV_V35;
460 for (i=9; i<12; ++i)
461 b->chan[i].type = T_SYNC_V35;
462 break;
463 case CRONYX_401:
464 case CRONYX_801:
465 b->chan[8].type = T_UNIV_RS449;
466 for (i=9; i<12; ++i)
467 b->chan[i].type = T_UNIV_RS232;
468 break;
469 case CRONYX_401s:
470 case CRONYX_801s:
471 b->chan[8].type = T_UNIV_RS449;
472 for (i=9; i<12; ++i)
473 b->chan[i].type = T_UNIV_RS232;
474 break;
475 case CRONYX_404:
476 b->chan[8].type = T_UNIV_RS449;
477 for (i=9; i<12; ++i)
478 b->chan[i].type = T_SYNC_RS449;
479 break;
480 case CRONYX_703:
481 b->chan[8].type = T_UNIV_RS449;
482 for (i=9; i<11; ++i)
483 b->chan[i].type = T_SYNC_RS449;
484 break;
485 }
486
487 /* If the second controller is present,
488 * then we have 4..7 channels in async. mode */
489 if (b->chip[3].port)
490 for (i=12; i<16; ++i)
491 b->chan[i].type = T_UNIV_RS232;
492 }
493
494 b->nuniv = b->nsync = b->nasync = 0;
495 for (c=b->chan; c<b->chan+NCHAN; ++c)
496 switch (c->type) {
497 case T_ASYNC: ++b->nasync; break;
498 case T_UNIV_RS232:
499 case T_UNIV_RS449:
500 case T_UNIV_V35: ++b->nuniv; break;
501 case T_SYNC_RS232:
502 case T_SYNC_V35:
503 case T_SYNC_RS449: ++b->nsync; break;
504 }
505
506 cx_reinit_board (b);
507 }
508
509 /*
510 * Reinitialize all channels, using new options and baud rate.
511 */
512 static void
513 cx_reinit_board (cx_board_t *b)
514 {
515 cx_chan_t *c;
516
517 b->if0type = b->if8type = cx_iftype;
518 for (c=b->chan; c<b->chan+NCHAN; ++c) {
519 switch (c->type) {
520 default:
521 case T_NONE:
522 continue;
523 case T_UNIV_RS232:
524 case T_UNIV_RS449:
525 case T_UNIV_V35:
526 c->mode = (cx_univ_mode == M_ASYNC) ?
527 M_ASYNC : cx_sync_mode;
528 break;
529 case T_SYNC_RS232:
530 case T_SYNC_V35:
531 case T_SYNC_RS449:
532 c->mode = cx_sync_mode;
533 break;
534 case T_ASYNC:
535 c->mode = M_ASYNC;
536 break;
537 }
538 c->rxbaud = cx_rxbaud;
539 c->txbaud = cx_txbaud;
540 c->opt = chan_opt_dflt;
541 c->aopt = opt_async_dflt;
542 c->hopt = opt_hdlc_dflt;
543 c->bopt = opt_bisync_dflt;
544 c->xopt = opt_x21_dflt;
545 }
546 }
547
548 /*
549 * Set up the board.
550 */
551 void cx_setup_board (cx_board_t *b)
552 {
553 int i;
554
555 /* Disable DMA channel. */
556 outb (DMA_MASK, (b->dma & 3) | DMA_MASK_CLEAR);
557
558 /* Reset the controller. */
559 outb (BCR0(b->port), 0);
560 if (b->chip[2].port || b->chip[3].port)
561 outb (BCR0(b->port+0x10), 0);
562
563 /*
564 * Set channels 0 and 8 to RS232 async. mode.
565 * Enable DMA and IRQ.
566 */
567 outb (BCR0(b->port), b->bcr0);
568 if (b->chip[2].port || b->chip[3].port)
569 outb (BCR0(b->port+0x10), b->bcr0b);
570
571 /* Clear DTR[0..3] and DTR[8..12]. */
572 outw (BCR1(b->port), b->bcr1);
573 if (b->chip[2].port || b->chip[3].port)
574 outw (BCR1(b->port+0x10), b->bcr1b);
575
576 /* Initialize all controllers. */
577 for (i=0; i<NCHIP; ++i)
578 if (b->chip[i].port)
579 cx_setup_chip (b->chip + i);
580
581 /* Set up DMA channel to master mode. */
582 outb (DMA_MODE, (b->dma & 3) | DMA_MODE_MASTER);
583
584 /* Enable DMA channel. */
585 outb (DMA_MASK, b->dma & 3);
586
587 /* Initialize all channels. */
588 for (i=0; i<NCHAN; ++i)
589 if (b->chan[i].type != T_NONE)
590 cx_setup_chan (b->chan + i);
591 }
592
593 /*
594 * Initialize the board.
595 */
596 static void cx_setup_chip (cx_chip_t *c)
597 {
598 /* Reset the chip. */
599 cx_reset (c->port);
600
601 /*
602 * Set all interrupt level registers to the same value.
603 * This enables the internal CD2400 priority scheme.
604 */
605 outb (RPILR(c->port), BRD_INTR_LEVEL);
606 outb (TPILR(c->port), BRD_INTR_LEVEL);
607 outb (MPILR(c->port), BRD_INTR_LEVEL);
608
609 /* Set bus error count to zero. */
610 outb (BERCNT(c->port), 0);
611
612 /* Set 16-bit DMA mode. */
613 outb (DMR(c->port), 0);
614
615 /* Set timer period register to 1 msec (approximately). */
616 outb (TPR(c->port), 10);
617 }
618
619 /*
620 * Initialize the CD2400 channel.
621 */
622 void cx_setup_chan (cx_chan_t *c)
623 {
624 unsigned short port = c->chip->port;
625 int clock, period;
626
627 if (c->num == 0) {
628 c->board->bcr0 &= ~BCR0_UMASK;
629 if (c->mode != M_ASYNC)
630 c->board->bcr0 |= BCR0_UM_SYNC;
631 if (c->board->if0type &&
632 (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
633 c->board->bcr0 |= BCR0_UI_RS449;
634 outb (BCR0(c->board->port), c->board->bcr0);
635 } else if (c->num == 8) {
636 c->board->bcr0b &= ~BCR0_UMASK;
637 if (c->mode != M_ASYNC)
638 c->board->bcr0b |= BCR0_UM_SYNC;
639 if (c->board->if8type &&
640 (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
641 c->board->bcr0b |= BCR0_UI_RS449;
642 outb (BCR0(c->board->port+0x10), c->board->bcr0b);
643 }
644
645 /* set current channel number */
646 outb (CAR(port), c->num & 3);
647
648 /* reset the channel */
649 cx_cmd (port, CCR_CLRCH);
650
651 /* set LIVR to contain the board and channel numbers */
652 outb (LIVR(port), c->board->num << 6 | c->num << 2);
653
654 /* clear DTR, RTS, set TXCout/DTR pin */
655 outb (MSVR_RTS(port), 0);
656 outb (MSVR_DTR(port), c->mode==M_ASYNC ? 0 : MSV_TXCOUT);
657
658 switch (c->mode) { /* initialize the channel mode */
659 case M_ASYNC:
660 /* set receiver timeout register */
661 outw (RTPR(port), 10); /* 10 msec, see TPR */
662
663 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_ASYNC);
664 outb (COR1(port), BYTE c->aopt.cor1);
665 outb (COR2(port), BYTE c->aopt.cor2);
666 outb (COR3(port), BYTE c->aopt.cor3);
667 outb (COR6(port), BYTE c->aopt.cor6);
668 outb (COR7(port), BYTE c->aopt.cor7);
669 outb (SCHR1(port), c->aopt.schr1);
670 outb (SCHR2(port), c->aopt.schr2);
671 outb (SCHR3(port), c->aopt.schr3);
672 outb (SCHR4(port), c->aopt.schr4);
673 outb (SCRL(port), c->aopt.scrl);
674 outb (SCRH(port), c->aopt.scrh);
675 outb (LNXT(port), c->aopt.lnxt);
676 break;
677 case M_HDLC:
678 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_HDLC);
679 outb (COR1(port), BYTE c->hopt.cor1);
680 outb (COR2(port), BYTE c->hopt.cor2);
681 outb (COR3(port), BYTE c->hopt.cor3);
682 outb (RFAR1(port), c->hopt.rfar1);
683 outb (RFAR2(port), c->hopt.rfar2);
684 outb (RFAR3(port), c->hopt.rfar3);
685 outb (RFAR4(port), c->hopt.rfar4);
686 outb (CPSR(port), c->hopt.cpsr);
687 break;
688 case M_BISYNC:
689 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_BISYNC);
690 outb (COR1(port), BYTE c->bopt.cor1);
691 outb (COR2(port), BYTE c->bopt.cor2);
692 outb (COR3(port), BYTE c->bopt.cor3);
693 outb (COR6(port), BYTE c->bopt.cor6);
694 outb (CPSR(port), c->bopt.cpsr);
695 break;
696 case M_X21:
697 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_X21);
698 outb (COR1(port), BYTE c->xopt.cor1);
699 outb (COR2(port), BYTE c->xopt.cor2);
700 outb (COR3(port), BYTE c->xopt.cor3);
701 outb (COR6(port), BYTE c->xopt.cor6);
702 outb (SCHR1(port), c->xopt.schr1);
703 outb (SCHR2(port), c->xopt.schr2);
704 outb (SCHR3(port), c->xopt.schr3);
705 break;
706 }
707
708 /* set mode-independent options */
709 outb (COR4(port), BYTE c->opt.cor4);
710 outb (COR5(port), BYTE c->opt.cor5);
711
712 /* set up receiver clock values */
713 if (c->mode == M_ASYNC || c->opt.rcor.dpll) {
714 cx_clock (c->chip->oscfreq, c->rxbaud, &clock, &period);
715 c->opt.rcor.clk = clock;
716 } else {
717 c->opt.rcor.clk = CLK_EXT;
718 period = 1;
719 }
720 outb (RCOR(port), BYTE c->opt.rcor);
721 outb (RBPR(port), period);
722
723 /* set up transmitter clock values */
724 if (c->mode == M_ASYNC || !c->opt.tcor.ext1x) {
725 unsigned ext1x = c->opt.tcor.ext1x;
726 c->opt.tcor.ext1x = 0;
727 cx_clock (c->chip->oscfreq, c->txbaud, &clock, &period);
728 c->opt.tcor.clk = clock;
729 c->opt.tcor.ext1x = ext1x;
730 } else {
731 c->opt.tcor.clk = CLK_EXT;
732 period = 1;
733 }
734 outb (TCOR(port), BYTE c->opt.tcor);
735 outb (TBPR(port), period);
736
737 /* set receiver A buffer physical address */
738 c->arphys = vtophys (c->arbuf);
739 outw (ARBADRU(port), (unsigned short) (c->arphys>>16));
740 outw (ARBADRL(port), (unsigned short) c->arphys);
741
742 /* set receiver B buffer physical address */
743 c->brphys = vtophys (c->brbuf);
744 outw (BRBADRU(port), (unsigned short) (c->brphys>>16));
745 outw (BRBADRL(port), (unsigned short) c->brphys);
746
747 /* set transmitter A buffer physical address */
748 c->atphys = vtophys (c->atbuf);
749 outw (ATBADRU(port), (unsigned short) (c->atphys>>16));
750 outw (ATBADRL(port), (unsigned short) c->atphys);
751
752 /* set transmitter B buffer physical address */
753 c->btphys = vtophys (c->btbuf);
754 outw (BTBADRU(port), (unsigned short) (c->btphys>>16));
755 outw (BTBADRL(port), (unsigned short) c->btphys);
756
757 c->dtr = 0;
758 c->rts = 0;
759 }
760
761 /*
762 * Control DTR signal for the channel.
763 * Turn it on/off.
764 */
765 void cx_chan_dtr (cx_chan_t *c, int on)
766 {
767 c->dtr = on ? 1 : 0;
768
769 if (c->mode == M_ASYNC) {
770 outb (CAR(c->chip->port), c->num & 3);
771 outb (MSVR_DTR(c->chip->port), on ? MSV_DTR : 0);
772 return;
773 }
774
775 switch (c->num) {
776 default:
777 /* Channels 4..7 and 12..15 in syncronous mode
778 * have no DTR signal. */
779 break;
780
781 case 1: case 2: case 3:
782 if (c->type == T_UNIV_RS232)
783 break;
784 case 0:
785 if (on)
786 c->board->bcr1 |= 0x100 << c->num;
787 else
788 c->board->bcr1 &= ~(0x100 << c->num);
789 outw (BCR1(c->board->port), c->board->bcr1);
790 break;
791
792 case 9: case 10: case 11:
793 if (c->type == T_UNIV_RS232)
794 break;
795 case 8:
796 if (on)
797 c->board->bcr1b |= 0x100 << (c->num & 3);
798 else
799 c->board->bcr1b &= ~(0x100 << (c->num & 3));
800 outw (BCR1(c->board->port+0x10), c->board->bcr1b);
801 break;
802 }
803 }
804
805 /*
806 * Control RTS signal for the channel.
807 * Turn it on/off.
808 */
809 void
810 cx_chan_rts (cx_chan_t *c, int on)
811 {
812 c->rts = on ? 1 : 0;
813 outb (CAR(c->chip->port), c->num & 3);
814 outb (MSVR_RTS(c->chip->port), on ? MSV_RTS : 0);
815 }
816
817
818 /*
819 * Get the state of CARRIER signal of the channel.
820 */
821 int
822 cx_chan_cd (cx_chan_t *c)
823 {
824 unsigned char sigval;
825
826 if (c->mode == M_ASYNC) {
827 outb (CAR(c->chip->port), c->num & 3);
828 return (inb (MSVR(c->chip->port)) & MSV_CD ? 1 : 0);
829 }
830
831 /*
832 * Channels 4..7 and 12..15 don't have CD signal available.
833 */
834 switch (c->num) {
835 default:
836 return (1);
837
838 case 1: case 2: case 3:
839 if (c->type == T_UNIV_RS232)
840 return (1);
841 case 0:
842 sigval = inw (BSR(c->board->port)) >> 8;
843 break;
844
845 case 9: case 10: case 11:
846 if (c->type == T_UNIV_RS232)
847 return (1);
848 case 8:
849 sigval = inw (BSR(c->board->port+0x10)) >> 8;
850 break;
851 }
852 return (~sigval >> 4 >> (c->num & 3) & 1);
853 }
854
855 /*
856 * Compute CD2400 clock values.
857 */
858 void cx_clock (long hz, long ba, int *clk, int *div)
859 {
860 static short clocktab[] = { 8, 32, 128, 512, 2048, 0 };
861
862 for (*clk=0; clocktab[*clk]; ++*clk) {
863 long c = ba * clocktab[*clk];
864 if (hz <= c*256) {
865 *div = (2 * hz + c) / (2 * c) - 1;
866 return;
867 }
868 }
869 /* Incorrect baud rate. Return some meaningful values. */
870 *clk = 0;
871 *div = 255;
872 }
873
874 static cx_chan_opt_t chan_opt_dflt = { /* mode-independent options */
875 { /* cor4 */
876 7, /* FIFO threshold, odd is better */
877 0,
878 0, /* don't detect 1 to 0 on CTS */
879 1, /* detect 1 to 0 on CD */
880 0, /* detect 1 to 0 on DSR */
881 },
882 { /* cor5 */
883 0, /* receive flow control FIFO threshold */
884 0,
885 0, /* don't detect 0 to 1 on CTS */
886 1, /* detect 0 to 1 on CD */
887 0, /* detect 0 to 1 on DSR */
888 },
889 { /* rcor */
890 0, /* dummy clock source */
891 ENCOD_NRZ, /* NRZ mode */
892 0, /* disable DPLL */
893 0,
894 0, /* transmit line value */
895 },
896 { /* tcor */
897 0,
898 0, /* local loopback mode */
899 0,
900 1, /* external 1x clock mode */
901 0,
902 0, /* dummy transmit clock source */
903 },
904 };
905
906 static cx_opt_async_t opt_async_dflt = { /* default async options */
907 { /* cor1 */
908 8-1, /* 8-bit char length */
909 0, /* don't ignore parity */
910 PARM_NOPAR, /* no parity */
911 PAR_EVEN, /* even parity */
912 },
913 { /* cor2 */
914 0, /* disable automatic DSR */
915 1, /* enable automatic CTS */
916 0, /* disable automatic RTS */
917 0, /* no remote loopback */
918 0,
919 0, /* disable embedded cmds */
920 0, /* disable XON/XOFF */
921 0, /* disable XANY */
922 },
923 { /* cor3 */
924 STOPB_1, /* 1 stop bit */
925 0,
926 0, /* disable special char detection */
927 FLOWCC_PASS, /* pass flow ctl chars to the host */
928 0, /* range detect disable */
929 0, /* disable extended spec. char detect */
930 },
931 { /* cor6 */
932 PERR_INTR, /* generate exception on parity errors */
933 BRK_INTR, /* generate exception on break condition */
934 0, /* don't translate NL to CR on input */
935 0, /* don't translate CR to NL on input */
936 0, /* don't discard CR on input */
937 },
938 { /* cor7 */
939 0, /* don't translate CR to NL on output */
940 0, /* don't translate NL to CR on output */
941 0,
942 0, /* don't process flow ctl err chars */
943 0, /* disable LNext option */
944 0, /* don't strip 8 bit on input */
945 },
946 0, 0, 0, 0, 0, 0, 0, /* clear schr1-4, scrl, scrh, lnxt */
947 };
948
949 static cx_opt_hdlc_t opt_hdlc_dflt = { /* default hdlc options */
950 { /* cor1 */
951 2, /* 2 inter-frame flags */
952 0, /* no-address mode */
953 CLRDET_DISABLE, /* disable clear detect */
954 AFLO_1OCT, /* 1-byte address field length */
955 },
956 { /* cor2 */
957 0, /* disable automatic DSR */
958 0, /* disable automatic CTS */
959 0, /* disable automatic RTS */
960 0,
961 CRC_INVERT, /* use CRC V.41 */
962 0,
963 FCS_NOTPASS, /* don't pass received CRC to the host */
964 0,
965 },
966 { /* cor3 */
967 0, /* 0 pad characters sent */
968 IDLE_FLAG, /* idle in flag */
969 0, /* enable FCS */
970 FCSP_ONES, /* FCS preset to all ones (V.41) */
971 SYNC_AA, /* use AAh as sync char */
972 0, /* disable pad characters */
973 },
974 0, 0, 0, 0, /* clear rfar1-4 */
975 POLY_V41, /* use V.41 CRC polynomial */
976 };
977
978 static cx_opt_bisync_t opt_bisync_dflt = { /* default bisync options */
979 { /* cor1 */
980 8-1, /* 8-bit char length */
981 0, /* don't ignore parity */
982 PARM_NOPAR, /* no parity */
983 PAR_EVEN, /* even parity */
984 },
985 { /* cor2 */
986 3-2, /* send three SYN chars */
987 CRC_DONT_INVERT,/* don't invert CRC (CRC-16) */
988 0, /* use ASCII, not EBCDIC */
989 0, /* disable bcc append */
990 BCC_CRC16, /* user CRC16, not LRC */
991 },
992 { /* cor3 */
993 0, /* send 0 pad chars */
994 IDLE_FLAG, /* idle in SYN */
995 0, /* enable FCS */
996 FCSP_ZEROS, /* FCS preset to all zeros (CRC-16) */
997 PAD_AA, /* use AAh as pad char */
998 0, /* disable pad characters */
999 },
1000 { /* cor6 */
1001 10, /* DLE - disable special termination char */
1002 },
1003 POLY_16, /* use CRC-16 polynomial */
1004 };
1005
1006 static cx_opt_x21_t opt_x21_dflt = { /* default x21 options */
1007 { /* cor1 */
1008 8-1, /* 8-bit char length */
1009 0, /* don't ignore parity */
1010 PARM_NOPAR, /* no parity */
1011 PAR_EVEN, /* even parity */
1012 },
1013 { /* cor2 */
1014 0,
1015 0, /* disable embedded transmitter cmds */
1016 0,
1017 },
1018 { /* cor3 */
1019 0,
1020 0, /* disable special character detect */
1021 0, /* don't treat SYN as special condition */
1022 0, /* disable steady state detect */
1023 X21SYN_2, /* 2 SYN chars on receive are required */
1024 },
1025 { /* cor6 */
1026 16, /* SYN - standard SYN character */
1027 },
1028 0, 0, 0, /* clear schr1-3 */
1029 };
Cache object: a14b7f64eb2111ce9afc8a1d37f61083
|