Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 30 Nov 1997 07:17:23 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bde@zeta.org.au, jak@cetlink.net
Cc:        hackers@freebsd.org
Subject:   Re: 650 UART, SIO driver, 8259 PIC
Message-ID:  <199711292017.HAA16179@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>...The
>>chance of a problem after 1 second (if we start scanning for interrupts =
>on
>>sio0 and don't go back to sio0 after finding an interrupt on sio1) is 1 =
>-
>>(1 - 1644/10**6)**822 =3D 74 in 100.
>
>That's no guarantee of avoiding a missed interrupt either.  After
>checking sio0 a second time and finding no interrupts, it will take a
>few clock cycles to reach to reach the instruction which sends EOI and
>then exit the ISR.  How can you be sure that sio1 does not reinterrupt
>before you exit cleanly?

Well, it can't interrupt the CPU since CPU interrupts are masked.
New interrupts only get as far as the IRR in the ICU.  Most of them
could be detected by reading the IRR, but that would be a pessimization,
and anyway ...

>You can't.  The reason it works is because you do get a new interrupt
>after exiting the ISR.

Right.  ... even if you read the IRR just before returning, an interrupt
may occur after you read the IRR but before you return fully.  BTW,
I remember why an EOI is sent on return and not at the start for the
non-auto-EOI case.  It is to reduce interrupt latency.

>It becomes clear if you trace the steps backwards:  Prior to checking
>sio0 for a second time, you had drained sio1, clearing its interrupt.
>Prior to that you had drained sio0, clearing its interrupt.  Now
>you've come around full circle and checked sio0 again.  You know that
>the state of sio0 has not changed since the last time you looked at it
>- sio0 has pulled its INT output to ground for the entire time it took
>to make that full circle.

It's slightly more complicated:

1. We don't always handle all the pending interrupts in siointr1().
This may result in the loop being iterated once more than necessary,
but it only costs a few integer instructions since it avoids a check of
the IIR after siointr1() returns.

2. Two more iterations of the loop after handling _all_ (that we
noticed) would be required for things to work like you said.  One more
is required to check that the sloppy handling done by siointr1() was
actually complete.

and subtler:

3. However, we only do one more.  This works because xx(x)50 UARTs never
drop their IRQ unless they are accessed in a certain way (or reset, or
power fails, etc.).  This implies that if there is no interrupt pending
on any of the UARTs when they are looked at in the loop, there must have
been no interrupt pending at the start of the loop, so the edge latch
must have been inactive at that time and any subsequent interrupt will
be seen by the ICU and we will get interrupted after we return.

>You also know that during all that time where sio0 held its INT output
>to ground, you drained sio1, causing its INT output to be pulled to
>ground.

Not quite - see above.

>That means that all the (two) UARTs on your multiport board
>have simultaneously pulled their output to ground for at least some
>brief time -- the proof is clear.  So if a new interrupt occurs before
>you can exit the ISR, you will have a low/high transition on the IRQ
>line, ESR will record the new edge, and when you exit the ISR you will
>get a new interrupt.

Correct.

>But it breaks down with more than two UARTs.  In the case of sio0,

No.

>...
>So now you have to recheck sio1 also.  But then what about sio0?  It
>could also reinterrupt, your IRQ line never goes ground, ESR cannot
>sense any edge, and you lose an interrupt.  And so on and so on ...
>with more than two UARTs, you can never stop looping or you might miss
>an interrupt!

We just go around once more when another interrupt becomes pending.
More than once is unlikely, and infinitely often is impossible if
the system isn't overloaded just handling the interrupts.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711292017.HAA16179>