📄 dgb.c
字号:
if(*(int *)data & TIOCM_RTS) port->omodem |=RTS; else port->omodem &=~RTS; cs=splclock(); setwin(sc,0); fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); hidewin(sc); splx(cs); break; case TIOCMBIS: if(*(int *)data & TIOCM_DTR) port->omodem |=DTR; if(*(int *)data & TIOCM_RTS) port->omodem |=RTS; cs=splclock(); setwin(sc,0); fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); hidewin(sc); splx(cs); break; case TIOCMBIC: if(*(int *)data & TIOCM_DTR) port->omodem &=~DTR; if(*(int *)data & TIOCM_RTS) port->omodem &=~RTS; cs=splclock(); setwin(sc,0); fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); hidewin(sc); splx(cs); break; case TIOCMGET: setwin(sc,0); port->imodem=bc->mstat; hidewin(sc); tiocm_xxx = TIOCM_LE; /* XXX - always enabled while open */ DPRINT3(DB_MODEM,"dgb%d: port%d: modem stat -- ",unit,pnum); if (port->imodem & DTR) { DPRINT1(DB_MODEM,"DTR "); tiocm_xxx |= TIOCM_DTR; } if (port->imodem & RTS) { DPRINT1(DB_MODEM,"RTS "); tiocm_xxx |= TIOCM_RTS; } if (port->imodem & CTS) { DPRINT1(DB_MODEM,"CTS "); tiocm_xxx |= TIOCM_CTS; } if (port->imodem & port->dcd) { DPRINT1(DB_MODEM,"DCD "); tiocm_xxx |= TIOCM_CD; } if (port->imodem & port->dsr) { DPRINT1(DB_MODEM,"DSR "); tiocm_xxx |= TIOCM_DSR; } if (port->imodem & RI) { DPRINT1(DB_MODEM,"RI "); tiocm_xxx |= TIOCM_RI; } *(int *)data = tiocm_xxx; DPRINT1(DB_MODEM,"--\n"); break; case TIOCMSDTRWAIT: /* must be root since the wait applies to following logins */ error = suser(p->p_ucred, &p->p_acflag); if (error != 0) { splx(s); return (error); } port->close_delay = *(int *)data * hz / 100; break; case TIOCMGDTRWAIT: *(int *)data = port->close_delay * 100 / hz; break; case TIOCTIMESTAMP: port->do_timestamp = TRUE; *(struct timeval *)data = port->timestamp; break; case TIOCDCDTIMESTAMP: port->do_dcd_timestamp = TRUE; *(struct timeval *)data = port->dcd_timestamp; break; default: bmws_set(ws); splx(s); return ENOTTY; } bmws_set(ws); splx(s); return 0;}static void wakeflush(p) void *p;{ struct dgb_p *port=p; wakeup(&port->draining);}/* wait for the output to drain */static intdgbdrain(port) struct dgb_p *port;{ struct dgb_softc *sc=&dgb_softc[port->unit]; volatile struct board_chan *bc=port->brdchan; int error; int head, tail; BoardMemWinState ws=bmws_get(); setwin(sc,0); bc->iempty=1; tail=bc->tout; head=bc->tin; while(tail!=head) { DPRINT5(DB_WR,"dgb%d: port%d: drain: head=%d tail=%d\n", port->unit, port->pnum, head, tail); hidewin(sc); port->draining=1; timeout(wakeflush,port, hz); error=tsleep(&port->draining, TTIPRI | PCATCH, "dgdrn", 0); port->draining=0; setwin(sc,0); if (error != 0) { DPRINT4(DB_WR,"dgb%d: port%d: tsleep(dgdrn) error=%d\n", port->unit,port->pnum,error); bc->iempty=0; bmws_set(ws); return error; } tail=bc->tout; head=bc->tin; } DPRINT5(DB_WR,"dgb%d: port%d: drain: head=%d tail=%d\n", port->unit, port->pnum, head, tail); bmws_set(ws); return 0;}/* wait for the output to drain *//* or simply clear the buffer it it's stopped */static voiddgb_drain_or_flush(port) struct dgb_p *port;{ struct tty *tp=port->tty; struct dgb_softc *sc=&dgb_softc[port->unit]; volatile struct board_chan *bc=port->brdchan; int error; int lasttail; int head, tail; setwin(sc,0); lasttail=-1; bc->iempty=1; tail=bc->tout; head=bc->tin; while(tail!=head /* && tail!=lasttail */ ) { DPRINT5(DB_WR,"dgb%d: port%d: flush: head=%d tail=%d\n", port->unit, port->pnum, head, tail); /* if there is no carrier simply clean the buffer */ if( !(tp->t_state & TS_CARR_ON) ) { bc->tout=bc->tin=0; bc->iempty=0; hidewin(sc); return; } hidewin(sc); port->draining=1; timeout(wakeflush,port, hz); error=tsleep(&port->draining, TTIPRI | PCATCH, "dgfls", 0); port->draining=0; setwin(sc,0); if (error != 0) { DPRINT4(DB_WR,"dgb%d: port%d: tsleep(dgfls) error=%d\n", port->unit,port->pnum,error); /* silently clean the buffer */ bc->tout=bc->tin=0; bc->iempty=0; hidewin(sc); return; } lasttail=tail; tail=bc->tout; head=bc->tin; } hidewin(sc); DPRINT5(DB_WR,"dgb%d: port%d: flush: head=%d tail=%d\n", port->unit, port->pnum, head, tail);}static intdgbparam(tp, t) struct tty *tp; struct termios *t;{ int dev=tp->t_dev; int mynor=minor(dev); int unit=MINOR_TO_UNIT(dev); int pnum=MINOR_TO_PORT(dev); struct dgb_softc *sc=&dgb_softc[unit]; struct dgb_p *port=&sc->ports[pnum]; volatile struct board_chan *bc=port->brdchan; int cflag; int head; int mval; int iflag; int hflow; int s,cs; BoardMemWinState ws=bmws_get(); DPRINT6(DB_PARAM,"dgb%d: port%d: dgbparm c=0x%x i=0x%x l=0x%x\n",unit,pnum,t->c_cflag,t->c_iflag,t->c_lflag); if(port->mustdrain) { DPRINT3(DB_PARAM,"dgb%d: port%d: must call dgbdrain()\n",unit,pnum); dgbdrain(port); } cflag=ttspeedtab(t->c_ospeed, dgbspeedtab); if (t->c_ispeed == 0) t->c_ispeed = t->c_ospeed; if (cflag < 0 /* || cflag > 0 && t->c_ispeed != t->c_ospeed */) { DPRINT4(DB_PARAM,"dgb%d: port%d: invalid cflag=0%o\n",unit,pnum,cflag); return (EINVAL); } cs=splclock(); setwin(sc,0); if(cflag==0) { /* hangup */ DPRINT3(DB_PARAM,"dgb%d: port%d: hangup\n",unit,pnum); head=bc->rin; bc->rout=head; head=bc->tin; fepcmd(port, STOUT, (unsigned)head, 0, 0, 0); mval= port->omodem & ~(DTR|RTS); } else { cflag |= dgbflags(dgb_cflags, t->c_cflag); if(cflag!=port->fepcflag) { port->fepcflag=cflag; DPRINT6(DB_PARAM,"dgb%d: port%d: set cflag=0x%x c=0x%x\n", unit,pnum,cflag&(FEP_CBAUD|FEP_FASTBAUD),cflag, t->c_cflag&~CRTSCTS); fepcmd(port, SETCTRLFLAGS, (unsigned)cflag, 0, 0, 0); } mval= port->omodem | (DTR|RTS); } iflag=dgbflags(dgb_iflags, t->c_iflag); if(iflag!=port->fepiflag) { port->fepiflag=iflag; DPRINT5(DB_PARAM,"dgb%d: port%d: set iflag=0x%x c=0x%x\n",unit,pnum,iflag,t->c_iflag); fepcmd(port, SETIFLAGS, (unsigned)iflag, 0, 0, 0); } bc->mint=port->dcd; hflow=dgbflags(dgb_flow, t->c_cflag); if(hflow!=port->hflow) { port->hflow=hflow; DPRINT5(DB_PARAM,"dgb%d: port%d: set hflow=0x%x f=0x%x\n",unit,pnum,hflow,t->c_cflag&CRTSCTS); fepcmd(port, SETHFLOW, (unsigned)hflow, 0xff, 0, 1); } if(port->omodem != mval) { DPRINT5(DB_PARAM,"dgb%d: port%d: setting modem parameters 0x%x was 0x%x\n", unit,pnum,mval,port->omodem); port->omodem=mval; fepcmd(port, SETMODEM, (unsigned)mval, RTS|DTR, 0, 1); } if(port->fepstartc!=t->c_cc[VSTART] || port->fepstopc!=t->c_cc[VSTOP]) { DPRINT5(DB_PARAM,"dgb%d: port%d: set startc=%d, stopc=%d\n",unit,pnum,t->c_cc[VSTART],t->c_cc[VSTOP]); port->fepstartc=t->c_cc[VSTART]; port->fepstopc=t->c_cc[VSTOP]; fepcmd(port, SONOFFC, port->fepstartc, port->fepstopc, 0, 1); } bmws_set(ws); splx(cs); return 0;}static voiddgbstart(tp) struct tty *tp;{ int unit; int pnum; struct dgb_p *port; struct dgb_softc *sc; volatile struct board_chan *bc; int head, tail; int size, ocount; int s; int wmask; BoardMemWinState ws=bmws_get(); unit=MINOR_TO_UNIT(minor(tp->t_dev)); pnum=MINOR_TO_PORT(minor(tp->t_dev)); sc=&dgb_softc[unit]; port=&sc->ports[pnum]; bc=port->brdchan; wmask=port->txbufsize-1; s=spltty(); while( tp->t_outq.c_cc!=0 ) { int cs;#ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */ ttwwakeup(tp);#else if(tp->t_outq.c_cc <= tp->t_lowat) { if(tp->t_state & TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup(TSA_OLOWAT(tp)); } /*selwakeup(&tp->t_wsel);*/ }#endif cs=splclock(); setwin(sc,0); head=bc->tin & wmask; do { tail=bc->tout; } while (tail != bc->tout); tail=bc->tout & wmask; DPRINT5(DB_WR,"dgb%d: port%d: s tx head=%d tail=%d\n",unit,pnum,head,tail);#ifdef LEAVE_FREE_CHARS if(tail>head) { size=tail-head-LEAVE_FREE_CHARS; if (size <0) size==0; } else { size=port->txbufsize-head; if(tail+port->txbufsize < head) size==0; } }#else if(tail>head) size=tail-head-1; else { size=port->txbufsize-head/*-1*/; if(tail==0) size--; }#endif if(size==0) { bc->iempty=1; bc->ilow=1; splx(cs); bmws_set(ws); tp->t_state|=TS_BUSY; splx(s); return; } towin(sc,port->txwin); ocount=q_to_b(&tp->t_outq, port->txptr+head, size); head+=ocount; if(head>=port->txbufsize) head-=port->txbufsize; setwin(sc,0); bc->tin=head; DPRINT5(DB_WR,"dgb%d: port%d: tx avail=%d count=%d\n",unit,pnum,size,ocount); hidewin(sc); splx(cs); } bmws_set(ws); splx(s);#ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */ if(tp->t_state & TS_BUSY) { tp->t_state&=~TS_BUSY; linesw[tp->t_line].l_start(tp); ttwwakeup(tp); }#else if(tp->t_state & TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup(TSA_OLOWAT(tp)); } tp->t_state&=~TS_BUSY;#endif}voiddgbstop(tp, rw) struct tty *tp; int rw;{ int unit; int pnum; struct dgb_p *port; struct dgb_softc *sc; volatile struct board_chan *bc; int head; int s; BoardMemWinState ws=bmws_get(); DPRINT3(DB_WR,"dgb%d: port%d: stop\n",port->unit, port->pnum); unit=MINOR_TO_UNIT(minor(tp->t_dev)); pnum=MINOR_TO_PORT(minor(tp->t_dev)); sc=&dgb_softc[unit]; port=&sc->ports[pnum]; bc=port->brdchan; s = spltty(); setwin(sc,0); if (rw & FWRITE) { /* clear output queue */ bc->tout=bc->tin=0; bc->ilow=0;bc->iempty=0; } if (rw & FREAD) { /* clear input queue */ bc->rout=bc->rin; bc->idata=1; } hidewin(sc); bmws_set(ws); splx(s); dgbstart(tp);}struct tty *dgbdevtotty(dev) dev_t dev;{ int mynor, pnum, unit; struct dgb_softc *sc; mynor = minor(dev); if (mynor & CONTROL_MASK) return (NULL); unit = MINOR_TO_UNIT(mynor); if ((u_int) unit >= NDGB) return (NULL); pnum = MINOR_TO_PORT(mynor); sc = &dgb_softc[unit]; if (pnum >= sc->numports) return (NULL); return (&sc->ttys[pnum]);}static void fepcmd(port, cmd, op1, op2, ncmds, bytecmd) struct dgb_p *port; unsigned cmd, op1, op2, ncmds, bytecmd;{ struct dgb_softc *sc=&dgb_softc[port->unit]; u_char *mem=sc->vmem; unsigned tail, head; int count, n; if(port->status==DISABLED) { printf("dgb%d: port%d: FEP command on disabled port\n", port->unit, port->pnum); return; } /* setwin(sc,0); Require this to be set by caller */ head=sc->mailbox->cin; if(head>=(FEP_CMAX-FEP_CSTART) || (head & 3)) { printf("dgb%d: port%d: wrong pointer head of command queue : 0x%x\n", port->unit, port->pnum, head); return; } mem[head+FEP_CSTART+0]=cmd; mem[head+FEP_CSTART+1]=port->pnum; if(bytecmd) { mem[head+FEP_CSTART+2]=op1; mem[head+FEP_CSTART+3]=op2; } else { mem[head+FEP_CSTART+2]=op1&0xff; mem[head+FEP_CSTART+3]=(op1>>8)&0xff; } DPRINT7(DB_FEP,"dgb%d: port%d: %s cmd=0x%x op1=0x%x op2=0x%x\n", port->unit, port->pnum, (bytecmd)?"byte":"word", cmd, mem[head+FEP_CSTART+2], mem[head+FEP_CSTART+3]); head=(head+4) & (FEP_CMAX-FEP_CSTART-4); sc->mailbox->cin=head; count=FEPTIMEOUT; while (count-- != 0) { head=sc->mailbox->cin; tail=sc->mailbox->cout; n = (head-tail) & (FEP_CMAX-FEP_CSTART-4); if(n <= ncmds * (sizeof(ushort)*4)) return; } printf("dgb%d(%d): timeout on FEP cmd=0x%x\n", port->unit, port->pnum, cmd);}static void disc_optim(tp, t) struct tty *tp; struct termios *t;{ /* * XXX can skip a lot more cases if Smarts. Maybe * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. */ if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) && (!(t->c_iflag & PARMRK) || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) && linesw[tp->t_line].l_rint == ttyinput) tp->t_state |= TS_CAN_BYPASS_L_RINT; else tp->t_state &= ~TS_CAN_BYPASS_L_RINT;}static dgb_devsw_installed = 0;static void dgb_drvinit(void *unused){ dev_t dev; if( ! dgb_devsw_installed ) { dev = makedev(CDEV_MAJOR, 0); cdevsw_add(&dev,&dgb_cdevsw, NULL); dgb_devsw_installed = 1; }}SYSINIT(dgbdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,dgb_drvinit,NULL)#endif /* NDGB > 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -