📄 com.c
字号:
tp->t_param = comparam; tp->t_dev = dev; if (!ISSET(tp->t_state, TS_ISOPEN)) { SET(tp->t_state, TS_WOPEN); ttychars(tp); tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) tp->t_cflag = comconscflag; else tp->t_cflag = TTYDEF_CFLAG; if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) SET(tp->t_cflag, CLOCAL); if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) SET(tp->t_cflag, CRTSCTS); if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) SET(tp->t_cflag, MDMBUF); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = comdefaultrate; s = spltty(); sc->sc_initialize = 1; comparam(tp, &tp->t_termios); ttsetwater(tp); if (comsopen++ == 0) timeout(compoll, NULL, 1); sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; iot = sc->sc_iot; ioh = sc->sc_ioh; /* * Wake up the sleepy heads. */ switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: bus_space_write_1(iot, ioh, com_lcr, 0xbf); bus_space_write_1(iot, ioh, com_efr, EFR_ECB); bus_space_write_1(iot, ioh, com_ier, 0); bus_space_write_1(iot, ioh, com_efr, 0); bus_space_write_1(iot, ioh, com_lcr, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, 0); break; } if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST; u_int8_t lcr; if (tp->t_ispeed <= 1200) fifo |= FIFO_TRIGGER_1; else fifo |= FIFO_TRIGGER_8; if (sc->sc_uarttype == COM_UART_TI16750) { fifo |= FIFO_ENABLE_64BYTE; lcr = bus_space_read_1(iot, ioh, com_lcr); bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); } /* * (Re)enable and drain FIFOs. * * Certain SMC chips cause problems if the FIFOs are * enabled while input is ready. Turn off the FIFO * if necessary to clear the input. Test the input * ready bit after enabling the FIFOs to handle races * between enabling and fresh input. * * Set the FIFO threshold based on the receive speed. */ for (;;) { bus_space_write_1(iot, ioh, com_fifo, 0); delay(100); (void) bus_space_read_1(iot, ioh, com_data); bus_space_write_1(iot, ioh, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST); delay(100); if(!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) break; } if (sc->sc_uarttype == COM_UART_TI16750) bus_space_write_1(iot, ioh, com_lcr, lcr); } /* flush any pending I/O */ while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) (void) bus_space_read_1(iot, ioh, com_data); /* you turn me on, baby */ sc->sc_mcr = MCR_DTR | MCR_RTS; if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) SET(sc->sc_mcr, MCR_IENABLE); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC; bus_space_write_1(iot, ioh, com_ier, sc->sc_ier); sc->sc_msr = bus_space_read_1(iot, ioh, com_msr); if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) || ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) SET(tp->t_state, TS_CARR_ON); else CLR(tp->t_state, TS_CARR_ON); } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) return EBUSY; else s = spltty(); if (DEVCUA(dev)) { if (ISSET(tp->t_state, TS_ISOPEN)) { /* Ah, but someone already is dialed in... */ splx(s); return EBUSY; } sc->sc_cua = 1; /* We go into CUA mode */ } else { /* tty (not cua) device; wait for carrier if necessary */ if (ISSET(flag, O_NONBLOCK)) { if (sc->sc_cua) { /* Opening TTY non-blocking... but the CUA is busy */ splx(s); return EBUSY; } } else { while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON))) { SET(tp->t_state, TS_WOPEN); error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0); /* * If TS_WOPEN has been reset, that means the cua device * has been closed. We don't want to fail in that case, * so just go around again. */ if (error && ISSET(tp->t_state, TS_WOPEN)) { CLR(tp->t_state, TS_WOPEN); if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN)) compwroff(sc); splx(s); return error; } } } } splx(s); return (*linesw[tp->t_line].l_open)(dev, tp);} intcomclose(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p;{ int unit = DEVUNIT(dev); struct com_softc *sc = com_cd.cd_devs[unit]; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; struct tty *tp = sc->sc_tty; int s; /* XXX This is for cons.c. */ if (!ISSET(tp->t_state, TS_ISOPEN)) return 0; (*linesw[tp->t_line].l_close)(tp, flag); s = spltty(); if (ISSET(tp->t_state, TS_WOPEN)) { /* tty device is waiting for carrier; drop dtr then re-raise */ CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); timeout(com_raisedtr, sc, hz * 2); } else { /* no one else waiting; turn off the uart */ compwroff(sc); } CLR(tp->t_state, TS_BUSY | TS_FLUSH); if (--comsopen == 0) untimeout(compoll, NULL); sc->sc_cua = 0; splx(s); ttyclose(tp);#ifdef notyet /* XXXX */ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { ttyfree(tp); sc->sc_tty = 0; }#endif return 0;}voidcompwroff(sc) struct com_softc *sc;{ bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; struct tty *tp = sc->sc_tty; CLR(sc->sc_lcr, LCR_SBREAK); bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); bus_space_write_1(iot, ioh, com_ier, 0); if (ISSET(tp->t_cflag, HUPCL) && !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { /* XXX perhaps only clear DTR */ sc->sc_mcr = 0; bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } /* * Turn FIFO off; enter sleep mode if possible. */ bus_space_write_1(iot, ioh, com_fifo, 0); delay(100); (void) bus_space_read_1(iot, ioh, com_data); delay(100); bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST); switch (sc->sc_uarttype) { case COM_UART_ST16650: case COM_UART_ST16650V2: bus_space_write_1(iot, ioh, com_lcr, 0xbf); bus_space_write_1(iot, ioh, com_efr, EFR_ECB); bus_space_write_1(iot, ioh, com_ier, IER_SLEEP); bus_space_write_1(iot, ioh, com_lcr, 0); break; case COM_UART_TI16750: bus_space_write_1(iot, ioh, com_ier, IER_SLEEP); break; }}voidcom_raisedtr(arg) void *arg;{ struct com_softc *sc = arg; SET(sc->sc_mcr, MCR_DTR | MCR_RTS); bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);}intcomread(dev, uio, flag) dev_t dev; struct uio *uio; int flag;{ struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)]; struct tty *tp = sc->sc_tty; return ((*linesw[tp->t_line].l_read)(tp, uio, flag));} intcomwrite(dev, uio, flag) dev_t dev; struct uio *uio; int flag;{ struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)]; struct tty *tp = sc->sc_tty; return ((*linesw[tp->t_line].l_write)(tp, uio, flag));}struct tty *comtty(dev) dev_t dev;{ struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)]; struct tty *tp = sc->sc_tty; return (tp);} static u_chartiocm_xxx2mcr(data) int data;{ u_char m = 0; if (ISSET(data, TIOCM_DTR)) SET(m, MCR_DTR); if (ISSET(data, TIOCM_RTS)) SET(m, MCR_RTS); return m;}intcomioctl(dev, cmd, data, flag, p) dev_t dev; u_long cmd; caddr_t data; int flag; struct proc *p;{ int unit = DEVUNIT(dev); struct com_softc *sc = com_cd.cd_devs[unit]; struct tty *tp = sc->sc_tty; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int error; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return error; error = ttioctl(tp, cmd, data, flag, p); if (error >= 0) return error; switch (cmd) { case TIOCSBRK: SET(sc->sc_lcr, LCR_SBREAK); bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); break; case TIOCCBRK: CLR(sc->sc_lcr, LCR_SBREAK); bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr); break; case TIOCSDTR: SET(sc->sc_mcr, sc->sc_dtr); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); break; case TIOCCDTR: CLR(sc->sc_mcr, sc->sc_dtr); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); break; case TIOCMSET: CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); case TIOCMBIS: SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); break; case TIOCMBIC: CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); break; case TIOCMGET: { u_char m; int bits = 0; m = sc->sc_mcr; if (ISSET(m, MCR_DTR)) SET(bits, TIOCM_DTR); if (ISSET(m, MCR_RTS)) SET(bits, TIOCM_RTS); m = sc->sc_msr; if (ISSET(m, MSR_DCD)) SET(bits, TIOCM_CD); if (ISSET(m, MSR_CTS)) SET(bits, TIOCM_CTS); if (ISSET(m, MSR_DSR)) SET(bits, TIOCM_DSR); if (ISSET(m, MSR_RI | MSR_TERI)) SET(bits, TIOCM_RI); if (bus_space_read_1(iot, ioh, com_ier)) SET(bits, TIOCM_LE); *(int *)data = bits; break; } case TIOCGFLAGS: { int driverbits, userbits = 0; driverbits = sc->sc_swflags; if (ISSET(driverbits, COM_SW_SOFTCAR)) SET(userbits, TIOCFLAG_SOFTCAR); if (ISSET(driverbits, COM_SW_CLOCAL)) SET(userbits, TIOCFLAG_CLOCAL); if (ISSET(driverbits, COM_SW_CRTSCTS)) SET(userbits, TIOCFLAG_CRTSCTS); if (ISSET(driverbits, COM_SW_MDMBUF)) SET(userbits, TIOCFLAG_MDMBUF); if (ISSET(driverbits, COM_SW_PPS)) SET(userbits, TIOCFLAG_PPS); *(int *)data = userbits; break; } case TIOCSFLAGS: { int userbits, driverbits = 0; error = suser(p->p_ucred, &p->p_acflag); if (error != 0) return(EPERM); userbits = *(int *)data; if (ISSET(userbits, TIOCFLAG_SOFTCAR) || ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) SET(driverbits, COM_SW_SOFTCAR); if (ISSET(userbits, TIOCFLAG_CLOCAL)) SET(driverbits, COM_SW_CLOCAL); if (ISSET(userbits, TIOCFLAG_CRTSCTS)) SET(driverbits, COM_SW_CRTSCTS); if (ISSET(userbits, TIOCFLAG_MDMBUF)) SET(driverbits, COM_SW_MDMBUF); if (ISSET(userbits, TIOCFLAG_PPS)) SET(driverbits, COM_SW_PPS); sc->sc_swflags = driverbits; break; } default: return ENOTTY; } return 0;}intcomparam(tp, t) struct tty *tp; struct termios *t;{ struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)]; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int ospeed = comspeed(t->c_ospeed); u_char lcr; tcflag_t oldcflag; int s; /* check requested parameters */ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return EINVAL; lcr = ISSET(sc->sc_lcr, LCR_SBREAK); switch (ISSET(t->c_cflag, CSIZE)) { case CS5: SET(lcr, LCR_5BITS); break; case CS6: SET(lcr, LCR_6BITS); break; case CS7: SET(lcr, LCR_7BITS); break; case CS8: SET(lcr, LCR_8BITS); break; } if (ISSET(t->c_cflag, PARENB)) { SET(lcr, LCR_PENAB); if (!ISSET(t->c_cflag, PARODD)) SET(lcr, LCR_PEVEN); } if (ISSET(t->c_cflag, CSTOPB)) SET(lcr, LCR_STOPB); sc->sc_lcr = lcr; s = spltty(); if (ospeed == 0) { CLR(sc->sc_mcr, MCR_DTR); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } /* * Set the FIFO threshold based on the receive speed, if we are * changing it. */ if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) { sc->sc_initialize = 0; if (ospeed != 0) { /* * Make sure the transmit FIFO is empty before * proceeding. If we don't do this, some revisions * of the UART will hang. Interestingly enough, * even if we do this while the last character is * still being pushed out, they don't hang. This * seems good enough. */ while (ISSET(tp->t_state, TS_BUSY)) { int error; ++sc->sc_halt; error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, "comprm", 0); --sc->sc_halt; if (error) { splx(s); comstart(tp); return (error); } } bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); bus_space_write_1(iot, ioh, com_dlbl, ospeed); bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8); bus_space_write_1(iot, ioh, com_lcr, lcr); SET(sc->sc_mcr, MCR_DTR); bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); } else bus_space_write_1(iot, ioh, com_lcr, lcr); if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) && ISSET(sc->sc_hwflags, COM_HW_FIFO)) { if (sc->sc_uarttype == COM_UART_TI16750) { bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | FIFO_ENABLE_64BYTE | (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); bus_space_write_1(iot, ioh, com_lcr, lcr); } else bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); } } else bus_space_write_1(iot, ioh, com_lcr, lcr); /* When not using CRTSCTS, RTS follows DTR. */ if (!ISSET(t->c_cflag, CRTSCTS)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -