156817Sralph /*- 256817Sralph * Copyright (c) 1992 The Regents of the University of California. 356817Sralph * All rights reserved. 456817Sralph * 556817Sralph * This code is derived from software contributed to Berkeley by 656817Sralph * Ralph Campbell and Rick Macklem. 756817Sralph * 856817Sralph * %sccs.include.redist.c% 956817Sralph * 10*57234Sralph * @(#)scc.c 7.2 (Berkeley) 12/20/92 1156817Sralph */ 1256817Sralph 1356817Sralph /* 1456817Sralph * Mach Operating System 1556817Sralph * Copyright (c) 1991,1990,1989 Carnegie Mellon University 1656817Sralph * All Rights Reserved. 1756817Sralph * 1856817Sralph * Permission to use, copy, modify and distribute this software and its 1956817Sralph * documentation is hereby granted, provided that both the copyright 2056817Sralph * notice and this permission notice appear in all copies of the 2156817Sralph * software, derivative works or modified versions, and any portions 2256817Sralph * thereof, and that both notices appear in supporting documentation. 2356817Sralph * 2456817Sralph * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 2556817Sralph * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 2656817Sralph * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 2756817Sralph * 2856817Sralph * Carnegie Mellon requests users of this software to return to 2956817Sralph * 3056817Sralph * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 3156817Sralph * School of Computer Science 3256817Sralph * Carnegie Mellon University 3356817Sralph * Pittsburgh PA 15213-3890 3456817Sralph * 3556817Sralph * any improvements or extensions that they make and grant Carnegie the 3656817Sralph * rights to redistribute these changes. 3756817Sralph */ 3856817Sralph 3956817Sralph #include <scc.h> 4056817Sralph #if NSCC > 0 4156817Sralph /* 4256817Sralph * Intel 82530 dual usart chip driver. Supports the serial port(s) on the 4356817Sralph * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard 4456817Sralph * and mouse on the 5000/1xx. (Don't ask me where the A channel signals 4556817Sralph * are on the 5000/xx.) 4656817Sralph * 4756817Sralph * See: Intel MicroCommunications Handbook, Section 2, pg. 155-173, 1992. 4856817Sralph */ 4956817Sralph #include <sys/param.h> 5056817Sralph #include <sys/systm.h> 5156817Sralph #include <sys/ioctl.h> 5256817Sralph #include <sys/tty.h> 5356817Sralph #include <sys/proc.h> 5456817Sralph #include <sys/map.h> 5556817Sralph #include <sys/buf.h> 5656817Sralph #include <sys/conf.h> 5756817Sralph #include <sys/file.h> 5856817Sralph #include <sys/uio.h> 5956817Sralph #include <sys/kernel.h> 6056817Sralph #include <sys/syslog.h> 6156817Sralph 6256817Sralph #include <machine/pmioctl.h> 6356817Sralph 6456817Sralph #include <pmax/dev/device.h> 6556817Sralph #include <pmax/dev/pdma.h> 6656817Sralph #include <pmax/dev/sccreg.h> 6756817Sralph #include <pmax/dev/fbreg.h> 6856817Sralph 6956817Sralph #include <pmax/pmax/cons.h> 7056817Sralph #include <pmax/pmax/pmaxtype.h> 7156817Sralph 7256817Sralph extern int pmax_boardtype; 7356817Sralph extern struct consdev cn_tab; 7456817Sralph extern void ttrstrt __P((void *)); 7556817Sralph extern void KBDReset __P((dev_t, void (*)())); 7656817Sralph extern void MouseInit __P((dev_t, void (*)(), int (*)())); 7756817Sralph 7856817Sralph /* 7956817Sralph * Driver information for auto-configuration stuff. 8056817Sralph */ 8156817Sralph int sccprobe(), sccopen(), sccparam(), sccGetc(); 8256817Sralph void sccintr(), sccstart(), sccPutc(); 8356817Sralph struct driver sccdriver = { 8456817Sralph "scc", sccprobe, 0, 0, sccintr, 8556817Sralph }; 8656817Sralph 8756817Sralph #define NSCCLINE (NSCC*2) 8856817Sralph #define SCCUNIT(dev) (minor(dev) >> 1) 8956817Sralph #define SCCLINE(dev) (minor(dev) & 0x1) 9056817Sralph 9156817Sralph struct tty scc_tty[NSCCLINE]; 9256817Sralph void (*sccDivertXInput)(); /* X windows keyboard input routine */ 9356817Sralph void (*sccMouseEvent)(); /* X windows mouse motion event routine */ 9456817Sralph void (*sccMouseButtons)(); /* X windows mouse buttons event routine */ 9556817Sralph #ifdef DEBUG 9656817Sralph int debugChar; 9756817Sralph #endif 9856817Sralph static void scc_modem_intr(), sccreset(); 9956817Sralph 10056817Sralph struct scc_softc { 10156817Sralph struct pdma scc_pdma[2]; 10256817Sralph struct { 10356817Sralph u_char wr1; 10456817Sralph u_char wr3; 10556817Sralph u_char wr4; 10656817Sralph u_char wr5; 10756817Sralph u_char wr14; 10856817Sralph } scc_wreg[2]; 10956817Sralph int scc_softCAR; 11056817Sralph } scc_softc[NSCC]; 11156817Sralph 11256817Sralph struct speedtab sccspeedtab[] = { 11356817Sralph 0, 0, 11456817Sralph 50, 4606, 11556817Sralph 75, 3070, 11656817Sralph 110, 2093, 11756817Sralph 134, 1711, 11856817Sralph 150, 1534, 11956817Sralph 300, 766, 12056817Sralph 600, 382, 12156817Sralph 1200, 190, 12256817Sralph 1800, 126, 12356817Sralph 2400, 94, 12456817Sralph 4800, 46, 12556817Sralph 9600, 22, 12656817Sralph 19200, 10, 12756817Sralph 38400, 4, 12856817Sralph -1, -1 12956817Sralph }; 13056817Sralph 13156817Sralph #ifndef PORTSELECTOR 13256817Sralph #define ISPEED TTYDEF_SPEED 13356817Sralph #define LFLAG TTYDEF_LFLAG 13456817Sralph #else 13556817Sralph #define ISPEED B4800 13656817Sralph #define LFLAG (TTYDEF_LFLAG & ~ECHO) 13756817Sralph #endif 13856817Sralph 13956817Sralph /* 14056817Sralph * Test to see if device is present. 14156817Sralph * Return true if found and initialized ok. 14256817Sralph */ 14356817Sralph sccprobe(cp) 14456817Sralph register struct pmax_ctlr *cp; 14556817Sralph { 14656817Sralph register struct scc_softc *sc; 14756817Sralph register struct pdma *pdp; 14856817Sralph register struct tty *tp; 14956817Sralph register int cntr; 15056817Sralph struct tty ctty; 15156817Sralph struct termios cterm; 15256817Sralph int s; 15356817Sralph 15456817Sralph if (cp->pmax_unit >= NSCC) 15556817Sralph return (0); 15656817Sralph if (badaddr(cp->pmax_addr, 2)) 15756817Sralph return (0); 15856817Sralph 159*57234Sralph /* 160*57234Sralph * For a remote console, wait a while for previous output to 161*57234Sralph * complete. 162*57234Sralph */ 163*57234Sralph if (major(cn_tab.cn_dev) == SCCDEV && cn_tab.cn_screen == 0 && 164*57234Sralph SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) 165*57234Sralph DELAY(10000); 166*57234Sralph 16756817Sralph sc = &scc_softc[cp->pmax_unit]; 16856817Sralph pdp = &sc->scc_pdma[0]; 16956817Sralph 17056817Sralph /* init pseudo DMA structures */ 17156817Sralph tp = &scc_tty[cp->pmax_unit * 2]; 17256817Sralph for (cntr = 0; cntr < 2; cntr++) { 17356817Sralph pdp->p_addr = (void *)cp->pmax_addr; 17456817Sralph pdp->p_arg = (int)tp; 17556817Sralph pdp->p_fcn = (void (*)())0; 17656817Sralph tp->t_addr = (caddr_t)pdp; 17756817Sralph tp->t_dev = (dev_t)((cp->pmax_unit << 1) | cntr); 17856817Sralph pdp++, tp++; 17956817Sralph } 18056817Sralph sc->scc_softCAR = cp->pmax_flags | 0x2; 18156817Sralph 18256817Sralph /* reset chip */ 18356817Sralph sccreset(sc); 18456817Sralph 18556817Sralph /* 18656817Sralph * Special handling for consoles. 18756817Sralph */ 18856817Sralph if (cn_tab.cn_screen) { 18956817Sralph if (cn_tab.cn_kbdgetc == sccGetc) { 19056817Sralph if (cp->pmax_unit == 0) { 19156817Sralph s = spltty(); 19256817Sralph ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); 19356817Sralph cterm.c_cflag = CS8; 19456817Sralph cterm.c_ospeed = cterm.c_ispeed = 4800; 19556817Sralph (void) sccparam(&ctty, &cterm); 196*57234Sralph DELAY(1000); 19756817Sralph KBDReset(ctty.t_dev, sccPutc); 19856817Sralph splx(s); 19956817Sralph } else if (cp->pmax_unit == 1) { 20056817Sralph s = spltty(); 20156817Sralph ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); 20256817Sralph cterm.c_cflag = CS8 | PARENB | PARODD; 20356817Sralph cterm.c_ospeed = cterm.c_ispeed = 4800; 20456817Sralph (void) sccparam(&ctty, &cterm); 205*57234Sralph DELAY(1000); 20656817Sralph MouseInit(ctty.t_dev, sccPutc, sccGetc); 20756817Sralph splx(s); 20856817Sralph } 20956817Sralph } 21056817Sralph } else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) { 21156817Sralph s = spltty(); 21256817Sralph ctty.t_dev = cn_tab.cn_dev; 21356817Sralph cterm.c_cflag = CS8; 21456817Sralph cterm.c_ospeed = cterm.c_ispeed = 9600; 21556817Sralph (void) sccparam(&ctty, &cterm); 216*57234Sralph DELAY(1000); 21756817Sralph cn_tab.cn_disabled = 0; 21856817Sralph splx(s); 21956817Sralph } 220*57234Sralph printf("scc%d at nexus0 csr 0x%x priority %d\n", 221*57234Sralph cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 22256817Sralph return (1); 22356817Sralph } 22456817Sralph 22556817Sralph /* 22656817Sralph * Reset the chip. 22756817Sralph */ 22856817Sralph static void 22956817Sralph sccreset(sc) 23056817Sralph register struct scc_softc *sc; 23156817Sralph { 23256817Sralph register scc_regmap_t *regs; 23356817Sralph register u_char val; 23456817Sralph 23556817Sralph regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 23656817Sralph /* 23756817Sralph * Chip once-only initialization 23856817Sralph * 23956817Sralph * NOTE: The wiring we assume is the one on the 3min: 24056817Sralph * 24156817Sralph * out A-TxD --> TxD keybd or mouse 24256817Sralph * in A-RxD --> RxD keybd or mouse 24356817Sralph * out A-DTR~ --> DTR comm 24456817Sralph * out A-RTS~ --> RTS comm 24556817Sralph * in A-CTS~ --> SI comm 24656817Sralph * in A-DCD~ --> RI comm 24756817Sralph * in A-SYNCH~--> DSR comm 24856817Sralph * out B-TxD --> TxD comm 24956817Sralph * in B-RxD --> RxD comm 25056817Sralph * in B-RxC --> TRxCB comm 25156817Sralph * in B-TxC --> RTxCB comm 25256817Sralph * out B-RTS~ --> SS comm 25356817Sralph * in B-CTS~ --> CTS comm 25456817Sralph * in B-DCD~ --> CD comm 25556817Sralph */ 25656817Sralph SCC_INIT_REG(regs, SCC_CHANNEL_A); 25756817Sralph SCC_INIT_REG(regs, SCC_CHANNEL_B); 25856817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET); 25956817Sralph DELAY(50000); /*enough ? */ 26056817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0); 26156817Sralph 26256817Sralph /* program the interrupt vector */ 26356817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0); 26456817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0); 26556817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS); 26656817Sralph 26756817Sralph /* timing base defaults */ 26856817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16; 26956817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16; 27056817Sralph 27156817Sralph /* enable DTR, RTS and SS */ 27256817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS; 27356817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR; 27456817Sralph 27556817Sralph /* baud rates */ 27656817Sralph val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC; 27756817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr14 = val; 27856817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr14 = val; 27956817Sralph 28056817Sralph /* interrupt conditions */ 28156817Sralph val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE | 282*57234Sralph SCC_WR1_EXT_IE; 28356817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr1 = val; 28456817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr1 = val; 28556817Sralph } 28656817Sralph 28756817Sralph sccopen(dev, flag, mode, p) 28856817Sralph dev_t dev; 28956817Sralph int flag, mode; 29056817Sralph struct proc *p; 29156817Sralph { 29256817Sralph register struct scc_softc *sc; 29356817Sralph register struct tty *tp; 29456817Sralph register int unit, line; 29556817Sralph int s, error = 0; 29656817Sralph 29756817Sralph unit = SCCUNIT(dev); 29856817Sralph if (unit >= NSCC) 29956817Sralph return (ENXIO); 30056817Sralph line = SCCLINE(dev); 30156817Sralph sc = &scc_softc[unit]; 30256817Sralph if (sc->scc_pdma[line].p_addr == (void *)0) 30356817Sralph return (ENXIO); 30456817Sralph tp = &scc_tty[minor(dev)]; 30556817Sralph tp->t_addr = (caddr_t)&sc->scc_pdma[line]; 30656817Sralph tp->t_oproc = sccstart; 30756817Sralph tp->t_param = sccparam; 30856817Sralph tp->t_dev = dev; 30956817Sralph if ((tp->t_state & TS_ISOPEN) == 0) { 31056817Sralph tp->t_state |= TS_WOPEN; 31156817Sralph ttychars(tp); 31256817Sralph #ifndef PORTSELECTOR 31356817Sralph if (tp->t_ispeed == 0) { 31456817Sralph #endif 31556817Sralph tp->t_iflag = TTYDEF_IFLAG; 31656817Sralph tp->t_oflag = TTYDEF_OFLAG; 31756817Sralph tp->t_cflag = TTYDEF_CFLAG; 31856817Sralph tp->t_lflag = LFLAG; 31956817Sralph tp->t_ispeed = tp->t_ospeed = ISPEED; 32056817Sralph #ifdef PORTSELECTOR 32156817Sralph tp->t_cflag |= HUPCL; 32256817Sralph #else 32356817Sralph } 32456817Sralph #endif 32556817Sralph (void) sccparam(tp, &tp->t_termios); 32656817Sralph ttsetwater(tp); 32756817Sralph } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 32856817Sralph return (EBUSY); 32956817Sralph (void) sccmctl(dev, DML_DTR, DMSET); 33056817Sralph s = spltty(); 33156817Sralph while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 33256817Sralph !(tp->t_state & TS_CARR_ON)) { 33356817Sralph tp->t_state |= TS_WOPEN; 33456817Sralph if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 33556817Sralph ttopen, 0)) 33656817Sralph break; 33756817Sralph } 33856817Sralph splx(s); 33956817Sralph if (error) 34056817Sralph return (error); 34156817Sralph return ((*linesw[tp->t_line].l_open)(dev, tp)); 34256817Sralph } 34356817Sralph 34456817Sralph /*ARGSUSED*/ 34556817Sralph sccclose(dev, flag, mode, p) 34656817Sralph dev_t dev; 34756817Sralph int flag, mode; 34856817Sralph struct proc *p; 34956817Sralph { 35056817Sralph register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)]; 35156817Sralph register struct tty *tp; 35256817Sralph register int bit, line; 35356817Sralph 35456817Sralph tp = &scc_tty[minor(dev)]; 35556817Sralph line = SCCLINE(dev); 35656817Sralph if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) { 35756817Sralph sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 35856817Sralph ttyoutput(0, tp); 35956817Sralph } 36056817Sralph (*linesw[tp->t_line].l_close)(tp, flag); 36156817Sralph if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 36256817Sralph !(tp->t_state & TS_ISOPEN)) 36356817Sralph (void) sccmctl(dev, 0, DMSET); 36456817Sralph return (ttyclose(tp)); 36556817Sralph } 36656817Sralph 36756817Sralph sccread(dev, uio, flag) 36856817Sralph dev_t dev; 36956817Sralph struct uio *uio; 37056817Sralph { 37156817Sralph register struct tty *tp; 37256817Sralph 37356817Sralph tp = &scc_tty[minor(dev)]; 37456817Sralph return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 37556817Sralph } 37656817Sralph 37756817Sralph sccwrite(dev, uio, flag) 37856817Sralph dev_t dev; 37956817Sralph struct uio *uio; 38056817Sralph { 38156817Sralph register struct tty *tp; 38256817Sralph 38356817Sralph tp = &scc_tty[minor(dev)]; 38456817Sralph return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 38556817Sralph } 38656817Sralph 38756817Sralph /*ARGSUSED*/ 38856817Sralph sccioctl(dev, cmd, data, flag, p) 38956817Sralph dev_t dev; 39056817Sralph int cmd; 39156817Sralph caddr_t data; 39256817Sralph int flag; 39356817Sralph struct proc *p; 39456817Sralph { 39556817Sralph register struct scc_softc *sc; 39656817Sralph register struct tty *tp; 39756817Sralph int error, line; 39856817Sralph 39956817Sralph tp = &scc_tty[minor(dev)]; 40056817Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 40156817Sralph if (error >= 0) 40256817Sralph return (error); 40356817Sralph error = ttioctl(tp, cmd, data, flag); 40456817Sralph if (error >= 0) 40556817Sralph return (error); 40656817Sralph 40756817Sralph line = SCCLINE(dev); 40856817Sralph sc = &scc_softc[SCCUNIT(dev)]; 40956817Sralph switch (cmd) { 41056817Sralph 41156817Sralph case TIOCSBRK: 41256817Sralph sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK; 41356817Sralph ttyoutput(0, tp); 41456817Sralph break; 41556817Sralph 41656817Sralph case TIOCCBRK: 41756817Sralph sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 41856817Sralph ttyoutput(0, tp); 41956817Sralph break; 42056817Sralph 42156817Sralph case TIOCSDTR: 42256817Sralph (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS); 42356817Sralph break; 42456817Sralph 42556817Sralph case TIOCCDTR: 42656817Sralph (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC); 42756817Sralph break; 42856817Sralph 42956817Sralph case TIOCMSET: 43056817Sralph (void) sccmctl(dev, *(int *)data, DMSET); 43156817Sralph break; 43256817Sralph 43356817Sralph case TIOCMBIS: 43456817Sralph (void) sccmctl(dev, *(int *)data, DMBIS); 43556817Sralph break; 43656817Sralph 43756817Sralph case TIOCMBIC: 43856817Sralph (void) sccmctl(dev, *(int *)data, DMBIC); 43956817Sralph break; 44056817Sralph 44156817Sralph case TIOCMGET: 44256817Sralph *(int *)data = sccmctl(dev, 0, DMGET); 44356817Sralph break; 44456817Sralph 44556817Sralph default: 44656817Sralph return (ENOTTY); 44756817Sralph } 44856817Sralph return (0); 44956817Sralph } 45056817Sralph 45156817Sralph sccparam(tp, t) 45256817Sralph register struct tty *tp; 45356817Sralph register struct termios *t; 45456817Sralph { 45556817Sralph register struct scc_softc *sc; 45656817Sralph register scc_regmap_t *regs; 45756817Sralph register int line; 45856817Sralph register u_char value, wvalue; 45956817Sralph register int cflag = t->c_cflag; 46056817Sralph int ospeed; 46156817Sralph 46256817Sralph if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 46356817Sralph return (EINVAL); 46456817Sralph sc = &scc_softc[SCCUNIT(tp->t_dev)]; 46556817Sralph line = SCCLINE(tp->t_dev); 46656817Sralph regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 46756817Sralph ospeed = ttspeedtab(t->c_ospeed, sccspeedtab); 46856817Sralph if (ospeed < 0) 46956817Sralph return (EINVAL); 47056817Sralph /* and copy to tty */ 47156817Sralph tp->t_ispeed = t->c_ispeed; 47256817Sralph tp->t_ospeed = t->c_ospeed; 47356817Sralph tp->t_cflag = cflag; 47456817Sralph 47556817Sralph /* 47656817Sralph * Handle console specially. 47756817Sralph */ 47856817Sralph if (cn_tab.cn_screen) { 47956817Sralph if (minor(tp->t_dev) == SCCKBD_PORT) { 48056817Sralph cflag = CS8; 48156817Sralph ospeed = ttspeedtab(4800, sccspeedtab); 48256817Sralph } else if (minor(tp->t_dev) == SCCMOUSE_PORT) { 48356817Sralph cflag = CS8 | PARENB | PARODD; 48456817Sralph ospeed = ttspeedtab(4800, sccspeedtab); 48556817Sralph } 48656817Sralph } else if (tp->t_dev == cn_tab.cn_dev) { 48756817Sralph cflag = CS8; 48856817Sralph ospeed = ttspeedtab(9600, sccspeedtab); 48956817Sralph } 49056817Sralph if (ospeed == 0) { 49156817Sralph (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */ 49256817Sralph return (0); 49356817Sralph } 49456817Sralph 49556817Sralph /* reset line */ 49656817Sralph if (line == SCC_CHANNEL_A) 49756817Sralph value = SCC_WR9_RESET_CHA_A; 49856817Sralph else 49956817Sralph value = SCC_WR9_RESET_CHA_B; 50056817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, value); 50156817Sralph DELAY(25); 50256817Sralph 50356817Sralph /* stop bits, normally 1 */ 50456817Sralph value = sc->scc_wreg[line].wr4 & 0xf0; 50556817Sralph if (cflag & CSTOPB) 50656817Sralph value |= SCC_WR4_2_STOP; 50756817Sralph else 50856817Sralph value |= SCC_WR4_1_STOP; 50956817Sralph if ((cflag & PARODD) == 0) 51056817Sralph value |= SCC_WR4_EVEN_PARITY; 51156817Sralph if (cflag & PARENB) 51256817Sralph value |= SCC_WR4_PARITY_ENABLE; 51356817Sralph 51456817Sralph /* set it now, remember it must be first after reset */ 51556817Sralph sc->scc_wreg[line].wr4 = value; 51656817Sralph SCC_WRITE_REG(regs, line, SCC_WR4, value); 51756817Sralph 51856817Sralph /* vector again */ 51956817Sralph SCC_WRITE_REG(regs, line, SCC_WR2, 0xf0); 52056817Sralph 52156817Sralph /* clear break, keep rts dtr */ 52256817Sralph wvalue = sc->scc_wreg[line].wr5 & (SCC_WR5_DTR|SCC_WR5_RTS); 52356817Sralph switch (cflag & CSIZE) { 52456817Sralph case CS5: 52556817Sralph value = SCC_WR3_RX_5_BITS; 52656817Sralph wvalue |= SCC_WR5_TX_5_BITS; 52756817Sralph break; 52856817Sralph case CS6: 52956817Sralph value = SCC_WR3_RX_6_BITS; 53056817Sralph wvalue |= SCC_WR5_TX_6_BITS; 53156817Sralph break; 53256817Sralph case CS7: 53356817Sralph value = SCC_WR3_RX_7_BITS; 53456817Sralph wvalue |= SCC_WR5_TX_7_BITS; 53556817Sralph break; 53656817Sralph case CS8: 53756817Sralph default: 53856817Sralph value = SCC_WR3_RX_8_BITS; 53956817Sralph wvalue |= SCC_WR5_TX_8_BITS; 54056817Sralph }; 54156817Sralph sc->scc_wreg[line].wr3 = value; 54256817Sralph SCC_WRITE_REG(regs, line, SCC_WR3, value); 54356817Sralph sc->scc_wreg[line].wr5 = wvalue; 54456817Sralph SCC_WRITE_REG(regs, line, SCC_WR5, wvalue); 54556817Sralph SCC_WRITE_REG(regs, line, SCC_WR6, 0); 54656817Sralph SCC_WRITE_REG(regs, line, SCC_WR7, 0); 54756817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, SCC_WR9_VIS); 54856817Sralph SCC_WRITE_REG(regs, line, SCC_WR10, 0); 54956817Sralph value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR | 55056817Sralph SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR; 55156817Sralph SCC_WRITE_REG(regs, line, SCC_WR11, value); 55256817Sralph SCC_SET_TIMING_BASE(regs, line, ospeed); 55356817Sralph value = sc->scc_wreg[line].wr14; 55456817Sralph SCC_WRITE_REG(regs, line, SCC_WR14, value); 55556817Sralph value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE; 55656817Sralph SCC_WRITE_REG(regs, line, SCC_WR15, value); 55756817Sralph 55856817Sralph /* and now the enables */ 55956817Sralph value = sc->scc_wreg[line].wr3 | SCC_WR3_RX_ENABLE; 56056817Sralph SCC_WRITE_REG(regs, line, SCC_WR3, value); 56156817Sralph value = sc->scc_wreg[line].wr5 | SCC_WR5_TX_ENABLE; 56256817Sralph sc->scc_wreg[line].wr5 = value; 56356817Sralph SCC_WRITE_REG(regs, line, SCC_WR5, value); 56456817Sralph 56556817Sralph /* master inter enable */ 56656817Sralph value = SCC_WR9_MASTER_IE | SCC_WR9_VIS; 56756817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, value); 56856817Sralph SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); 56956817Sralph MachEmptyWriteBuffer(); 57056817Sralph return (0); 57156817Sralph } 57256817Sralph 57356817Sralph /* 57456817Sralph * Check for interrupts from all devices. 57556817Sralph */ 57656817Sralph void 57756817Sralph sccintr(unit) 57856817Sralph register int unit; 57956817Sralph { 58056817Sralph register scc_regmap_t *regs; 58156817Sralph register struct tty *tp; 58256817Sralph register struct pdma *dp; 58356817Sralph register struct scc_softc *sc; 58456817Sralph register int cc, chan, rr1, rr2, rr3; 58556817Sralph int overrun = 0; 58656817Sralph 58756817Sralph sc = &scc_softc[unit]; 58856817Sralph regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 58956817Sralph unit <<= 1; 59056817Sralph for (;;) { 59156817Sralph SCC_READ_REG(regs, SCC_CHANNEL_B, SCC_RR2, rr2); 59256817Sralph rr2 = SCC_RR2_STATUS(rr2); 59356817Sralph /* are we done yet ? */ 59456817Sralph if (rr2 == 6) { /* strange, distinguished value */ 59556817Sralph SCC_READ_REG(regs, SCC_CHANNEL_A, SCC_RR3, rr3); 59656817Sralph if (rr3 == 0) 59756817Sralph return; 59856817Sralph } 59956817Sralph 60056817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); 60156817Sralph if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { 60256817Sralph chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? 60356817Sralph SCC_CHANNEL_A : SCC_CHANNEL_B; 60456817Sralph tp = &scc_tty[unit | chan]; 60556817Sralph dp = (struct pdma *)tp->t_addr; 60656817Sralph if (dp->p_mem < dp->p_end) { 60756817Sralph SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 60856817Sralph MachEmptyWriteBuffer(); 60956817Sralph } else { 61056817Sralph tp->t_state &= ~TS_BUSY; 61156817Sralph if (tp->t_state & TS_FLUSH) 61256817Sralph tp->t_state &= ~TS_FLUSH; 61356817Sralph else { 61456817Sralph ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 61556817Sralph dp->p_end = dp->p_mem = tp->t_outq.c_cf; 61656817Sralph } 61756817Sralph if (tp->t_line) 61856817Sralph (*linesw[tp->t_line].l_start)(tp); 61956817Sralph else 62056817Sralph sccstart(tp); 62156817Sralph if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 62256817Sralph SCC_READ_REG(regs, chan, SCC_RR15, cc); 62356817Sralph cc &= ~SCC_WR15_TX_UNDERRUN_IE; 62456817Sralph SCC_WRITE_REG(regs, chan, SCC_WR15, cc); 62556817Sralph cc = sc->scc_wreg[chan].wr1 & ~SCC_WR1_TX_IE; 62656817Sralph SCC_WRITE_REG(regs, chan, SCC_WR1, cc); 62756817Sralph sc->scc_wreg[chan].wr1 = cc; 62856817Sralph MachEmptyWriteBuffer(); 62956817Sralph } 63056817Sralph } 631*57234Sralph } else if (rr2 == SCC_RR2_A_RECV_DONE || 632*57234Sralph rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL || 633*57234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 634*57234Sralph if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL) 635*57234Sralph chan = SCC_CHANNEL_A; 636*57234Sralph else 637*57234Sralph chan = SCC_CHANNEL_B; 638*57234Sralph tp = &scc_tty[unit | chan]; 639*57234Sralph SCC_READ_DATA(regs, chan, cc); 640*57234Sralph if (rr2 == SCC_RR2_A_RECV_SPECIAL || 641*57234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 642*57234Sralph SCC_READ_REG(regs, chan, SCC_RR1, rr1); 643*57234Sralph SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_ERROR); 644*57234Sralph if ((rr1 & SCC_RR1_RX_OVERRUN) && overrun == 0) { 645*57234Sralph log(LOG_WARNING, "scc%d,%d: silo overflow\n", 646*57234Sralph unit >> 1, chan); 647*57234Sralph overrun = 1; 648*57234Sralph } 649*57234Sralph } 65056817Sralph 65156817Sralph /* 65256817Sralph * Keyboard needs special treatment. 65356817Sralph */ 65456817Sralph if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 65556817Sralph #ifdef KADB 65656817Sralph if (cc == LK_DO) { 65756817Sralph spl0(); 65856817Sralph kdbpanic(); 65956817Sralph return; 66056817Sralph } 66156817Sralph #endif 66256817Sralph #ifdef DEBUG 66356817Sralph debugChar = cc; 66456817Sralph #endif 66556817Sralph if (sccDivertXInput) { 66656817Sralph (*sccDivertXInput)(cc); 66756817Sralph continue; 66856817Sralph } 66956817Sralph if ((cc = kbdMapChar(cc)) < 0) 67056817Sralph continue; 67156817Sralph /* 67256817Sralph * Now for mousey 67356817Sralph */ 67456817Sralph } else if (tp == &scc_tty[SCCMOUSE_PORT] && sccMouseButtons) { 67556817Sralph register MouseReport *mrp; 67656817Sralph static MouseReport currentRep; 67756817Sralph 67856817Sralph mrp = ¤tRep; 67956817Sralph mrp->byteCount++; 68056817Sralph if (cc & MOUSE_START_FRAME) { 68156817Sralph /* 68256817Sralph * The first mouse report byte (button state). 68356817Sralph */ 68456817Sralph mrp->state = cc; 68556817Sralph if (mrp->byteCount > 1) 68656817Sralph mrp->byteCount = 1; 68756817Sralph } else if (mrp->byteCount == 2) { 68856817Sralph /* 68956817Sralph * The second mouse report byte (delta x). 69056817Sralph */ 69156817Sralph mrp->dx = cc; 69256817Sralph } else if (mrp->byteCount == 3) { 69356817Sralph /* 69456817Sralph * The final mouse report byte (delta y). 69556817Sralph */ 69656817Sralph mrp->dy = cc; 69756817Sralph mrp->byteCount = 0; 69856817Sralph if (mrp->dx != 0 || mrp->dy != 0) { 69956817Sralph /* 70056817Sralph * If the mouse moved, 70156817Sralph * post a motion event. 70256817Sralph */ 70356817Sralph (*sccMouseEvent)(mrp); 70456817Sralph } 70556817Sralph (*sccMouseButtons)(mrp); 70656817Sralph } 70756817Sralph continue; 70856817Sralph } 70956817Sralph if (!(tp->t_state & TS_ISOPEN)) { 71056817Sralph wakeup((caddr_t)&tp->t_rawq); 71156817Sralph #ifdef PORTSELECTOR 71256817Sralph if (!(tp->t_state & TS_WOPEN)) 71356817Sralph #endif 71456817Sralph continue; 71556817Sralph } 716*57234Sralph if (rr2 == SCC_RR2_A_RECV_SPECIAL || 717*57234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 718*57234Sralph if (rr1 & SCC_RR1_PARITY_ERR) 719*57234Sralph cc |= TTY_PE; 720*57234Sralph if (rr1 & SCC_RR1_FRAME_ERR) 721*57234Sralph cc |= TTY_FE; 72256817Sralph } 72356817Sralph (*linesw[tp->t_line].l_rint)(cc, tp); 72456817Sralph } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { 72556817Sralph chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? 72656817Sralph SCC_CHANNEL_A : SCC_CHANNEL_B; 72756817Sralph SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_EXT_IP); 72856817Sralph scc_modem_intr(unit | chan); 72956817Sralph } 73056817Sralph } 73156817Sralph } 73256817Sralph 73356817Sralph void 73456817Sralph sccstart(tp) 73556817Sralph register struct tty *tp; 73656817Sralph { 73756817Sralph register struct pdma *dp; 73856817Sralph register scc_regmap_t *regs; 73956817Sralph register struct scc_softc *sc; 74056817Sralph register int cc, chan; 74156817Sralph u_char temp; 742*57234Sralph int s, sendone; 74356817Sralph 74456817Sralph dp = (struct pdma *)tp->t_addr; 74556817Sralph regs = (scc_regmap_t *)dp->p_addr; 74656817Sralph sc = &scc_softc[SCCUNIT(tp->t_dev)]; 74756817Sralph s = spltty(); 74856817Sralph if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 74956817Sralph goto out; 75056817Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 75156817Sralph if (tp->t_state & TS_ASLEEP) { 75256817Sralph tp->t_state &= ~TS_ASLEEP; 75356817Sralph wakeup((caddr_t)&tp->t_outq); 75456817Sralph } 75556817Sralph selwakeup(&tp->t_wsel); 75656817Sralph } 75756817Sralph if (tp->t_outq.c_cc == 0) 75856817Sralph goto out; 75956817Sralph /* handle console specially */ 76056817Sralph if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 76156817Sralph while (tp->t_outq.c_cc > 0) { 76256817Sralph cc = getc(&tp->t_outq) & 0x7f; 76356817Sralph cnputc(cc); 76456817Sralph } 76556817Sralph /* 76656817Sralph * After we flush the output queue we may need to wake 76756817Sralph * up the process that made the output. 76856817Sralph */ 76956817Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 77056817Sralph if (tp->t_state & TS_ASLEEP) { 77156817Sralph tp->t_state &= ~TS_ASLEEP; 77256817Sralph wakeup((caddr_t)&tp->t_outq); 77356817Sralph } 77456817Sralph selwakeup(&tp->t_wsel); 77556817Sralph } 77656817Sralph goto out; 77756817Sralph } 77856817Sralph if (tp->t_flags & (RAW|LITOUT)) 77956817Sralph cc = ndqb(&tp->t_outq, 0); 78056817Sralph else { 78156817Sralph cc = ndqb(&tp->t_outq, 0200); 78256817Sralph if (cc == 0) { 78356817Sralph cc = getc(&tp->t_outq); 78456817Sralph timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); 78556817Sralph tp->t_state |= TS_TIMEOUT; 78656817Sralph goto out; 78756817Sralph } 78856817Sralph } 78956817Sralph tp->t_state |= TS_BUSY; 79056817Sralph dp->p_end = dp->p_mem = tp->t_outq.c_cf; 79156817Sralph dp->p_end += cc; 79256817Sralph 79356817Sralph /* 79456817Sralph * Enable transmission and send the first char, as required. 79556817Sralph */ 79656817Sralph chan = SCCLINE(tp->t_dev); 797*57234Sralph SCC_READ_REG(regs, chan, SCC_RR0, temp); 798*57234Sralph sendone = (temp & SCC_RR0_TX_EMPTY); 79956817Sralph SCC_READ_REG(regs, chan, SCC_RR15, temp); 80056817Sralph temp |= SCC_WR15_TX_UNDERRUN_IE; 80156817Sralph SCC_WRITE_REG(regs, chan, SCC_WR15, temp); 80256817Sralph temp = sc->scc_wreg[chan].wr1 | SCC_WR1_TX_IE; 80356817Sralph SCC_WRITE_REG(regs, chan, SCC_WR1, temp); 80456817Sralph sc->scc_wreg[chan].wr1 = temp; 805*57234Sralph if (sendone) { 80656817Sralph #ifdef DIAGNOSTIC 80756817Sralph if (cc == 0) 80856817Sralph panic("sccstart: No chars"); 80956817Sralph #endif 81056817Sralph SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 81156817Sralph } 81256817Sralph MachEmptyWriteBuffer(); 81356817Sralph out: 81456817Sralph splx(s); 81556817Sralph } 81656817Sralph 81756817Sralph /* 81856817Sralph * Stop output on a line. 81956817Sralph */ 82056817Sralph /*ARGSUSED*/ 82156817Sralph sccstop(tp, flag) 82256817Sralph register struct tty *tp; 82356817Sralph { 82456817Sralph register struct pdma *dp; 82556817Sralph register int s; 82656817Sralph 82756817Sralph dp = (struct pdma *)tp->t_addr; 82856817Sralph s = spltty(); 82956817Sralph if (tp->t_state & TS_BUSY) { 83056817Sralph dp->p_end = dp->p_mem; 83156817Sralph if (!(tp->t_state & TS_TTSTOP)) 83256817Sralph tp->t_state |= TS_FLUSH; 83356817Sralph } 83456817Sralph splx(s); 83556817Sralph } 83656817Sralph 83756817Sralph sccmctl(dev, bits, how) 83856817Sralph dev_t dev; 83956817Sralph int bits, how; 84056817Sralph { 84156817Sralph register struct scc_softc *sc; 84256817Sralph register scc_regmap_t *regs; 84356817Sralph register int line, mbits; 84456817Sralph register u_char value; 84556817Sralph int s; 84656817Sralph 84756817Sralph sc = &scc_softc[SCCUNIT(dev)]; 84856817Sralph line = SCCLINE(dev); 84956817Sralph regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 85056817Sralph s = spltty(); 85156817Sralph /* 85256817Sralph * only channel B has modem control, however the DTR and RTS 85356817Sralph * pins on the comm port are wired to the DTR and RTS A channel 85456817Sralph * signals. 85556817Sralph */ 85656817Sralph mbits = DML_DTR | DML_DSR | DML_CAR; 85756817Sralph if (line == SCC_CHANNEL_B) { 85856817Sralph if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & SCC_WR5_DTR) 85956817Sralph mbits = DML_DTR | DML_DSR; 86056817Sralph else 86156817Sralph mbits = 0; 86256817Sralph SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value); 86356817Sralph if (value & SCC_RR0_DCD) 86456817Sralph mbits |= DML_CAR; 86556817Sralph } 86656817Sralph switch (how) { 86756817Sralph case DMSET: 86856817Sralph mbits = bits; 86956817Sralph break; 87056817Sralph 87156817Sralph case DMBIS: 87256817Sralph mbits |= bits; 87356817Sralph break; 87456817Sralph 87556817Sralph case DMBIC: 87656817Sralph mbits &= ~bits; 87756817Sralph break; 87856817Sralph 87956817Sralph case DMGET: 88056817Sralph (void) splx(s); 88156817Sralph return (mbits); 88256817Sralph } 88356817Sralph if (line == SCC_CHANNEL_B) { 88456817Sralph if (mbits & DML_DTR) 88556817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5 |= SCC_WR5_DTR; 88656817Sralph else 88756817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~SCC_WR5_DTR; 88856817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5, 88956817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5); 89056817Sralph } 89156817Sralph if ((mbits & DML_DTR) && (sc->scc_softCAR & (1 << line))) 89256817Sralph scc_tty[minor(dev)].t_state |= TS_CARR_ON; 89356817Sralph (void) splx(s); 89456817Sralph return (mbits); 89556817Sralph } 89656817Sralph 89756817Sralph /* 89856817Sralph * Check for carrier transition. 89956817Sralph */ 90056817Sralph static void 90156817Sralph scc_modem_intr(dev) 90256817Sralph dev_t dev; 90356817Sralph { 90456817Sralph register scc_regmap_t *regs; 90556817Sralph register struct scc_softc *sc; 90656817Sralph register struct tty *tp; 90756817Sralph register int car, chan; 90856817Sralph register u_char value; 90956817Sralph int s; 91056817Sralph 91156817Sralph sc = &scc_softc[SCCUNIT(dev)]; 91256817Sralph tp = &scc_tty[minor(dev)]; 91356817Sralph regs = (scc_regmap_t *)((struct pdma *)tp->t_addr)->p_addr; 91456817Sralph chan = SCCLINE(dev); 91556817Sralph if (chan == SCC_CHANNEL_A) 91656817Sralph return; 91756817Sralph s = spltty(); 91856817Sralph if (sc->scc_softCAR & (1 << chan)) 91956817Sralph car = 1; 92056817Sralph else { 92156817Sralph SCC_READ_REG_ZERO(regs, chan, value); 92256817Sralph car = value & SCC_RR0_DCD; 92356817Sralph } 92456817Sralph if (car) { 92556817Sralph /* carrier present */ 92656817Sralph if (!(tp->t_state & TS_CARR_ON)) 92756817Sralph (void)(*linesw[tp->t_line].l_modem)(tp, 1); 92856817Sralph } else if (tp->t_state & TS_CARR_ON) 92956817Sralph (void)(*linesw[tp->t_line].l_modem)(tp, 0); 93056817Sralph splx(s); 93156817Sralph } 93256817Sralph 93356817Sralph /* 93456817Sralph * Get a char off the appropriate line via. a busy wait loop. 93556817Sralph */ 93656817Sralph int 93756817Sralph sccGetc(dev) 93856817Sralph dev_t dev; 93956817Sralph { 94056817Sralph register scc_regmap_t *regs; 94156817Sralph register int c, line; 94256817Sralph register u_char value; 94356817Sralph int s; 94456817Sralph 94556817Sralph line = SCCLINE(dev); 94656817Sralph regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 94756817Sralph if (!regs) 94856817Sralph return (0); 94956817Sralph s = spltty(); 95056817Sralph for (;;) { 95156817Sralph SCC_READ_REG(regs, line, SCC_RR0, value); 95256817Sralph if (value & SCC_RR0_RX_AVAIL) { 95356817Sralph SCC_READ_REG(regs, line, SCC_RR1, value); 95456817Sralph if (value & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | 95556817Sralph SCC_RR1_FRAME_ERR)) { 95656817Sralph SCC_WRITE_REG(regs, line, SCC_WR0, SCC_RESET_ERROR); 95756817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 95856817Sralph SCC_RESET_HIGHEST_IUS); 95956817Sralph } else { 96056817Sralph SCC_READ_DATA(regs, line, c); 96156817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 96256817Sralph SCC_RESET_HIGHEST_IUS); 96356817Sralph splx(s); 96456817Sralph return (c & 0xff); 96556817Sralph } 96656817Sralph } else 96756817Sralph DELAY(10); 96856817Sralph } 96956817Sralph } 97056817Sralph 97156817Sralph /* 97256817Sralph * Send a char on a port, via a busy wait loop. 97356817Sralph */ 97456817Sralph void 97556817Sralph sccPutc(dev, c) 97656817Sralph dev_t dev; 97756817Sralph int c; 97856817Sralph { 97956817Sralph register scc_regmap_t *regs; 980*57234Sralph register int line; 98156817Sralph register u_char value; 98256817Sralph int s; 98356817Sralph 98456817Sralph s = spltty(); 98556817Sralph line = SCCLINE(dev); 98656817Sralph regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 987*57234Sralph 98856817Sralph /* 98956817Sralph * Wait for transmitter to be not busy. 99056817Sralph */ 99156817Sralph do { 99256817Sralph SCC_READ_REG(regs, line, SCC_RR0, value); 993*57234Sralph if (value & SCC_RR0_TX_EMPTY) 994*57234Sralph break; 995*57234Sralph DELAY(100); 996*57234Sralph } while (1); 997*57234Sralph 998*57234Sralph /* 999*57234Sralph * Send the char. 1000*57234Sralph */ 1001*57234Sralph SCC_WRITE_DATA(regs, line, c); 1002*57234Sralph MachEmptyWriteBuffer(); 100356817Sralph splx(s); 100456817Sralph } 100556817Sralph #endif /* NSCC */ 1006