Example #1
0
File: uhid.c Project: MarginC/kame
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);
}
Example #2
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);
}
Example #3
0
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);
}
Example #5
0
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);
}
Example #6
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);
	}
}
Example #7
0
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;
}
Example #8
0
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);
}
Example #9
0
/*
 * 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);
}
Example #10
0
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);
}
Example #11
0
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);
}
Example #13
0
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);
	}
}
Example #15
0
/*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);
}
Example #16
0
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);
		}
	}
}
Example #17
0
/*
 * 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...) */
    }
}
Example #18
0
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);
			}
		}
	}
}
Example #19
0
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);
	}
}
Example #20
0
/*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);
}