int uhidclose(dev_t dev, int flag, int mode, usb_proc_ptr p) { struct uhid_softc *sc; USB_GET_SC(uhid, UHIDUNIT(dev), sc); DPRINTF(("uhidclose: sc=%p\n", sc)); /* Disable interrupts. */ usbd_abort_pipe(sc->sc_intrpipe); usbd_close_pipe(sc->sc_intrpipe); sc->sc_intrpipe = 0; ndflush(&sc->sc_q, sc->sc_q.c_cc); clfree(&sc->sc_q); free(sc->sc_ibuf, M_USBDEV); free(sc->sc_obuf, M_USBDEV); sc->sc_state &= ~UHID_OPEN; sc->sc_async = 0; return (0); }
void dzxint(struct dz_softc *sc, uint32_t csr) { struct tty *tp; struct clist *cl; int ch; struct _Usart *dzr; dzr = sc->sc_dr; tp = sc->sc_dz.dz_tty; cl = &tp->t_outq; tp->t_state &= ~TS_BUSY; /* Just send out a char if we have one */ if (cl->c_cc) { tp->t_state |= TS_BUSY; ch = getc(cl); dzr->TxData = ch; dzr->IntrEnable = USI_TXRDY; return; } /* Nothing to send; turn off intr */ dzr->IntrDisable = USI_TXRDY; if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH; else ndflush(&tp->t_outq, cl->c_cc); (*tp->t_linesw->l_start)(tp); }
inline static void at91dbgu_txsoft(struct at91dbgu_softc *sc, struct tty *tp) { CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); (*tp->t_linesw->l_start)(tp); }
integrate void sscom_txsoft(struct sscom_softc *sc, struct tty *tp) { CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); (*tp->t_linesw->l_start)(tp); }
int ugen_do_close(struct ugen_softc *sc, int endpt, int flag) { struct ugen_endpoint *sce; int dir, i; #ifdef DIAGNOSTIC if (!sc->sc_is_open[endpt]) { printf("ugenclose: not open\n"); return (EINVAL); } #endif if (endpt == USB_CONTROL_ENDPOINT) { DPRINTFN(5, ("ugenclose: close control\n")); sc->sc_is_open[endpt] = 0; return (0); } for (dir = OUT; dir <= IN; dir++) { if (!(flag & (dir == OUT ? FWRITE : FREAD))) continue; sce = &sc->sc_endpoints[endpt][dir]; if (sce == NULL || sce->pipeh == NULL) continue; DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", endpt, dir, sce)); usbd_close_pipe(sce->pipeh); sce->pipeh = NULL; switch (sce->edesc->bmAttributes & UE_XFERTYPE) { case UE_INTERRUPT: ndflush(&sce->q, sce->q.c_cc); clfree(&sce->q); break; case UE_ISOCHRONOUS: for (i = 0; i < UGEN_NISOREQS; ++i) usbd_free_xfer(sce->isoreqs[i].xfer); default: break; } if (sce->ibuf != NULL) { free(sce->ibuf, M_USBDEV, 0); sce->ibuf = NULL; } } sc->sc_is_open[endpt] = 0; return (0); }
void sabtty_softintr(struct sabtty_softc *sc) { struct tty *tp = sc->sc_tty; int s, flags; uint8_t r; if (tp == NULL) return; if ((tp->t_state & TS_ISOPEN) == 0) return; while (sc->sc_rget != sc->sc_rput) { int data; uint8_t stat; data = sc->sc_rget[0]; stat = sc->sc_rget[1]; sc->sc_rget += 2; if (stat & SAB_RSTAT_PE) data |= TTY_PE; if (stat & SAB_RSTAT_FE) data |= TTY_FE; if (sc->sc_rget == sc->sc_rend) sc->sc_rget = sc->sc_rbuf; (*tp->t_linesw->l_rint)(data, tp); } s = splhigh(); flags = sc->sc_flags; sc->sc_flags &= ~(SABTTYF_DONE|SABTTYF_CDCHG|SABTTYF_RINGOVERFLOW); splx(s); if (flags & SABTTYF_CDCHG) { s = spltty(); r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD; splx(s); (*tp->t_linesw->l_modem)(tp, r); } if (flags & SABTTYF_RINGOVERFLOW) log(LOG_WARNING, "%s: ring overflow\n", device_xname(&sc->sc_dv)); if (flags & SABTTYF_DONE) { ndflush(&tp->t_outq, sc->sc_txp - tp->t_outq.c_cf); tp->t_state &= ~TS_BUSY; (*tp->t_linesw->l_start)(tp); } }
Static void ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) { struct ucom_softc *sc = (struct ucom_softc *)p; struct tty *tp = sc->sc_tty; u_int32_t cc; int s; DPRINTF(("ucomwritecb: status = %d\n", status)); if (status == USBD_CANCELLED || sc->sc_dying) goto error; if (status != USBD_NORMAL_COMPLETION) { printf("%s: ucomwritecb: %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(status)); if (status == USBD_STALLED) usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); /* XXX we should restart after some delay. */ goto error; } usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); DPRINTF(("ucomwritecb: cc = %d\n", cc)); if (cc <= sc->sc_opkthdrlen) { printf("%s: sent size too small, cc = %d\n", USBDEVNAME(sc->sc_dev), cc); goto error; } /* convert from USB bytes to tty bytes */ cc -= sc->sc_opkthdrlen; s = spltty(); CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, cc); (*linesw[tp->t_line].l_start)(tp); splx(s); return; error: s = spltty(); CLR(tp->t_state, TS_BUSY); splx(s); return; }
void zstty_txsoft(struct zstty_softc *zst, struct tty *tp) { int s; CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else { s = splzs(); ndflush(&tp->t_outq, (int)(zst->zst_tba - tp->t_outq.c_cf)); splx(s); } (*linesw[tp->t_line].l_start)(tp); }
/* * cztty_transmit() * * Look at the tty for this port and start sending. */ static int cztty_transmit(struct cztty_softc *sc, struct tty *tp) { struct cz_softc *cz = CZTTY_CZ(sc); u_int move, get, put, size, address; #ifdef HOSTRAMCODE int error, done = 0; #else int done = 0; #endif size = CZTTY_BUF_READ(sc, BUFCTL_TX_BUFSIZE); get = CZTTY_BUF_READ(sc, BUFCTL_TX_GET); put = CZTTY_BUF_READ(sc, BUFCTL_TX_PUT); address = CZTTY_BUF_READ(sc, BUFCTL_TX_BUFADDR); while ((tp->t_outq.c_cc > 0) && ((move = TX_MOVEABLE(get, put, size)))){ #ifdef HOSTRAMCODE if (0) { move = min(tp->t_outq.c_cc, move); error = q_to_b(&tp->t_outq, 0, move); if (error != move) { printf("%s: channel %d: error moving to " "transmit buf\n", device_xname(cz->cz_dev), sc->sc_channel); move = error; } } else { #endif move = min(ndqb(&tp->t_outq, 0), move); bus_space_write_region_1(cz->cz_win_st, cz->cz_win_sh, address + put, tp->t_outq.c_cf, move); ndflush(&tp->t_outq, move); #ifdef HOSTRAMCODE } #endif put = ((put + move) % size); done = 1; } if (done) { CZTTY_BUF_WRITE(sc, BUFCTL_TX_PUT, put); } return (done); }
void ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status) { struct ucom_softc *sc = (struct ucom_softc *)p; struct tty *tp = sc->sc_tty; u_int32_t cc; int s; DPRINTFN(5,("ucomwritecb: %p %p status=%d\n", xfer, p, status)); if (status == USBD_CANCELLED || usbd_is_dying(sc->sc_uparent)) goto error; if (sc->sc_bulkin_pipe != NULL) { if (status) { usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); /* XXX we should restart after some delay. */ goto error; } usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); } else { usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); // XXX above gives me wrong cc, no? } DPRINTFN(5,("ucomwritecb: cc=%d\n", cc)); /* convert from USB bytes to tty bytes */ cc -= sc->sc_opkthdrlen; s = spltty(); CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, cc); (*LINESW(tp, l_start))(tp); splx(s); return; error: s = spltty(); CLR(tp->t_state, TS_BUSY); splx(s); }
static void ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub, usbd_status err) { struct tty *tp = sc->sc_tty; uint32_t cc = ub->ub_len; switch (err) { case USBD_IN_PROGRESS: ub->ub_index = ub->ub_len; break; case USBD_STALLED: ub->ub_index = 0; softint_schedule(sc->sc_si); break; case USBD_NORMAL_COMPLETION: usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL); #if defined(__NetBSD__) && NRND > 0 rnd_add_uint32(&sc->sc_rndsource, cc); #endif /*FALLTHROUGH*/ default: SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link); SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link); cc -= sc->sc_opkthdrlen; CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, cc); if (err != USBD_CANCELLED && err != USBD_IOERROR && !sc->sc_dying) { if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL) ucom_submit_write(sc, ub); (*tp->t_linesw->l_start)(tp); } break; } }
void arcbios_tty_start(struct tty *tp) { u_long count; int s; s = spltty(); if (tp->t_state & (TS_TTSTOP | TS_BUSY)) goto out; ttypull(tp); tp->t_state |= TS_BUSY; while (tp->t_outq.c_cc != 0) { arcbios_Write(ARCBIOS_STDOUT, tp->t_outq.c_cf, ndqb(&tp->t_outq, 0), &count); ndflush(&tp->t_outq, count); } tp->t_state &= ~TS_BUSY; out: splx(s); }
void uart_start(struct tty *tp) { int s,i,cnt; s = spltty(); if (tp->t_state & (TS_TTSTOP | TS_BUSY)) goto out; ttypull(tp); tp->t_state |= TS_BUSY; while (tp->t_outq.c_cc != 0) { cnt = ndqb(&tp->t_outq, 0); for (i=0; i<cnt; i++) uart_cnputc(0,tp->t_outq.c_cf[i]); ndflush(&tp->t_outq, cnt); } tp->t_state &= ~TS_BUSY; out: splx(s); }
static void at91usart_filltx(struct at91usart_softc *sc) { struct tty *tp = sc->sc_tty; int len; void *dst; // post write handler AT91PDC_FIFO_POSTWRITE(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_tx_fifo); // copy more data to fifo: if (sc->sc_tbc > 0 && (dst = AT91PDC_FIFO_WRPTR(&sc->sc_tx_fifo, &len)) != NULL) { // copy data to fifo if (len > sc->sc_tbc) len = sc->sc_tbc; memcpy(dst, sc->sc_tba, len); sc->sc_tba += len; if ((sc->sc_tbc -= len) <= 0) CLR(tp->t_state, TS_BUSY); // update fifo AT91PDC_FIFO_WRITTEN(&sc->sc_tx_fifo, len); // tell tty interface we've sent some bytes ndflush(&tp->t_outq, len); } // start sending data... if (AT91PDC_FIFO_PREWRITE(sc->sc_iot, sc->sc_ioh, sc->sc_dmat, US_PDC, &sc->sc_tx_fifo, PDC_BLOCK_SIZE)) { at91usart_start_tx(sc); SET(sc->sc_ier, US_CSR_TXEMPTY | US_CSR_ENDTX); } else { CLR(sc->sc_ier, US_CSR_ENDTX); } }
/*ARGSUSED*/ int ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct pt_softc *pti = pt_softc[minor(dev)]; struct tty *tp = pti->pt_tty; u_char *cc = tp->t_cc; int stop, error; /* * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. * ttywflush(tp) will hang if there are characters in the outq. */ if (cmd == TIOCEXT) { /* * When the EXTPROC bit is being toggled, we need * to send an TIOCPKT_IOCTL if the packet driver * is turned on. */ if (*(int *)data) { if (pti->pt_flags & PF_PKT) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag |= EXTPROC; } else { if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag &= ~EXTPROC; } return(0); } else if (cdevsw[major(dev)].d_open == ptcopen) switch (cmd) { case TIOCGPGRP: #ifdef COMPAT_SUNOS { /* * I'm not sure about SunOS TIOCGPGRP semantics * on PTYs, but it's something like this: */ extern struct emul emul_sunos; if (p->p_emul == &emul_sunos) { if (tp->t_pgrp == 0) return (EIO); *(int *)data = tp->t_pgrp->pg_id; return (0); } } #endif /* * We avoid calling ttioctl on the controller since, * in that case, tp must be the controlling terminal. */ *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; return (0); case TIOCPKT: if (*(int *)data) { if (pti->pt_flags & PF_UCNTL) return (EINVAL); pti->pt_flags |= PF_PKT; } else pti->pt_flags &= ~PF_PKT; return (0); case TIOCUCNTL: if (*(int *)data) { if (pti->pt_flags & PF_PKT) return (EINVAL); pti->pt_flags |= PF_UCNTL; } else pti->pt_flags &= ~PF_UCNTL; return (0); case TIOCREMOTE: if (*(int *)data) pti->pt_flags |= PF_REMOTE; else pti->pt_flags &= ~PF_REMOTE; ttyflush(tp, FREAD|FWRITE); return (0); #ifdef COMPAT_OLDTTY case TIOCSETP: case TIOCSETN: #endif case TIOCSETD: case TIOCSETA: case TIOCSETAW: case TIOCSETAF: ndflush(&tp->t_outq, tp->t_outq.c_cc); break; case TIOCSIG: if (*(unsigned int *)data >= NSIG || *(unsigned int *)data == 0) return(EINVAL); if ((tp->t_lflag&NOFLSH) == 0) ttyflush(tp, FREAD|FWRITE); pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); if ((*(unsigned int *)data == SIGINFO) && ((tp->t_lflag&NOKERNINFO) == 0)) ttyinfo(tp); return(0); } error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error < 0) error = ttioctl(tp, cmd, data, flag, p); if (error < 0) { if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) { if (cmd & 0xff) { pti->pt_ucntl = (u_char)cmd; ptcwakeup(tp, FREAD); } return (0); } error = ENOTTY; } /* * If external processing and packet mode send ioctl packet. */ if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { switch (cmd) { case TIOCSETA: case TIOCSETAW: case TIOCSETAF: #ifdef COMPAT_OLDTTY case TIOCSETP: case TIOCSETN: case TIOCSETC: case TIOCSLTC: case TIOCLBIS: case TIOCLBIC: case TIOCLSET: #endif pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); default: break; } } stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) && CCEQ(cc[VSTART], CTRL('q')); if (pti->pt_flags & PF_NOSTOP) { if (stop) { pti->pt_send &= ~TIOCPKT_NOSTOP; pti->pt_send |= TIOCPKT_DOSTOP; pti->pt_flags &= ~PF_NOSTOP; ptcwakeup(tp, FREAD); } } else { if (!stop) { pti->pt_send &= ~TIOCPKT_DOSTOP; pti->pt_send |= TIOCPKT_NOSTOP; pti->pt_flags |= PF_NOSTOP; ptcwakeup(tp, FREAD); } } return (error); }
void clmpcc_softintr(void *arg) { struct clmpcc_softc *sc = (struct clmpcc_softc *)arg; struct clmpcc_chan *ch; struct tty *tp; int (*rint)(int, struct tty *); u_char *get; u_char reg; u_int c; int chan; /* Handle Modem state changes too... */ for (chan = 0; chan < CLMPCC_NUM_CHANS; chan++) { ch = &sc->sc_chans[chan]; tp = ch->ch_tty; get = ch->ch_ibuf_rd; rint = tp->t_linesw->l_rint; /* Squirt buffered incoming data into the tty layer */ while ( get != ch->ch_ibuf_wr ) { c = get[0]; c |= ((u_int)get[1]) << 8; if ( (rint)(c, tp) == -1 ) { ch->ch_ibuf_rd = ch->ch_ibuf_wr; break; } get += 2; if ( get == ch->ch_ibuf_end ) get = ch->ch_ibuf; ch->ch_ibuf_rd = get; } /* * Is the transmitter idle and in need of attention? */ if ( ch->ch_tx_done ) { ch->ch_tx_done = 0; if ( ISSET(ch->ch_flags, CLMPCC_FLG_NEED_INIT) ) { clmpcc_channel_cmd(sc, ch->ch_car, CLMPCC_CCR_T0_INIT | CLMPCC_CCR_T0_RX_EN | CLMPCC_CCR_T0_TX_EN); CLR(ch->ch_flags, CLMPCC_FLG_NEED_INIT); /* * Allow time for the channel to initialise. * (Empirically derived duration; there must * be another way to determine the command * has completed without busy-waiting...) */ delay(800); /* * Update the tty layer's idea of the carrier * bit, in case we changed CLOCAL or MDMBUF. * We don't hang up here; we only do that by * explicit request. */ reg = clmpcc_rd_msvr(sc) & CLMPCC_MSVR_CD; (*tp->t_linesw->l_modem)(tp, reg != 0); } CLR(tp->t_state, TS_BUSY); if ( ISSET(tp->t_state, TS_FLUSH) ) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, (int)(ch->ch_obuf_addr - tp->t_outq.c_cf)); (*tp->t_linesw->l_start)(tp); } } }
/* * magma soft interrupt handler * * returns 1 if it handled it, 0 otherwise * * runs at spltty() */ void magma_soft(void *arg) { struct magma_softc *sc = arg; struct mtty_softc *mtty = sc->ms_mtty; struct mbpp_softc *mbpp = sc->ms_mbpp; int port; int serviced = 0; int s, flags; /* * check the tty ports (if any) to see what needs doing */ if (mtty) { for (port = 0 ; port < mtty->ms_nports ; port++) { struct mtty_port *mp = &mtty->ms_port[port]; struct tty *tp = mp->mp_tty; if (!ISSET(tp->t_state, TS_ISOPEN)) continue; /* * handle any received data */ while (mp->mp_rget != mp->mp_rput) { u_char stat; int data; stat = mp->mp_rget[0]; data = mp->mp_rget[1]; mp->mp_rget = ((mp->mp_rget + 2) == mp->mp_rend) ? mp->mp_rbuf : (mp->mp_rget + 2); if (stat & (CD1400_RDSR_BREAK | CD1400_RDSR_FE)) data |= TTY_FE; if (stat & CD1400_RDSR_PE) data |= TTY_PE; if (stat & CD1400_RDSR_OE) log(LOG_WARNING, "%s%x: fifo overflow\n", mtty->ms_dev.dv_xname, port); (*linesw[tp->t_line].l_rint)(data, tp); serviced = 1; } s = splhigh(); /* block out hard interrupt routine */ flags = mp->mp_flags; CLR(mp->mp_flags, MTTYF_DONE | MTTYF_CARRIER_CHANGED | MTTYF_RING_OVERFLOW); splx(s); /* ok */ if (ISSET(flags, MTTYF_CARRIER_CHANGED)) { dprintf(("%s%x: cd %s\n", mtty->ms_dev.dv_xname, port, mp->mp_carrier ? "on" : "off")); (*linesw[tp->t_line].l_modem)(tp, mp->mp_carrier); serviced = 1; } if (ISSET(flags, MTTYF_RING_OVERFLOW)) { log(LOG_WARNING, "%s%x: ring buffer overflow\n", mtty->ms_dev.dv_xname, port); serviced = 1; } if (ISSET(flags, MTTYF_DONE)) { ndflush(&tp->t_outq, mp->mp_txp - tp->t_outq.c_cf); CLR(tp->t_state, TS_BUSY); (*linesw[tp->t_line].l_start)(tp); /* might be some more */ serviced = 1; } } /* for (each mtty...) */ } /* * check the bpp ports (if any) to see what needs doing */ if (mbpp) { for (port = 0 ; port < mbpp->ms_nports ; port++) { struct mbpp_port *mp = &mbpp->ms_port[port]; if (!ISSET(mp->mp_flags, MBPPF_OPEN)) continue; s = splhigh(); /* block out hard intr routine */ flags = mp->mp_flags; CLR(mp->mp_flags, MBPPF_WAKEUP); splx(s); if (ISSET(flags, MBPPF_WAKEUP)) { wakeup(mp); serviced = 1; } } /* for (each mbpp...) */ } }
void spif_softintr(void *vsc) { struct spif_softc *sc = (struct spif_softc *)vsc; struct stty_softc *stc = sc->sc_ttys; int i, data, s, flags; uint8_t stat, msvr; struct stty_port *sp; struct tty *tp; if (stc != NULL) { for (i = 0; i < stc->sc_nports; i++) { sp = &stc->sc_port[i]; tp = sp->sp_tty; if (!ISSET(tp->t_state, TS_ISOPEN)) continue; while (sp->sp_rget != sp->sp_rput) { stat = sp->sp_rget[0]; data = sp->sp_rget[1]; sp->sp_rget += 2; if (sp->sp_rget == sp->sp_rend) sp->sp_rget = sp->sp_rbuf; if (stat & (CD180_RCSR_BE | CD180_RCSR_FE)) data |= TTY_FE; if (stat & CD180_RCSR_PE) data |= TTY_PE; (*tp->t_linesw->l_rint)(data, tp); } s = splhigh(); flags = sp->sp_flags; CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG | STTYF_RING_OVERFLOW); splx(s); if (ISSET(flags, STTYF_CDCHG)) { s = spltty(); STC_WRITE(sc, STC_CAR, i); msvr = STC_READ(sc, STC_MSVR); splx(s); sp->sp_carrier = msvr & CD180_MSVR_CD; (*tp->t_linesw->l_modem)(tp, sp->sp_carrier); } if (ISSET(flags, STTYF_RING_OVERFLOW)) { log(LOG_WARNING, "%s-%x: ring overflow\n", device_xname(stc->sc_dev), i); } if (ISSET(flags, STTYF_DONE)) { ndflush(&tp->t_outq, sp->sp_txp - tp->t_outq.c_cf); CLR(tp->t_state, TS_BUSY); (*tp->t_linesw->l_start)(tp); } } } }
STATIC void gtmpsc_softintr(void *arg) { struct gtmpsc_softc *sc = arg; struct tty *tp = sc->sc_tty; gtmpsc_pollrx_t *vrxp; int code; u_int cc; u_char *get, *end, lsr; int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; if (sc->sc_rx_ready) { sc->sc_rx_ready = 0; cc = sc->sc_rcvcnt; /* If not yet open, drop the entire buffer content here */ if (!ISSET(tp->t_state, TS_ISOPEN)) cc = 0; vrxp = &sc->sc_poll_sdmapage->rx[sc->sc_rcvrx]; end = vrxp->rxbuf + vrxp->rxdesc.sdma_cnt; get = vrxp->rxbuf + sc->sc_roffset; while (cc > 0) { code = *get; lsr = vrxp->rxdesc.sdma_csr; if (ISSET(lsr, SDMA_CSR_RX_PE | SDMA_CSR_RX_FR | SDMA_CSR_RX_OR | SDMA_CSR_RX_BR)) { if (ISSET(lsr, SDMA_CSR_RX_OR)) ; /* XXXXX not yet... */ if (ISSET(lsr, SDMA_CSR_RX_BR | SDMA_CSR_RX_FR)) SET(code, TTY_FE); if (ISSET(lsr, SDMA_CSR_RX_PE)) SET(code, TTY_PE); } if ((*rint)(code, tp) == -1) { /* * The line discipline's buffer is out of space. */ /* XXXXX not yet... */ } if (++get >= end) { /* cleanup this descriptor, and return to DMA */ CLEANUP_AND_RETURN_RXDMA(sc, sc->sc_rcvrx); sc->sc_rcvrx = (sc->sc_rcvrx + 1) % GTMPSC_NTXDESC; vrxp = &sc->sc_poll_sdmapage->rx[sc->sc_rcvrx]; end = vrxp->rxbuf + vrxp->rxdesc.sdma_cnt; get = vrxp->rxbuf + sc->sc_roffset; } cc--; } } if (sc->sc_tx_done) { sc->sc_tx_done = 0; CLR(tp->t_state, TS_BUSY); if (ISSET(tp->t_state, TS_FLUSH)) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); (*tp->t_linesw->l_start)(tp); } }
/*ARGSUSED*/ static int ptyioctl(struct dev_ioctl_args *ap) { cdev_t dev = ap->a_head.a_dev; struct tty *tp = dev->si_tty; struct pt_ioctl *pti = dev->si_drv1; u_char *cc = tp->t_cc; int stop, error; lwkt_gettoken(&tty_token); if (dev_dflags(dev) & D_MASTER) { switch (ap->a_cmd) { case TIOCGPGRP: /* * We avoid calling ttioctl on the controller since, * in that case, tp must be the controlling terminal. */ *(int *)ap->a_data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; lwkt_reltoken(&tty_token); return (0); case TIOCPKT: if (*(int *)ap->a_data) { if (pti->pt_flags & PF_UCNTL) { lwkt_reltoken(&tty_token); return (EINVAL); } pti->pt_flags |= PF_PKT; } else { pti->pt_flags &= ~PF_PKT; } lwkt_reltoken(&tty_token); return (0); case TIOCUCNTL: if (*(int *)ap->a_data) { if (pti->pt_flags & PF_PKT) { lwkt_reltoken(&tty_token); return (EINVAL); } pti->pt_flags |= PF_UCNTL; } else { pti->pt_flags &= ~PF_UCNTL; } lwkt_reltoken(&tty_token); return (0); case TIOCREMOTE: if (*(int *)ap->a_data) pti->pt_flags |= PF_REMOTE; else pti->pt_flags &= ~PF_REMOTE; ttyflush(tp, FREAD|FWRITE); lwkt_reltoken(&tty_token); return (0); #ifdef UNIX98_PTYS case TIOCISPTMASTER: if ((pti->pt_flags & PF_UNIX98) && (pti->devc == dev)) { lwkt_reltoken(&tty_token); return (0); } else { lwkt_reltoken(&tty_token); return (EINVAL); } } #endif /* * The rest of the ioctls shouldn't be called until * the slave is open. */ if ((tp->t_state & TS_ISOPEN) == 0) { lwkt_reltoken(&tty_token); return (EAGAIN); } switch (ap->a_cmd) { #ifdef COMPAT_43 case TIOCSETP: case TIOCSETN: #endif case TIOCSETD: case TIOCSETA: case TIOCSETAW: case TIOCSETAF: /* * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG. * ttywflush(tp) will hang if there are characters in * the outq. */ ndflush(&tp->t_outq, tp->t_outq.c_cc); break; case TIOCSIG: if (*(unsigned int *)ap->a_data >= NSIG || *(unsigned int *)ap->a_data == 0) { lwkt_reltoken(&tty_token); return(EINVAL); } if ((tp->t_lflag&NOFLSH) == 0) ttyflush(tp, FREAD|FWRITE); pgsignal(tp->t_pgrp, *(unsigned int *)ap->a_data, 1); if ((*(unsigned int *)ap->a_data == SIGINFO) && ((tp->t_lflag&NOKERNINFO) == 0)) ttyinfo(tp); lwkt_reltoken(&tty_token); return(0); } } if (ap->a_cmd == TIOCEXT) { /* * When the EXTPROC bit is being toggled, we need * to send an TIOCPKT_IOCTL if the packet driver * is turned on. */ if (*(int *)ap->a_data) { if (pti->pt_flags & PF_PKT) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag |= EXTPROC; } else { if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); } tp->t_lflag &= ~EXTPROC; } lwkt_reltoken(&tty_token); return(0); } error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data, ap->a_fflag, ap->a_cred); if (error == ENOIOCTL) error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag); if (error == ENOIOCTL) { if (pti->pt_flags & PF_UCNTL && (ap->a_cmd & ~0xff) == UIOCCMD(0)) { if (ap->a_cmd & 0xff) { pti->pt_ucntl = (u_char)ap->a_cmd; ptcwakeup(tp, FREAD); } lwkt_reltoken(&tty_token); return (0); } error = ENOTTY; } /* * If external processing and packet mode send ioctl packet. */ if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { switch(ap->a_cmd) { case TIOCSETA: case TIOCSETAW: case TIOCSETAF: #ifdef COMPAT_43 case TIOCSETP: case TIOCSETN: #endif #if defined(COMPAT_43) || defined(COMPAT_SUNOS) case TIOCSETC: case TIOCSLTC: case TIOCLBIS: case TIOCLBIC: case TIOCLSET: #endif pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); default: break; } } stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) && CCEQ(cc[VSTART], CTRL('q')); if (pti->pt_flags & PF_NOSTOP) { if (stop) { pti->pt_send &= ~TIOCPKT_NOSTOP; pti->pt_send |= TIOCPKT_DOSTOP; pti->pt_flags &= ~PF_NOSTOP; ptcwakeup(tp, FREAD); } } else { if (!stop) { pti->pt_send &= ~TIOCPKT_DOSTOP; pti->pt_send |= TIOCPKT_NOSTOP; pti->pt_flags |= PF_NOSTOP; ptcwakeup(tp, FREAD); } } lwkt_reltoken(&tty_token); return (error); }