So, I've done some more tinkering with the vblank IRQ on the G400. By putting debug messages in a few places I managed to determine that interrupts are not happening. I looked at the code to enable interrupts (in programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/mga_irq.c), and went back to some old skool hacking tricks: if the int you want isn't getting enabled, turn them all on and see which ones actually trigger. :)

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 ) {


Reply via email to