2 * Low-level subroutines for Cronyx-Sigma adapter.
4 * Copyright (C) 1994-95 Cronyx Ltd.
5 * Author: Serge Vakulenko, <vak@cronyx.ru>
7 * This software is distributed with NO WARRANTIES, not even the implied
8 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
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.
14 * Version 1.6, Wed May 31 16:03:20 MSD 1995
15 * $FreeBSD: src/sys/i386/isa/cronyx.c,v 1.10.6.1 2000/08/03 01:01:20 peter Exp $
16 * $DragonFly: src/sys/dev/serial/cronyx/cronyx.c,v 1.4 2004/02/13 01:45:14 joerg Exp $
18 #if defined (MSDOS) || defined (__MSDOS__)
21 # define inb(port) inportb(port)
22 # define inw(port) inport(port)
23 # define outb(port,b) outportb(port,b)
24 # define outw(port,w) outport(port,w)
25 # define vtophys(a) (((unsigned long)(a)>>12 & 0xffff0) +\
26 ((unsigned)(a) & 0xffff))
30 # include <sys/param.h>
31 # include <sys/systm.h>
32 # include <sys/socket.h>
35 # include <vm/vm_param.h>
37 # if !defined(__DragonFly__) && !defined(__FreeBSD__)
38 # include <machine/inline.h>
40 # include <machine/cronyx.h>
41 # include <dev/netif/cx/cxreg.h>
44 #define DMA_MASK 0xd4 /* DMA mask register */
45 #define DMA_MASK_CLEAR 0x04 /* DMA clear mask */
46 #define DMA_MODE 0xd6 /* DMA mode register */
47 #define DMA_MODE_MASTER 0xc0 /* DMA master mode */
49 #define BYTE *(unsigned char*)&
51 static unsigned char irqmask [] = {
52 BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_3,
53 BCR0_IRQ_DIS, BCR0_IRQ_5, BCR0_IRQ_DIS, BCR0_IRQ_7,
54 BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_10, BCR0_IRQ_11,
55 BCR0_IRQ_12, BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_15,
58 static unsigned char dmamask [] = {
59 BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_DIS,
60 BCR0_DMA_DIS, BCR0_DMA_5, BCR0_DMA_6, BCR0_DMA_7,
63 static long cx_rxbaud = CX_SPEED_DFLT; /* receiver baud rate */
64 static long cx_txbaud = CX_SPEED_DFLT; /* transmitter baud rate */
66 static int cx_univ_mode = M_ASYNC; /* univ. chan. mode: async or sync */
67 static int cx_sync_mode = M_HDLC; /* sync. chan. mode: HDLC, Bisync or X.21 */
68 static int cx_iftype = 0; /* univ. chan. interface: upper/lower */
70 static cx_chan_opt_t chan_opt_dflt = { /* mode-independent options */
72 7, /* FIFO threshold, odd is better */
74 0, /* don't detect 1 to 0 on CTS */
75 1, /* detect 1 to 0 on CD */
76 0, /* detect 1 to 0 on DSR */
79 0, /* receive flow control FIFO threshold */
81 0, /* don't detect 0 to 1 on CTS */
82 1, /* detect 0 to 1 on CD */
83 0, /* detect 0 to 1 on DSR */
86 0, /* dummy clock source */
87 ENCOD_NRZ, /* NRZ mode */
90 0, /* transmit line value */
94 0, /* local loopback mode */
96 1, /* external 1x clock mode */
98 0, /* dummy transmit clock source */
102 static cx_opt_async_t opt_async_dflt = { /* default async options */
104 8-1, /* 8-bit char length */
105 0, /* don't ignore parity */
106 PARM_NOPAR, /* no parity */
107 PAR_EVEN, /* even parity */
110 0, /* disable automatic DSR */
111 1, /* enable automatic CTS */
112 0, /* disable automatic RTS */
113 0, /* no remote loopback */
115 0, /* disable embedded cmds */
116 0, /* disable XON/XOFF */
117 0, /* disable XANY */
120 STOPB_1, /* 1 stop bit */
122 0, /* disable special char detection */
123 FLOWCC_PASS, /* pass flow ctl chars to the host */
124 0, /* range detect disable */
125 0, /* disable extended spec. char detect */
128 PERR_INTR, /* generate exception on parity errors */
129 BRK_INTR, /* generate exception on break condition */
130 0, /* don't translate NL to CR on input */
131 0, /* don't translate CR to NL on input */
132 0, /* don't discard CR on input */
135 0, /* don't translate CR to NL on output */
136 0, /* don't translate NL to CR on output */
138 0, /* don't process flow ctl err chars */
139 0, /* disable LNext option */
140 0, /* don't strip 8 bit on input */
142 0, 0, 0, 0, 0, 0, 0, /* clear schr1-4, scrl, scrh, lnxt */
145 static cx_opt_hdlc_t opt_hdlc_dflt = { /* default hdlc options */
147 2, /* 2 inter-frame flags */
148 0, /* no-address mode */
149 CLRDET_DISABLE, /* disable clear detect */
150 AFLO_1OCT, /* 1-byte address field length */
153 0, /* disable automatic DSR */
154 0, /* disable automatic CTS */
155 0, /* disable automatic RTS */
157 CRC_INVERT, /* use CRC V.41 */
159 FCS_NOTPASS, /* don't pass received CRC to the host */
163 0, /* 0 pad characters sent */
164 IDLE_FLAG, /* idle in flag */
166 FCSP_ONES, /* FCS preset to all ones (V.41) */
167 SYNC_AA, /* use AAh as sync char */
168 0, /* disable pad characters */
170 0, 0, 0, 0, /* clear rfar1-4 */
171 POLY_V41, /* use V.41 CRC polynomial */
174 static cx_opt_bisync_t opt_bisync_dflt = { /* default bisync options */
176 8-1, /* 8-bit char length */
177 0, /* don't ignore parity */
178 PARM_NOPAR, /* no parity */
179 PAR_EVEN, /* even parity */
182 3-2, /* send three SYN chars */
183 CRC_DONT_INVERT,/* don't invert CRC (CRC-16) */
184 0, /* use ASCII, not EBCDIC */
185 0, /* disable bcc append */
186 BCC_CRC16, /* user CRC16, not LRC */
189 0, /* send 0 pad chars */
190 IDLE_FLAG, /* idle in SYN */
192 FCSP_ZEROS, /* FCS preset to all zeros (CRC-16) */
193 PAD_AA, /* use AAh as pad char */
194 0, /* disable pad characters */
197 10, /* DLE - disable special termination char */
199 POLY_16, /* use CRC-16 polynomial */
202 static cx_opt_x21_t opt_x21_dflt = { /* default x21 options */
204 8-1, /* 8-bit char length */
205 0, /* don't ignore parity */
206 PARM_NOPAR, /* no parity */
207 PAR_EVEN, /* even parity */
211 0, /* disable embedded transmitter cmds */
216 0, /* disable special character detect */
217 0, /* don't treat SYN as special condition */
218 0, /* disable steady state detect */
219 X21SYN_2, /* 2 SYN chars on receive are required */
222 16, /* SYN - standard SYN character */
224 0, 0, 0, /* clear schr1-3 */
227 static int cx_probe_chip (int base);
228 static void cx_setup_chip (cx_chip_t *c);
229 static void cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,
230 int chain, int rev, int osc, int rev2, int osc2);
231 static void cx_reinit_board (cx_board_t *b);
234 * Wait for CCR to clear.
236 void cx_cmd (int base, int cmd)
238 unsigned short port = CCR(base);
239 unsigned short count;
241 /* Wait 10 msec for the previous command to complete. */
242 for (count=0; inb(port) && count<20000; ++count)
245 /* Issue the command. */
248 /* Wait 10 msec for the command to complete. */
249 for (count=0; inb(port) && count<20000; ++count)
256 static int cx_reset (unsigned short port)
260 /* Wait up to 10 msec for revision code to appear after reset. */
261 for (count=0; count<20000; ++count)
262 if (inb(GFRCR(port)) != 0)
265 cx_cmd (port, CCR_RSTALL);
267 /* Firmware revision code should clear imediately. */
268 /* Wait up to 10 msec for revision code to appear again. */
269 for (count=0; count<20000; ++count)
270 if (inb(GFRCR(port)) != 0)
278 * Check if the CD2400 board is present at the given base port.
280 static int cx_probe_chained_board (int port, int *c0, int *c1)
284 /* Read and check the board revision code. */
285 rev = inb (BSR(port));
287 switch (rev & BSR_VAR_MASK) {
288 case CRONYX_100: *c0 = 1; break;
289 case CRONYX_400: *c1 = 1; break;
290 case CRONYX_500: *c0 = *c1 = 1; break;
291 case CRONYX_410: *c0 = 1; break;
292 case CRONYX_810: *c0 = *c1 = 1; break;
293 case CRONYX_410s: *c0 = 1; break;
294 case CRONYX_810s: *c0 = *c1 = 1; break;
295 case CRONYX_440: *c0 = 1; break;
296 case CRONYX_840: *c0 = *c1 = 1; break;
297 case CRONYX_401: *c0 = 1; break;
298 case CRONYX_801: *c0 = *c1 = 1; break;
299 case CRONYX_401s: *c0 = 1; break;
300 case CRONYX_801s: *c0 = *c1 = 1; break;
301 case CRONYX_404: *c0 = 1; break;
302 case CRONYX_703: *c0 = *c1 = 1; break;
303 default: return (0); /* invalid variant code */
306 switch (rev & BSR_OSC_MASK) {
307 case BSR_OSC_20: /* 20 MHz */
308 case BSR_OSC_18432: /* 18.432 MHz */
311 return (0); /* oscillator frequency does not match */
314 for (i=2; i<0x10; i+=2)
315 if ((inb (BSR(port)+i) & BSR_REV_MASK) != (rev & BSR_REV_MASK))
316 return (0); /* status changed? */
321 * Check if the CD2400 board is present at the given base port.
324 cx_probe_board (int port)
326 int c0, c1, c2=0, c3=0, result;
328 if (! cx_probe_chained_board (port, &c0, &c1))
329 return (0); /* no board detected */
331 if (! (inb (BSR(port)) & BSR_NOCHAIN)) { /* chained board attached */
332 if (! cx_probe_chained_board (port + 0x10, &c2, &c3))
333 return (0); /* invalid chained board? */
335 if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN))
336 return (0); /* invalid chained board flag? */
339 /* Turn off the reset bit. */
340 outb (BCR0(port), BCR0_NORESET);
342 outb (BCR0(port + 0x10), BCR0_NORESET);
345 if (c0 && ! cx_probe_chip (CS0(port)))
346 result = 0; /* no CD2400 chip here */
347 else if (c1 && ! cx_probe_chip (CS1(port)))
348 result = 0; /* no second CD2400 chip */
349 else if (c2 && ! cx_probe_chip (CS0(port + 0x10)))
350 result = 0; /* no CD2400 chip on the slave board */
351 else if (c3 && ! cx_probe_chip (CS1(port + 0x10)))
352 result = 0; /* no second CD2400 chip on the slave board */
354 /* Reset the controller. */
355 outb (BCR0(port), 0);
357 outb (BCR0(port + 0x10), 0);
359 /* Yes, we really have valid CD2400 board. */
364 * Check if the CD2400 chip is present at the given base port.
366 static int cx_probe_chip (int base)
368 int rev, newrev, count;
370 /* Wait up to 10 msec for revision code to appear after reset. */
371 for (count=0; inb(GFRCR(base))==0; ++count)
373 return (0); /* reset failed */
375 /* Read and check the global firmware revision code. */
376 rev = inb (GFRCR(base));
377 if (rev<REVCL_MIN || rev>REVCL_MAX)
378 return (0); /* CD2400 revision does not match */
380 /* Reset the chip. */
381 if (! cx_reset (base))
384 /* Read and check the new global firmware revision code. */
385 newrev = inb (GFRCR(base));
387 return (0); /* revision changed */
389 /* Yes, we really have CD2400 chip here. */
394 * Probe and initialize the board structure.
396 void cx_init (cx_board_t *b, int num, int port, int irq, int dma)
398 int rev, chain, rev2;
400 rev = inb (BSR(port));
401 chain = !(rev & BSR_NOCHAIN);
402 rev2 = chain ? inb (BSR(port+0x10)) : 0;
403 cx_init_board (b, num, port, irq, dma, chain,
404 (rev & BSR_VAR_MASK), (rev & BSR_OSC_MASK),
405 (rev2 & BSR_VAR_MASK), (rev2 & BSR_OSC_MASK));
409 * Initialize the board structure, given the type of the board.
412 cx_init_board (cx_board_t *b, int num, int port, int irq, int dma,
413 int chain, int rev, int osc, int rev2, int osc2)
418 /* Initialize board structure. */
423 b->if0type = b->if8type = cx_iftype;
425 /* Set channels 0 and 8 mode, set DMA and IRQ. */
426 b->bcr0 = b->bcr0b = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq];
428 /* Clear DTR[0..3] and DTR[8..12]. */
429 b->bcr1 = b->bcr1b = 0;
431 /* Initialize chip structures. */
432 for (i=0; i<NCHIP; ++i) {
434 b->chip[i].board = b;
436 b->chip[0].port = CS0(port);
437 b->chip[1].port = CS1(port);
438 b->chip[2].port = CS0(port+0x10);
439 b->chip[3].port = CS1(port+0x10);
441 /*------------------ Master board -------------------*/
443 /* Read and check the board revision code. */
447 case CRONYX_100: strcpy (b->name, "100"); c0 = 1; break;
448 case CRONYX_400: strcpy (b->name, "400"); c1 = 1; break;
449 case CRONYX_500: strcpy (b->name, "500"); c0 = c1 = 1; break;
450 case CRONYX_410: strcpy (b->name, "410"); c0 = 1; break;
451 case CRONYX_810: strcpy (b->name, "810"); c0 = c1 = 1; break;
452 case CRONYX_410s: strcpy (b->name, "410s"); c0 = 1; break;
453 case CRONYX_810s: strcpy (b->name, "810s"); c0 = c1 = 1; break;
454 case CRONYX_440: strcpy (b->name, "440"); c0 = 1; break;
455 case CRONYX_840: strcpy (b->name, "840"); c0 = c1 = 1; break;
456 case CRONYX_401: strcpy (b->name, "401"); c0 = 1; break;
457 case CRONYX_801: strcpy (b->name, "801"); c0 = c1 = 1; break;
458 case CRONYX_401s: strcpy (b->name, "401s"); c0 = 1; break;
459 case CRONYX_801s: strcpy (b->name, "801s"); c0 = c1 = 1; break;
460 case CRONYX_404: strcpy (b->name, "404"); c0 = 1; break;
461 case CRONYX_703: strcpy (b->name, "703"); c0 = c1 = 1; break;
466 case BSR_OSC_20: /* 20 MHz */
467 b->chip[0].oscfreq = b->chip[1].oscfreq = 20000000L;
468 strcat (b->name, "a");
470 case BSR_OSC_18432: /* 18.432 MHz */
471 b->chip[0].oscfreq = b->chip[1].oscfreq = 18432000L;
472 strcat (b->name, "b");
481 /*------------------ Slave board -------------------*/
484 b->chip[2].oscfreq = b->chip[3].oscfreq = 0L;
485 b->chip[2].port = b->chip[3].port = 0;
487 /* Read and check the board revision code. */
489 strcat (b->name, "/");
491 case CRONYX_100: strcat(b->name,"100"); c0=1; break;
492 case CRONYX_400: strcat(b->name,"400"); c1=1; break;
493 case CRONYX_500: strcat(b->name,"500"); c0=c1=1; break;
494 case CRONYX_410: strcat(b->name,"410"); c0=1; break;
495 case CRONYX_810: strcat(b->name,"810"); c0=c1=1; break;
496 case CRONYX_410s: strcat(b->name,"410s"); c0=1; break;
497 case CRONYX_810s: strcat(b->name,"810s"); c0=c1=1; break;
498 case CRONYX_440: strcat(b->name,"440"); c0=1; break;
499 case CRONYX_840: strcat(b->name,"840"); c0=c1=1; break;
500 case CRONYX_401: strcat(b->name,"401"); c0=1; break;
501 case CRONYX_801: strcat(b->name,"801"); c0=c1=1; break;
502 case CRONYX_401s: strcat(b->name,"401s"); c0=1; break;
503 case CRONYX_801s: strcat(b->name,"801s"); c0=c1=1; break;
504 case CRONYX_404: strcat(b->name,"404"); c0=1; break;
505 case CRONYX_703: strcat(b->name,"703"); c0=c1=1; break;
510 case BSR_OSC_20: /* 20 MHz */
511 b->chip[2].oscfreq = b->chip[3].oscfreq = 20000000L;
512 strcat (b->name, "a");
514 case BSR_OSC_18432: /* 18.432 MHz */
515 b->chip[2].oscfreq = b->chip[3].oscfreq = 18432000L;
516 strcat (b->name, "b");
526 /* Initialize channel structures. */
527 for (i=0; i<NCHAN; ++i) {
528 cx_chan_t *c = b->chan + i;
532 c->chip = b->chip + i*NCHIP/NCHAN;
533 c->stat = b->stat + i;
537 /*------------------ Master board -------------------*/
544 b->chan[0].type = T_UNIV_RS232;
548 b->chan[0].type = T_UNIV_V35;
550 b->chan[i].type = T_UNIV_RS232;
554 b->chan[0].type = T_UNIV_V35;
556 b->chan[i].type = T_SYNC_RS232;
560 b->chan[0].type = T_UNIV_V35;
562 b->chan[i].type = T_SYNC_V35;
566 b->chan[0].type = T_UNIV_RS449;
568 b->chan[i].type = T_UNIV_RS232;
572 b->chan[0].type = T_UNIV_RS449;
574 b->chan[i].type = T_SYNC_RS232;
577 b->chan[0].type = T_UNIV_RS449;
579 b->chan[i].type = T_SYNC_RS449;
582 b->chan[0].type = T_UNIV_RS449;
584 b->chan[i].type = T_SYNC_RS449;
588 /* If the second controller is present,
589 * then we have 4..7 channels in async. mode */
592 b->chan[i].type = T_UNIV_RS232;
594 /*------------------ Slave board -------------------*/
602 b->chan[8].type = T_UNIV_RS232;
606 b->chan[8].type = T_UNIV_V35;
608 b->chan[i].type = T_UNIV_RS232;
612 b->chan[8].type = T_UNIV_V35;
614 b->chan[i].type = T_SYNC_RS232;
618 b->chan[8].type = T_UNIV_V35;
620 b->chan[i].type = T_SYNC_V35;
624 b->chan[8].type = T_UNIV_RS449;
626 b->chan[i].type = T_UNIV_RS232;
630 b->chan[8].type = T_UNIV_RS449;
632 b->chan[i].type = T_UNIV_RS232;
635 b->chan[8].type = T_UNIV_RS449;
637 b->chan[i].type = T_SYNC_RS449;
640 b->chan[8].type = T_UNIV_RS449;
642 b->chan[i].type = T_SYNC_RS449;
646 /* If the second controller is present,
647 * then we have 4..7 channels in async. mode */
649 for (i=12; i<16; ++i)
650 b->chan[i].type = T_UNIV_RS232;
653 b->nuniv = b->nsync = b->nasync = 0;
654 for (c=b->chan; c<b->chan+NCHAN; ++c)
656 case T_ASYNC: ++b->nasync; break;
659 case T_UNIV_V35: ++b->nuniv; break;
662 case T_SYNC_RS449: ++b->nsync; break;
669 * Reinitialize all channels, using new options and baud rate.
672 cx_reinit_board (cx_board_t *b)
676 b->if0type = b->if8type = cx_iftype;
677 for (c=b->chan; c<b->chan+NCHAN; ++c) {
685 c->mode = (cx_univ_mode == M_ASYNC) ?
686 M_ASYNC : cx_sync_mode;
691 c->mode = cx_sync_mode;
697 c->rxbaud = cx_rxbaud;
698 c->txbaud = cx_txbaud;
699 c->opt = chan_opt_dflt;
700 c->aopt = opt_async_dflt;
701 c->hopt = opt_hdlc_dflt;
702 c->bopt = opt_bisync_dflt;
703 c->xopt = opt_x21_dflt;
710 void cx_setup_board (cx_board_t *b)
714 /* Disable DMA channel. */
715 outb (DMA_MASK, (b->dma & 3) | DMA_MASK_CLEAR);
717 /* Reset the controller. */
718 outb (BCR0(b->port), 0);
719 if (b->chip[2].port || b->chip[3].port)
720 outb (BCR0(b->port+0x10), 0);
723 * Set channels 0 and 8 to RS232 async. mode.
724 * Enable DMA and IRQ.
726 outb (BCR0(b->port), b->bcr0);
727 if (b->chip[2].port || b->chip[3].port)
728 outb (BCR0(b->port+0x10), b->bcr0b);
730 /* Clear DTR[0..3] and DTR[8..12]. */
731 outw (BCR1(b->port), b->bcr1);
732 if (b->chip[2].port || b->chip[3].port)
733 outw (BCR1(b->port+0x10), b->bcr1b);
735 /* Initialize all controllers. */
736 for (i=0; i<NCHIP; ++i)
738 cx_setup_chip (b->chip + i);
740 /* Set up DMA channel to master mode. */
741 outb (DMA_MODE, (b->dma & 3) | DMA_MODE_MASTER);
743 /* Enable DMA channel. */
744 outb (DMA_MASK, b->dma & 3);
746 /* Initialize all channels. */
747 for (i=0; i<NCHAN; ++i)
748 if (b->chan[i].type != T_NONE)
749 cx_setup_chan (b->chan + i);
753 * Initialize the board.
755 static void cx_setup_chip (cx_chip_t *c)
757 /* Reset the chip. */
761 * Set all interrupt level registers to the same value.
762 * This enables the internal CD2400 priority scheme.
764 outb (RPILR(c->port), BRD_INTR_LEVEL);
765 outb (TPILR(c->port), BRD_INTR_LEVEL);
766 outb (MPILR(c->port), BRD_INTR_LEVEL);
768 /* Set bus error count to zero. */
769 outb (BERCNT(c->port), 0);
771 /* Set 16-bit DMA mode. */
772 outb (DMR(c->port), 0);
774 /* Set timer period register to 1 msec (approximately). */
775 outb (TPR(c->port), 10);
779 * Initialize the CD2400 channel.
781 void cx_setup_chan (cx_chan_t *c)
783 unsigned short port = c->chip->port;
787 c->board->bcr0 &= ~BCR0_UMASK;
788 if (c->mode != M_ASYNC)
789 c->board->bcr0 |= BCR0_UM_SYNC;
790 if (c->board->if0type &&
791 (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
792 c->board->bcr0 |= BCR0_UI_RS449;
793 outb (BCR0(c->board->port), c->board->bcr0);
794 } else if (c->num == 8) {
795 c->board->bcr0b &= ~BCR0_UMASK;
796 if (c->mode != M_ASYNC)
797 c->board->bcr0b |= BCR0_UM_SYNC;
798 if (c->board->if8type &&
799 (c->type==T_UNIV_RS449 || c->type==T_UNIV_V35))
800 c->board->bcr0b |= BCR0_UI_RS449;
801 outb (BCR0(c->board->port+0x10), c->board->bcr0b);
804 /* set current channel number */
805 outb (CAR(port), c->num & 3);
807 /* reset the channel */
808 cx_cmd (port, CCR_CLRCH);
810 /* set LIVR to contain the board and channel numbers */
811 outb (LIVR(port), c->board->num << 6 | c->num << 2);
813 /* clear DTR, RTS, set TXCout/DTR pin */
814 outb (MSVR_RTS(port), 0);
815 outb (MSVR_DTR(port), c->mode==M_ASYNC ? 0 : MSV_TXCOUT);
817 switch (c->mode) { /* initialize the channel mode */
819 /* set receiver timeout register */
820 outw (RTPR(port), 10); /* 10 msec, see TPR */
822 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_ASYNC);
823 outb (COR1(port), BYTE c->aopt.cor1);
824 outb (COR2(port), BYTE c->aopt.cor2);
825 outb (COR3(port), BYTE c->aopt.cor3);
826 outb (COR6(port), BYTE c->aopt.cor6);
827 outb (COR7(port), BYTE c->aopt.cor7);
828 outb (SCHR1(port), c->aopt.schr1);
829 outb (SCHR2(port), c->aopt.schr2);
830 outb (SCHR3(port), c->aopt.schr3);
831 outb (SCHR4(port), c->aopt.schr4);
832 outb (SCRL(port), c->aopt.scrl);
833 outb (SCRH(port), c->aopt.scrh);
834 outb (LNXT(port), c->aopt.lnxt);
837 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_HDLC);
838 outb (COR1(port), BYTE c->hopt.cor1);
839 outb (COR2(port), BYTE c->hopt.cor2);
840 outb (COR3(port), BYTE c->hopt.cor3);
841 outb (RFAR1(port), c->hopt.rfar1);
842 outb (RFAR2(port), c->hopt.rfar2);
843 outb (RFAR3(port), c->hopt.rfar3);
844 outb (RFAR4(port), c->hopt.rfar4);
845 outb (CPSR(port), c->hopt.cpsr);
848 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_BISYNC);
849 outb (COR1(port), BYTE c->bopt.cor1);
850 outb (COR2(port), BYTE c->bopt.cor2);
851 outb (COR3(port), BYTE c->bopt.cor3);
852 outb (COR6(port), BYTE c->bopt.cor6);
853 outb (CPSR(port), c->bopt.cpsr);
856 outb (CMR(port), CMR_RXDMA | CMR_TXDMA | CMR_X21);
857 outb (COR1(port), BYTE c->xopt.cor1);
858 outb (COR2(port), BYTE c->xopt.cor2);
859 outb (COR3(port), BYTE c->xopt.cor3);
860 outb (COR6(port), BYTE c->xopt.cor6);
861 outb (SCHR1(port), c->xopt.schr1);
862 outb (SCHR2(port), c->xopt.schr2);
863 outb (SCHR3(port), c->xopt.schr3);
867 /* set mode-independent options */
868 outb (COR4(port), BYTE c->opt.cor4);
869 outb (COR5(port), BYTE c->opt.cor5);
871 /* set up receiver clock values */
872 if (c->mode == M_ASYNC || c->opt.rcor.dpll) {
873 cx_clock (c->chip->oscfreq, c->rxbaud, &clock, &period);
874 c->opt.rcor.clk = clock;
876 c->opt.rcor.clk = CLK_EXT;
879 outb (RCOR(port), BYTE c->opt.rcor);
880 outb (RBPR(port), period);
882 /* set up transmitter clock values */
883 if (c->mode == M_ASYNC || !c->opt.tcor.ext1x) {
884 unsigned ext1x = c->opt.tcor.ext1x;
885 c->opt.tcor.ext1x = 0;
886 cx_clock (c->chip->oscfreq, c->txbaud, &clock, &period);
887 c->opt.tcor.clk = clock;
888 c->opt.tcor.ext1x = ext1x;
890 c->opt.tcor.clk = CLK_EXT;
893 outb (TCOR(port), BYTE c->opt.tcor);
894 outb (TBPR(port), period);
896 /* set receiver A buffer physical address */
897 c->arphys = vtophys (c->arbuf);
898 outw (ARBADRU(port), (unsigned short) (c->arphys>>16));
899 outw (ARBADRL(port), (unsigned short) c->arphys);
901 /* set receiver B buffer physical address */
902 c->brphys = vtophys (c->brbuf);
903 outw (BRBADRU(port), (unsigned short) (c->brphys>>16));
904 outw (BRBADRL(port), (unsigned short) c->brphys);
906 /* set transmitter A buffer physical address */
907 c->atphys = vtophys (c->atbuf);
908 outw (ATBADRU(port), (unsigned short) (c->atphys>>16));
909 outw (ATBADRL(port), (unsigned short) c->atphys);
911 /* set transmitter B buffer physical address */
912 c->btphys = vtophys (c->btbuf);
913 outw (BTBADRU(port), (unsigned short) (c->btphys>>16));
914 outw (BTBADRL(port), (unsigned short) c->btphys);
921 * Control DTR signal for the channel.
924 void cx_chan_dtr (cx_chan_t *c, int on)
928 if (c->mode == M_ASYNC) {
929 outb (CAR(c->chip->port), c->num & 3);
930 outb (MSVR_DTR(c->chip->port), on ? MSV_DTR : 0);
936 /* Channels 4..7 and 12..15 in syncronous mode
937 * have no DTR signal. */
940 case 1: case 2: case 3:
941 if (c->type == T_UNIV_RS232)
945 c->board->bcr1 |= 0x100 << c->num;
947 c->board->bcr1 &= ~(0x100 << c->num);
948 outw (BCR1(c->board->port), c->board->bcr1);
951 case 9: case 10: case 11:
952 if (c->type == T_UNIV_RS232)
956 c->board->bcr1b |= 0x100 << (c->num & 3);
958 c->board->bcr1b &= ~(0x100 << (c->num & 3));
959 outw (BCR1(c->board->port+0x10), c->board->bcr1b);
965 * Control RTS signal for the channel.
969 cx_chan_rts (cx_chan_t *c, int on)
972 outb (CAR(c->chip->port), c->num & 3);
973 outb (MSVR_RTS(c->chip->port), on ? MSV_RTS : 0);
978 * Get the state of CARRIER signal of the channel.
981 cx_chan_cd (cx_chan_t *c)
983 unsigned char sigval;
985 if (c->mode == M_ASYNC) {
986 outb (CAR(c->chip->port), c->num & 3);
987 return (inb (MSVR(c->chip->port)) & MSV_CD ? 1 : 0);
991 * Channels 4..7 and 12..15 don't have CD signal available.
997 case 1: case 2: case 3:
998 if (c->type == T_UNIV_RS232)
1001 sigval = inw (BSR(c->board->port)) >> 8;
1004 case 9: case 10: case 11:
1005 if (c->type == T_UNIV_RS232)
1008 sigval = inw (BSR(c->board->port+0x10)) >> 8;
1011 return (~sigval >> 4 >> (c->num & 3) & 1);
1015 * Compute CD2400 clock values.
1017 void cx_clock (long hz, long ba, int *clk, int *div)
1019 static short clocktab[] = { 8, 32, 128, 512, 2048, 0 };
1021 for (*clk=0; clocktab[*clk]; ++*clk) {
1022 long c = ba * clocktab[*clk];
1024 *div = (2 * hz + c) / (2 * c) - 1;
1028 /* Incorrect baud rate. Return some meaningful values. */