Subject: Re: tty input flow control with a "silo"
To: Charles M. Hannum <mycroft@NetBSD.ORG>
From: Bill Studenmund <wrstuden@loki.Stanford.EDU>
List: tech-kern
Date: 02/15/1996 16:03:34
>    I gather that Charles has adding multi-byte character reads to the tty
>    system somewhere near the top of his to-do list. (sorry that sentence
>    doesn't read well) Maybe this question can (has been) addressed as part
>    of this change (since we can't really get multiple bytes if we don't
>    have an intermediate buffer)?
> 
> It sounds to me like Gordon was referring to the case of a mid-level buffer
> in the device driver getting close to full.  There's obviously already a
> way for the device driver to do hardware flow control in this case, 
> although there's no prescribed mechanism for asserting software flow
> control.
> 
> For the case of the tty buffer filling up (which is the case I think you
> are referring to), there is already code to handle both software and
> hardware flow control, in ttyblock(), by using a callback to the device
> driver.

I agree we have the pieces, except for the lack of prescribed software
flow control in the hardware driver. What I was thinking about, though,
is we have no way of coordinating the two (or if we do, I missed it).

Say the mid-level buffer starts to fill up, so the hardware layer
requests a stop. Then a lot of bytes get sent to the tty driver by
the software interrupt servicer. So now the mid-level buffer is empty,
so it can request the other computer resume sending. But say these
bytes have filled the tty-layer buffer, so it too requests a stop.

As is, the final state when all is said and done depends up on who 
touches the blocking code last. If the mid-level says unblock, then the
tty says block, we end up blocked. If it happens the other way around,
then we end up unblocked when we should be blocked.

Worse yet, say we are doing software flow control, and have set ixany
(the flag that says any bute sent resumes transmission after an xoff).
The sent sequence would be XOFF XOFF XON (from mid-level block,
tty-level block, and mid-level release, respectively). As I understand
it, w/ ixany the second XOFF, being a character after an XOFF, restarts
transmission.  The XON is then taken as a data character (since it is
not just after an XOFF), so we polute the data stream. :-(

So the idea is: we track blocking from both levels. If either
level requests a block when there was no block, we really block.
When both levels release their blocks, then we really unblock.

For compatability, couldn't we do the signaling with clever TTY flag
definitions (I don't have a copy of the headers, so I might mis-name
things, but I hope I get the idea across)?

We make the TTY_BLOCK mask (used in statements like
"if ((tp->flag_register & TTY_BLOCK) != 0) {code for when blocked}")
have two set bits, just as the flow control mask does. One bit
indicates that the mid-level buffer is blocking, and the other
indicates that the tty layer is blocking. Thus when either level wants
to block, if both bits are = 0, it blocks. Either way, it then sets its
bit. If either layer wants to unblock, it clears its bit, and if both
bits are clear, then it unblocks.

Does this idea make sense?

Take care,

Bill