156817Sralph /*- 2*63207Sbostic * Copyright (c) 1992, 1993 3*63207Sbostic * The Regents of the University of California. 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*63207Sbostic * @(#)scc.c 8.1 (Berkeley) 06/10/93 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 15957234Sralph /* 16057234Sralph * For a remote console, wait a while for previous output to 16157234Sralph * complete. 16257234Sralph */ 16357234Sralph if (major(cn_tab.cn_dev) == SCCDEV && cn_tab.cn_screen == 0 && 16457234Sralph SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) 16557234Sralph DELAY(10000); 16657234Sralph 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) { 19058793Sralph if (cp->pmax_unit == 1) { 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); 19658793Sralph DELAY(10000); 19758793Sralph #ifdef notyet 19858793Sralph /* 19958793Sralph * For some reason doing this hangs the 3min 20058793Sralph * during booting. Fortunately the keyboard 20158793Sralph * works ok without it. 20258793Sralph */ 20356817Sralph KBDReset(ctty.t_dev, sccPutc); 20458793Sralph #endif 20558793Sralph DELAY(10000); 20656817Sralph splx(s); 20758793Sralph } else if (cp->pmax_unit == 0) { 20856817Sralph s = spltty(); 20956817Sralph ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); 21056817Sralph cterm.c_cflag = CS8 | PARENB | PARODD; 21156817Sralph cterm.c_ospeed = cterm.c_ispeed = 4800; 21256817Sralph (void) sccparam(&ctty, &cterm); 21358793Sralph DELAY(10000); 21456817Sralph MouseInit(ctty.t_dev, sccPutc, sccGetc); 21558793Sralph DELAY(10000); 21656817Sralph splx(s); 21756817Sralph } 21856817Sralph } 21956817Sralph } else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) { 22056817Sralph s = spltty(); 22156817Sralph ctty.t_dev = cn_tab.cn_dev; 22256817Sralph cterm.c_cflag = CS8; 22356817Sralph cterm.c_ospeed = cterm.c_ispeed = 9600; 22456817Sralph (void) sccparam(&ctty, &cterm); 22557234Sralph DELAY(1000); 22656817Sralph cn_tab.cn_disabled = 0; 22756817Sralph splx(s); 22856817Sralph } 22957234Sralph printf("scc%d at nexus0 csr 0x%x priority %d\n", 23057234Sralph cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 23156817Sralph return (1); 23256817Sralph } 23356817Sralph 23456817Sralph /* 23556817Sralph * Reset the chip. 23656817Sralph */ 23756817Sralph static void 23856817Sralph sccreset(sc) 23956817Sralph register struct scc_softc *sc; 24056817Sralph { 24156817Sralph register scc_regmap_t *regs; 24256817Sralph register u_char val; 24356817Sralph 24456817Sralph regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 24556817Sralph /* 24656817Sralph * Chip once-only initialization 24756817Sralph * 24856817Sralph * NOTE: The wiring we assume is the one on the 3min: 24956817Sralph * 25056817Sralph * out A-TxD --> TxD keybd or mouse 25156817Sralph * in A-RxD --> RxD keybd or mouse 25256817Sralph * out A-DTR~ --> DTR comm 25356817Sralph * out A-RTS~ --> RTS comm 25456817Sralph * in A-CTS~ --> SI comm 25556817Sralph * in A-DCD~ --> RI comm 25656817Sralph * in A-SYNCH~--> DSR comm 25756817Sralph * out B-TxD --> TxD comm 25856817Sralph * in B-RxD --> RxD comm 25956817Sralph * in B-RxC --> TRxCB comm 26056817Sralph * in B-TxC --> RTxCB comm 26156817Sralph * out B-RTS~ --> SS comm 26256817Sralph * in B-CTS~ --> CTS comm 26356817Sralph * in B-DCD~ --> CD comm 26456817Sralph */ 26556817Sralph SCC_INIT_REG(regs, SCC_CHANNEL_A); 26656817Sralph SCC_INIT_REG(regs, SCC_CHANNEL_B); 26756817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET); 26856817Sralph DELAY(50000); /*enough ? */ 26956817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0); 27056817Sralph 27156817Sralph /* program the interrupt vector */ 27256817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0); 27356817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0); 27456817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS); 27556817Sralph 27656817Sralph /* timing base defaults */ 27756817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16; 27856817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16; 27956817Sralph 28056817Sralph /* enable DTR, RTS and SS */ 28156817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS; 28256817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR; 28356817Sralph 28456817Sralph /* baud rates */ 28556817Sralph val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC; 28656817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr14 = val; 28756817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr14 = val; 28856817Sralph 28956817Sralph /* interrupt conditions */ 29056817Sralph val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE | 29157234Sralph SCC_WR1_EXT_IE; 29256817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr1 = val; 29356817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr1 = val; 29456817Sralph } 29556817Sralph 29656817Sralph sccopen(dev, flag, mode, p) 29756817Sralph dev_t dev; 29856817Sralph int flag, mode; 29956817Sralph struct proc *p; 30056817Sralph { 30156817Sralph register struct scc_softc *sc; 30256817Sralph register struct tty *tp; 30356817Sralph register int unit, line; 30456817Sralph int s, error = 0; 30556817Sralph 30656817Sralph unit = SCCUNIT(dev); 30756817Sralph if (unit >= NSCC) 30856817Sralph return (ENXIO); 30956817Sralph line = SCCLINE(dev); 31056817Sralph sc = &scc_softc[unit]; 31156817Sralph if (sc->scc_pdma[line].p_addr == (void *)0) 31256817Sralph return (ENXIO); 31356817Sralph tp = &scc_tty[minor(dev)]; 31456817Sralph tp->t_addr = (caddr_t)&sc->scc_pdma[line]; 31556817Sralph tp->t_oproc = sccstart; 31656817Sralph tp->t_param = sccparam; 31756817Sralph tp->t_dev = dev; 31856817Sralph if ((tp->t_state & TS_ISOPEN) == 0) { 31956817Sralph tp->t_state |= TS_WOPEN; 32056817Sralph ttychars(tp); 32156817Sralph #ifndef PORTSELECTOR 32256817Sralph if (tp->t_ispeed == 0) { 32356817Sralph #endif 32456817Sralph tp->t_iflag = TTYDEF_IFLAG; 32556817Sralph tp->t_oflag = TTYDEF_OFLAG; 32656817Sralph tp->t_cflag = TTYDEF_CFLAG; 32756817Sralph tp->t_lflag = LFLAG; 32856817Sralph tp->t_ispeed = tp->t_ospeed = ISPEED; 32956817Sralph #ifdef PORTSELECTOR 33056817Sralph tp->t_cflag |= HUPCL; 33156817Sralph #else 33256817Sralph } 33356817Sralph #endif 33456817Sralph (void) sccparam(tp, &tp->t_termios); 33556817Sralph ttsetwater(tp); 33656817Sralph } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 33756817Sralph return (EBUSY); 33856817Sralph (void) sccmctl(dev, DML_DTR, DMSET); 33956817Sralph s = spltty(); 34056817Sralph while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 34156817Sralph !(tp->t_state & TS_CARR_ON)) { 34256817Sralph tp->t_state |= TS_WOPEN; 34356817Sralph if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 34456817Sralph ttopen, 0)) 34556817Sralph break; 34656817Sralph } 34756817Sralph splx(s); 34856817Sralph if (error) 34956817Sralph return (error); 35056817Sralph return ((*linesw[tp->t_line].l_open)(dev, tp)); 35156817Sralph } 35256817Sralph 35356817Sralph /*ARGSUSED*/ 35456817Sralph sccclose(dev, flag, mode, p) 35556817Sralph dev_t dev; 35656817Sralph int flag, mode; 35756817Sralph struct proc *p; 35856817Sralph { 35956817Sralph register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)]; 36056817Sralph register struct tty *tp; 36156817Sralph register int bit, line; 36256817Sralph 36356817Sralph tp = &scc_tty[minor(dev)]; 36456817Sralph line = SCCLINE(dev); 36556817Sralph if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) { 36656817Sralph sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 36756817Sralph ttyoutput(0, tp); 36856817Sralph } 36956817Sralph (*linesw[tp->t_line].l_close)(tp, flag); 37056817Sralph if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 37156817Sralph !(tp->t_state & TS_ISOPEN)) 37256817Sralph (void) sccmctl(dev, 0, DMSET); 37356817Sralph return (ttyclose(tp)); 37456817Sralph } 37556817Sralph 37656817Sralph sccread(dev, uio, flag) 37756817Sralph dev_t dev; 37856817Sralph struct uio *uio; 37956817Sralph { 38056817Sralph register struct tty *tp; 38156817Sralph 38256817Sralph tp = &scc_tty[minor(dev)]; 38356817Sralph return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 38456817Sralph } 38556817Sralph 38656817Sralph sccwrite(dev, uio, flag) 38756817Sralph dev_t dev; 38856817Sralph struct uio *uio; 38956817Sralph { 39056817Sralph register struct tty *tp; 39156817Sralph 39256817Sralph tp = &scc_tty[minor(dev)]; 39356817Sralph return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 39456817Sralph } 39556817Sralph 39656817Sralph /*ARGSUSED*/ 39756817Sralph sccioctl(dev, cmd, data, flag, p) 39856817Sralph dev_t dev; 39956817Sralph int cmd; 40056817Sralph caddr_t data; 40156817Sralph int flag; 40256817Sralph struct proc *p; 40356817Sralph { 40456817Sralph register struct scc_softc *sc; 40556817Sralph register struct tty *tp; 40656817Sralph int error, line; 40756817Sralph 40856817Sralph tp = &scc_tty[minor(dev)]; 40956817Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 41056817Sralph if (error >= 0) 41156817Sralph return (error); 41256817Sralph error = ttioctl(tp, cmd, data, flag); 41356817Sralph if (error >= 0) 41456817Sralph return (error); 41556817Sralph 41656817Sralph line = SCCLINE(dev); 41756817Sralph sc = &scc_softc[SCCUNIT(dev)]; 41856817Sralph switch (cmd) { 41956817Sralph 42056817Sralph case TIOCSBRK: 42156817Sralph sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK; 42256817Sralph ttyoutput(0, tp); 42356817Sralph break; 42456817Sralph 42556817Sralph case TIOCCBRK: 42656817Sralph sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 42756817Sralph ttyoutput(0, tp); 42856817Sralph break; 42956817Sralph 43056817Sralph case TIOCSDTR: 43156817Sralph (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS); 43256817Sralph break; 43356817Sralph 43456817Sralph case TIOCCDTR: 43556817Sralph (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC); 43656817Sralph break; 43756817Sralph 43856817Sralph case TIOCMSET: 43956817Sralph (void) sccmctl(dev, *(int *)data, DMSET); 44056817Sralph break; 44156817Sralph 44256817Sralph case TIOCMBIS: 44356817Sralph (void) sccmctl(dev, *(int *)data, DMBIS); 44456817Sralph break; 44556817Sralph 44656817Sralph case TIOCMBIC: 44756817Sralph (void) sccmctl(dev, *(int *)data, DMBIC); 44856817Sralph break; 44956817Sralph 45056817Sralph case TIOCMGET: 45156817Sralph *(int *)data = sccmctl(dev, 0, DMGET); 45256817Sralph break; 45356817Sralph 45456817Sralph default: 45556817Sralph return (ENOTTY); 45656817Sralph } 45756817Sralph return (0); 45856817Sralph } 45956817Sralph 46056817Sralph sccparam(tp, t) 46156817Sralph register struct tty *tp; 46256817Sralph register struct termios *t; 46356817Sralph { 46456817Sralph register struct scc_softc *sc; 46556817Sralph register scc_regmap_t *regs; 46656817Sralph register int line; 46756817Sralph register u_char value, wvalue; 46856817Sralph register int cflag = t->c_cflag; 46956817Sralph int ospeed; 47056817Sralph 47156817Sralph if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 47256817Sralph return (EINVAL); 47356817Sralph sc = &scc_softc[SCCUNIT(tp->t_dev)]; 47456817Sralph line = SCCLINE(tp->t_dev); 47556817Sralph regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 47656817Sralph ospeed = ttspeedtab(t->c_ospeed, sccspeedtab); 47756817Sralph if (ospeed < 0) 47856817Sralph return (EINVAL); 47956817Sralph /* and copy to tty */ 48056817Sralph tp->t_ispeed = t->c_ispeed; 48156817Sralph tp->t_ospeed = t->c_ospeed; 48256817Sralph tp->t_cflag = cflag; 48356817Sralph 48456817Sralph /* 48556817Sralph * Handle console specially. 48656817Sralph */ 48756817Sralph if (cn_tab.cn_screen) { 48856817Sralph if (minor(tp->t_dev) == SCCKBD_PORT) { 48956817Sralph cflag = CS8; 49056817Sralph ospeed = ttspeedtab(4800, sccspeedtab); 49156817Sralph } else if (minor(tp->t_dev) == SCCMOUSE_PORT) { 49256817Sralph cflag = CS8 | PARENB | PARODD; 49356817Sralph ospeed = ttspeedtab(4800, sccspeedtab); 49456817Sralph } 49556817Sralph } else if (tp->t_dev == cn_tab.cn_dev) { 49656817Sralph cflag = CS8; 49756817Sralph ospeed = ttspeedtab(9600, sccspeedtab); 49856817Sralph } 49956817Sralph if (ospeed == 0) { 50056817Sralph (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */ 50156817Sralph return (0); 50256817Sralph } 50356817Sralph 50456817Sralph /* reset line */ 50556817Sralph if (line == SCC_CHANNEL_A) 50656817Sralph value = SCC_WR9_RESET_CHA_A; 50756817Sralph else 50856817Sralph value = SCC_WR9_RESET_CHA_B; 50956817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, value); 51056817Sralph DELAY(25); 51156817Sralph 51256817Sralph /* stop bits, normally 1 */ 51356817Sralph value = sc->scc_wreg[line].wr4 & 0xf0; 51456817Sralph if (cflag & CSTOPB) 51556817Sralph value |= SCC_WR4_2_STOP; 51656817Sralph else 51756817Sralph value |= SCC_WR4_1_STOP; 51856817Sralph if ((cflag & PARODD) == 0) 51956817Sralph value |= SCC_WR4_EVEN_PARITY; 52056817Sralph if (cflag & PARENB) 52156817Sralph value |= SCC_WR4_PARITY_ENABLE; 52256817Sralph 52356817Sralph /* set it now, remember it must be first after reset */ 52456817Sralph sc->scc_wreg[line].wr4 = value; 52556817Sralph SCC_WRITE_REG(regs, line, SCC_WR4, value); 52656817Sralph 52756817Sralph /* vector again */ 52856817Sralph SCC_WRITE_REG(regs, line, SCC_WR2, 0xf0); 52956817Sralph 53056817Sralph /* clear break, keep rts dtr */ 53156817Sralph wvalue = sc->scc_wreg[line].wr5 & (SCC_WR5_DTR|SCC_WR5_RTS); 53256817Sralph switch (cflag & CSIZE) { 53356817Sralph case CS5: 53456817Sralph value = SCC_WR3_RX_5_BITS; 53556817Sralph wvalue |= SCC_WR5_TX_5_BITS; 53656817Sralph break; 53756817Sralph case CS6: 53856817Sralph value = SCC_WR3_RX_6_BITS; 53956817Sralph wvalue |= SCC_WR5_TX_6_BITS; 54056817Sralph break; 54156817Sralph case CS7: 54256817Sralph value = SCC_WR3_RX_7_BITS; 54356817Sralph wvalue |= SCC_WR5_TX_7_BITS; 54456817Sralph break; 54556817Sralph case CS8: 54656817Sralph default: 54756817Sralph value = SCC_WR3_RX_8_BITS; 54856817Sralph wvalue |= SCC_WR5_TX_8_BITS; 54956817Sralph }; 55056817Sralph sc->scc_wreg[line].wr3 = value; 55156817Sralph SCC_WRITE_REG(regs, line, SCC_WR3, value); 55256817Sralph sc->scc_wreg[line].wr5 = wvalue; 55356817Sralph SCC_WRITE_REG(regs, line, SCC_WR5, wvalue); 55456817Sralph SCC_WRITE_REG(regs, line, SCC_WR6, 0); 55556817Sralph SCC_WRITE_REG(regs, line, SCC_WR7, 0); 55656817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, SCC_WR9_VIS); 55756817Sralph SCC_WRITE_REG(regs, line, SCC_WR10, 0); 55856817Sralph value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR | 55956817Sralph SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR; 56056817Sralph SCC_WRITE_REG(regs, line, SCC_WR11, value); 56156817Sralph SCC_SET_TIMING_BASE(regs, line, ospeed); 56256817Sralph value = sc->scc_wreg[line].wr14; 56356817Sralph SCC_WRITE_REG(regs, line, SCC_WR14, value); 56456817Sralph value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE; 56556817Sralph SCC_WRITE_REG(regs, line, SCC_WR15, value); 56656817Sralph 56756817Sralph /* and now the enables */ 56856817Sralph value = sc->scc_wreg[line].wr3 | SCC_WR3_RX_ENABLE; 56956817Sralph SCC_WRITE_REG(regs, line, SCC_WR3, value); 57056817Sralph value = sc->scc_wreg[line].wr5 | SCC_WR5_TX_ENABLE; 57156817Sralph sc->scc_wreg[line].wr5 = value; 57256817Sralph SCC_WRITE_REG(regs, line, SCC_WR5, value); 57356817Sralph 57456817Sralph /* master inter enable */ 57556817Sralph value = SCC_WR9_MASTER_IE | SCC_WR9_VIS; 57656817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, value); 57756817Sralph SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); 57856817Sralph MachEmptyWriteBuffer(); 57956817Sralph return (0); 58056817Sralph } 58156817Sralph 58256817Sralph /* 58356817Sralph * Check for interrupts from all devices. 58456817Sralph */ 58556817Sralph void 58656817Sralph sccintr(unit) 58756817Sralph register int unit; 58856817Sralph { 58956817Sralph register scc_regmap_t *regs; 59056817Sralph register struct tty *tp; 59156817Sralph register struct pdma *dp; 59256817Sralph register struct scc_softc *sc; 59356817Sralph register int cc, chan, rr1, rr2, rr3; 59456817Sralph int overrun = 0; 59556817Sralph 59656817Sralph sc = &scc_softc[unit]; 59756817Sralph regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 59856817Sralph unit <<= 1; 59956817Sralph for (;;) { 60056817Sralph SCC_READ_REG(regs, SCC_CHANNEL_B, SCC_RR2, rr2); 60156817Sralph rr2 = SCC_RR2_STATUS(rr2); 60256817Sralph /* are we done yet ? */ 60356817Sralph if (rr2 == 6) { /* strange, distinguished value */ 60456817Sralph SCC_READ_REG(regs, SCC_CHANNEL_A, SCC_RR3, rr3); 60556817Sralph if (rr3 == 0) 60656817Sralph return; 60756817Sralph } 60856817Sralph 60956817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); 61056817Sralph if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { 61156817Sralph chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? 61256817Sralph SCC_CHANNEL_A : SCC_CHANNEL_B; 61356817Sralph tp = &scc_tty[unit | chan]; 61456817Sralph dp = (struct pdma *)tp->t_addr; 61556817Sralph if (dp->p_mem < dp->p_end) { 61656817Sralph SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 61756817Sralph MachEmptyWriteBuffer(); 61856817Sralph } else { 61956817Sralph tp->t_state &= ~TS_BUSY; 62056817Sralph if (tp->t_state & TS_FLUSH) 62156817Sralph tp->t_state &= ~TS_FLUSH; 62256817Sralph else { 62356817Sralph ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 62456817Sralph dp->p_end = dp->p_mem = tp->t_outq.c_cf; 62556817Sralph } 62656817Sralph if (tp->t_line) 62756817Sralph (*linesw[tp->t_line].l_start)(tp); 62856817Sralph else 62956817Sralph sccstart(tp); 63056817Sralph if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 63156817Sralph SCC_READ_REG(regs, chan, SCC_RR15, cc); 63256817Sralph cc &= ~SCC_WR15_TX_UNDERRUN_IE; 63356817Sralph SCC_WRITE_REG(regs, chan, SCC_WR15, cc); 63456817Sralph cc = sc->scc_wreg[chan].wr1 & ~SCC_WR1_TX_IE; 63556817Sralph SCC_WRITE_REG(regs, chan, SCC_WR1, cc); 63656817Sralph sc->scc_wreg[chan].wr1 = cc; 63756817Sralph MachEmptyWriteBuffer(); 63856817Sralph } 63956817Sralph } 64057234Sralph } else if (rr2 == SCC_RR2_A_RECV_DONE || 64157234Sralph rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL || 64257234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 64357234Sralph if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL) 64457234Sralph chan = SCC_CHANNEL_A; 64557234Sralph else 64657234Sralph chan = SCC_CHANNEL_B; 64757234Sralph tp = &scc_tty[unit | chan]; 64857234Sralph SCC_READ_DATA(regs, chan, cc); 64957234Sralph if (rr2 == SCC_RR2_A_RECV_SPECIAL || 65057234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 65157234Sralph SCC_READ_REG(regs, chan, SCC_RR1, rr1); 65257234Sralph SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_ERROR); 65357234Sralph if ((rr1 & SCC_RR1_RX_OVERRUN) && overrun == 0) { 65457234Sralph log(LOG_WARNING, "scc%d,%d: silo overflow\n", 65557234Sralph unit >> 1, chan); 65657234Sralph overrun = 1; 65757234Sralph } 65857234Sralph } 65956817Sralph 66056817Sralph /* 66156817Sralph * Keyboard needs special treatment. 66256817Sralph */ 66356817Sralph if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 66456817Sralph #ifdef KADB 66556817Sralph if (cc == LK_DO) { 66656817Sralph spl0(); 66756817Sralph kdbpanic(); 66856817Sralph return; 66956817Sralph } 67056817Sralph #endif 67156817Sralph #ifdef DEBUG 67256817Sralph debugChar = cc; 67356817Sralph #endif 67456817Sralph if (sccDivertXInput) { 67556817Sralph (*sccDivertXInput)(cc); 67656817Sralph continue; 67756817Sralph } 67856817Sralph if ((cc = kbdMapChar(cc)) < 0) 67956817Sralph continue; 68056817Sralph /* 68156817Sralph * Now for mousey 68256817Sralph */ 68356817Sralph } else if (tp == &scc_tty[SCCMOUSE_PORT] && sccMouseButtons) { 68456817Sralph register MouseReport *mrp; 68556817Sralph static MouseReport currentRep; 68656817Sralph 68756817Sralph mrp = ¤tRep; 68856817Sralph mrp->byteCount++; 68956817Sralph if (cc & MOUSE_START_FRAME) { 69056817Sralph /* 69156817Sralph * The first mouse report byte (button state). 69256817Sralph */ 69356817Sralph mrp->state = cc; 69456817Sralph if (mrp->byteCount > 1) 69556817Sralph mrp->byteCount = 1; 69656817Sralph } else if (mrp->byteCount == 2) { 69756817Sralph /* 69856817Sralph * The second mouse report byte (delta x). 69956817Sralph */ 70056817Sralph mrp->dx = cc; 70156817Sralph } else if (mrp->byteCount == 3) { 70256817Sralph /* 70356817Sralph * The final mouse report byte (delta y). 70456817Sralph */ 70556817Sralph mrp->dy = cc; 70656817Sralph mrp->byteCount = 0; 70756817Sralph if (mrp->dx != 0 || mrp->dy != 0) { 70856817Sralph /* 70956817Sralph * If the mouse moved, 71056817Sralph * post a motion event. 71156817Sralph */ 71256817Sralph (*sccMouseEvent)(mrp); 71356817Sralph } 71456817Sralph (*sccMouseButtons)(mrp); 71556817Sralph } 71656817Sralph continue; 71756817Sralph } 71856817Sralph if (!(tp->t_state & TS_ISOPEN)) { 71956817Sralph wakeup((caddr_t)&tp->t_rawq); 72056817Sralph #ifdef PORTSELECTOR 72156817Sralph if (!(tp->t_state & TS_WOPEN)) 72256817Sralph #endif 72356817Sralph continue; 72456817Sralph } 72557234Sralph if (rr2 == SCC_RR2_A_RECV_SPECIAL || 72657234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 72757234Sralph if (rr1 & SCC_RR1_PARITY_ERR) 72857234Sralph cc |= TTY_PE; 72957234Sralph if (rr1 & SCC_RR1_FRAME_ERR) 73057234Sralph cc |= TTY_FE; 73156817Sralph } 73256817Sralph (*linesw[tp->t_line].l_rint)(cc, tp); 73356817Sralph } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { 73456817Sralph chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? 73556817Sralph SCC_CHANNEL_A : SCC_CHANNEL_B; 73656817Sralph SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_EXT_IP); 73756817Sralph scc_modem_intr(unit | chan); 73856817Sralph } 73956817Sralph } 74056817Sralph } 74156817Sralph 74256817Sralph void 74356817Sralph sccstart(tp) 74456817Sralph register struct tty *tp; 74556817Sralph { 74656817Sralph register struct pdma *dp; 74756817Sralph register scc_regmap_t *regs; 74856817Sralph register struct scc_softc *sc; 74956817Sralph register int cc, chan; 75056817Sralph u_char temp; 75157234Sralph int s, sendone; 75256817Sralph 75356817Sralph dp = (struct pdma *)tp->t_addr; 75456817Sralph regs = (scc_regmap_t *)dp->p_addr; 75556817Sralph sc = &scc_softc[SCCUNIT(tp->t_dev)]; 75656817Sralph s = spltty(); 75756817Sralph if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 75856817Sralph goto out; 75956817Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 76056817Sralph if (tp->t_state & TS_ASLEEP) { 76156817Sralph tp->t_state &= ~TS_ASLEEP; 76256817Sralph wakeup((caddr_t)&tp->t_outq); 76356817Sralph } 76456817Sralph selwakeup(&tp->t_wsel); 76556817Sralph } 76656817Sralph if (tp->t_outq.c_cc == 0) 76756817Sralph goto out; 76856817Sralph /* handle console specially */ 76956817Sralph if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 77056817Sralph while (tp->t_outq.c_cc > 0) { 77156817Sralph cc = getc(&tp->t_outq) & 0x7f; 77256817Sralph cnputc(cc); 77356817Sralph } 77456817Sralph /* 77556817Sralph * After we flush the output queue we may need to wake 77656817Sralph * up the process that made the output. 77756817Sralph */ 77856817Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 77956817Sralph if (tp->t_state & TS_ASLEEP) { 78056817Sralph tp->t_state &= ~TS_ASLEEP; 78156817Sralph wakeup((caddr_t)&tp->t_outq); 78256817Sralph } 78356817Sralph selwakeup(&tp->t_wsel); 78456817Sralph } 78556817Sralph goto out; 78656817Sralph } 78756817Sralph if (tp->t_flags & (RAW|LITOUT)) 78856817Sralph cc = ndqb(&tp->t_outq, 0); 78956817Sralph else { 79056817Sralph cc = ndqb(&tp->t_outq, 0200); 79156817Sralph if (cc == 0) { 79256817Sralph cc = getc(&tp->t_outq); 79356817Sralph timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); 79456817Sralph tp->t_state |= TS_TIMEOUT; 79556817Sralph goto out; 79656817Sralph } 79756817Sralph } 79856817Sralph tp->t_state |= TS_BUSY; 79956817Sralph dp->p_end = dp->p_mem = tp->t_outq.c_cf; 80056817Sralph dp->p_end += cc; 80156817Sralph 80256817Sralph /* 80356817Sralph * Enable transmission and send the first char, as required. 80456817Sralph */ 80556817Sralph chan = SCCLINE(tp->t_dev); 80657234Sralph SCC_READ_REG(regs, chan, SCC_RR0, temp); 80757234Sralph sendone = (temp & SCC_RR0_TX_EMPTY); 80856817Sralph SCC_READ_REG(regs, chan, SCC_RR15, temp); 80956817Sralph temp |= SCC_WR15_TX_UNDERRUN_IE; 81056817Sralph SCC_WRITE_REG(regs, chan, SCC_WR15, temp); 81156817Sralph temp = sc->scc_wreg[chan].wr1 | SCC_WR1_TX_IE; 81256817Sralph SCC_WRITE_REG(regs, chan, SCC_WR1, temp); 81356817Sralph sc->scc_wreg[chan].wr1 = temp; 81457234Sralph if (sendone) { 81556817Sralph #ifdef DIAGNOSTIC 81656817Sralph if (cc == 0) 81756817Sralph panic("sccstart: No chars"); 81856817Sralph #endif 81956817Sralph SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 82056817Sralph } 82156817Sralph MachEmptyWriteBuffer(); 82256817Sralph out: 82356817Sralph splx(s); 82456817Sralph } 82556817Sralph 82656817Sralph /* 82756817Sralph * Stop output on a line. 82856817Sralph */ 82956817Sralph /*ARGSUSED*/ 83056817Sralph sccstop(tp, flag) 83156817Sralph register struct tty *tp; 83256817Sralph { 83356817Sralph register struct pdma *dp; 83456817Sralph register int s; 83556817Sralph 83656817Sralph dp = (struct pdma *)tp->t_addr; 83756817Sralph s = spltty(); 83856817Sralph if (tp->t_state & TS_BUSY) { 83956817Sralph dp->p_end = dp->p_mem; 84056817Sralph if (!(tp->t_state & TS_TTSTOP)) 84156817Sralph tp->t_state |= TS_FLUSH; 84256817Sralph } 84356817Sralph splx(s); 84456817Sralph } 84556817Sralph 84656817Sralph sccmctl(dev, bits, how) 84756817Sralph dev_t dev; 84856817Sralph int bits, how; 84956817Sralph { 85056817Sralph register struct scc_softc *sc; 85156817Sralph register scc_regmap_t *regs; 85256817Sralph register int line, mbits; 85356817Sralph register u_char value; 85456817Sralph int s; 85556817Sralph 85656817Sralph sc = &scc_softc[SCCUNIT(dev)]; 85756817Sralph line = SCCLINE(dev); 85856817Sralph regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 85956817Sralph s = spltty(); 86056817Sralph /* 86156817Sralph * only channel B has modem control, however the DTR and RTS 86256817Sralph * pins on the comm port are wired to the DTR and RTS A channel 86356817Sralph * signals. 86456817Sralph */ 86556817Sralph mbits = DML_DTR | DML_DSR | DML_CAR; 86656817Sralph if (line == SCC_CHANNEL_B) { 86756817Sralph if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & SCC_WR5_DTR) 86856817Sralph mbits = DML_DTR | DML_DSR; 86956817Sralph else 87056817Sralph mbits = 0; 87156817Sralph SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value); 87256817Sralph if (value & SCC_RR0_DCD) 87356817Sralph mbits |= DML_CAR; 87456817Sralph } 87556817Sralph switch (how) { 87656817Sralph case DMSET: 87756817Sralph mbits = bits; 87856817Sralph break; 87956817Sralph 88056817Sralph case DMBIS: 88156817Sralph mbits |= bits; 88256817Sralph break; 88356817Sralph 88456817Sralph case DMBIC: 88556817Sralph mbits &= ~bits; 88656817Sralph break; 88756817Sralph 88856817Sralph case DMGET: 88956817Sralph (void) splx(s); 89056817Sralph return (mbits); 89156817Sralph } 89256817Sralph if (line == SCC_CHANNEL_B) { 89356817Sralph if (mbits & DML_DTR) 89456817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5 |= SCC_WR5_DTR; 89556817Sralph else 89656817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~SCC_WR5_DTR; 89756817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5, 89856817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5); 89956817Sralph } 90056817Sralph if ((mbits & DML_DTR) && (sc->scc_softCAR & (1 << line))) 90156817Sralph scc_tty[minor(dev)].t_state |= TS_CARR_ON; 90256817Sralph (void) splx(s); 90356817Sralph return (mbits); 90456817Sralph } 90556817Sralph 90656817Sralph /* 90756817Sralph * Check for carrier transition. 90856817Sralph */ 90956817Sralph static void 91056817Sralph scc_modem_intr(dev) 91156817Sralph dev_t dev; 91256817Sralph { 91356817Sralph register scc_regmap_t *regs; 91456817Sralph register struct scc_softc *sc; 91556817Sralph register struct tty *tp; 91656817Sralph register int car, chan; 91756817Sralph register u_char value; 91856817Sralph int s; 91956817Sralph 92056817Sralph sc = &scc_softc[SCCUNIT(dev)]; 92156817Sralph tp = &scc_tty[minor(dev)]; 92256817Sralph regs = (scc_regmap_t *)((struct pdma *)tp->t_addr)->p_addr; 92356817Sralph chan = SCCLINE(dev); 92456817Sralph if (chan == SCC_CHANNEL_A) 92556817Sralph return; 92656817Sralph s = spltty(); 92756817Sralph if (sc->scc_softCAR & (1 << chan)) 92856817Sralph car = 1; 92956817Sralph else { 93056817Sralph SCC_READ_REG_ZERO(regs, chan, value); 93156817Sralph car = value & SCC_RR0_DCD; 93256817Sralph } 93356817Sralph if (car) { 93456817Sralph /* carrier present */ 93556817Sralph if (!(tp->t_state & TS_CARR_ON)) 93656817Sralph (void)(*linesw[tp->t_line].l_modem)(tp, 1); 93756817Sralph } else if (tp->t_state & TS_CARR_ON) 93856817Sralph (void)(*linesw[tp->t_line].l_modem)(tp, 0); 93956817Sralph splx(s); 94056817Sralph } 94156817Sralph 94256817Sralph /* 94356817Sralph * Get a char off the appropriate line via. a busy wait loop. 94456817Sralph */ 94556817Sralph int 94656817Sralph sccGetc(dev) 94756817Sralph dev_t dev; 94856817Sralph { 94956817Sralph register scc_regmap_t *regs; 95056817Sralph register int c, line; 95156817Sralph register u_char value; 95256817Sralph int s; 95356817Sralph 95456817Sralph line = SCCLINE(dev); 95556817Sralph regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 95656817Sralph if (!regs) 95756817Sralph return (0); 95856817Sralph s = spltty(); 95956817Sralph for (;;) { 96056817Sralph SCC_READ_REG(regs, line, SCC_RR0, value); 96156817Sralph if (value & SCC_RR0_RX_AVAIL) { 96256817Sralph SCC_READ_REG(regs, line, SCC_RR1, value); 96358793Sralph SCC_READ_DATA(regs, line, c); 96456817Sralph if (value & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN | 96556817Sralph SCC_RR1_FRAME_ERR)) { 96656817Sralph SCC_WRITE_REG(regs, line, SCC_WR0, SCC_RESET_ERROR); 96756817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 96856817Sralph SCC_RESET_HIGHEST_IUS); 96956817Sralph } else { 97056817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0, 97156817Sralph SCC_RESET_HIGHEST_IUS); 97256817Sralph splx(s); 97356817Sralph return (c & 0xff); 97456817Sralph } 97556817Sralph } else 97656817Sralph DELAY(10); 97756817Sralph } 97856817Sralph } 97956817Sralph 98056817Sralph /* 98156817Sralph * Send a char on a port, via a busy wait loop. 98256817Sralph */ 98356817Sralph void 98456817Sralph sccPutc(dev, c) 98556817Sralph dev_t dev; 98656817Sralph int c; 98756817Sralph { 98856817Sralph register scc_regmap_t *regs; 98957234Sralph register int line; 99056817Sralph register u_char value; 99156817Sralph int s; 99256817Sralph 99356817Sralph s = spltty(); 99456817Sralph line = SCCLINE(dev); 99556817Sralph regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr; 99657234Sralph 99756817Sralph /* 99856817Sralph * Wait for transmitter to be not busy. 99956817Sralph */ 100056817Sralph do { 100156817Sralph SCC_READ_REG(regs, line, SCC_RR0, value); 100257234Sralph if (value & SCC_RR0_TX_EMPTY) 100357234Sralph break; 100457234Sralph DELAY(100); 100557234Sralph } while (1); 100657234Sralph 100757234Sralph /* 100857234Sralph * Send the char. 100957234Sralph */ 101057234Sralph SCC_WRITE_DATA(regs, line, c); 101157234Sralph MachEmptyWriteBuffer(); 101256817Sralph splx(s); 101356817Sralph } 101456817Sralph #endif /* NSCC */ 1015