Fix hard lockup on COM port open from stale UART interrupt

Clear IER and read IIR/LSR/MSR/RBR before hookIsr unmasks the PIC.
A pending interrupt from a previous session would fire immediately,
but the ISR skipped dispatch (isOpen still FALSE), leaving the IRQ
asserted on level-triggered ISA -- infinite ISR loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Duensing 2026-03-03 17:18:31 -06:00
parent fd56c8003d
commit eebcf100ad

View file

@ -886,6 +886,18 @@ int16_t FAR PASCAL _export inicom(DCB FAR *dcb)
port->is16550 = (uint8_t)detect16550(port->baseAddr);
dbgHex16("KPCOMM: inicom is16550", (uint16_t)port->is16550);
// Disable UART interrupts and clear all pending conditions BEFORE
// hooking ISR. Without this, a stale interrupt from a previous
// session fires the moment hookIsr unmasks the PIC. The ISR sees
// isOpen=FALSE, skips isrDispatch, sends EOI, but the UART's IRQ
// line stays asserted (level-triggered ISA). Result: infinite
// ISR loop, hard lockup.
_outp(port->baseAddr + UART_IER, 0);
(void)_inp(port->baseAddr + UART_IIR);
(void)_inp(port->baseAddr + UART_LSR);
(void)_inp(port->baseAddr + UART_MSR);
(void)_inp(port->baseAddr + UART_RBR);
// Hook ISR
if (hookIsr(port) != 0) {
dbgStr("KPCOMM: inicom hookIsr FAIL\r\n");