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:
parent
fd56c8003d
commit
eebcf100ad
1 changed files with 12 additions and 0 deletions
|
|
@ -886,6 +886,18 @@ int16_t FAR PASCAL _export inicom(DCB FAR *dcb)
|
||||||
port->is16550 = (uint8_t)detect16550(port->baseAddr);
|
port->is16550 = (uint8_t)detect16550(port->baseAddr);
|
||||||
dbgHex16("KPCOMM: inicom is16550", (uint16_t)port->is16550);
|
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
|
// Hook ISR
|
||||||
if (hookIsr(port) != 0) {
|
if (hookIsr(port) != 0) {
|
||||||
dbgStr("KPCOMM: inicom hookIsr FAIL\r\n");
|
dbgStr("KPCOMM: inicom hookIsr FAIL\r\n");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue