📄 scc.c
字号:
*/ if (!rex_base) { if ((atoi(prom_getenv("osconsole")) & 0x1) == 1) { slu.mouse_init = scc_mouse_init; slu.mouse_putc = scc_mouse_putc; slu.mouse_getc = scc_mouse_getc; slu.kbd_init = scc_kbd_init; slu.kbd_putc = scc_kbd_putc; slu.kbd_getc = scc_kbd_getc; slu.slu_tty = scc_tty; slu.slu_putc = scc_putc; for( i = 0 ; vcons_init[i] ; i++ ) if ((*vcons_init[i])()) { /* found a virtual console */ consDev = GRAPHIC_DEV; return; } } scc_init(0); /* need to initialize channel A for modem control */ scc_init(1); /* * set up line 3 as alternate console line: no parity, 9600 baud */ scc_init(3); } else { if ((strlen(rex_getenv("osconsole"))) > 1) { slu.mouse_init = scc_mouse_init; slu.mouse_putc = scc_mouse_putc; slu.mouse_getc = scc_mouse_getc; slu.kbd_init = scc_kbd_init; slu.kbd_putc = scc_kbd_putc; slu.kbd_getc = scc_kbd_getc; slu.slu_tty = scc_tty; slu.slu_putc = scc_putc; for( i = 0 ; vcons_init[i] ; i++ ) if ((*vcons_init[i])()) { /* found a virtual console */ consDev = GRAPHIC_DEV; return; } } scc_init(0); /* need to initialize channel A for modem control */ scc_init(1); /* * set up line 3 as alternate console line: no parity, 9600 baud */ scc_init(3); } /* enable functions */ rsp = sc->sc_regs[3]; ssp = &sc->sc_saved_regs[3]; ssp->wr14 |= SCC_WR14_BRGEN_EN; SCC_WRITE(rsp, SCC_WR14, ssp->wr14); /* WR14 BRG enable */ ssp->wr5 |= SCC_WR5_TXEN; SCC_WRITE(rsp, SCC_WR5, ssp->wr5); /* WR5 Tx enable */ ssp->wr3 |= SCC_WR3_RXEN; SCC_WRITE(rsp, SCC_WR3, ssp->wr3); /* WR3 Rx enable */}sccopen(dev, flag) dev_t dev;{ register struct scc_softc *sc = sccsc; register struct tty *tp; register int unit; register int maj, error; int inuse; /*hold state of inuse bit while blocked waiting for carr*/ register struct scc_reg *rsp, *rsp0; register struct scc_saved_reg *ssp0; maj = major(dev); unit = minor(dev); /* * If a diagnostic console is attached to SLU line 3, * don't allow open of the printer port (also line 3). * This could cause lpr to write to the console. */ if((consDev != GRAPHIC_DEV) && (unit == 3)) return (ENXIO); /* don't allow open of minor device 0 of major device SCCMAJOR */ /* because it is already reserved for /dev/console */ if ((maj != CONSOLEMAJOR) && (unit == 0)) return (ENXIO); /* only allow open of /dev/console of major device 0 */ if ((maj == CONSOLEMAJOR) && (unit != 0)) return (ENXIO); if ((consDev != GRAPHIC_DEV) && (maj == CONSOLEMAJOR) && (unit == 0)) unit |= 3; /* diag console on SLU line 3 */ if (unit >= scc_cnt) return (ENXIO); /* * Call the graphics device open routine * if there is one and the open if for the fancy tube. */ if (vs_gdopen && (unit <= 1)) { error = (*vs_gdopen)(dev, flag); if (error == 0) { sccparam(unit); SCC_INT_ON(unit); /* turn on interrupts for kbd and mouse */ } return(error); } tp = &scc_tty[unit]; rsp = sc->sc_regs[unit]; if (tp->t_state&TS_XCLUDE && u.u_uid != 0) { return (EBUSY); } while (tp->t_state&TS_CLOSING) { /* let DTR stay down for awhile */ sleep((caddr_t)&tp->t_rawq, TTIPRI); } tp->t_addr = (caddr_t)tp; tp->t_oproc = sccstart; tp->t_baudrate = sccbaudrate; tty_def_open(tp, dev, flag, (sccsoftCAR&(1<<(unit&LINEMASK)))); if ((tp->t_state & TS_ISOPEN) == 0) { /* * Prevent spurious startups by making the 500ms timer * initially high. */ sccmodem[unit] = MODEM_DSR_START; if((maj == CONSOLEMAJOR) && ((minor(dev)&3) == 0)) { tp->t_cflag &= ~CBAUD; tp->t_cflag |= B9600; /* modem control not supported on console */ tp->t_cflag |= CLOCAL; tp->t_cflag_ext &= ~CBAUD; tp->t_cflag_ext |= B9600; tp->t_flags = ANYP|ECHO|CRMOD; tp->t_iflag |= ICRNL; /* Map CRMOD */ tp->t_oflag |= ONLCR; /* Map CRMOD */ } } sccparam(unit); SCC_INT_ON(unit); /* enable interrupts */ (void) spltty(); /* * No modem control provided for lines with softCAR set. */ if (tp->t_cflag & CLOCAL) { /* * This is a local connection - ignore carrier * receive enable interrupts enabled above */ tp->t_state |= TS_CARR_ON; /* * Turn off external modem interrupts */ SCC_MODEM_OFF(unit); SCC_SET_DTR(unit); SCC_SET_RTS(unit); SCC_SET_SS(unit); /* * Set state bit to tell tty.c not to assign this line as the * controlling terminal for the process which opens this line. */ if ((flag & O_NOCTTY) && (u.u_procp->p_progenv == A_POSIX)) tp->t_state |= TS_ONOCTTY; (void) spl0(); return ((*linesw[tp->t_line].l_open)(dev, tp)); } /* * this is a modem line */ SCC_MODEM_ON(unit); /* enable modem interrupts */ SCC_SET_DTR(unit); SCC_SET_RTS(unit); SCC_SET_SS(unit); /* * After DSR first comes up we must wait for the other signals * before commencing transmission. */ if ((flag & (O_NDELAY|O_NONBLOCK)) == 0) { /* * Delay before examining other signals if DSR is being followed * otherwise proceed directly to scc_dsr_check to look for * carrier detect and clear to send. */ if (SCC_DSR(unit)) { sccmodem[unit] |= (MODEM_DSR_START|MODEM_DSR); tp->t_dev = dev; /* need it for timeouts */ /* * Give CD and CTS 30 sec. to * come up. Start transmission * immediately, no longer need * 500ms delay. */ timeout(scc_dsr_check, tp, hz*30); scc_dsr_check(tp); } } if (flag & (O_NDELAY|O_NONBLOCK)) tp->t_state |= TS_ONDELAY; else while ((tp->t_state & TS_CARR_ON) == 0) { tp->t_state |= TS_WOPEN; inuse = tp->t_state&TS_INUSE; sleep((caddr_t)&tp->t_rawq, TTIPRI); /* * See if we were awoken by a false call to the modem * line by a non-modem. */ if (sccmodem[unit]&MODEM_BADCALL){ (void) spl0(); return(EWOULDBLOCK); } /* if we opened "block if in use" and * the terminal was not inuse at that time * but is became "in use" while we were * waiting for carrier then return */ if ((flag & O_BLKINUSE) && (inuse==0) && (tp->t_state&TS_INUSE)) { (void) spl0(); return(EALREADY); } } /* * Set state bit to tell tty.c not to assign this line as the * controlling terminal for the process which opens this line. */ if ((flag & O_NOCTTY) && (u.u_procp->p_progenv == A_POSIX)) tp->t_state |= TS_ONOCTTY; (void) spl0(); return ((*linesw[tp->t_line].l_open)(dev, tp));}sccclose(dev, flag) dev_t dev;{ register struct scc_softc *sc = sccsc; register struct tty *tp; register int unit, maj; register int s; extern int wakeup(); unit = minor(dev); maj = major(dev); if((consDev != GRAPHIC_DEV) && (major(dev) == CONSOLEMAJOR) && ((unit&LINEMASK) == 0)) unit |= 3; /* diag console on SLU line 3 */ /* * Call the graphics device close routine * if ther is one and the close is for it. */ if (vs_gdclose && (unit <= 1)) { (*vs_gdclose)(dev, flag); return; } tp = &scc_tty[unit]; /* * Do line discipline specific close functions then return here * in the old line disc for final closing. */ if (tp->t_line) (*linesw[tp->t_line].l_close)(tp); /* * Clear breaks for this line on close. */ s = spltty(); SCC_CLR_BRK(unit); splx(s); if ((tp->t_cflag&HUPCL) || (tp->t_state&TS_WOPEN) || (tp->t_state&TS_ISOPEN)==0) { tp->t_state &= ~TS_CARR_ON; /* prevents recv intr. timeouts */ /* * Drop appropriate signals to terminate the connection. */ SCC_CLR_DTR(unit); SCC_CLR_RTS(unit); SCC_CLR_SS(unit); if ((tp->t_cflag & CLOCAL) == 0) { s = spltty(); /*drop DTR for at least a sec. if modem line*/ tp->t_state |= TS_CLOSING; /* * Wait at most 5 sec for DSR to go off. * Also hold DTR down for a period. */ if (SCC_DSR(unit)) { timeout(wakeup,(caddr_t)&tp->t_dev,5*hz); sleep((caddr_t)&tp->t_dev, PZERO-10); } /* * Hold DTR down for 200+ ms. */ timeout(wakeup, (caddr_t) &tp->t_dev, hz/5); sleep((caddr_t)&tp->t_dev, PZERO-10); tp->t_state &= ~(TS_CLOSING); wakeup((caddr_t)&tp->t_rawq); splx(s); } /* * No disabling of interrupts is done. Characters read in on * a non-open line will be discarded. */ } /* reset line to default mode */ sccsoftCAR &= ~(1<<(unit&LINEMASK)); sccsoftCAR |= (1<<(unit&LINEMASK)) & sccdefaultCAR; sccmodem[unit] = 0; /* ttyclose() must be called before clear up termio flags */ ttyclose(tp); tty_def_close(tp);}sccread(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp; register int unit; unit = minor(dev); if((consDev != GRAPHIC_DEV) && (major(dev) == CONSOLEMAJOR) && ((unit&LINEMASK) == 0)) unit |= 3; /* diag console on SLU line 3 */ tp = &scc_tty[unit]; return ((*linesw[tp->t_line].l_read)(tp, uio));}sccwrite(dev, uio) dev_t dev; struct uio *uio;{ register struct tty *tp; register int unit; unit = minor(dev); if((consDev != GRAPHIC_DEV) && (major(dev) == CONSOLEMAJOR) && ((unit&LINEMASK) == 0)) unit |= 3; /* diag console on SLU line 3 */ /* * Don't allow writes to the mouse, * just fake the I/O and return. */ if (vs_gdopen && (unit == 1)) { uio->uio_offset = uio->uio_resid; uio->uio_resid = 0; return(0); } tp = &scc_tty[unit]; return ((*linesw[tp->t_line].l_write)(tp, uio));}sccselect(dev, rw) dev_t dev;{ register int unit = minor(dev); if((consDev != GRAPHIC_DEV) && (major(dev) == CONSOLEMAJOR) && (unit == 0)) dev |= 3; if ((unit == 1) && vs_gdselect) { return((*vs_gdselect)(dev, rw)); } return(ttselect(dev, rw));}sccintr(){ register struct scc_reg *rsp; register char ip; register struct scc_softc *sc = sccsc; register int sir; IOC_RD(IOC_SIR, sir); /* read sir */ while (sir & SCC_INTR) { /* error routines must appear before the regular routines */ if (sir & SIR_COMM1_RERROR) /* comm. port1 receive DMA error */ scc_dma_rerror(SCC_COMM1); if (sir & SIR_COMM1_RINT) /* comm. port1 receive interrupt */ scc_dma_rint(SCC_COMM1); if (sir & SIR_COMM2_RERROR) /* comm. port2 receive DMA error */ scc_dma_rerror(SCC_COMM2); if (sir & SIR_COMM2_RINT) /* comm. port2 receive interrupt */ scc_dma_rint(SCC_COMM2); if (sir & SIR_COMM1_XERROR) /* comm. port1 transmit DMA error */ scc_dma_xerror(SCC_COMM1); if (sir & SIR_COMM1_XINT) /* comm. port1 transmit interrupt */ scc_dma_xint(SCC_COMM1); if (sir & SIR_COMM2_XERROR) /* comm. port2 transmit DMA error */ scc_dma_xerror(SCC_COMM2); if (sir & SIR_COMM2_XINT) /* comm. port2 transmit interrupt */ scc_dma_xint(SCC_COMM2); if (sir & SIR_SCC1) { /* SCC(1) serial interrupt */ rsp = sc->sc_regs[SCC1_A]; /* channel A of SCC(1) */ SCC_READ(rsp, SCC_RR3, ip); /* read RR3A for interrupts pending */ while (ip) { if (ip & SCC_RR3_B_EXT_IP) { /* channel B external/status IP */ scc_ext_rint(SCC_COMM2); sc->sc_regs[SCC1_B]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; } if (ip & SCC_RR3_A_EXT_IP) { /* channel A external/status IP */ scc_ext_rint(SCC_COMM2); sc->sc_regs[SCC1_A]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; } if (ip & SCC_RR3_B_RIP) /* channel B receive IP */ scc_spec_rint(SCC_COMM2); if (ip & SCC_RR3_A_RIP) /* channel A receive IP */ scc_mkbd_rint(SCC_KYBD); SCC_READ(rsp, SCC_RR3, ip); /* read RR3A */ } } if (sir & SIR_SCC0) { /* SCC(0) serial interrupt */ rsp = sc->sc_regs[SCC0_A]; SCC_READ(rsp, SCC_RR3, ip); /* read RR3A */ while (ip) { IOC_RD(IOC_SIR, sir); if (ip & SCC_RR3_B_EXT_IP) { scc_ext_rint(SCC_COMM1); sc->sc_regs[SCC0_B]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; SCC_READ(rsp, SCC_RR3, ip); } if (ip & SCC_RR3_A_EXT_IP) { scc_ext_rint(SCC_COMM1); sc->sc_regs[SCC0_A]->SCC_CMD = SCC_WR0_RESET_EXT_INT<<8; } if (ip & SCC_RR3_B_RIP) scc_spec_rint(SCC_COMM1); if (ip & SCC_RR3_A_RIP) scc_mkbd_rint(SCC_MOUSE); SCC_READ(rsp, SCC_RR3, ip); /* read RR3A */ } } IOC_RD(IOC_SIR, sir); /* read sir */ } /* while */}/* should never happen */scc_dma_rerror(line) register int line;{ register struct scc_softc *sc = sccsc; printf("Com. Port. Receive DMA Overrun, line = %d\n", line); sc->ioc_regs[line]->RDMA_REG = (u_long) /* reset DMA pointer */ (svtophy(sc->rbuf[line][sc->rflag[line]] + SCC_HALF_PAGE - SCC_WORD) << 3); IOC_WR(IOC_SIR, ~scc_rerror[line]); /* clear error bit to restart */}scc_dma_xerror(line) register int line;{ register struct scc_softc *sc = sccsc; caddr_t pa; struct tc_memerr_status status; pa = (caddr_t)((sc->ioc_regs[line]->XDMA_REG) >> 3); printf("Com. Port. Transmit DMA Read Error, line = %d\n", line); status.pa = pa; status.va = 0; status.log = TC_LOG_MEMERR; status.blocksize = 1; tc_isolate_memerr(&status); IOC_SET(IOC_SSR, scc_xdma_en[line]); /* enable transmit DMA */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -