In any case, I managed to get it to work, but I'm not sure why it works. There's two real changes.
1. Change mga_driver_irq_postinstall to write 0x0c to MGA_IEN instead of 0x20.
2. Change mga_dma_service to get the interrupt status register with 0x08 instead of 0x20.
Any other combination of enable & test that did not include those bits failed. I would understand if it was 0x08 in both places. I could just write it off as the wrong bit value in the header file. But why does bit 2 also need to be set to enable the interrupt source?
In any case, I've attached my hack-patch. I'm considering applying a cleaned-up version of this to the texmem branch. Thoughts?
Index: mga_irq.c
===================================================================
RCS file:
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_irq.c,v
retrieving revision 1.1.4.2
diff -u -d -r1.1.4.2 mga_irq.c
--- mga_irq.c 5 Dec 2002 15:28:09 -0000 1.1.4.2
+++ mga_irq.c 2 Jan 2003 23:51:46 -0000
@@ -36,6 +36,11 @@
#include "mga_drm.h"
#include "mga_drv.h"
+#define IDR_VBLANK_HACK 1
+#if IDR_VBLANK_HACK
+static int irq_foo = 0;
+#endif
+
void mga_dma_service( DRM_IRQ_ARGS )
{
drm_device_t *dev = (drm_device_t *) arg;
@@ -46,12 +51,22 @@
status = MGA_READ( MGA_STATUS );
/* VBLANK interrupt */
+#if IDR_VBLANK_HACK
+ if ( status & 0x08 ) {
+ irq_foo = status;
+ MGA_WRITE( MGA_ICLEAR, status );
+ atomic_inc(&dev->vbl_received);
+ DRM_WAKEUP(&dev->vbl_queue);
+ DRM(vbl_send_signals)( dev );
+ }
+#else
if ( status & MGA_VLINEPEN ) {
MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue);
DRM(vbl_send_signals)( dev );
}
+#endif
}
int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence)
@@ -68,7 +83,9 @@
- *sequence ) <= (1<<23) ) );
*sequence = cur_vblank;
-
+#if IDR_VBLANK_HACK
+ printk( "irq_foo = 0x%04x\n", irq_foo & 0x0ffff );
+#endif
return ret;
}
@@ -87,7 +104,11 @@
(drm_mga_private_t *)dev->dev_private;
/* Turn on VBL interrupt */
+#if IDR_VBLANK_HACK
+ MGA_WRITE( MGA_IEN, 0x0000000c );
+#else
MGA_WRITE( MGA_IEN, MGA_VLINEIEN );
+#endif
}
void mga_driver_irq_uninstall( drm_device_t *dev ) {
