156817Sralph /*- 263207Sbostic * Copyright (c) 1992, 1993 363207Sbostic * 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*64979Smckusick * @(#)scc.c 8.2 (Berkeley) 11/30/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_dev = (dev_t)((cp->pmax_unit << 1) | cntr); 17756817Sralph pdp++, tp++; 17856817Sralph } 17956817Sralph sc->scc_softCAR = cp->pmax_flags | 0x2; 18056817Sralph 18156817Sralph /* reset chip */ 18256817Sralph sccreset(sc); 18356817Sralph 18456817Sralph /* 18556817Sralph * Special handling for consoles. 18656817Sralph */ 18756817Sralph if (cn_tab.cn_screen) { 18856817Sralph if (cn_tab.cn_kbdgetc == sccGetc) { 18958793Sralph if (cp->pmax_unit == 1) { 19056817Sralph s = spltty(); 19156817Sralph ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT); 19256817Sralph cterm.c_cflag = CS8; 19356817Sralph cterm.c_ospeed = cterm.c_ispeed = 4800; 19456817Sralph (void) sccparam(&ctty, &cterm); 19558793Sralph DELAY(10000); 19658793Sralph #ifdef notyet 19758793Sralph /* 19858793Sralph * For some reason doing this hangs the 3min 19958793Sralph * during booting. Fortunately the keyboard 20058793Sralph * works ok without it. 20158793Sralph */ 20256817Sralph KBDReset(ctty.t_dev, sccPutc); 20358793Sralph #endif 20458793Sralph DELAY(10000); 20556817Sralph splx(s); 20658793Sralph } else if (cp->pmax_unit == 0) { 20756817Sralph s = spltty(); 20856817Sralph ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT); 20956817Sralph cterm.c_cflag = CS8 | PARENB | PARODD; 21056817Sralph cterm.c_ospeed = cterm.c_ispeed = 4800; 21156817Sralph (void) sccparam(&ctty, &cterm); 21258793Sralph DELAY(10000); 21356817Sralph MouseInit(ctty.t_dev, sccPutc, sccGetc); 21458793Sralph DELAY(10000); 21556817Sralph splx(s); 21656817Sralph } 21756817Sralph } 21856817Sralph } else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) { 21956817Sralph s = spltty(); 22056817Sralph ctty.t_dev = cn_tab.cn_dev; 22156817Sralph cterm.c_cflag = CS8; 22256817Sralph cterm.c_ospeed = cterm.c_ispeed = 9600; 22356817Sralph (void) sccparam(&ctty, &cterm); 22457234Sralph DELAY(1000); 22556817Sralph cn_tab.cn_disabled = 0; 22656817Sralph splx(s); 22756817Sralph } 22857234Sralph printf("scc%d at nexus0 csr 0x%x priority %d\n", 22957234Sralph cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 23056817Sralph return (1); 23156817Sralph } 23256817Sralph 23356817Sralph /* 23456817Sralph * Reset the chip. 23556817Sralph */ 23656817Sralph static void 23756817Sralph sccreset(sc) 23856817Sralph register struct scc_softc *sc; 23956817Sralph { 24056817Sralph register scc_regmap_t *regs; 24156817Sralph register u_char val; 24256817Sralph 24356817Sralph regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 24456817Sralph /* 24556817Sralph * Chip once-only initialization 24656817Sralph * 24756817Sralph * NOTE: The wiring we assume is the one on the 3min: 24856817Sralph * 24956817Sralph * out A-TxD --> TxD keybd or mouse 25056817Sralph * in A-RxD --> RxD keybd or mouse 25156817Sralph * out A-DTR~ --> DTR comm 25256817Sralph * out A-RTS~ --> RTS comm 25356817Sralph * in A-CTS~ --> SI comm 25456817Sralph * in A-DCD~ --> RI comm 25556817Sralph * in A-SYNCH~--> DSR comm 25656817Sralph * out B-TxD --> TxD comm 25756817Sralph * in B-RxD --> RxD comm 25856817Sralph * in B-RxC --> TRxCB comm 25956817Sralph * in B-TxC --> RTxCB comm 26056817Sralph * out B-RTS~ --> SS comm 26156817Sralph * in B-CTS~ --> CTS comm 26256817Sralph * in B-DCD~ --> CD comm 26356817Sralph */ 26456817Sralph SCC_INIT_REG(regs, SCC_CHANNEL_A); 26556817Sralph SCC_INIT_REG(regs, SCC_CHANNEL_B); 26656817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET); 26756817Sralph DELAY(50000); /*enough ? */ 26856817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0); 26956817Sralph 27056817Sralph /* program the interrupt vector */ 27156817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0); 27256817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0); 27356817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS); 27456817Sralph 27556817Sralph /* timing base defaults */ 27656817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16; 27756817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16; 27856817Sralph 27956817Sralph /* enable DTR, RTS and SS */ 28056817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS; 28156817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR; 28256817Sralph 28356817Sralph /* baud rates */ 28456817Sralph val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC; 28556817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr14 = val; 28656817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr14 = val; 28756817Sralph 28856817Sralph /* interrupt conditions */ 28956817Sralph val = SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE | 29057234Sralph SCC_WR1_EXT_IE; 29156817Sralph sc->scc_wreg[SCC_CHANNEL_A].wr1 = val; 29256817Sralph sc->scc_wreg[SCC_CHANNEL_B].wr1 = val; 29356817Sralph } 29456817Sralph 29556817Sralph sccopen(dev, flag, mode, p) 29656817Sralph dev_t dev; 29756817Sralph int flag, mode; 29856817Sralph struct proc *p; 29956817Sralph { 30056817Sralph register struct scc_softc *sc; 30156817Sralph register struct tty *tp; 30256817Sralph register int unit, line; 30356817Sralph int s, error = 0; 30456817Sralph 30556817Sralph unit = SCCUNIT(dev); 30656817Sralph if (unit >= NSCC) 30756817Sralph return (ENXIO); 30856817Sralph line = SCCLINE(dev); 30956817Sralph sc = &scc_softc[unit]; 31056817Sralph if (sc->scc_pdma[line].p_addr == (void *)0) 31156817Sralph return (ENXIO); 31256817Sralph tp = &scc_tty[minor(dev)]; 31356817Sralph tp->t_oproc = sccstart; 31456817Sralph tp->t_param = sccparam; 31556817Sralph tp->t_dev = dev; 31656817Sralph if ((tp->t_state & TS_ISOPEN) == 0) { 31756817Sralph tp->t_state |= TS_WOPEN; 31856817Sralph ttychars(tp); 31956817Sralph #ifndef PORTSELECTOR 32056817Sralph if (tp->t_ispeed == 0) { 32156817Sralph #endif 32256817Sralph tp->t_iflag = TTYDEF_IFLAG; 32356817Sralph tp->t_oflag = TTYDEF_OFLAG; 32456817Sralph tp->t_cflag = TTYDEF_CFLAG; 32556817Sralph tp->t_lflag = LFLAG; 32656817Sralph tp->t_ispeed = tp->t_ospeed = ISPEED; 32756817Sralph #ifdef PORTSELECTOR 32856817Sralph tp->t_cflag |= HUPCL; 32956817Sralph #else 33056817Sralph } 33156817Sralph #endif 33256817Sralph (void) sccparam(tp, &tp->t_termios); 33356817Sralph ttsetwater(tp); 33456817Sralph } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 33556817Sralph return (EBUSY); 33656817Sralph (void) sccmctl(dev, DML_DTR, DMSET); 33756817Sralph s = spltty(); 33856817Sralph while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 33956817Sralph !(tp->t_state & TS_CARR_ON)) { 34056817Sralph tp->t_state |= TS_WOPEN; 34156817Sralph if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 34256817Sralph ttopen, 0)) 34356817Sralph break; 34456817Sralph } 34556817Sralph splx(s); 34656817Sralph if (error) 34756817Sralph return (error); 34856817Sralph return ((*linesw[tp->t_line].l_open)(dev, tp)); 34956817Sralph } 35056817Sralph 35156817Sralph /*ARGSUSED*/ 35256817Sralph sccclose(dev, flag, mode, p) 35356817Sralph dev_t dev; 35456817Sralph int flag, mode; 35556817Sralph struct proc *p; 35656817Sralph { 35756817Sralph register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)]; 35856817Sralph register struct tty *tp; 35956817Sralph register int bit, line; 36056817Sralph 36156817Sralph tp = &scc_tty[minor(dev)]; 36256817Sralph line = SCCLINE(dev); 36356817Sralph if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) { 36456817Sralph sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 36556817Sralph ttyoutput(0, tp); 36656817Sralph } 36756817Sralph (*linesw[tp->t_line].l_close)(tp, flag); 36856817Sralph if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 36956817Sralph !(tp->t_state & TS_ISOPEN)) 37056817Sralph (void) sccmctl(dev, 0, DMSET); 37156817Sralph return (ttyclose(tp)); 37256817Sralph } 37356817Sralph 37456817Sralph sccread(dev, uio, flag) 37556817Sralph dev_t dev; 37656817Sralph struct uio *uio; 37756817Sralph { 37856817Sralph register struct tty *tp; 37956817Sralph 38056817Sralph tp = &scc_tty[minor(dev)]; 38156817Sralph return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 38256817Sralph } 38356817Sralph 38456817Sralph sccwrite(dev, uio, flag) 38556817Sralph dev_t dev; 38656817Sralph struct uio *uio; 38756817Sralph { 38856817Sralph register struct tty *tp; 38956817Sralph 39056817Sralph tp = &scc_tty[minor(dev)]; 39156817Sralph return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 39256817Sralph } 39356817Sralph 39456817Sralph /*ARGSUSED*/ 39556817Sralph sccioctl(dev, cmd, data, flag, p) 39656817Sralph dev_t dev; 39756817Sralph int cmd; 39856817Sralph caddr_t data; 39956817Sralph int flag; 40056817Sralph struct proc *p; 40156817Sralph { 40256817Sralph register struct scc_softc *sc; 40356817Sralph register struct tty *tp; 40456817Sralph int error, line; 40556817Sralph 40656817Sralph tp = &scc_tty[minor(dev)]; 40756817Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 40856817Sralph if (error >= 0) 40956817Sralph return (error); 41056817Sralph error = ttioctl(tp, cmd, data, flag); 41156817Sralph if (error >= 0) 41256817Sralph return (error); 41356817Sralph 41456817Sralph line = SCCLINE(dev); 41556817Sralph sc = &scc_softc[SCCUNIT(dev)]; 41656817Sralph switch (cmd) { 41756817Sralph 41856817Sralph case TIOCSBRK: 41956817Sralph sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK; 42056817Sralph ttyoutput(0, tp); 42156817Sralph break; 42256817Sralph 42356817Sralph case TIOCCBRK: 42456817Sralph sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK; 42556817Sralph ttyoutput(0, tp); 42656817Sralph break; 42756817Sralph 42856817Sralph case TIOCSDTR: 42956817Sralph (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS); 43056817Sralph break; 43156817Sralph 43256817Sralph case TIOCCDTR: 43356817Sralph (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC); 43456817Sralph break; 43556817Sralph 43656817Sralph case TIOCMSET: 43756817Sralph (void) sccmctl(dev, *(int *)data, DMSET); 43856817Sralph break; 43956817Sralph 44056817Sralph case TIOCMBIS: 44156817Sralph (void) sccmctl(dev, *(int *)data, DMBIS); 44256817Sralph break; 44356817Sralph 44456817Sralph case TIOCMBIC: 44556817Sralph (void) sccmctl(dev, *(int *)data, DMBIC); 44656817Sralph break; 44756817Sralph 44856817Sralph case TIOCMGET: 44956817Sralph *(int *)data = sccmctl(dev, 0, DMGET); 45056817Sralph break; 45156817Sralph 45256817Sralph default: 45356817Sralph return (ENOTTY); 45456817Sralph } 45556817Sralph return (0); 45656817Sralph } 45756817Sralph 45856817Sralph sccparam(tp, t) 45956817Sralph register struct tty *tp; 46056817Sralph register struct termios *t; 46156817Sralph { 46256817Sralph register struct scc_softc *sc; 46356817Sralph register scc_regmap_t *regs; 46456817Sralph register int line; 46556817Sralph register u_char value, wvalue; 46656817Sralph register int cflag = t->c_cflag; 46756817Sralph int ospeed; 46856817Sralph 46956817Sralph if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 47056817Sralph return (EINVAL); 47156817Sralph sc = &scc_softc[SCCUNIT(tp->t_dev)]; 47256817Sralph line = SCCLINE(tp->t_dev); 47356817Sralph regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr; 47456817Sralph ospeed = ttspeedtab(t->c_ospeed, sccspeedtab); 47556817Sralph if (ospeed < 0) 47656817Sralph return (EINVAL); 47756817Sralph /* and copy to tty */ 47856817Sralph tp->t_ispeed = t->c_ispeed; 47956817Sralph tp->t_ospeed = t->c_ospeed; 48056817Sralph tp->t_cflag = cflag; 48156817Sralph 48256817Sralph /* 48356817Sralph * Handle console specially. 48456817Sralph */ 48556817Sralph if (cn_tab.cn_screen) { 48656817Sralph if (minor(tp->t_dev) == SCCKBD_PORT) { 48756817Sralph cflag = CS8; 48856817Sralph ospeed = ttspeedtab(4800, sccspeedtab); 48956817Sralph } else if (minor(tp->t_dev) == SCCMOUSE_PORT) { 49056817Sralph cflag = CS8 | PARENB | PARODD; 49156817Sralph ospeed = ttspeedtab(4800, sccspeedtab); 49256817Sralph } 49356817Sralph } else if (tp->t_dev == cn_tab.cn_dev) { 49456817Sralph cflag = CS8; 49556817Sralph ospeed = ttspeedtab(9600, sccspeedtab); 49656817Sralph } 49756817Sralph if (ospeed == 0) { 49856817Sralph (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */ 49956817Sralph return (0); 50056817Sralph } 50156817Sralph 50256817Sralph /* reset line */ 50356817Sralph if (line == SCC_CHANNEL_A) 50456817Sralph value = SCC_WR9_RESET_CHA_A; 50556817Sralph else 50656817Sralph value = SCC_WR9_RESET_CHA_B; 50756817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, value); 50856817Sralph DELAY(25); 50956817Sralph 51056817Sralph /* stop bits, normally 1 */ 51156817Sralph value = sc->scc_wreg[line].wr4 & 0xf0; 51256817Sralph if (cflag & CSTOPB) 51356817Sralph value |= SCC_WR4_2_STOP; 51456817Sralph else 51556817Sralph value |= SCC_WR4_1_STOP; 51656817Sralph if ((cflag & PARODD) == 0) 51756817Sralph value |= SCC_WR4_EVEN_PARITY; 51856817Sralph if (cflag & PARENB) 51956817Sralph value |= SCC_WR4_PARITY_ENABLE; 52056817Sralph 52156817Sralph /* set it now, remember it must be first after reset */ 52256817Sralph sc->scc_wreg[line].wr4 = value; 52356817Sralph SCC_WRITE_REG(regs, line, SCC_WR4, value); 52456817Sralph 52556817Sralph /* vector again */ 52656817Sralph SCC_WRITE_REG(regs, line, SCC_WR2, 0xf0); 52756817Sralph 52856817Sralph /* clear break, keep rts dtr */ 52956817Sralph wvalue = sc->scc_wreg[line].wr5 & (SCC_WR5_DTR|SCC_WR5_RTS); 53056817Sralph switch (cflag & CSIZE) { 53156817Sralph case CS5: 53256817Sralph value = SCC_WR3_RX_5_BITS; 53356817Sralph wvalue |= SCC_WR5_TX_5_BITS; 53456817Sralph break; 53556817Sralph case CS6: 53656817Sralph value = SCC_WR3_RX_6_BITS; 53756817Sralph wvalue |= SCC_WR5_TX_6_BITS; 53856817Sralph break; 53956817Sralph case CS7: 54056817Sralph value = SCC_WR3_RX_7_BITS; 54156817Sralph wvalue |= SCC_WR5_TX_7_BITS; 54256817Sralph break; 54356817Sralph case CS8: 54456817Sralph default: 54556817Sralph value = SCC_WR3_RX_8_BITS; 54656817Sralph wvalue |= SCC_WR5_TX_8_BITS; 54756817Sralph }; 54856817Sralph sc->scc_wreg[line].wr3 = value; 54956817Sralph SCC_WRITE_REG(regs, line, SCC_WR3, value); 55056817Sralph sc->scc_wreg[line].wr5 = wvalue; 55156817Sralph SCC_WRITE_REG(regs, line, SCC_WR5, wvalue); 55256817Sralph SCC_WRITE_REG(regs, line, SCC_WR6, 0); 55356817Sralph SCC_WRITE_REG(regs, line, SCC_WR7, 0); 55456817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, SCC_WR9_VIS); 55556817Sralph SCC_WRITE_REG(regs, line, SCC_WR10, 0); 55656817Sralph value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR | 55756817Sralph SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR; 55856817Sralph SCC_WRITE_REG(regs, line, SCC_WR11, value); 55956817Sralph SCC_SET_TIMING_BASE(regs, line, ospeed); 56056817Sralph value = sc->scc_wreg[line].wr14; 56156817Sralph SCC_WRITE_REG(regs, line, SCC_WR14, value); 56256817Sralph value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE; 56356817Sralph SCC_WRITE_REG(regs, line, SCC_WR15, value); 56456817Sralph 56556817Sralph /* and now the enables */ 56656817Sralph value = sc->scc_wreg[line].wr3 | SCC_WR3_RX_ENABLE; 56756817Sralph SCC_WRITE_REG(regs, line, SCC_WR3, value); 56856817Sralph value = sc->scc_wreg[line].wr5 | SCC_WR5_TX_ENABLE; 56956817Sralph sc->scc_wreg[line].wr5 = value; 57056817Sralph SCC_WRITE_REG(regs, line, SCC_WR5, value); 57156817Sralph 57256817Sralph /* master inter enable */ 57356817Sralph value = SCC_WR9_MASTER_IE | SCC_WR9_VIS; 57456817Sralph SCC_WRITE_REG(regs, line, SCC_WR9, value); 57556817Sralph SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1); 57656817Sralph MachEmptyWriteBuffer(); 57756817Sralph return (0); 57856817Sralph } 57956817Sralph 58056817Sralph /* 58156817Sralph * Check for interrupts from all devices. 58256817Sralph */ 58356817Sralph void 58456817Sralph sccintr(unit) 58556817Sralph register int unit; 58656817Sralph { 58756817Sralph register scc_regmap_t *regs; 58856817Sralph register struct tty *tp; 58956817Sralph register struct pdma *dp; 59056817Sralph register struct scc_softc *sc; 59156817Sralph register int cc, chan, rr1, rr2, rr3; 59256817Sralph int overrun = 0; 59356817Sralph 59456817Sralph sc = &scc_softc[unit]; 59556817Sralph regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr; 59656817Sralph unit <<= 1; 59756817Sralph for (;;) { 59856817Sralph SCC_READ_REG(regs, SCC_CHANNEL_B, SCC_RR2, rr2); 59956817Sralph rr2 = SCC_RR2_STATUS(rr2); 60056817Sralph /* are we done yet ? */ 60156817Sralph if (rr2 == 6) { /* strange, distinguished value */ 60256817Sralph SCC_READ_REG(regs, SCC_CHANNEL_A, SCC_RR3, rr3); 60356817Sralph if (rr3 == 0) 60456817Sralph return; 60556817Sralph } 60656817Sralph 60756817Sralph SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS); 60856817Sralph if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) { 60956817Sralph chan = (rr2 == SCC_RR2_A_XMIT_DONE) ? 61056817Sralph SCC_CHANNEL_A : SCC_CHANNEL_B; 61156817Sralph tp = &scc_tty[unit | chan]; 612*64979Smckusick dp = &sc->scc_pdma[chan]; 61356817Sralph if (dp->p_mem < dp->p_end) { 61456817Sralph SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 61556817Sralph MachEmptyWriteBuffer(); 61656817Sralph } else { 61756817Sralph tp->t_state &= ~TS_BUSY; 61856817Sralph if (tp->t_state & TS_FLUSH) 61956817Sralph tp->t_state &= ~TS_FLUSH; 62056817Sralph else { 62156817Sralph ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 62256817Sralph dp->p_end = dp->p_mem = tp->t_outq.c_cf; 62356817Sralph } 62456817Sralph if (tp->t_line) 62556817Sralph (*linesw[tp->t_line].l_start)(tp); 62656817Sralph else 62756817Sralph sccstart(tp); 62856817Sralph if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 62956817Sralph SCC_READ_REG(regs, chan, SCC_RR15, cc); 63056817Sralph cc &= ~SCC_WR15_TX_UNDERRUN_IE; 63156817Sralph SCC_WRITE_REG(regs, chan, SCC_WR15, cc); 63256817Sralph cc = sc->scc_wreg[chan].wr1 & ~SCC_WR1_TX_IE; 63356817Sralph SCC_WRITE_REG(regs, chan, SCC_WR1, cc); 63456817Sralph sc->scc_wreg[chan].wr1 = cc; 63556817Sralph MachEmptyWriteBuffer(); 63656817Sralph } 63756817Sralph } 63857234Sralph } else if (rr2 == SCC_RR2_A_RECV_DONE || 63957234Sralph rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL || 64057234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 64157234Sralph if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL) 64257234Sralph chan = SCC_CHANNEL_A; 64357234Sralph else 64457234Sralph chan = SCC_CHANNEL_B; 64557234Sralph tp = &scc_tty[unit | chan]; 64657234Sralph SCC_READ_DATA(regs, chan, cc); 64757234Sralph if (rr2 == SCC_RR2_A_RECV_SPECIAL || 64857234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 64957234Sralph SCC_READ_REG(regs, chan, SCC_RR1, rr1); 65057234Sralph SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_ERROR); 65157234Sralph if ((rr1 & SCC_RR1_RX_OVERRUN) && overrun == 0) { 65257234Sralph log(LOG_WARNING, "scc%d,%d: silo overflow\n", 65357234Sralph unit >> 1, chan); 65457234Sralph overrun = 1; 65557234Sralph } 65657234Sralph } 65756817Sralph 65856817Sralph /* 65956817Sralph * Keyboard needs special treatment. 66056817Sralph */ 66156817Sralph if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 66256817Sralph #ifdef KADB 66356817Sralph if (cc == LK_DO) { 66456817Sralph spl0(); 66556817Sralph kdbpanic(); 66656817Sralph return; 66756817Sralph } 66856817Sralph #endif 66956817Sralph #ifdef DEBUG 67056817Sralph debugChar = cc; 67156817Sralph #endif 67256817Sralph if (sccDivertXInput) { 67356817Sralph (*sccDivertXInput)(cc); 67456817Sralph continue; 67556817Sralph } 67656817Sralph if ((cc = kbdMapChar(cc)) < 0) 67756817Sralph continue; 67856817Sralph /* 67956817Sralph * Now for mousey 68056817Sralph */ 68156817Sralph } else if (tp == &scc_tty[SCCMOUSE_PORT] && sccMouseButtons) { 68256817Sralph register MouseReport *mrp; 68356817Sralph static MouseReport currentRep; 68456817Sralph 68556817Sralph mrp = ¤tRep; 68656817Sralph mrp->byteCount++; 68756817Sralph if (cc & MOUSE_START_FRAME) { 68856817Sralph /* 68956817Sralph * The first mouse report byte (button state). 69056817Sralph */ 69156817Sralph mrp->state = cc; 69256817Sralph if (mrp->byteCount > 1) 69356817Sralph mrp->byteCount = 1; 69456817Sralph } else if (mrp->byteCount == 2) { 69556817Sralph /* 69656817Sralph * The second mouse report byte (delta x). 69756817Sralph */ 69856817Sralph mrp->dx = cc; 69956817Sralph } else if (mrp->byteCount == 3) { 70056817Sralph /* 70156817Sralph * The final mouse report byte (delta y). 70256817Sralph */ 70356817Sralph mrp->dy = cc; 70456817Sralph mrp->byteCount = 0; 70556817Sralph if (mrp->dx != 0 || mrp->dy != 0) { 70656817Sralph /* 70756817Sralph * If the mouse moved, 70856817Sralph * post a motion event. 70956817Sralph */ 71056817Sralph (*sccMouseEvent)(mrp); 71156817Sralph } 71256817Sralph (*sccMouseButtons)(mrp); 71356817Sralph } 71456817Sralph continue; 71556817Sralph } 71656817Sralph if (!(tp->t_state & TS_ISOPEN)) { 71756817Sralph wakeup((caddr_t)&tp->t_rawq); 71856817Sralph #ifdef PORTSELECTOR 71956817Sralph if (!(tp->t_state & TS_WOPEN)) 72056817Sralph #endif 72156817Sralph continue; 72256817Sralph } 72357234Sralph if (rr2 == SCC_RR2_A_RECV_SPECIAL || 72457234Sralph rr2 == SCC_RR2_B_RECV_SPECIAL) { 72557234Sralph if (rr1 & SCC_RR1_PARITY_ERR) 72657234Sralph cc |= TTY_PE; 72757234Sralph if (rr1 & SCC_RR1_FRAME_ERR) 72857234Sralph cc |= TTY_FE; 72956817Sralph } 73056817Sralph (*linesw[tp->t_line].l_rint)(cc, tp); 73156817Sralph } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) { 73256817Sralph chan = (rr2 == SCC_RR2_A_EXT_STATUS) ? 73356817Sralph SCC_CHANNEL_A : SCC_CHANNEL_B; 73456817Sralph SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_EXT_IP); 73556817Sralph scc_modem_intr(unit | chan); 73656817Sralph } 73756817Sralph } 73856817Sralph } 73956817Sralph 74056817Sralph void 74156817Sralph sccstart(tp) 74256817Sralph register struct tty *tp; 74356817Sralph { 74456817Sralph register struct pdma *dp; 74556817Sralph register scc_regmap_t *regs; 74656817Sralph register struct scc_softc *sc; 74756817Sralph register int cc, chan; 74856817Sralph u_char temp; 74957234Sralph int s, sendone; 75056817Sralph 751*64979Smckusick sc = &scc_softc[SCCUNIT(tp->t_dev)]; 752*64979Smckusick dp = &sc->scc_pdma[SCCLINE(tp->t_dev)]; 75356817Sralph regs = (scc_regmap_t *)dp->p_addr; 75456817Sralph s = spltty(); 75556817Sralph if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 75656817Sralph goto out; 75756817Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 75856817Sralph if (tp->t_state & TS_ASLEEP) { 75956817Sralph tp->t_state &= ~TS_ASLEEP; 76056817Sralph wakeup((caddr_t)&tp->t_outq); 76156817Sralph } 76256817Sralph selwakeup(&tp->t_wsel); 76356817Sralph } 76456817Sralph if (tp->t_outq.c_cc == 0) 76556817Sralph goto out; 76656817Sralph /* handle console specially */ 76756817Sralph if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) { 76856817Sralph while (tp->t_outq.c_cc > 0) { 76956817Sralph cc = getc(&tp->t_outq) & 0x7f; 77056817Sralph cnputc(cc); 77156817Sralph } 77256817Sralph /* 77356817Sralph * After we flush the output queue we may need to wake 77456817Sralph * up the process that made the output. 77556817Sralph */ 77656817Sralph if (tp->t_outq.c_cc <= tp->t_lowat) { 77756817Sralph if (tp->t_state & TS_ASLEEP) { 77856817Sralph tp->t_state &= ~TS_ASLEEP; 77956817Sralph wakeup((caddr_t)&tp->t_outq); 78056817Sralph } 78156817Sralph selwakeup(&tp->t_wsel); 78256817Sralph } 78356817Sralph goto out; 78456817Sralph } 78556817Sralph if (tp->t_flags & (RAW|LITOUT)) 78656817Sralph cc = ndqb(&tp->t_outq, 0); 78756817Sralph else { 78856817Sralph cc = ndqb(&tp->t_outq, 0200); 78956817Sralph if (cc == 0) { 79056817Sralph cc = getc(&tp->t_outq); 79156817Sralph timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); 79256817Sralph tp->t_state |= TS_TIMEOUT; 79356817Sralph goto out; 79456817Sralph } 79556817Sralph } 79656817Sralph tp->t_state |= TS_BUSY; 79756817Sralph dp->p_end = dp->p_mem = tp->t_outq.c_cf; 79856817Sralph dp->p_end += cc; 79956817Sralph 80056817Sralph /* 80156817Sralph * Enable transmission and send the first char, as required. 80256817Sralph */ 80356817Sralph chan = SCCLINE(tp->t_dev); 80457234Sralph SCC_READ_REG(regs, chan, SCC_RR0, temp); 80557234Sralph sendone = (temp & SCC_RR0_TX_EMPTY); 80656817Sralph SCC_READ_REG(regs, chan, SCC_RR15, temp); 80756817Sralph temp |= SCC_WR15_TX_UNDERRUN_IE; 80856817Sralph SCC_WRITE_REG(regs, chan, SCC_WR15, temp); 80956817Sralph temp = sc->scc_wreg[chan].wr1 | SCC_WR1_TX_IE; 81056817Sralph SCC_WRITE_REG(regs, chan, SCC_WR1, temp); 81156817Sralph sc->scc_wreg[chan].wr1 = temp; 81257234Sralph if (sendone) { 81356817Sralph #ifdef DIAGNOSTIC 81456817Sralph if (cc == 0) 81556817Sralph panic("sccstart: No chars"); 81656817Sralph #endif 81756817Sralph SCC_WRITE_DATA(regs, chan, *dp->p_mem++); 81856817Sralph } 81956817Sralph MachEmptyWriteBuffer(); 82056817Sralph out: 82156817Sralph splx(s); 82256817Sralph } 82356817Sralph 82456817Sralph /* 82556817Sralph * Stop output on a line. 82656817Sralph */ 82756817Sralph /*ARGSUSED*/ 82856817Sralph sccstop(tp, flag) 82956817Sralph register struct tty *tp; 83056817Sralph { 83156817Sralph register struct pdma *dp; 832*64979Smckusick register struct scc_softc *sc; 83356817Sralph register int s; 83456817Sralph 835*64979Smckusick sc = &scc_softc[SCCUNIT(tp->t_dev)]; 836*64979Smckusick dp = &sc->scc_pdma[SCCLINE(tp->t_dev)]; 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 chan = SCCLINE(dev); 923*64979Smckusick regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr; 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