[comp.sys.ibm.pc.hardware] 8250 and 8259 chips

gordon@vaxeline.COM (Gordon Lee) (10/30/90)

I have encountered some ambiguity in the IBM AT Tech Ref concerning the 
interaction between the 8250 and 8259 PIC chip.  The 8250 generates four
types of interrupt, namely: Modem Status, Receive, Transmit Completion, 
and Line Status.  To service an interrupt, the interrupt handling routine
must read the Interrupt Identification Register (IIR) to demux on the type 
of interrupt.  This much is fairly clear.

My Interrupt Service Routine (ISR) is currently defficient in that it 
can miss a transmit completion, thereby wedging my outgoing data stream.  
This only happens under heavy bidirectional traffic, which leads me to 
believe that my ISR is losing when a transmit completion intr and a receive 
intr happen "simultaneously".  I think my routine is handling the receive
interrupt while allowing the transmit completion interrupt to drop on 
the floor.

Under a description of the IIR, the Tech Ref says: "When the IIR is 
addressed, the pending interrupt with the highest priority is held 
and no other interrupts are acknowledged until the microprocessor 
services that interrupt."  I interpret that as follows:  
	- more than one interrupt type can be pending at once
	- of the interrupts pending, the IIR returns that which
		has the highest priority, and occured before any 
		other interrupts of the same type
What I have not been able to determine, is exactly what condition/state 
constitutes "(when the) microprocessor services that interrupt".  I also
cannot determine what my issuing a specific EOI to the PIC will do to the 
state of the machine.  And above all, I cannot determine how interrupts
of other types are dealt with while my ISR is executing.

The crux of what I need to know and what the manual doesn't want
to tell me is:  how to cleanly service a single physical interrupt
which is signalling the occurence of more than one type of UART 
interrupt condition.  I also need to know how to expect a subsequent
interrupt while I am in my service routine, and the proper way to 
acknowledge to the PIC notification of multiple "simultaneous" interrupts.

Any advice or pointers would be much appreciated.

-- 
==========================================================================
Gordon Lee
Member, Technical Staff
FTP Software, Inc.   (617) 246-0900 x287

markd@silogic.UUCP (Mark DiVecchio) (11/05/90)

In <1210@vaxeline.COM> gordon@vaxeline.COM (Gordon Lee) writes:

> My Interrupt Service Routine (ISR) is currently defficient in that it 
> can miss a transmit completion, thereby wedging my outgoing data stream.  

I had this problem here is a summary of what I found (take directly from
the source file of my program PC-VT :

;	There is problem with the 8250-A USART chips in the
; PC and PC compatible communications ports. The problem is that if
; there are several stacked interrupts, only the highest priority
; one is ever processed. PC-VT will just hang up waiting for the
; others. The 8250 and 8250-B work fine in the PC.
;
; I have rewritten PC-VT to only use one interrupt, the Data Ready
; interrupt. This should reduce the problem considerably.
;
; The problem is not "in" the 8250 but is in the interface between the
; 8250 and the 8259. The 8259 is operated in edge-trigger mode, but some
; of the versions of the 8250 do not drop their interrupt line if several
; interrupts are stacked up. Thus the 8259 never "sees" them.
; Specifically, the 8250 and 8250-B do "glitch" their interrupt lines.
; The 8250-A does not. Therefore, if you have a PC with an 8250-A, PC-VT
; would regularly hangup.
;
; In the PC AT, the problem compounds. The AT uses the new Serial
; chip from National, the 16450. All I know at this point, is that
; with only one interrupt, PC-VT works ok on the AT
;
; I would like to thank Marty in the applications department at
; National Semi in Santa Clara for his help. Two relevant documents
; from NSC are B01361 and B01511-1
;

-- 
Mark DiVecchio, Silogic Systems, 619-549-9841                       K3FWT
-----   9888 Carroll Center Road, Suite 113, San Diego, CA 92126    -----
markd@silogic.uucp                             BBS 619-549-3927
...!ucsd!celit!silogic!markd     celit!silogic!markd@ucsd.edu

david@csource.oz.au (david nugent) (11/06/90)

In <1210@vaxeline.COM> gordon@vaxeline.COM (Gordon Lee) writes:

> My Interrupt Service Routine (ISR) is currently defficient in that it 
> can miss a transmit completion, thereby wedging my outgoing data stream.  
> This only happens under heavy bidirectional traffic, which leads me to 
> believe that my ISR is losing when a transmit completion intr and a receive 
> intr happen "simultaneously".  I think my routine is handling the receive
> interrupt while allowing the transmit completion interrupt to drop on 
> the floor.

You are no doubt absolutely correct. This is a real pain, and somewhat of
an "undocumented feature" of most UARTS. Even 16550A series UARTS have the
same problem.

>
> [....]
>
> The crux of what I need to know and what the manual doesn't want
> to tell me is:  how to cleanly service a single physical interrupt
> which is signalling the occurence of more than one type of UART 
> interrupt condition.  I also need to know how to expect a subsequent
> interrupt while I am in my service routine, and the proper way to 
> acknowledge to the PIC notification of multiple "simultaneous" interrupts.

Ok, within the ISR the state of the PIC is irrelevent except that it's 
always a good idea, however, to rearm the PIC as soon as possible (assuming
you're working in a standard PC/AT edge triggered non-autoEOI mode).

Within a communications ISR, you simply loop back and re-test the UART's
IID register for new interrupts - you've probably done this.  The "bug"
I refer to above is within the UART itself - it will not recognise lower
priority interrupts (ie. modem status changes and transmit empty) when
servicing interupts of a higher priority.

Wonderful design.  :-(  If your ISR depends on getting each and every
transmit interrupt, one such missing interrupt causes a transmitter
"freeze".  Only by actually sending another character can you restart
it.

A partial solution is to read the line status register on the way out
of the ISR, and loop back of a) there are any characters in your software
transmit queue, and b) if the transmit holding register bit is empty.

Partial, I say, because it's not entirely reliable.  The INS8250 lies
through it's teeth - it often says it's empty when it isn't, resulting
in loss of characters in the transmit stream since the ISR stuffs something
into the THR when it isn't really empty. Most other UARTs I've come across 
don't suffer this same problem, so it should work just fine.

The best solution I've come up with is to disable transmitter interrupts
by masking out the appropriate bit in the IED, then masking it again -
immediately before servicing the higher priority interrupts - receive
data available, and on delta receive line status.  This does effectively
prevent the UART not noticing that the transmit holding register becomes
empty while within the service routine.

I've used this technique with great success, and some more. The transmitter
I've developed is now entirely driven by the transmit enable bit of the IER;
and relies on the feature in UARTS that triggers a THRE interrupt whenever 
that bit is set while the transmit holding register is empty.  That makes 
it entirely possible to limit all UART I/O to within the interrupt service 
code.

There's probably not enough bandwidth here for further expansion on the
subject and all the horror stories I could tell you about it, so email 
if you need any further clarification or help.


    - david
-- 

        Fidonet: 3:632/348   SIGnet: 28:4100/1  Imex: 90:833/387
              Data:  +61-3-885-7864   Voice: +61-3-826-6711
 Internet/ACSnet: david@csource.oz.au    Uucp: ..!uunet!munnari!csource!david