*** si.c.dist Thu Sep 4 11:11:22 2008 --- si.c Thu Sep 4 11:12:49 2008 *************** static const char si_copyright1[] = "@( *** 44,50 **** #include "opt_compat.h" #include "opt_debug_si.h" #include "opt_eisa.h" - #include "opt_tty.h" #include #include --- 44,49 ---- *************** static const char si_copyright1[] = "@( *** 95,107 **** static void si_command(struct si_port *, int, int); static int si_Sioctl(struct cdev *, u_long, caddr_t, int, struct thread *); static void si_start(struct tty *); ! static void si_stop(struct tty *, int); static timeout_t si_lstart; ! static t_break_t sibreak; ! static t_close_t siclose; ! static t_modem_t simodem; ! static t_open_t siopen; static int siparam(struct tty *, struct termios *); --- 94,106 ---- static void si_command(struct si_port *, int, int); static int si_Sioctl(struct cdev *, u_long, caddr_t, int, struct thread *); static void si_start(struct tty *); ! /* static void si_stop(struct tty *, int); */ static timeout_t si_lstart; ! static tsw_ioctl_t siioctl; ! static tsw_close_t siclose; ! static tsw_modem_t simodem; ! static tsw_open_t siopen; static int siparam(struct tty *, struct termios *); *************** static int si_numunits; *** 126,131 **** --- 125,136 ---- devclass_t si_devclass; + + struct speedtab { + int sp_speed; /* Speed. */ + int sp_code; /* Code. */ + }; + #ifndef B2000 /* not standard, but the hardware knows it. */ # define B2000 2000 #endif *************** si_bcopyv(const void *src, volatile void *** 261,266 **** --- 266,295 ---- *d++ = *s++; } + static int + ttspeedtab(int speed, struct speedtab *table) + { + if (speed == 0) + return (0); /* hangup */ + for ( ; table->sp_speed > 0; table++) + if (table->sp_speed <= speed) /* nearest one, rounded down */ + return (table->sp_code); + return (1); /* 50, min and not hangup */ + } + + + static struct ttydevsw si_tty_class = { + .tsw_flags = TF_INITLOCK|TF_CALLOUT, + .tsw_open = siopen, + .tsw_close = siclose, + .tsw_outwakeup = si_start, + /* .tsw_stop = si_stop */ + .tsw_ioctl = siioctl, + .tsw_param = siparam, + .tsw_modem = simodem, + }; + + /* * Attach the device. Initialize the card. */ *************** try_next: *** 579,595 **** sprintf(pp->sp_name, "si%r%r", unit, (int)(pp - sc->sc_ports)); #endif ! tp = pp->sp_tty = ttyalloc(); ! tp->t_sc = pp; ! tp->t_break = sibreak; ! tp->t_close = siclose; ! tp->t_modem = simodem; ! tp->t_open = siopen; ! tp->t_oproc = si_start; ! tp->t_param = siparam; ! tp->t_stop = si_stop; ! ttycreate(tp, TS_CALLOUT, "A%r%r", unit, ! (int)(pp - sc->sc_ports)); } try_next2: if (modp->sm_next == 0) { --- 608,615 ---- sprintf(pp->sp_name, "si%r%r", unit, (int)(pp - sc->sc_ports)); #endif ! tp = pp->sp_tty = tty_alloc(&si_tty_class, pp, NULL); ! tty_makedev(tp, NULL, "A%r%r", unit, (int)(pp - sc->sc_ports)); } try_next2: if (modp->sm_next == 0) { *************** try_next2: *** 620,626 **** } static int ! siopen(struct tty *tp, struct cdev *dev) { mtx_assert(&Giant, MA_OWNED); --- 640,646 ---- } static int ! siopen(struct tty *tp) { mtx_assert(&Giant, MA_OWNED); *************** siclose(struct tty *tp) *** 642,665 **** struct si_port *pp; mtx_assert(&Giant, MA_OWNED); ! pp = tp->t_sc; (void) si_command(pp, FCLOSE, SI_WAIT); } ! static void ! sibreak(struct tty *tp, int sig) { struct si_port *pp; mtx_assert(&Giant, MA_OWNED); ! pp = tp->t_sc; ! if (sig) si_command(pp, SBREAK, SI_WAIT); ! else si_command(pp, EBREAK, SI_WAIT); } - /* * Handle the Specialix ioctls on the control dev. */ --- 662,689 ---- struct si_port *pp; mtx_assert(&Giant, MA_OWNED); ! pp = tty_softc(tp); (void) si_command(pp, FCLOSE, SI_WAIT); } ! static int ! siioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) { struct si_port *pp; mtx_assert(&Giant, MA_OWNED); ! pp = tty_softc(tp); ! switch (cmd) { ! case TIOCSBRK: si_command(pp, SBREAK, SI_WAIT); ! return (0); ! case TIOCCBRK: si_command(pp, EBREAK, SI_WAIT); + return (0); + } + return (0); } /* * Handle the Specialix ioctls on the control dev. */ *************** out: *** 805,811 **** static int siparam(struct tty *tp, struct termios *t) { ! struct si_port *pp = tp->t_sc; volatile struct si_channel *ccbp; int oldspl, cflag, iflag, oflag, lflag; int error = 0; /* shutup gcc */ --- 829,835 ---- static int siparam(struct tty *tp, struct termios *t) { ! struct si_port *pp = tty_softc(tp); volatile struct si_channel *ccbp; int oldspl, cflag, iflag, oflag, lflag; int error = 0; /* shutup gcc */ *************** simodem(struct tty *tp, int sigon, int s *** 981,987 **** volatile struct si_channel *ccbp; int x; ! pp = tp->t_sc; DPRINT((pp, DBG_ENTRY|DBG_MODEM, "simodem(%x,%x)\n", sigon, sigoff)); mtx_assert(&Giant, MA_OWNED); ccbp = pp->sp_ccb; /* Find channel address */ --- 1005,1011 ---- volatile struct si_channel *ccbp; int x; ! pp = tty_softc(tp); DPRINT((pp, DBG_ENTRY|DBG_MODEM, "simodem(%x,%x)\n", sigon, sigoff)); mtx_assert(&Giant, MA_OWNED); ccbp = pp->sp_ccb; /* Find channel address */ *************** si_modem_state(struct si_port *pp, struc *** 1021,1035 **** mtx_assert(&Giant, MA_OWNED); if (hi_ip & IP_DCD) { if (!(pp->sp_last_hi_ip & IP_DCD)) { ! DPRINT((pp, DBG_INTR, "modem carr on t_line %d\n", ! tp->t_line)); ! (void)ttyld_modem(tp, 1); } } else { if (pp->sp_last_hi_ip & IP_DCD) { DPRINT((pp, DBG_INTR, "modem carr off\n")); ! if (ttyld_modem(tp, 0)) (void) simodem(tp, 0, SER_DTR | SER_RTS); } } pp->sp_last_hi_ip = hi_ip; --- 1045,1062 ---- mtx_assert(&Giant, MA_OWNED); if (hi_ip & IP_DCD) { if (!(pp->sp_last_hi_ip & IP_DCD)) { ! DPRINT((pp, DBG_INTR, "modem carr on%d\n")); ! (void)ttydisc_modem(tp, 1); } } else { if (pp->sp_last_hi_ip & IP_DCD) { DPRINT((pp, DBG_INTR, "modem carr off\n")); ! #if 0 /* XXX mpsafetty ttyld_modem used to tell us to shutdown the port or not */ ! if (ttydisc_modem(tp, 0)) (void) simodem(tp, 0, SER_DTR | SER_RTS); + #else + ttydisc_modem(tp, 0); + #endif } } pp->sp_last_hi_ip = hi_ip; *************** si_intr(void *arg) *** 1184,1189 **** --- 1211,1217 ---- pp++, port++) { ccbp = pp->sp_ccb; tp = pp->sp_tty; + tty_lock(tp); /* * See if a command has completed ? *************** si_intr(void *arg) *** 1223,1240 **** /* * Check to see if we should 'receive' characters. */ ! if (tp->t_state & TS_CONNECTED && ! tp->t_state & TS_ISOPEN) ! isopen = 1; ! else ! isopen = 0; /* * Do input break processing */ if (ccbp->hi_state & ST_BREAK) { if (isopen) ! ttyld_rint(tp, TTY_BI); ccbp->hi_state &= ~ST_BREAK; /* A Bit iffy this */ DPRINT((pp, DBG_INTR, "si_intr break\n")); } --- 1251,1264 ---- /* * Check to see if we should 'receive' characters. */ ! isopen = tty_opened(tp); /* * Do input break processing */ if (ccbp->hi_state & ST_BREAK) { if (isopen) ! ttydisc_rint(tp, 0, TRE_BREAK); ccbp->hi_state &= ~ST_BREAK; /* A Bit iffy this */ DPRINT((pp, DBG_INTR, "si_intr break\n")); } *************** si_intr(void *arg) *** 1255,1260 **** --- 1279,1285 ---- goto end_rx; } + #if 0 /* XXXMPSAFETTY */ /* * If the tty input buffers are blocked, stop emptying * the incoming buffers and let the auto flow control *************** si_intr(void *arg) *** 1262,1267 **** --- 1287,1293 ---- */ if (tp->t_state & TS_TBLOCK) goto end_rx; + #endif /* * Process read characters if not skipped above *************** si_intr(void *arg) *** 1315,1352 **** * n = number of chars placed in si_rxbuf */ ! /* ! * Avoid the grotesquely inefficient lineswitch ! * routine (ttyinput) in "raw" mode. It usually ! * takes about 450 instructions (that's without ! * canonical processing or echo!). slinput is ! * reasonably fast (usually 40 instructions ! * plus call overhead). ! */ ! if (tp->t_state & TS_CAN_BYPASS_L_RINT) { - /* block if the driver supports it */ - if (tp->t_rawq.c_cc + n >= SI_I_HIGH_WATER && - (tp->t_cflag & CRTS_IFLOW || - tp->t_iflag & IXOFF) && - !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - - tk_nin += n; - tk_rawcc += n; - tp->t_rawcc += n; - - pp->sp_delta_overflows += - b_to_q((char *)si_rxbuf, n, &tp->t_rawq); - - ttwakeup(tp); - if (tp->t_state & TS_TTSTOP && - (tp->t_iflag & IXANY || - tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { - tp->t_state &= ~TS_TTSTOP; - tp->t_lflag &= ~FLUSHO; - si_start(tp); - } } else { /* * It'd be nice to not have to go through the --- 1341,1352 ---- * n = number of chars placed in si_rxbuf */ ! if (ttydisc_can_bypass(tp)) { ! ! i = ttydisc_rint_bypass(tp, (char *)si_rxbuf, n); ! if (i < n) ! pp->sp_delta_overflows += (n - i); } else { /* * It'd be nice to not have to go through the *************** si_intr(void *arg) *** 1356,1362 **** */ for(x = 0; x < n; x++) { i = si_rxbuf[x]; ! if (ttyld_rint(tp, i) == -1) pp->sp_delta_overflows++; } } --- 1356,1362 ---- */ for(x = 0; x < n; x++) { i = si_rxbuf[x]; ! if (ttydisc_rint(tp, i, 0) == -1) pp->sp_delta_overflows++; } } *************** si_intr(void *arg) *** 1364,1373 **** end_rx: /* * Do TX stuff */ ! ttyld_start(tp); } /* end of for (all ports on this controller) */ } /* end of for (all controllers) */ --- 1364,1376 ---- end_rx: + ttydisc_rint_done(tp); + /* * Do TX stuff */ ! si_start(tp); ! tty_unlock(tp); } /* end of for (all ports on this controller) */ } /* end of for (all controllers) */ *************** si_start(struct tty *tp) *** 1390,1452 **** { struct si_port *pp; volatile struct si_channel *ccbp; ! struct clist *qp; ! BYTE ipos; int nchar; ! int oldspl, count, n, amount; oldspl = spltty(); mtx_assert(&Giant, MA_OWNED); ! qp = &tp->t_outq; ! pp = tp->t_sc; DPRINT((pp, DBG_ENTRY|DBG_START, ! "si_start(%x) t_state %x sp_state %x t_outq.c_cc %d\n", ! tp, tp->t_state, pp->sp_state, qp->c_cc)); ! ! if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) ! goto out; ccbp = pp->sp_ccb; ! count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos; ! DPRINT((pp, DBG_START, "count %d\n", (BYTE)count)); ! ! while ((nchar = qp->c_cc) > 0) { ! if ((BYTE)count >= 255) ! break; ! amount = min(nchar, (255 - (BYTE)count)); ipos = (unsigned int)ccbp->hi_txipos; ! n = q_to_b(&tp->t_outq, si_txbuf, amount); ! /* will it fit in one lump? */ ! if ((SI_BUFFERSIZE - ipos) >= n) { ! si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], n); ! } else { ! si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], ! SI_BUFFERSIZE - ipos); ! si_bcopyv(si_txbuf + (SI_BUFFERSIZE - ipos), ! &ccbp->hi_txbuf[0], n - (SI_BUFFERSIZE - ipos)); ! } ccbp->hi_txipos += n; - count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos; } ! if (count != 0 && nchar == 0) ! tp->t_state |= TS_BUSY; ! else ! tp->t_state &= ~TS_BUSY; ! ! /* wakeup time? */ ! ttwwakeup(tp); ! ! DPRINT((pp, DBG_START, "count %d, nchar %d, tp->t_state 0x%x\n", ! (BYTE)count, nchar, tp->t_state)); ! if (tp->t_state & TS_BUSY) { int time; ! time = ttspeedtab(tp->t_ospeed, chartimes); if (time > 0) { if (time < nchar) --- 1393,1433 ---- { struct si_port *pp; volatile struct si_channel *ccbp; ! BYTE ipos, count; int nchar; ! int oldspl, n, amount; oldspl = spltty(); mtx_assert(&Giant, MA_OWNED); ! pp = tty_softc(tp); DPRINT((pp, DBG_ENTRY|DBG_START, ! "si_start(%x) sp_state %x\n", ! tp, pp->sp_state)); ccbp = pp->sp_ccb; ! while ((count = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos) < 255) { ! DPRINT((pp, DBG_START, "count %d\n", (BYTE)count)); ipos = (unsigned int)ccbp->hi_txipos; ! if ((int)ccbp->hi_txopos <= ipos) ! amount = SI_BUFFERSIZE - ipos; ! else ! amount = 255 - count; ! n = ttydisc_getc(tp, si_txbuf, amount); ! si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], n); ccbp->hi_txipos += n; } ! nchar = ttyoutq_bytesleft(&tp->t_outq); ! DPRINT((pp, DBG_START, "count %d, nchar %d\n", ! (BYTE)count, nchar)); ! if (count != 0 && nchar == 0) { int time; ! time = ttspeedtab(tp->t_termios.c_ospeed, chartimes); if (time > 0) { if (time < nchar) *************** si_start(struct tty *tp) *** 1466,1472 **** pp->lstart_ch = timeout(si_lstart, (caddr_t)pp, time); } - out: splx(oldspl); DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n")); } --- 1447,1452 ---- *************** si_lstart(void *arg) *** 1492,1511 **** pp->sp_state &= ~SS_LSTART; tp = pp->sp_tty; ! if ((tp->t_state & TS_ISOPEN) == 0) { ! splx(oldspl); ! return; ! } ! ! /* deal with the process exit case */ ! ttwwakeup(tp); ! ! /* nudge protocols - eg: ppp */ ! ttyld_start(tp); splx(oldspl); } /* * Stop output on a line. called at spltty(); */ --- 1472,1483 ---- pp->sp_state &= ~SS_LSTART; tp = pp->sp_tty; ! si_start(tp); splx(oldspl); } + #if 0 /* XXX mpsafetty */ /* * Stop output on a line. called at spltty(); */ *************** si_stop(struct tty *tp, int rw) *** 1516,1522 **** struct si_port *pp; mtx_assert(&Giant, MA_OWNED); ! pp = tp->t_sc; ccbp = pp->sp_ccb; DPRINT((pp, DBG_ENTRY|DBG_STOP, "si_stop(%x,%x)\n", tp, rw)); --- 1488,1494 ---- struct si_port *pp; mtx_assert(&Giant, MA_OWNED); ! pp = tty_softc(tp); ccbp = pp->sp_ccb; DPRINT((pp, DBG_ENTRY|DBG_STOP, "si_stop(%x,%x)\n", tp, rw)); *************** si_stop(struct tty *tp, int rw) *** 1541,1546 **** --- 1513,1519 ---- } #endif } + #endif /* * Issue a command to the host card CPU. *************** si_command(struct si_port *pp, int cmd, *** 1567,1574 **** x != IDLE_CLOSE && x != IDLE_BREAK && x != cmd) { ! if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH, ! "sicmd1", hz/4)) { DPRINT((pp, DBG_PARAM, "sicmd1 timeout: hi_stat (%s)\n", si_cmdname(ccbp->hi_stat))); /* This is very very bad. The card has crashed. */ --- 1540,1546 ---- x != IDLE_CLOSE && x != IDLE_BREAK && x != cmd) { ! if (tsleep(&pp->sp_state, (PSOCK+1)|PCATCH, "sicmd1", hz/4)) { DPRINT((pp, DBG_PARAM, "sicmd1 timeout: hi_stat (%s)\n", si_cmdname(ccbp->hi_stat))); /* This is very very bad. The card has crashed. */ *************** si_command(struct si_port *pp, int cmd, *** 1602,1609 **** while((x = ccbp->hi_stat) != IDLE_OPEN && x != IDLE_CLOSE && x != IDLE_BREAK) { ! if (ttysleep(pp->sp_tty, (caddr_t)&pp->sp_state, TTIPRI|PCATCH, ! "sicmd2", 0)) break; } } --- 1574,1580 ---- while((x = ccbp->hi_stat) != IDLE_OPEN && x != IDLE_CLOSE && x != IDLE_BREAK) { ! if (tsleep(&pp->sp_state, (PSOCK+1)|PCATCH, "sicmd2", 0)) break; } }