📄 dgb.c
字号:
DPRINT3(DB_CLOSE,"dgb%d: port%d: draining port\n",unit,pnum); dgb_drain_or_flush(port); s=spltty(); port->closing=1; DPRINT3(DB_CLOSE,"dgb%d: port%d: closing line disc\n",unit,pnum); linesw[tp->t_line].l_close(tp,flag); disc_optim(tp,&tp->t_termios); DPRINT3(DB_CLOSE,"dgb%d: port%d: hard closing\n",unit,pnum); dgbhardclose(port); DPRINT3(DB_CLOSE,"dgb%d: port%d: closing tty\n",unit,pnum); ttyclose(tp); port->closing=0; wakeup(&port->closing); port->used=0; /* mark the card idle when all ports are closed */ for(i=0; i<sc->numports; i++) if(sc->ports[i].used) break; splx(s); DPRINT3(DB_CLOSE,"dgb%d: port%d: closed\n",unit,pnum); wakeup(TSA_CARR_ON(tp)); wakeup(&port->active_out); port->active_out=0; DPRINT3(DB_CLOSE,"dgb%d: port%d: close exit\n",unit,pnum); return 0;}static voiddgbhardclose(port) struct dgb_p *port;{ struct dgb_softc *sc=&dgb_softc[port->unit]; volatile struct board_chan *bc=port->brdchan; int cs; cs=splclock(); port->do_timestamp = 0; setwin(sc,0); bc->idata=0; bc->iempty=0; bc->ilow=0; if(port->tty->t_cflag & HUPCL) { port->omodem &= ~(RTS|DTR); fepcmd(port, SETMODEM, 0, DTR|RTS, 0, 1); } hidewin(sc); splx(cs); timeout(dgb_pause, &port->brdchan, hz/2); tsleep(&port->brdchan, TTIPRI | PCATCH, "dgclo", 0);}static void dgb_pause(chan) void *chan;{wakeup((caddr_t)chan);}static intdgbread(dev, uio, flag) dev_t dev; struct uio *uio; int flag;{ int mynor; struct tty *tp; int error, unit, pnum; mynor=minor(dev); if (mynor & CONTROL_MASK) return (ENODEV); unit=MINOR_TO_UNIT(mynor); pnum=MINOR_TO_PORT(mynor); tp=&dgb_softc[unit].ttys[pnum]; error=linesw[tp->t_line].l_read(tp, uio, flag); DPRINT4(DB_RD,"dgb%d: port%d: read() returns %d\n",unit,pnum,error); return error;}static intdgbwrite(dev, uio, flag) dev_t dev; struct uio *uio; int flag;{ int mynor; struct tty *tp; int error, unit, pnum; mynor=minor(dev); if (mynor & CONTROL_MASK) return (ENODEV); unit=MINOR_TO_UNIT(mynor); pnum=MINOR_TO_PORT(mynor); tp=&dgb_softc[unit].ttys[pnum]; error=linesw[tp->t_line].l_write(tp, uio, flag); DPRINT4(DB_WR,"dgb%d: port%d: write() returns %d\n",unit,pnum,error); return error;}static voiddgbpoll(unit_c) void *unit_c;{ int unit=(int)unit_c; int pnum; struct dgb_p *port; struct dgb_softc *sc=&dgb_softc[unit]; int head, tail; u_char *eventbuf; int event, mstat, lstat; volatile struct board_chan *bc; struct tty *tp; int rhead, rtail; int whead, wtail; int size; int c=0; u_char *ptr; int ocount; int ibuf_full,obuf_full; BoardMemWinState ws=bmws_get(); if(sc->status==DISABLED) { printf("dgb%d: polling of disabled board stopped\n",unit); return; } setwin(sc,0); head=sc->mailbox->ein; tail=sc->mailbox->eout; while(head!=tail) { if(head >= FEP_IMAX-FEP_ISTART || tail >= FEP_IMAX-FEP_ISTART || (head|tail) & 03 ) { printf("dgb%d: event queue's head or tail is wrong! hd=%d,tl=%d\n", unit,head,tail); break; } eventbuf=sc->vmem+tail+FEP_ISTART; pnum=eventbuf[0]; event=eventbuf[1]; mstat=eventbuf[2]; lstat=eventbuf[3]; port=&sc->ports[pnum]; bc=port->brdchan; tp=&sc->ttys[pnum]; if(pnum>=sc->numports || port->status==DISABLED) { printf("dgb%d: port%d: got event on nonexisting port\n",unit,pnum); } else if(port->used || port->wopeners>0 ) { int wrapmask=port->rxbufsize-1; if( !(event & ALL_IND) ) printf("dgb%d: port%d: ? event 0x%x mstat 0x%x lstat 0x%x\n", unit, pnum, event, mstat, lstat); if(event & DATA_IND) { DPRINT3(DB_DATA,"dgb%d: port%d: DATA_IND\n",unit,pnum); rhead=bc->rin & wrapmask; rtail=bc->rout & wrapmask; if( !(tp->t_cflag & CREAD) || !port->used ) { bc->rout=rhead; goto end_of_data; } if(bc->orun) { printf("dgb%d: port%d: overrun\n", unit, pnum); bc->orun=0; } if(!(tp->t_state & TS_ISOPEN)) goto end_of_data; for(ibuf_full=FALSE;rhead!=rtail && !ibuf_full;) { DPRINT5(DB_RXDATA,"dgb%d: port%d: p rx head=%d tail=%d\n", unit,pnum,rhead,rtail); if(rhead>rtail) size=rhead-rtail; else size=port->rxbufsize-rtail; ptr=port->rxptr+rtail;/* Helg: */ if( tp->t_rawq.c_cc + size > DGB_IBUFSIZE ) { size=DGB_IBUFSIZE-tp->t_rawq.c_cc; DPRINT1(DB_RXDATA,"*"); ibuf_full=TRUE; } if(size) { /*if (0) {*/ if (tp->t_state & TS_CAN_BYPASS_L_RINT) { DPRINT1(DB_RXDATA,"!"); towin(sc,port->rxwin); tk_nin += size; tk_rawcc += size; tp->t_rawcc += size; b_to_q(ptr,size,&tp->t_rawq); setwin(sc,0); } else { int i=size; unsigned char chr; do { towin(sc,port->rxwin); chr= *ptr++; hidewin(sc); (*linesw[tp->t_line].l_rint)(chr, tp); } while (--i > 0 ); setwin(sc,0); } } rtail= (rtail + size) & wrapmask; bc->rout=rtail; rhead=bc->rin & wrapmask; hidewin(sc); ttwakeup(tp); setwin(sc,0); } end_of_data: } if(event & MODEMCHG_IND) { DPRINT3(DB_MODEM,"dgb%d: port%d: MODEMCHG_IND\n",unit,pnum); port->imodem=mstat; if(mstat & port->dcd) { hidewin(sc); linesw[tp->t_line].l_modem(tp,1); setwin(sc,0); wakeup(TSA_CARR_ON(tp)); } else { hidewin(sc); linesw[tp->t_line].l_modem(tp,0); setwin(sc,0); if( port->draining) { port->draining=0; wakeup(&port->draining); } } } if(event & BREAK_IND) { if((tp->t_state & TS_ISOPEN) && (tp->t_iflag & IGNBRK)) { DPRINT3(DB_BREAK,"dgb%d: port%d: BREAK_IND\n",unit,pnum); hidewin(sc); linesw[tp->t_line].l_rint(TTY_BI, tp); setwin(sc,0); } }/* Helg: with output flow control */ if(event & (LOWTX_IND | EMPTYTX_IND) ) { DPRINT3(DB_TXDATA,"dgb%d: port%d: LOWTX_IND or EMPTYTX_IND\n",unit,pnum); if( (event & EMPTYTX_IND ) && tp->t_outq.c_cc==0 && port->draining) { port->draining=0; wakeup(&port->draining); bc->ilow=0; bc->iempty=0; } else { int wrapmask=port->txbufsize-1; for(obuf_full=FALSE; tp->t_outq.c_cc!=0 && !obuf_full; ) { int s; /* add "last-minute" data to write buffer */ if(!(tp->t_state & TS_BUSY)) { hidewin(sc);#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 setwin(sc,0); } s=spltty(); whead=bc->tin & wrapmask; wtail=bc->tout & wrapmask; if(whead<wtail) size=wtail-whead-1; else { size=port->txbufsize-whead; if(wtail==0) size--; } if(size==0) { DPRINT5(DB_WR,"dgb: head=%d tail=%d size=%d full=%d\n", whead,wtail,size,obuf_full); bc->iempty=1; bc->ilow=1; obuf_full=TRUE; splx(s); break; } towin(sc,port->txwin); ocount=q_to_b(&tp->t_outq, port->txptr+whead, size); whead+=ocount; setwin(sc,0); bc->tin=whead; bc->tin=whead & wrapmask; splx(s); } if(obuf_full) { DPRINT1(DB_WR," +BUSY\n"); tp->t_state|=TS_BUSY; } else { DPRINT1(DB_WR," -BUSY\n"); hidewin(sc);#ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */ /* should clear TS_BUSY before ttwwakeup */ 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 setwin(sc,0); } } end_of_buffer: } bc->idata=1; /* require event on incoming data */ } else { bc=port->brdchan; DPRINT4(DB_EXCEPT,"dgb%d: port%d: got event 0x%x on closed port\n", unit,pnum,event); bc->rout=bc->rin; bc->idata=bc->iempty=bc->ilow=0; } tail= (tail+4) & (FEP_IMAX-FEP_ISTART-4); } sc->mailbox->eout=tail; bmws_set(ws); timeout(dgbpoll, unit_c, hz/POLLSPERSEC);}#if 0static voiddgbintr(unit) int unit;{}#endifstatic intdgbioctl(dev, cmd, data, flag, p) dev_t dev; int cmd; caddr_t data; int flag; struct proc *p;{ struct dgb_softc *sc; int unit, pnum; struct dgb_p *port; int mynor; struct tty *tp; volatile struct board_chan *bc; int error; int s,cs; int tiocm_xxx;#if defined(COMPAT_43) || defined(COMPAT_SUNOS) int oldcmd; struct termios term;#endif BoardMemWinState ws=bmws_get(); mynor=minor(dev); unit=MINOR_TO_UNIT(mynor); pnum=MINOR_TO_PORT(mynor); sc=&dgb_softc[unit]; port=&sc->ports[pnum]; tp=&sc->ttys[pnum]; bc=port->brdchan; if (mynor & CONTROL_MASK) { struct termios *ct; switch (mynor & CONTROL_MASK) { case CONTROL_INIT_STATE: ct = mynor & CALLOUT_MASK ? &port->it_out : &port->it_in; break; case CONTROL_LOCK_STATE: ct = mynor & CALLOUT_MASK ? &port->lt_out : &port->lt_in; break; default: return (ENODEV); /* /dev/nodev */ } switch (cmd) { case TIOCSETA: error = suser(p->p_ucred, &p->p_acflag); if (error != 0) return (error); *ct = *(struct termios *)data; return (0); case TIOCGETA: *(struct termios *)data = *ct; return (0); case TIOCGETD: *(int *)data = TTYDISC; return (0); case TIOCGWINSZ: bzero(data, sizeof(struct winsize)); return (0); default: return (ENOTTY); } }#if defined(COMPAT_43) || defined(COMPAT_SUNOS) term = tp->t_termios; if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { DPRINT6(DB_PARAM,"dgb%d: port%d: dgbioctl-ISNOW c=0x%x i=0x%x l=0x%x\n",unit,pnum,term.c_cflag,term.c_iflag,term.c_lflag); } oldcmd = cmd; error = ttsetcompat(tp, &cmd, data, &term); if (error != 0) return (error); if (cmd != oldcmd) data = (caddr_t)&term;#endif if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { int cc; struct termios *dt = (struct termios *)data; struct termios *lt = mynor & CALLOUT_MASK ? &port->lt_out : &port->lt_in; DPRINT6(DB_PARAM,"dgb%d: port%d: dgbioctl-TOSET c=0x%x i=0x%x l=0x%x\n",unit,pnum,dt->c_cflag,dt->c_iflag,dt->c_lflag); dt->c_iflag = (tp->t_iflag & lt->c_iflag) | (dt->c_iflag & ~lt->c_iflag); dt->c_oflag = (tp->t_oflag & lt->c_oflag) | (dt->c_oflag & ~lt->c_oflag); dt->c_cflag = (tp->t_cflag & lt->c_cflag) | (dt->c_cflag & ~lt->c_cflag); dt->c_lflag = (tp->t_lflag & lt->c_lflag) | (dt->c_lflag & ~lt->c_lflag); for (cc = 0; cc < NCCS; ++cc) if (lt->c_cc[cc] != 0) dt->c_cc[cc] = tp->t_cc[cc]; if (lt->c_ispeed != 0) dt->c_ispeed = tp->t_ispeed; if (lt->c_ospeed != 0) dt->c_ospeed = tp->t_ospeed; } if(cmd==TIOCSTOP) { cs=splclock(); setwin(sc,0); fepcmd(port, PAUSETX, 0, 0, 0, 0); bmws_set(ws); splx(cs); return 0; } else if(cmd==TIOCSTART) { cs=splclock(); setwin(sc,0); fepcmd(port, RESUMETX, 0, 0, 0, 0); bmws_set(ws); splx(cs); return 0; } if(cmd==TIOCSETAW || cmd==TIOCSETAF) port->mustdrain=1; error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, p); if (error >= 0) return error; s = spltty(); error = ttioctl(tp, cmd, data, flag); disc_optim(tp,&tp->t_termios); port->mustdrain=0; if (error >= 0) { splx(s); if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { DPRINT6(DB_PARAM,"dgb%d: port%d: dgbioctl-RES c=0x%x i=0x%x l=0x%x\n",unit,pnum,tp->t_cflag,tp->t_iflag,tp->t_lflag); } return error; } switch (cmd) { case TIOCSBRK:/* Helg: commented *//* error=dgbdrain(port);*/ if(error!=0) { splx(s); return error; } cs=splclock(); setwin(sc,0); /* now it sends 250 millisecond break because I don't know */ /* how to send an infinite break */ fepcmd(port, SENDBREAK, 250, 0, 10, 0); hidewin(sc); splx(cs); break; case TIOCCBRK: /* now it's empty */ break; case TIOCSDTR: DPRINT3(DB_MODEM,"dgb%d: port%d: set DTR\n",unit,pnum); port->omodem |= DTR; cs=splclock(); setwin(sc,0); fepcmd(port, SETMODEM, port->omodem, RTS, 0, 1); if( !(bc->mstat & DTR) ) { DPRINT3(DB_MODEM,"dgb%d: port%d: DTR is off\n",unit,pnum); } hidewin(sc); splx(cs); break; case TIOCCDTR: DPRINT3(DB_MODEM,"dgb%d: port%d: reset DTR\n",unit,pnum); port->omodem &= ~DTR; cs=splclock(); setwin(sc,0); fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); if( bc->mstat & DTR ) { DPRINT3(DB_MODEM,"dgb%d: port%d: DTR is on\n",unit,pnum); } hidewin(sc); splx(cs); break; case TIOCMSET: if(*(int *)data & TIOCM_DTR) port->omodem |=DTR; else port->omodem &=~DTR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -