BRACKENRIDGE%USC-ISIB@sri-unix.UUCP (01/10/84)
From: Billy <BRACKENRIDGE@USC-ISIB> Here is an edited version of the edge triggered interrupt debate. These messages will be of interest to anyone writing code for the IBM async port. It also should shed some light on some of the design decisions taken in the two MIT comm packages supported in the INFO-IBMPC library: Date: 30 Nov 1983 1619-PST Subject: Bugs in the COM: Package From: Craig Milo Rogers <ROGERS@USC-ISIB> To: Romkey@MIT-CSR Hi. I've been using a version of your interrupt-driven COM: package for the IBM PC. I think that I've discovered a timing bug in it, as follows: 1) The IBM PC uses the 8259 interrupt controller in edge-triggered mode. 2) The COM interrupt routine checks for interrupts from the 8250 before clearing the interrupt flag in the 8259 with a specific end-of-interrupt. 3) Between the time that the interrupt code checks for interrupt sources, and the time that it clears the interrupt flag, a new interrupt source could appear on the 8250. The resulting edge to the 8259 would be lost when the EOI is issued. My conclusion is that the end-of-interrupt should be issued to the 8259 BEFORE the 8250 is checked for interrupt sources. How does this sound to you? Craig Milo Rogers ------- ------------------------------ Date: 16 December 1983 23:53 est From: Saltzer at MIT-MULTICS Subject: edge-triggered interrupts To: Rogers at USC-ISIB cc: Saltzer at MIT-MULTICS, romkey at MIT-CSR Craig, Now that classes are over, I finally had a chance to look into the 8250-8259 interrupt interaction question that you raised. The documentation on the 8259 is a little vague on this point, but I believe that it is actually quite clever in edge-triggered mode. If an edge comes along, it latches the fact, and ignores more edges till the signal goes back down again AND the interrupt gets forwarded to the 8088. Then it begins watching for more edges. For the case of an 8250, the 8250 brings up its interrupt line, the 8259 latches and, unless there is other activity, notifies the 8088. The 8088 accepts the interrupt and begins running the COM interrupt handler, which knocks down the interrupt line when it reads the IIR of the 8250. That dropping of the interrupt line in turn causes the 8259 to start watching for another edge. The EOI has as its only function allowing the 8259 to coordinate interrupts among various levels. Until the EOI is issued, not recognized by the 8259. After the EOI, they will be. The EOI has nothing to do with whether or not edges are noticed and latched for later handling. Thus the EOI should be set as the last thing on the way out. If you set it early in the routine, the manipulation of the registers in the 8250 will cycle the interrupt line and generate a COM interrupt on top of the COM interrupt. The result is a series of nested COM interrupts until you get deep enough that the IIR seems empty and no further COM interrupts get generated. That is how I read the manual, though I am the first to admit that any interpretation of the manual seems to require a leap or two of the imagination to fill in some of the gaps. In any case, this model of how it works is consistent with all the external observations we have been able to make of the two chips and with the bugs we have tripped over when we tried different models (such as yours.) Jerry Saltzer ------------------------------ Date: 19 Dec 1983 1147-PST Subject: Re: edge-triggered interrupts From: Craig Milo Rogers <ROGERS@USC-ISIB> To: Saltzer@MIT-MULTICS cc: romkey@MIT-CSR, Gillmann@USC-ISIB Thank you for your analysis of the problem. That must explain the "LATCH ARMED" indications on the "IR Trigerring Timing Requirements" diagram in the 8259A specs from Intel. Your empirical experiences certainly outweigh my theoretical speculations. However, I would like to speculate some more based on the new data. Assume that the receiver were to request an interrupt. The 8250 would request an interrupt. IRR would be set active in the 8259A. Eventually, the 8088 interrupts. IRR is set inactive, ISR is set active. The interrupt routine checks the receive condition, and clears it. The 8250 drops its interrupt request line. The 8259A latch is reenabled. Suppose that the transmit section were now to request an interrupt. The 8250 would raise its interrupt line. The 8259A would latch it, and set IRR again. The 8088 is still in the interrupt service routine, which now repolls the 8250 for transmit interrupts. Seeing one, it clears it. The 8250 drops its interrupt line. The interrupt service routine issues the EOI, clearing the ISR bit. The 8088 returns from the interrupt routine, reenabling its interrupts. The 8259A has been waiting for the 8088 to process the interrupt cycle caused by the IRR bit activated by the transmit request. However, since the 8250's interrupt line was dropped before the 8088 acknowleged the interrupt to the 8259A, the 8259A should perform a "Default IR7" interrupt cycle, instead of a normal interrupt. If the line printer (IR7) is enabled at the same time, this will cause a false line printer interrupt. Any objections to this scenario? In any case, I fail to see how nested COM interrupts could result. 8088 interrupts are disabled throughout execution of the interrupt routine (no STI or POPF). At least, this is true of the version the Dick Gillmann gave me to start with. Craig Milo Rogers ------- ------------------------------ Date: 20 December 1983 20:57 est From: Saltzer at MIT-MULTICS Subject: Re: edge-triggered interrupts To: Craig Milo Rogers <ROGERS at USC-ISIB> cc: Saltzer at MIT-MULTICS, romkey at MIT-CSR, Gillmann at USC-ISIB Craig, Your scenario is one I hadn't thought about before, but it sounds correct. It also explains one mystery. Our serial line interrupt handler has a counter to pick up interrupts for which no condition code is set; that counter has never registered anything but zero. Yet the repoll sequence ought to cause some conditions to be serviced in advance of the interrupt that they cause, so that counter ought to occasionally record something. (We are certain that such early conditions actually occur because the handler loses characters if you don't repoll.) Your scenario calls for such early-serviced conditions to lead to level-7 interrupts rather than serial line interrupts, so this handler never sees them. I suppose that whatever level-7 handler is available is smart enough to ignore interrupts that don't have serviceable conditions to back them up so it doesn't matter. And I don't suppose it counts these cases so I can't verify that the com line is giving it extra things to ignore. I forgot that the CPU remains masked through the handler--the nested interrupt thing can't happen. It would help a bit if INTEL would publish the wiring diagram of the 8259 (and the 8250). The English language description sure leaves a lot to the imagination. Jerry ------------------------------ Date: 20 Dec 1983 18:42:39 PST Subject: Re: edge-triggered interrupts From: Craig Milo Rogers <ROGERS@USC-ISIB> To: Saltzer@MIT-MULTICS cc: romkey@MIT-CSR, Gillmann@USC-ISIB Interesting. I expect that your repoll sequence is necessary to prevent lost characters because the 8250 is presenting an interrupt *level* condition, rather than an interrupt *edge* condition. Thus, if more than one interrupt source is present withing the chip (say, receive and transmit), the interrupt request will remain active until all sources have been serviced. If the interrupt service routine were to service only one source before returning, the 8250 would not generate another edge for the 8259A. At least, this is how I read the 8250 documentation in the IBM Technical Reference manual. Thus, if you don't repoll to verify that all possible interrupt sources on the 8250 are clear before returning from the current interrupt, I would expect you to eventually reach a state where no more characters get through. This is somewhat different from your description of "losing characters" when repolling isn't present. I am concerned about the discrepancy. Does your application code perhaps time out and reset the 8250? So, even if you were to instrument the IRQ7 (line printer) service routine, I would expect to find few fake interrupts due to the 8250 ports. Considering the various windows involved, missing interrupt request edges should be far more common than delayed interrupt request edges, up to the point where the interrupt service routine itself is consuming 50% or so of the 8088 CPU. By the way, I believe that there is a wiring error in the IBM Line Printer interface circuit, so that all line printer interrupts are treated by the 8259A as fake IRQ7 interrupts rather than real ones. If you have time, you might review my analysis at the start of the line printer interrupt handler in [ISIB]<INFO-IBMPC.INT>LPT_PKG.ASM. I am interested in any comments you have. Craig Milo Rogers ------- ------------------------------ Date: 20 December 1983 22:45 est From: Saltzer at MIT-MULTICS Subject: Re: edge-triggered interrupts To: Craig Milo Rogers <ROGERS at USC-ISIB> cc: Saltzer at MIT-MULTICS, romkey at MIT-CSR, Gillmann at USC-ISIB Craig, You are certainly correct in your analysis of why one must repoll for further conditions after servicing the first one found. However I am unconvinced by the argument that suggests that early handling of conditions will be rare. If the line is operating full-duplex, a transmit holding register empty condition can occur at any time. If it occurs before the receive condition is read (but after the receive condition is registered) the interrupt line out of the 8250 will stay high, causing the "lost interrupt" effect. And that small window definitely does get hit, at least at 9600 baud and 19.2K, in our experience. If the THRE condition occurs after the receive condtion is read, then there should be a fake interrupt at level 7. If this window is at least as large as the previous one (and it is in this code) then unneeded interrupts should be at least as frequent as lost interrupts without repolling. This whole area I haven't looked carefully at for at least 18 months, so my recall sometimes is a little fuzzy. Jerry ------------------------------ Subject: Re: edge-triggered interrupts From: Craig Milo Rogers <ROGERS@USC-ISIB> To: Saltzer@MIT-MULTICS cc: romkey@MIT-CSR, Gillmann@USC-ISIB By the way, the repoll code in the COM routines doesn't check for line/modem status transition interrupts. It seems to me that this is an error. A line/modem status transition could take place while a transmit or receive interrupt is being processed; the interrupt request line will not drop; the interrupt routine will dismiss; no more COM interrupts. Craig Milo Rogers ------- ------------------------------ Date: 22 December 1983 21:31 est From: Saltzer at MIT-MULTICS Subject: Re: edge-triggered interrupts To: Craig Milo Rogers <ROGERS at USC-ISIB> Craig, Good try, but no cigar. The COM code (as I left it behind--hope you didn't change this property) doesn't enable line/modem status transition conditions, so they don't affect the interrupt request line. If they were enabled, they would have to be polled, agreed. There is a place in the code to go to in case the conditions appear in the IIR, but that path was provided as a safety net, not because I expected it ever to be followed. I ran into a subtle interaction in the polling for transmit interrupts, which led me look for every possible excuse to avoid enabling for lower priority interrupts. The reading of the IIR (which you have to do to find out whether or not the lower priority interrupts are there) resets the THRE condition. So I couldn't figure out any way to repoll without taking a chance on losing a THRE condition. Repolling again for an empty transmitter register would work, but then one would have to repoll yet again for a modem/line interrupt, etc., forever. So I just ducked the issue and left it for someone to sort out who really needed those conditions monitored. Jerry -------