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