intel_extreme: read and loop for new interrupts. Fix #9718.

* MSI seems to trigger the need to loop: interrupts are not generated for bits
set while we process.
This commit is contained in:
Jérôme Duval
2014-03-18 21:43:31 +01:00
parent 4fc7f247a8
commit ab1f2cd08d
@@ -78,36 +78,41 @@ static int32
intel_interrupt_handler(void* data) intel_interrupt_handler(void* data)
{ {
intel_info &info = *(intel_info*)data; intel_info &info = *(intel_info*)data;
uint32 reg = find_reg(info, INTEL_INTERRUPT_IDENTITY);
uint16 identity = read16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY)); uint16 identity = read16(info, reg);
if (identity == 0) if (identity == 0)
return B_UNHANDLED_INTERRUPT; return B_UNHANDLED_INTERRUPT;
int32 handled = B_HANDLED_INTERRUPT; int32 handled = B_HANDLED_INTERRUPT;
// TODO: verify that these aren't actually the same while (identity != 0) {
bool hasPCH = info.device_type.HasPlatformControlHub();
uint16 mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA : INTERRUPT_VBLANK_PIPEA;
if ((identity & mask) != 0) {
handled = release_vblank_sem(info);
// make sure we'll get another one of those // TODO: verify that these aren't actually the same
write32(info, INTEL_DISPLAY_A_PIPE_STATUS, bool hasPCH = info.device_type.HasPlatformControlHub();
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); uint16 mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA
: INTERRUPT_VBLANK_PIPEA;
if ((identity & mask) != 0) {
handled = release_vblank_sem(info);
// make sure we'll get another one of those
write32(info, INTEL_DISPLAY_A_PIPE_STATUS,
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
}
mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEB : INTERRUPT_VBLANK_PIPEB;
if ((identity & mask) != 0) {
handled = release_vblank_sem(info);
// make sure we'll get another one of those
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
}
// setting the bit clears it!
write16(info, reg, identity);
identity = read16(info, reg);
} }
mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEB : INTERRUPT_VBLANK_PIPEB;
if ((identity & mask) != 0) {
handled = release_vblank_sem(info);
// make sure we'll get another one of those
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
}
// setting the bit clears it!
write16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY), identity);
return handled; return handled;
} }