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