Example #1
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"));
}
Example #2
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;
	struct clist *qp;
	BYTE ipos;
	int nchar;
	int oldspl, count, n, amount, buffer_full;

	oldspl = spltty();

	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;

	buffer_full = 0;
	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) {
			buffer_full++;
			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)
				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|SS_INLSTART)) == SS_LSTART) {
			untimeout(si_lstart, (caddr_t)pp, pp->lstart_ch);
		} else {
			pp->sp_state |= SS_LSTART;
		}
		DPRINT((pp, DBG_START, "arming lstart, time=%d\n", time));
		pp->lstart_ch = timeout(si_lstart, (caddr_t)pp, time);
	}

out:
	splx(oldspl);
	DPRINT((pp, DBG_EXIT|DBG_START, "leave si_start()\n"));
}