pc_serial: fix KDL on close

It's working \o/
Just need to figure out why it waits for \n to transmit.

We now only destroy the cookies in the free hook.

Mention pending DPC as soon as when inside the irq handler.

Also limit the number of loops in the IRQ handler to avoid busy looping.
It only happened when testing with normal priority but you never know...
This commit is contained in:
François Revol 2014-08-29 00:34:25 +02:00
parent 7b97fd6dd8
commit c5c041a5ba
1 changed files with 24 additions and 13 deletions

View File

@ -346,7 +346,13 @@ SerialDevice::IsInterruptPending()
// the next time we'll read we'll miss the IRQ condition
// so we just cache the value for the real handler
fCachedIIR = ReadReg8(IIR);
return ((fCachedIIR & IIR_PENDING) == 0); // 0 means yes
bool pending = (fCachedIIR & IIR_PENDING) == 0;
if (pending)
atomic_add(&fPendingDPC, 1);
return pending; // 0 means yes
}
@ -358,10 +364,9 @@ SerialDevice::InterruptHandler()
uint8 iir, lsr, msr;
uint8 buffer[64];
int tries = 8; // avoid busy looping
TRACE(("InterruptHandler()\n"));
atomic_add(&fPendingDPC, 1);
// start with the first (cached) irq condition
iir = fCachedIIR;
while ((iir & IIR_PENDING) == 0) { // 0 means yes
@ -455,6 +460,10 @@ SerialDevice::InterruptHandler()
ret = B_HANDLED_INTERRUPT;
TRACE(("IRQ:h\n"));
// enough for now
if (tries-- == 0)
break;
// check the next IRQ condition
iir = ReadReg8(IIR);
}
@ -654,19 +663,12 @@ SerialDevice::Close()
fDeviceOpen = false;
gTTYModule->tty_close_cookie(fSystemTTYCookie);
gTTYModule->tty_close_cookie(fDeviceTTYCookie);
//XXX: we shouldn't have to do this!
bool en = false;
Service(fMasterTTY, TTYENABLE, &en, sizeof(en));
// XXX: shouldn't we tty_close_cookie() as well ??
// wait until currently executing DPC is done. In case another one
// is run beyond this point it will just bail out on !IsOpen().
while (atomic_get(&fPendingDPC))
snooze(1000);
gTTYModule->tty_destroy_cookie(fSystemTTYCookie);
gTTYModule->tty_destroy_cookie(fDeviceTTYCookie);
fSystemTTYCookie = fDeviceTTYCookie = NULL;
return status;
}
@ -677,6 +679,15 @@ SerialDevice::Free()
{
status_t status = B_OK;
// wait until currently executing DPC is done. In case another one
// is run beyond this point it will just bail out on !IsOpen().
while (atomic_get(&fPendingDPC))
snooze(1000);
gTTYModule->tty_destroy_cookie(fSystemTTYCookie);
gTTYModule->tty_destroy_cookie(fDeviceTTYCookie);
fSystemTTYCookie = fDeviceTTYCookie = NULL;
gTTYModule->tty_destroy(fMasterTTY);
gTTYModule->tty_destroy(fSlaveTTY);
fMasterTTY = fSlaveTTY = NULL;