Пример #1
0
/*
 * Send output to the UART until either there's none left to send, or we run
 * out of room and need to await an interrupt so that we can start sending
 * again.
 *
 * XXXRW: It would be nice to query WSPACE at the beginning and write to the
 * FIFO in bugger chunks.
 */
static void
aju_handle_output(struct altera_jtag_uart_softc *sc, struct tty *tp)
{
	uint32_t v;
	uint8_t ch;

	tty_lock_assert(tp, MA_OWNED);
	AJU_LOCK_ASSERT(sc);

	AJU_UNLOCK(sc);
	while (ttydisc_getc_poll(tp) != 0) {
		AJU_LOCK(sc);
		v = aju_control_read(sc);
		if ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) != 0) {
			AJU_UNLOCK(sc);
			if (ttydisc_getc(tp, &ch, sizeof(ch)) != sizeof(ch))
				panic("%s: ttydisc_getc", __func__);
			AJU_LOCK(sc);

			/*
			 * XXXRW: There is a slight race here in which we test
			 * for writability, drop the lock, get the character
			 * from the tty layer, re-acquire the lock, and then
			 * write.  It's possible for other code --
			 * specifically, the low-level console -- to have
			 * written in the mean time, which might mean that
			 * there is no longer space.  The BERI memory bus will
			 * cause this write to block, wedging the processor
			 * until space is available -- which could be a while
			 * if JTAG is not attached!
			 *
			 * The 'easy' fix is to drop the character if WSPACE
			 * has become unset.  Not sure what the 'hard' fix is.
			 */
			aju_data_write(sc, ch);
		} else {
			/*
			 * If JTAG is not present, then we will drop this
			 * character instead of perhaps scheduling an
			 * interrupt to let us know when there is buffer
			 * space.  Otherwise we might get a write interrupt
			 * later even though we aren't interested in sending
			 * anymore.  Loop to drain TTY-layer buffer.
			 */
			if (*sc->ajus_jtag_presentp == 0) {
				if (ttydisc_getc(tp, &ch, sizeof(ch)) !=
				    sizeof(ch))
					panic("%s: ttydisc_getc 2", __func__);
				AJU_UNLOCK(sc);
				continue;
			}
			if (sc->ajus_irq_res != NULL)
				aju_intr_writable_enable(sc);
			return;
		}
		AJU_UNLOCK(sc);
	}
	AJU_LOCK(sc);
	aju_intr_writable_disable(sc);
}
Пример #2
0
/*
 * Send output to the UART until either there's none left to send, or we run
 * out of room and need to await an interrupt so that we can start sending
 * again.
 *
 * XXXRW: It would be nice to query WSPACE at the beginning and write to the
 * FIFO in bugger chunks.
 */
