153905Smckusick /*
2*63314Sbostic * Copyright (c) 1992, 1993
3*63314Sbostic * The Regents of the University of California. All rights reserved.
453905Smckusick *
553905Smckusick * This code is derived from software contributed to Berkeley by
653905Smckusick * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
753905Smckusick *
853905Smckusick * %sccs.include.redist.c%
953905Smckusick *
1053905Smckusick * from: $Hdr: scc.c,v 4.300 91/06/09 06:44:53 root Rel41 $ SONY
1153905Smckusick *
12*63314Sbostic * @(#)scc.c 8.1 (Berkeley) 06/11/93
1353905Smckusick */
1453905Smckusick
1553905Smckusick /*
1653905Smckusick * LH8530 SCC (serial communication controller) driver
1753905Smckusick *
1853905Smckusick * NOTE: This driver is available only for news700/1200/1700/3400.
1953905Smckusick *
2053905Smckusick * Any code and mechanism in this module may not be used
2153905Smckusick * in any form without permissions. COPYRIGHT (C) 1989-
2253905Smckusick * SONY Corporation, Super Microsystems Group (SMSG),
2353905Smckusick * Work Station Division, all rights RESERVED.
2453905Smckusick */
2553905Smckusick
2657184Sutashiro #include <machine/adrsmap.h>
2753905Smckusick
2853905Smckusick #include "rs.h"
2953905Smckusick
3057184Sutashiro #include <sys/param.h>
3157184Sutashiro #include <sys/ioctl.h>
3257184Sutashiro #include <sys/tty.h>
3357184Sutashiro #include <sys/malloc.h>
3453905Smckusick
3557184Sutashiro #include <news3400/sio/sccparam.h>
3657184Sutashiro #include <news3400/sio/sccreg.h>
3757184Sutashiro #include <news3400/sio/scc.h>
3857184Sutashiro #include <news3400/sio/scc.conf>
3953905Smckusick
4053905Smckusick #define PROBE_DATA 0x55
4153905Smckusick
4253905Smckusick #ifdef mips
4353905Smckusick #define VOLATILE volatile
4453905Smckusick #else
4553905Smckusick #define VOLATILE
4653905Smckusick #endif
4753905Smckusick
4853905Smckusick int tty00_is_console = 0;
4953905Smckusick
5053905Smckusick #define SCC_BUFSIZE 256
5153905Smckusick
5253905Smckusick char scc_buf[2][SCC_BUFSIZE];
5353905Smckusick
scc_open(chan)5453905Smckusick scc_open(chan)
5553905Smckusick int chan;
5653905Smckusick {
5753905Smckusick register Scc_channel *scc = &sccsw[chan];
5853905Smckusick register int s;
5953905Smckusick
6053905Smckusick s = splscc();
6153905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) {
6253905Smckusick scc_init(chan);
6353905Smckusick if (chan <= SCC_REMOTE1)
6453905Smckusick scc->r_dma.dma_addr = scc_buf[chan];
6553905Smckusick else
6653905Smckusick scc->r_dma.dma_addr =
6753905Smckusick malloc(SCC_BUFSIZE, M_DEVBUF, M_WAITOK);
6853905Smckusick scc->r_dma.dma_count = 0;
6953905Smckusick scc->scc_status |= CHAN_ACTIVE;
7053905Smckusick }
7153905Smckusick (void) splx(s);
7253905Smckusick return (0);
7353905Smckusick }
7453905Smckusick
scc_probe(chan)7553905Smckusick scc_probe(chan)
7653905Smckusick register int chan;
7753905Smckusick {
7853905Smckusick VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
7953905Smckusick int s, temp, probe;
8053905Smckusick
8153905Smckusick if (badaddr(port, 1))
8253905Smckusick return (0);
8353905Smckusick s = splscc();
8453905Smckusick temp = scc_read_reg(chan, RR12);
8553905Smckusick scc_write_reg(chan, WR12, PROBE_DATA);
8653905Smckusick probe = scc_read_reg(chan, RR12);
8753905Smckusick scc_write_reg(chan, WR12, temp);
8853905Smckusick (void) splx(s);
8953905Smckusick return (probe == PROBE_DATA);
9053905Smckusick }
9153905Smckusick
scc_getc(chan)9253905Smckusick scc_getc(chan)
9353905Smckusick int chan;
9453905Smckusick {
9553905Smckusick VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
9653905Smckusick int c;
9753905Smckusick
9853905Smckusick if (port->ctrl & R0_RxCA) {
9953905Smckusick SCCWAIT;
10053905Smckusick c = port->data;
10153905Smckusick SCCWAIT;
10253905Smckusick return (c);
10353905Smckusick }
10453905Smckusick SCCWAIT;
10553905Smckusick return (-1);
10653905Smckusick }
10753905Smckusick
10853905Smckusick #ifndef notdef
scc_putc(chan,c)10953905Smckusick scc_putc(chan, c)
11053905Smckusick int chan, c;
11153905Smckusick {
11253905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
11353905Smckusick
11453905Smckusick while ((port->ctrl & R0_TxBE) == 0)
11553905Smckusick SCCWAIT;
11653905Smckusick SCCWAIT;
11753905Smckusick port->data = c;
11853905Smckusick SCCWAIT;
11953905Smckusick }
12053905Smckusick #else
scc_putc(chan,c)12153905Smckusick scc_putc(chan, c)
12253905Smckusick int chan, c;
12353905Smckusick {
12453905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
12553905Smckusick register VOLATILE u_char *ctrl = &sccsw[chan].scc_port->ctrl;
12653905Smckusick register VOLATILE u_char *data = &sccsw[chan].scc_port->data;
12753905Smckusick
12853905Smckusick SCCWAIT;
12953905Smckusick while ((*ctrl & R0_TxBE) == 0) {
13053905Smckusick SCCWAIT;
13153905Smckusick }
13253905Smckusick SCCWAIT;
13353905Smckusick
13453905Smckusick *ctrl = W0_RES_TxINT;
13553905Smckusick SCCWAIT;
13653905Smckusick *data = (char)(c & 0xff);
13753905Smckusick SCCWAIT;
13853905Smckusick scc_write_reg(chan, WR1, W1_RxINT_ALL|W1_TxINTE|W1_EXTINTE|W1_PARITY);
13953905Smckusick SCCWAIT;
14053905Smckusick }
14153905Smckusick #endif
14253905Smckusick
scc_init(chan)14353905Smckusick scc_init(chan)
14453905Smckusick int chan;
14553905Smckusick {
14653905Smckusick register VOLATILE struct scc_reg *port;
14753905Smckusick register char *data;
14853905Smckusick register int i;
14953905Smckusick register Scc_channel *scc = &sccsw[chan];
15053905Smckusick int s;
15153905Smckusick
15253905Smckusick s = splscc();
15353905Smckusick data = scc->scc_init;
15453905Smckusick port = scc->scc_port;
15553905Smckusick for (i = 0; i < N_INITDATA; i++) {
15653905Smckusick port->ctrl = *data++;
15753905Smckusick SCCWAIT;
15853905Smckusick }
15953905Smckusick scc_write_reg(chan, WR2, scc->scc_vec & ~0x0f);
16053905Smckusick /* KU:XXX
16153905Smckusick This must be bug because scc->scc_param is not initialized yet.
16253905Smckusick scc_set_param(chan, scc->scc_param);
16353905Smckusick */
16453905Smckusick (void) splx(s);
16553905Smckusick }
16653905Smckusick
16753905Smckusick #define vec_to_scc(vec) ((((vec) - SCCVEC0) >> 3) & 0x000f)
16853905Smckusick #define vec_to_chan(vec) scc2chan[vec_to_scc(vec)]
16953905Smckusick
17053905Smckusick int scc2chan[] = {
17153905Smckusick 1, 0,
17253905Smckusick 3, 2,
17353905Smckusick 5, 4,
17453905Smckusick 7, 6,
17553905Smckusick 9, 8
17653905Smckusick };
17753905Smckusick
scc_rint(vec)17853905Smckusick scc_rint(vec)
17953905Smckusick int vec;
18053905Smckusick {
18153905Smckusick int chan = vec_to_chan(vec);
18253905Smckusick register Scc_channel *scc = &sccsw[chan];
18353905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port;
18453905Smckusick register int c;
18553905Smckusick
18653905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) {
18753905Smckusick scc_reset(chan);
18853905Smckusick goto out;
18953905Smckusick }
19053905Smckusick if (scc->scc_status & LINE_BREAK){
19153905Smckusick scc->scc_status &= ~LINE_BREAK;
19253905Smckusick c = port->data;
19353905Smckusick SCCWAIT;
19453905Smckusick }
19553905Smckusick while (port->ctrl & R0_RxCA) {
19653905Smckusick SCCWAIT;
19753905Smckusick c = port->data;
19853905Smckusick SCCWAIT;
19953905Smckusick #if NRS > 0
20053905Smckusick scc_pdma(chan, c);
20153905Smckusick #endif
20253905Smckusick }
20353905Smckusick SCCWAIT;
20453905Smckusick out:
20553905Smckusick port->ctrl = W0_RES_IUS;
20653905Smckusick SCCWAIT;
20753905Smckusick }
20853905Smckusick
20953905Smckusick #if NRS > 0
scc_enable(chan)21053905Smckusick scc_enable(chan)
21153905Smckusick int chan;
21253905Smckusick {
21353905Smckusick register Scc_channel *scc = &sccsw[chan];
21453905Smckusick int n;
21553905Smckusick int s;
21653905Smckusick
21753905Smckusick s = splscc();
21853905Smckusick if ((n = scc->r_dma.dma_count) > 0) {
21953905Smckusick scc->r_dma.dma_count = 0;
22053905Smckusick rsrint(chan, scc->r_dma.dma_addr, n);
22153905Smckusick } else
22253905Smckusick scc->scc_status |= ENABLE;
22353905Smckusick (void) splx(s);
22453905Smckusick }
22553905Smckusick
scc_pdma(chan,c)22653905Smckusick scc_pdma(chan, c)
22753905Smckusick int chan;
22853905Smckusick int c;
22953905Smckusick {
23053905Smckusick register Scc_channel *scc = &sccsw[chan];
23153905Smckusick int n;
23253905Smckusick
23353905Smckusick if (scc->r_dma.dma_count >= SCC_BUFSIZE)
23453905Smckusick printf("rs%d soft fifo overflow\n", chan);
23553905Smckusick else
23653905Smckusick scc->r_dma.dma_addr[scc->r_dma.dma_count++] = c;
23753905Smckusick if (scc->scc_status & ENABLE || scc->r_dma.dma_count >= SCC_BUFSIZE) {
23853905Smckusick scc->scc_status &= ~ENABLE;
23953905Smckusick n = scc->r_dma.dma_count;
24053905Smckusick scc->r_dma.dma_count = 0;
24153905Smckusick rsrint(chan, scc->r_dma.dma_addr, n);
24253905Smckusick }
24353905Smckusick }
24453905Smckusick #endif /* NRS > 0 */
24553905Smckusick
scc_xint(vec)24653905Smckusick scc_xint(vec)
24753905Smckusick int vec;
24853905Smckusick {
24953905Smckusick int chan = vec_to_chan(vec);
25053905Smckusick register Scc_channel *scc = &sccsw[chan];
25153905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port;
25253905Smckusick
25353905Smckusick if (scc->scc_status & OSTOP)
25453905Smckusick scc->scc_status &= ~(OACTIVE|OSTOP);
25553905Smckusick if (scc->scc_status & OFLUSH) {
25653905Smckusick scc->x_dma.dma_count = 0;
25753905Smckusick scc->scc_status &= ~(OACTIVE|OFLUSH);
25853905Smckusick }
25953905Smckusick if ((scc->scc_status & OACTIVE) && (scc->x_dma.dma_count > 0)) {
26053905Smckusick port->data = *(scc->x_dma.dma_addr)++;
26153905Smckusick SCCWAIT;
26253905Smckusick scc->x_dma.dma_count--;
26353905Smckusick } else {
26453905Smckusick port->ctrl = W0_RES_TxINT;
26553905Smckusick SCCWAIT;
26653905Smckusick scc->scc_status &= ~OACTIVE;
26753905Smckusick #if NRS > 0
26853905Smckusick if (scc->x_dma.dma_count == 0)
26953905Smckusick rsxint(chan);
27053905Smckusick #endif
27153905Smckusick }
27253905Smckusick port->ctrl = W0_RES_IUS;
27353905Smckusick SCCWAIT;
27453905Smckusick }
27553905Smckusick
scc_sint(vec)27653905Smckusick scc_sint(vec)
27753905Smckusick int vec;
27853905Smckusick {
27953905Smckusick int chan = vec_to_chan(vec);
28053905Smckusick register Scc_channel *scc = &sccsw[chan];
28153905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port;
28253905Smckusick register int status;
28353905Smckusick register int param = 0;
28453905Smckusick
28553905Smckusick port->ctrl = W0_RES_EXT;
28653905Smckusick SCCWAIT;
28753905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) {
28853905Smckusick scc_reset(chan);
28953905Smckusick goto out;
29053905Smckusick }
29153905Smckusick status = port->ctrl;
29253905Smckusick SCCWAIT;
29353905Smckusick if (status & R0_DCD)
29453905Smckusick param |= DCD;
29553905Smckusick if (status & R0_CTS)
29653905Smckusick param |= CTS;
29753905Smckusick if (status & R0_BREAK){
29853905Smckusick param |= RBREAK;
29953905Smckusick scc->scc_status |= LINE_BREAK;
30053905Smckusick }
30153905Smckusick if ((scc->scc_param & (DCD|CTS|RBREAK)) != param) {
30253905Smckusick scc->scc_param = (scc->scc_param & ~(DCD|CTS|RBREAK)) | param;
30353905Smckusick #if NRS > 0
30453905Smckusick rssint(chan, scc->scc_param);
30553905Smckusick #endif
30653905Smckusick }
30753905Smckusick out:
30853905Smckusick port->ctrl = W0_RES_IUS;
30953905Smckusick SCCWAIT;
31053905Smckusick }
31153905Smckusick
scc_cint(vec)31253905Smckusick scc_cint(vec)
31353905Smckusick int vec;
31453905Smckusick {
31553905Smckusick int chan = vec_to_chan(vec);
31653905Smckusick register Scc_channel *scc = &sccsw[chan];
31753905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port;
31853905Smckusick register int status;
31953905Smckusick int c;
32053905Smckusick
32153905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) {
32253905Smckusick scc_reset(chan);
32353905Smckusick goto out;
32453905Smckusick }
32553905Smckusick status = scc_read_reg(chan, RR1);
32653905Smckusick if (status & R1_CRC)
32753905Smckusick scc->scc_param |= FRAMING_ERROR;
32853905Smckusick if (status & R1_OVRUN) {
32953905Smckusick if ((scc->scc_param & OVERRUN_ERROR) == 0) {
33053905Smckusick scc->scc_param |= OVERRUN_ERROR;
33153905Smckusick #if NRS > 0
33253905Smckusick rssint(chan, scc->scc_param);
33357610Sutashiro #endif
33453905Smckusick }
33553905Smckusick }
33653905Smckusick if (status & R1_PARITY) {
33753905Smckusick scc->scc_param |= SCC_PARITY_ERROR;
33853905Smckusick while (port->ctrl & R0_RxCA) {
33953905Smckusick SCCWAIT;
34053905Smckusick c = port->data;
34153905Smckusick SCCWAIT;
34253905Smckusick #if NRS > 0
34353905Smckusick if (scc->scc_param & NOCHECK)
34453905Smckusick scc_pdma(chan, c);
34553905Smckusick #endif
34653905Smckusick }
34753905Smckusick SCCWAIT;
34853905Smckusick }
34953905Smckusick out:
35053905Smckusick port->ctrl = W0_RES_ERROR;
35153905Smckusick SCCWAIT;
35253905Smckusick port->ctrl = W0_RES_IUS;
35353905Smckusick SCCWAIT;
35453905Smckusick }
35553905Smckusick
scc_write_reg(chan,reg,data)35653905Smckusick scc_write_reg(chan, reg, data)
35753905Smckusick int chan, reg, data;
35853905Smckusick {
35953905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
36053905Smckusick
36153905Smckusick port->ctrl = reg;
36253905Smckusick SCCWAIT;
36353905Smckusick port->ctrl = data;
36453905Smckusick SCCWAIT;
36553905Smckusick }
36653905Smckusick
scc_read_reg(chan,reg)36753905Smckusick scc_read_reg(chan, reg)
36853905Smckusick int chan, reg;
36953905Smckusick {
37053905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
37153905Smckusick int result;
37253905Smckusick
37353905Smckusick port->ctrl = reg;
37453905Smckusick SCCWAIT;
37553905Smckusick result = port->ctrl;
37653905Smckusick SCCWAIT;
37753905Smckusick return (result);
37853905Smckusick }
37953905Smckusick
38053905Smckusick #ifdef news3400
38153905Smckusick #define DSRA 0x01
38253905Smckusick #define RIA 0x02
38353905Smckusick #define DSRB 0x04
38453905Smckusick #define RIB 0x08
38553905Smckusick
38653905Smckusick #define DSRC 0x01
38753905Smckusick #define RIC 0x02
38853905Smckusick #define DSRD 0x04
38953905Smckusick #define RID 0x08
39053905Smckusick #define DSRE 0x10
39153905Smckusick #define RIE 0x20
39253905Smckusick #define DSRF 0x40
39353905Smckusick #define RIF 0x80
39453905Smckusick #endif /* news3400 */
39553905Smckusick
39653905Smckusick struct ri_dsr {
39753905Smckusick char *status;
39853905Smckusick int ri;
39953905Smckusick int dsr;
40053905Smckusick } ri_dsr[] = {
40153905Smckusick { (char *)SCC_STATUS0, RIA, DSRA },
40253905Smckusick { (char *)SCC_STATUS0, RIB, DSRB },
40357610Sutashiro #if !defined(news3200)
40453905Smckusick { (char *)SCC_STATUS1, RIC, DSRC },
40553905Smckusick { (char *)SCC_STATUS1, RID, DSRD },
40653905Smckusick { (char *)SCC_STATUS1, RIE, DSRE },
40753905Smckusick { (char *)SCC_STATUS1, RIF, DSRF },
40853905Smckusick { (char *)SCC_STATUS2, RIC, DSRC },
40953905Smckusick { (char *)SCC_STATUS2, RID, DSRD },
41053905Smckusick { (char *)SCC_STATUS2, RIE, DSRE },
41153905Smckusick { (char *)SCC_STATUS2, RIF, DSRF }
41257610Sutashiro #endif /* !news3200 */
41353905Smckusick };
41453905Smckusick
get_ri_dsr(chan)41553905Smckusick get_ri_dsr(chan)
41653905Smckusick int chan;
41753905Smckusick {
41853905Smckusick register struct ri_dsr *p;
41953905Smckusick register int status, param;
42053905Smckusick
42153905Smckusick param = 0;
42253905Smckusick p = &ri_dsr[chan];
42353905Smckusick status = *p->status;
42453905Smckusick if ((status & p->ri) == 0)
42553905Smckusick param |= RI;
42653905Smckusick if ((status & p->dsr) == 0)
42753905Smckusick param |= DSR;
42853905Smckusick return (param);
42953905Smckusick }
43053905Smckusick
43157610Sutashiro #if defined(news3400)
43253905Smckusick /*
43353905Smckusick * tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5);
43453905Smckusick */
43553905Smckusick static int tc0[] = {
43653905Smckusick 0, /* B0 */
43753905Smckusick 3070, /* B50 */
43853905Smckusick 2046, /* B75 */
43953905Smckusick 1394, /* B110 */
44053905Smckusick 1144, /* B134 */
44153905Smckusick 1022, /* B150 */
44253905Smckusick 766, /* B200 */
44353905Smckusick 510, /* B300 */
44453905Smckusick 254, /* B600 */
44553905Smckusick 126, /* B1200 */
44653905Smckusick 83, /* B1800 */
44753905Smckusick 62, /* B2400 */
44853905Smckusick 30, /* B4800 */
44953905Smckusick 14, /* B9600 */
45053905Smckusick 6, /* EXTA (B19200) */
45153905Smckusick 2 /* EXTB (B38400) */
45253905Smckusick };
45357610Sutashiro #endif /* news3400 */
45453905Smckusick
45553905Smckusick static int tc1[] = {
45653905Smckusick /*
45753905Smckusick * tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5);
45853905Smckusick */
45953905Smckusick 0, /* B0 */
46053905Smckusick 2302, /* B50 */
46153905Smckusick 1534, /* B75 */
46253905Smckusick 1045, /* B110 */
46353905Smckusick 858, /* B134 */
46453905Smckusick 766, /* B150 */
46553905Smckusick 574, /* B200 */
46653905Smckusick 382, /* B300 */
46753905Smckusick 190, /* B600 */
46853905Smckusick 94, /* B1200 */
46953905Smckusick 62, /* B1800 */
47053905Smckusick 46, /* B2400 */
47153905Smckusick 22, /* B4800 */
47253905Smckusick 10, /* B9600 */
47353905Smckusick 4, /* B19200 */
47453905Smckusick 1, /* B38400 */
47553905Smckusick };
47653905Smckusick
scc_set_param(chan,param)47753905Smckusick scc_set_param(chan, param)
47853905Smckusick int chan;
47953905Smckusick register int param;
48053905Smckusick {
48153905Smckusick register Scc_channel *scc = &sccsw[chan];
48253905Smckusick register int bit, baud, *tc;
48353905Smckusick int s;
48453905Smckusick
48553905Smckusick s = splscc();
48653905Smckusick
48753905Smckusick /*
48853905Smckusick * Baud rate / external clock
48953905Smckusick */
49053905Smckusick if ((baud = param & BAUD_RATE) == EXTB && chan <= SCC_REMOTE1 &&
49153905Smckusick param & EXTCLK_ENABLE) {
49253905Smckusick scc_write_reg(chan, WR11, W11_RxC_RTxC|W11_TxC_TRxC);
49353905Smckusick bit = W4_X1;
49453905Smckusick } else {
49553905Smckusick tc = (chan <= SCC_REMOTE1) ? tc0 : tc1;
49653905Smckusick scc_write_reg(chan, WR11, W11_RxC_BRG|W11_TxC_BRG);
49753905Smckusick scc_write_reg(chan, WR12, tc[baud] & 0xff);
49853905Smckusick scc_write_reg(chan, WR13, tc[baud] >> 8);
49953905Smckusick bit = W4_X16;
50053905Smckusick }
50153905Smckusick
50253905Smckusick /*
50353905Smckusick * Clock mode / parity / stop bit
50453905Smckusick */
50553905Smckusick if (param & PARITY) {
50653905Smckusick bit |= W4_PARITY;
50753905Smckusick if (param & EVEN)
50853905Smckusick bit |= W4_EVEN;
50953905Smckusick }
51053905Smckusick switch (param & STOPBIT) {
51153905Smckusick
51253905Smckusick case STOP1:
51353905Smckusick bit |= W4_STOP1;
51453905Smckusick break;
51553905Smckusick
51653905Smckusick case STOP1_5:
51753905Smckusick bit |= W4_STOP1_5;
51853905Smckusick break;
51953905Smckusick
52053905Smckusick case STOP2:
52153905Smckusick bit |= W4_STOP2;
52253905Smckusick break;
52353905Smckusick
52453905Smckusick }
52553905Smckusick scc_write_reg(chan, WR4, bit);
52653905Smckusick
52753905Smckusick /*
52853905Smckusick * Receiver enable / receive character size / auto enable
52953905Smckusick */
53053905Smckusick bit = (param & RXE ? W3_RxE : 0);
53153905Smckusick switch (param & CHAR_SIZE) {
53253905Smckusick
53353905Smckusick case C5BIT:
53453905Smckusick break;
53553905Smckusick
53653905Smckusick case C6BIT:
53753905Smckusick bit |= W3_Rx6BIT;
53853905Smckusick break;
53953905Smckusick
54053905Smckusick case C7BIT:
54153905Smckusick bit |= W3_Rx7BIT;
54253905Smckusick break;
54353905Smckusick
54453905Smckusick case C8BIT:
54553905Smckusick bit |= W3_Rx8BIT;
54653905Smckusick break;
54753905Smckusick }
54853905Smckusick #ifdef AUTO_ENABLE
54953905Smckusick if (param & AUTO_ENABLE)
55053905Smckusick bit |= W3_AUTO;
55153905Smckusick #endif /* AUTO_ENABLE */
55253905Smckusick scc_write_reg(chan, WR3, bit);
55353905Smckusick
55453905Smckusick /*
55553905Smckusick * Transmitter enable / transmit character size / RTS / DTR / BREAK
55653905Smckusick */
55753905Smckusick bit = (param & TXE ? W5_TxE : 0);
55853905Smckusick switch (param & CHAR_SIZE) {
55953905Smckusick
56053905Smckusick case C5BIT:
56153905Smckusick break;
56253905Smckusick
56353905Smckusick case C6BIT:
56453905Smckusick bit |= W5_Tx6BIT;
56553905Smckusick break;
56653905Smckusick
56753905Smckusick case C7BIT:
56853905Smckusick bit |= W5_Tx7BIT;
56953905Smckusick break;
57053905Smckusick
57153905Smckusick case C8BIT:
57253905Smckusick bit |= W5_Tx8BIT;
57353905Smckusick break;
57453905Smckusick }
57553905Smckusick if (param & RTS)
57653905Smckusick bit |= W5_RTS;
57753905Smckusick if (param & DTR)
57853905Smckusick bit |= W5_DTR;
57953905Smckusick if (param & XBREAK)
58053905Smckusick bit |= W5_BREAK;
58153905Smckusick scc_write_reg(chan, WR5, bit);
58253905Smckusick scc->scc_param = param;
58353905Smckusick (void) splx(s);
58453905Smckusick return (0);
58553905Smckusick }
58653905Smckusick
scc_get_param(chan)58753905Smckusick scc_get_param(chan)
58853905Smckusick int chan;
58953905Smckusick {
59053905Smckusick register Scc_channel *scc = &sccsw[chan];
59153905Smckusick
59253905Smckusick scc->scc_param = (scc->scc_param & ~(RI|DSR)) | get_ri_dsr(chan);
59353905Smckusick return (scc->scc_param);
59453905Smckusick }
59553905Smckusick
scc_get_status(chan)59653905Smckusick scc_get_status(chan)
59753905Smckusick int chan;
59853905Smckusick {
59953905Smckusick
60053905Smckusick return (sccsw[chan].scc_status);
60153905Smckusick }
60253905Smckusick
scc_set_status(chan,stat)60353905Smckusick scc_set_status(chan, stat)
60453905Smckusick int chan, stat;
60553905Smckusick {
60653905Smckusick
60753905Smckusick sccsw[chan].scc_status = stat;
60853905Smckusick
60953905Smckusick return (0);
61053905Smckusick }
61153905Smckusick
scc_flush(chan)61253905Smckusick scc_flush(chan)
61353905Smckusick int chan;
61453905Smckusick {
61553905Smckusick register Scc_channel *scc = &sccsw[chan];
61653905Smckusick
61753905Smckusick if (scc->scc_status & OACTIVE)
61853905Smckusick scc->scc_status |= OFLUSH;
61953905Smckusick else if (scc->x_dma.dma_count > 0) {
62053905Smckusick scc->x_dma.dma_count = 0;
62153905Smckusick #if NRS > 0
62253905Smckusick rsxint(chan);
62353905Smckusick #endif
62453905Smckusick }
62553905Smckusick return (0);
62653905Smckusick }
62753905Smckusick
scc_start(chan)62853905Smckusick scc_start(chan)
62953905Smckusick int chan;
63053905Smckusick {
63153905Smckusick register Scc_channel *scc = &sccsw[chan];
63253905Smckusick
63353905Smckusick if ((scc->scc_status & OACTIVE) == 0 && scc->x_dma.dma_count > 0) {
63453905Smckusick scc->scc_port->data = *(scc->x_dma.dma_addr)++;
63553905Smckusick SCCWAIT;
63653905Smckusick scc->x_dma.dma_count--;
63753905Smckusick scc->scc_status |= OACTIVE;
63853905Smckusick }
63953905Smckusick return (0);
64053905Smckusick }
64153905Smckusick
scc_stop(chan)64253905Smckusick scc_stop(chan)
64353905Smckusick int chan;
64453905Smckusick {
64553905Smckusick register Scc_channel *scc = &sccsw[chan];
64653905Smckusick
64753905Smckusick if (scc->scc_status & OACTIVE)
64853905Smckusick scc->scc_status |= OSTOP;
64953905Smckusick return (0);
65053905Smckusick }
65153905Smckusick
scc_write(chan,buf,count)65253905Smckusick scc_write(chan, buf, count)
65353905Smckusick int chan;
65453905Smckusick caddr_t buf;
65553905Smckusick int count;
65653905Smckusick {
65753905Smckusick register Scc_channel *scc = &sccsw[chan];
65853905Smckusick
65953905Smckusick if (count <= 0)
66053905Smckusick return (0);
66153905Smckusick scc->x_dma.dma_addr = buf;
66253905Smckusick scc->x_dma.dma_count = count;
66353905Smckusick scc_start(chan);
66453905Smckusick return (count);
66553905Smckusick }
66653905Smckusick
scc_error_write(chan,buf,count)66753905Smckusick scc_error_write(chan, buf, count)
66853905Smckusick int chan;
66953905Smckusick register char *buf;
67053905Smckusick register int count;
67153905Smckusick {
67253905Smckusick register int i;
67353905Smckusick
67453905Smckusick for (i = 0; i < count; i++)
67553905Smckusick scc_putc(chan, *buf++);
67653905Smckusick return (i);
67753905Smckusick }
67853905Smckusick
scc_reset(chan)67953905Smckusick scc_reset(chan)
68053905Smckusick int chan;
68153905Smckusick {
68253905Smckusick register Scc_channel *scc = &sccsw[chan];
68353905Smckusick
68453905Smckusick while (scc_getc(chan) != -1)
68553905Smckusick ;
68653905Smckusick scc->scc_status &= ~CHAN_ACTIVE;
68753905Smckusick }
688