📄 com.c
字号:
c = inb(com+com_data); if ((tp->t_state & TS_ISOPEN) == 0) {#ifdef KGDB /* we don't care about parity errors */ if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && kgdb_dev == makedev(commajor, unit) && c == FRAME_END) kgdb_connect(0); /* trap into kgdb */#endif return; } if (stat & (LSR_BI | LSR_FE)) c |= TTY_FE; else if (stat & LSR_PE) c |= TTY_PE; else if (stat & LSR_OE) log(LOG_WARNING, "com%d: silo overflow\n", unit); (*linesw[tp->t_line].l_rint)(c, tp);}commint(unit, com) register int unit; register com;{ register struct tty *tp; register int stat; tp = &com_tty[unit]; stat = inb(com+com_msr); if ((stat & MSR_DDCD) && (comsoftCAR & (1 << unit)) == 0) { if (stat & MSR_DCD) (void)(*linesw[tp->t_line].l_modem)(tp, 1); else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) outb(com+com_mcr, inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS) | MCR_IENABLE); } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && (tp->t_flags & CRTSCTS)) { /* the line is up and we want to do rts/cts flow control */ if (stat & MSR_CTS) { tp->t_state &=~ TS_TTSTOP; ttstart(tp); } else tp->t_state |= TS_TTSTOP; }}comioctl(dev, cmd, data, flag, p) dev_t dev; int cmd, flag; caddr_t data; struct proc *p;{ register struct tty *tp; register int unit = UNIT(dev); register com; register int error; tp = &com_tty[unit]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return (error); error = ttioctl(tp, cmd, data, flag); if (error >= 0) return (error); com = com_addr[unit]; switch (cmd) { case TIOCSBRK: outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_SBREAK); break; case TIOCCBRK: outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK); break; case TIOCSDTR: (void) commctl(dev, MCR_DTR | MCR_RTS, DMBIS); break; case TIOCCDTR: (void) commctl(dev, MCR_DTR | MCR_RTS, DMBIC); break; case TIOCMSET: (void) commctl(dev, *(int *)data, DMSET); break; case TIOCMBIS: (void) commctl(dev, *(int *)data, DMBIS); break; case TIOCMBIC: (void) commctl(dev, *(int *)data, DMBIC); break; case TIOCMGET: *(int *)data = commctl(dev, 0, DMGET); break; default: return (ENOTTY); } return (0);}comparam(tp, t) register struct tty *tp; register struct termios *t;{ register com; register int cfcr, cflag = t->c_cflag; int unit = UNIT(tp->t_dev); int ospeed = ttspeedtab(t->c_ospeed, comspeedtab); /* check requested parameters */ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) return(EINVAL); /* and copy to tty */ tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; tp->t_cflag = cflag; com = com_addr[unit]; outb(com+com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS /*| IER_EMSC*/); if (ospeed == 0) { (void) commctl(unit, 0, DMSET); /* hang up line */ return(0); } outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_DLAB); outb(com+com_data, ospeed & 0xFF); outb(com+com_ier, ospeed >> 8); switch (cflag&CSIZE) { case CS5: cfcr = CFCR_5BITS; break; case CS6: cfcr = CFCR_6BITS; break; case CS7: cfcr = CFCR_7BITS; break; case CS8: cfcr = CFCR_8BITS; break; } if (cflag&PARENB) { cfcr |= CFCR_PENAB; if ((cflag&PARODD) == 0) cfcr |= CFCR_PEVEN; } if (cflag&CSTOPB) cfcr |= CFCR_STOPB; outb(com+com_cfcr, cfcr); if (com_hasfifo & (1 << unit)) outb(com+com_fifo, FIFO_ENABLE | FIFO_TRIGGER_14); return(0);} voidcomstart(tp) register struct tty *tp;{ register com; int s, unit, c; unit = UNIT(tp->t_dev); com = com_addr[unit]; s = spltty(); if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) goto out; if (tp->t_outq.c_cc <= tp->t_lowat) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } selwakeup(&tp->t_wsel); } if (tp->t_outq.c_cc == 0) goto out; if (inb(com+com_lsr) & LSR_TXRDY) { c = getc(&tp->t_outq); tp->t_state |= TS_BUSY; outb(com+com_data, c); if (com_hasfifo & (1 << unit)) for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) outb(com+com_data, getc(&tp->t_outq)); }out: splx(s);} /* * Stop output on a line. *//*ARGSUSED*/comstop(tp, flag) register struct tty *tp;{ register int s; s = spltty(); if (tp->t_state & TS_BUSY) { if ((tp->t_state&TS_TTSTOP)==0) tp->t_state |= TS_FLUSH; } splx(s);} commctl(dev, bits, how) dev_t dev; int bits, how;{ register com; register int unit; int s; unit = UNIT(dev); com = com_addr[unit]; s = spltty(); switch (how) { case DMSET: outb(com+com_mcr, bits | MCR_IENABLE); break; case DMBIS: outb(com+com_mcr, inb(com+com_mcr) | bits | MCR_IENABLE); break; case DMBIC: outb(com+com_mcr, inb(com+com_mcr) & ~bits | MCR_IENABLE); break; case DMGET: bits = inb(com+com_msr); break; } (void) splx(s); return(bits);}/* * Following are all routines needed for COM to act as console */#include <i386/i386/cons.h>comcnprobe(cp) struct consdev *cp;{ int unit; /* locate the major number */ for (commajor = 0; commajor < nchrdev; commajor++) if (cdevsw[commajor].d_open == comopen) break; /* XXX: ick */ unit = CONUNIT; com_addr[CONUNIT] = CONADDR; /* make sure hardware exists? XXX */ /* initialize required fields */ cp->cn_dev = makedev(commajor, unit); cp->cn_tp = &com_tty[unit];#ifdef COMCONSOLE cp->cn_pri = CN_REMOTE; /* Force a serial port console */#else cp->cn_pri = CN_NORMAL;#endif}comcninit(cp) struct consdev *cp;{ int unit = UNIT(cp->cn_dev); cominit(unit, comdefaultrate); comconsole = unit; comconsinit = 1;}cominit(unit, rate) int unit, rate;{ register int com; int s; short stat;#ifdef lint stat = unit; if (stat) return;#endif com = com_addr[unit]; s = splhigh(); outb(com+com_cfcr, CFCR_DLAB); rate = ttspeedtab(comdefaultrate, comspeedtab); outb(com+com_data, rate & 0xFF); outb(com+com_ier, rate >> 8); outb(com+com_cfcr, CFCR_8BITS); outb(com+com_ier, IER_ERXRDY | IER_ETXRDY); outb(com+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14); stat = inb(com+com_iir); splx(s);}comcngetc(dev){ register com = com_addr[UNIT(dev)]; short stat; int c, s;#ifdef lint stat = dev; if (stat) return(0);#endif s = splhigh(); while (((stat = inb(com+com_lsr)) & LSR_RXRDY) == 0) ; c = inb(com+com_data); stat = inb(com+com_iir); splx(s); return(c);}/* * Console kernel output character routine. */comcnputc(dev, c) dev_t dev; register int c;{ register com = com_addr[UNIT(dev)]; register int timo; short stat; int s = splhigh();#ifdef lint stat = dev; if (stat) return;#endif#ifdef KGDB if (dev != kgdb_dev)#endif if (comconsinit == 0) { (void) cominit(UNIT(dev), comdefaultrate); comconsinit = 1; } /* wait for any pending transmission to finish */ timo = 50000; while (((stat = inb(com+com_lsr)) & LSR_TXRDY) == 0 && --timo) ; outb(com+com_data, c); /* wait for this transmission to complete */ timo = 1500000; while (((stat = inb(com+com_lsr)) & LSR_TXRDY) == 0 && --timo) ; /* clear any interrupts generated by this transmission */ stat = inb(com+com_iir); splx(s);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -