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