static void
aju_handle_output(struct altera_jtag_uart_softc *sc, struct tty *tp)
{
	uint32_t v;
	uint8_t ch;

	tty_lock_assert(tp, MA_OWNED);
	AJU_LOCK_ASSERT(sc);

	AJU_UNLOCK(sc);
	while (ttydisc_getc_poll(tp) != 0) {
		AJU_LOCK(sc);
		v = aju_control_read(sc);
		if ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) != 0) {
			AJU_UNLOCK(sc);
			if (ttydisc_getc(tp, &ch, sizeof(ch)) != sizeof(ch))
				panic("%s: ttydisc_getc", __func__);
			AJU_LOCK(sc);
			aju_data_write(sc, ch);
		} else {
			/*
			 * If JTAG is not present, then we will drop this
			 * character instead of perhaps scheduling an
			 * interrupt to let us know when there is buffer
			 * space.  Otherwise we might get a write interrupt
			 * later even though we aren't interested in sending
			 * anymore.  Loop to drain TTY-layer buffer.
			 */
			if (*sc->ajus_jtag_presentp == 0) {
				if (ttydisc_getc(tp, &ch, sizeof(ch)) !=
				    sizeof(ch))
					panic("%s: ttydisc_getc 2", __func__);
				AJU_UNLOCK(sc);
				continue;
			}
			if (sc->ajus_irq_res != NULL)
				aju_intr_writable_enable(sc);
			return;
		}
		AJU_UNLOCK(sc);
	}
	AJU_LOCK(sc);
	aju_intr_writable_disable(sc);
}
Пример #3
0
static void
dcons_outwakeup(struct tty *tp)
{
	struct dcons_softc *dc;
	char ch;

	dc = tty_softc(tp);

	while (ttydisc_getc(tp, &ch, sizeof ch) != 0)
		dcons_os_putc(dc, ch);
}
Пример #4
0
static void
uart_phyp_ttyoutwakeup(struct tty *tp)
{
	struct uart_phyp_softc *sc;
	char buffer[8];
	int len;

	sc = tty_softc(tp);
	
	while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0)
		uart_phyp_put(sc, buffer, len);
}
Пример #5
0
static void
mambotty_outwakeup(struct tty *tp)
{
	int len;
	u_char buf[MAMBOBURSTLEN];

	for (;;) {
		len = ttydisc_getc(tp, buf, sizeof buf);
		if (len == 0)
			break;
		mambocall(MAMBO_CONSOLE_WRITE, buf, (register_t)len, 1UL);
	}
}
Пример #6
0
static void
ofwtty_outwakeup(struct tty *tp)
{
	int len;
	u_char buf[OFBURSTLEN];

	for (;;) {
		len = ttydisc_getc(tp, buf, sizeof buf);
		if (len == 0)
			break;
		OF_write(stdout, buf, len);
	}
}
Пример #7
0
static void
xcoutwakeup(struct tty *tp)
{
	boolean_t cons_full = FALSE;
	char c;

	while (ttydisc_getc(tp, &c, 1) == 1 && !cons_full)
		cons_full = xcons_putc(c);

	if (cons_full) {
	    	/* let the timeout kick us in a bit */
	    	xc_start_needed = TRUE;
	}

}
Пример #8
0
static void
nmdm_task_tty(void *arg, int pending __unused)
{
	struct tty *tp, *otp;
	struct nmdmpart *np = arg;
	char c;

	tp = np->np_tty;
	tty_lock(tp);
	if (tty_gone(tp)) {
		tty_unlock(tp);
		return;
	}

	otp = np->np_other->np_tty;
	KASSERT(otp != NULL, ("NULL otp in nmdmstart"));
	KASSERT(otp != tp, ("NULL otp == tp nmdmstart"));
	if (np->np_other->np_dcd) {
		if (!tty_opened(tp)) {
			np->np_other->np_dcd = 0;
			ttydisc_modem(otp, 0);
		}
	} else {
		if (tty_opened(tp)) {
			np->np_other->np_dcd = 1;
			ttydisc_modem(otp, 1);
		}
	}

	/* This may happen when we are in detach process. */
	if (tty_gone(otp)) {
		tty_unlock(otp);
		return;
	}

	while (ttydisc_rint_poll(otp) > 0) {
		if (np->np_rate && !np->np_quota)
			break;
		if (ttydisc_getc(tp, &c, 1) != 1)
			break;
		np->np_quota--;
		ttydisc_rint(otp, c, 0);
	}

	ttydisc_rint_done(otp);

	tty_unlock(tp);
}
Пример #9
0
static void
bvm_tty_outwakeup(struct tty *tp)
{
	int len, written;
	u_char buf[BVMBURSTLEN];

	for (;;) {
		len = ttydisc_getc(tp, buf, sizeof(buf));
		if (len == 0)
			break;

		written = 0;
		while (written < len)
			bvm_wcons(buf[written++]);
	}
}
Пример #10
0
/*------------------------------------------------------------------------*
 *	ucom_get_data
 *
 * Return values:
 * 0: No data is available.
 * Else: Data is available.
 *------------------------------------------------------------------------*/
uint8_t
ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc,
    uint32_t offset, uint32_t len, uint32_t *actlen)
{
	struct usb_page_search res;
	struct tty *tp = sc->sc_tty;
	uint32_t cnt;
	uint32_t offset_orig;

	mtx_assert(sc->sc_mtx, MA_OWNED);

	if (tty_gone(tp) ||
	    !(sc->sc_flag & UCOM_FLAG_GP_DATA)) {
		actlen[0] = 0;
		return (0);		/* multiport device polling */
	}
	offset_orig = offset;

	while (len != 0) {

		usbd_get_page(pc, offset, &res);

		if (res.length > len) {
			res.length = len;
		}
		/* copy data directly into USB buffer */
		cnt = ttydisc_getc(tp, res.buffer, res.length);

		offset += cnt;
		len -= cnt;

		if (cnt < res.length) {
			/* end of buffer */
			break;
		}
	}

	actlen[0] = offset - offset_orig;

	DPRINTF("cnt=%d\n", actlen[0]);

	if (actlen[0] == 0) {
		return (0);
	}
	return (1);
}
Пример #11
0
static void
cfe_tty_outwakeup(struct tty *tp)
{
	int len, written, rc;
	u_char buf[CFEBURSTLEN];

	for (;;) {
		len = ttydisc_getc(tp, buf, sizeof buf);
		if (len == 0)
			break;

		written = 0;
		while (written < len) {
			rc = cfe_write(conhandle, &buf[written], len - written);
			if (rc < 0)
				break;
			written += rc;
		}
	}
}
Пример #12
0
static void
hvcn_outwakeup(struct tty *tp)
{

	for (;;) {
		/* Refill the input buffer. */
		if (buflen == 0) {
			buflen = ttydisc_getc(tp, buf, PCBURST);
			bufindex = 0;
		}

		/* Transmit the input buffer. */
		while (buflen) {
			if (hv_cons_putchar(buf[bufindex]) == H_EWOULDBLOCK)
				return;
			bufindex++;
			buflen--;
		}
	}
}
Пример #13
0
static void
uart_tty_outwakeup(struct tty *tp)
{
	struct uart_softc *sc;

	sc = tty_softc(tp);
	if (sc == NULL || sc->sc_leaving)
		return;

	if (sc->sc_txbusy)
		return;

	/*
	 * Respect RTS/CTS (output) flow control if enabled and not already
	 * handled by hardware.
	 */
	if ((tp->t_termios.c_cflag & CCTS_OFLOW) && !sc->sc_hwoflow &&
	    !(sc->sc_hwsig & SER_CTS))
		return;

	sc->sc_txdatasz = ttydisc_getc(tp, sc->sc_txbuf, sc->sc_txfifosz);
	if (sc->sc_txdatasz != 0)
		UART_TRANSMIT(sc);
}
Пример #14
0
/*
 * Nudge the transmitter...
 *
 * XXX: I inherited some funny code here.  It implies the host card only
 * interrupts when the transmit buffer reaches the low-water-mark, and does
 * not interrupt when it's actually hits empty.  In some cases, we have
 * processes waiting for complete drain, and we need to simulate an interrupt
 * about when we think the buffer is going to be empty (and retry if not).
 * I really am not certain about this...  I *need* the hardware manuals.
 */
static void
si_start(struct tty *tp)
{
	struct si_port *pp;
	volatile struct si_channel *ccbp;
	BYTE ipos, count;
#if 0
	int nchar;
#endif
	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, "txbuf pend 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;
		DPRINT((pp, DBG_START, "spaceleft amount %d\n", amount));
		if (amount == 0)
			break;
		n = ttydisc_getc(tp, si_txbuf, amount);
		DPRINT((pp, DBG_START, "getc n=%d\n", n));
		if (n == 0)
			break;
		si_bcopyv(si_txbuf, &ccbp->hi_txbuf[ipos], n);
		ccbp->hi_txipos += n;
	}

#if 0
	/*
	 * See if there are any characters still to come.  If so, we can
	 * depend on si_start being called again.
	 *
	 * XXX the manual is vague on this.  It implies we get an interrupt
	 * when the transmit queue reaches the 25% low water mark, but NOT
	 * when it hits empty.
	 */
	nchar = ttyoutq_getsize(&tp->t_outq) - ttyoutq_bytesleft(&tp->t_outq);
	DPRINT((pp, DBG_START, "count %d, nchar %d\n",
		(BYTE)count, nchar));

	if (count != 0 && nchar == 0) {
		int time;

		/* XXX lame. Ticks per character. used to be a table. */
		time = (tp->t_termios.c_ospeed + 9) / 10;

		if (time > 0) {
			if (time < nchar)
				time = nchar / time;
			else
				time = 2;
		} else {
			DPRINT((pp, DBG_START,
				"bad char time value! %d\n", time));
			time = hz/10;
		}

		if ((pp->sp_state & SS_LSTART) != 0)
			untimeout(si_lstart, (caddr_t)pp, pp->lstart_ch);
		DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));
		pp->sp_state |= SS_LSTART;
		pp->lstart_ch = timeout(si_lstart, (caddr_t)pp, time);
	}
#endif

	splx(oldspl);
	DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));
}
Пример #15
0
/*------------------------------------------------------------------------*
 *	ucom_get_data
 *
 * Return values:
 * 0: No data is available.
 * Else: Data is available.
 *------------------------------------------------------------------------*/
uint8_t
ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc,
    uint32_t offset, uint32_t len, uint32_t *actlen)
{
	struct usb_page_search res;
	struct tty *tp = sc->sc_tty;
	uint32_t cnt;
	uint32_t offset_orig;

	UCOM_MTX_ASSERT(sc, MA_OWNED);

	if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
		unsigned int temp;

		/* get total TX length */

		temp = ucom_cons_tx_high - ucom_cons_tx_low;
		temp %= UCOM_CONS_BUFSIZE;

		/* limit TX length */

		if (temp > (UCOM_CONS_BUFSIZE - ucom_cons_tx_low))
			temp = (UCOM_CONS_BUFSIZE - ucom_cons_tx_low);

		if (temp > len)
			temp = len;

		/* copy in data */

		usbd_copy_in(pc, offset, ucom_cons_tx_buf + ucom_cons_tx_low, temp);

		/* update counters */

		ucom_cons_tx_low += temp;
		ucom_cons_tx_low %= UCOM_CONS_BUFSIZE;

		/* store actual length */

		*actlen = temp;

		return (temp ? 1 : 0);
	}

	if (tty_gone(tp) ||
	    !(sc->sc_flag & UCOM_FLAG_GP_DATA)) {
		actlen[0] = 0;
		return (0);		/* multiport device polling */
	}
	offset_orig = offset;

	while (len != 0) {

		usbd_get_page(pc, offset, &res);

		if (res.length > len) {
			res.length = len;
		}
		/* copy data directly into USB buffer */
		cnt = ttydisc_getc(tp, res.buffer, res.length);

		offset += cnt;
		len -= cnt;

		if (cnt < res.length) {
			/* end of buffer */
			break;
		}
	}

	actlen[0] = offset - offset_orig;

	DPRINTF("cnt=%d\n", actlen[0]);

	if (actlen[0] == 0) {
		return (0);
	}
	return (1);
}