I have been doing more hacking on the kernel DRM for rage 128 on my G4
powerbook.  This machine has a "UniNorth" v1.0 host bridge which can
(allegedly) do 2x AGP.  I have got DRI with AGP to work but it is a
bit of a saga.  The main problem is with the chip writing back the
ring read pointer.  With the DRM code in CVS, every call to
r128_do_cce_idle() times out because it isn't seeing the read pointer
updated.

I started with a patch by Ben Herrenschmidt to the r128 DRM which adds
a powermac-specific hack to reserve the last page of physical memory
and use that for the ring read pointer, rather than the piece of AGP
memory which is normally used for it.  We then write the physical
address of that bit of memory into the R128_PM4_BUFFER_DL_RPTR_ADDR
register.

I also split up ADVANCE_RING into separate ADVANCE_RING and
COMMIT_RING macros like the radeon DRM does, at Michel Daenzer's
suggestion.

With that, DRI with AGP runs well on my powerbook at 1x.  At 2x it
runs for a little while and then locks up the video chip, usually with
bizaare technicolor patterns.

Ben's hack is a bit ugly, though, so I tried various things to see if
I could get the chip to write back anything to AGP memory.  Nothing
worked.  Ben suggests that early versions of the UniNorth are buggy
and perhaps the hardware just can't do AGP writes.

So I tried another approach, which is to just read the
R128_PM4_BUFFER_DL_RPTR register when we need to know what the ring
head pointer is.  That seems to work fine, with no slowdown in
performance that I could measure (with glxgears and tuxracer).  I have
seen GL apps freeze up on a couple of occasions though.

The patch below is what I am using at the moment.  I would appreciate
comments on this approach.  I also tried this patch on an x86 box with
a Rage 128 (TR) chip and it seems to be working fine.

Also, is there some simple test I could do to work out whether AGP
writes work at all?

I still have the problem of the texture on the floor of the pinball
machine in emilia pinball not being rendered.

Finally, if someone can explain how addresses that are programmed into
the card are mapped back to main memory, that would be very useful.
In particular, how does the card decide whether an address (for
instance in the R128_PM4_BUFFER_DL_RPTR_ADDR register) is a physical
address to be used directly, or an AGP address?

Thanks,
Paul.

diff -urN shared/drm/kernel/r128_cce.c 
/home/paulus/kernel/pmac-2.5/drivers/char/drm/r128_cce.c
--- shared/drm/kernel/r128_cce.c        2003-05-21 20:05:00.000000000 +1000
+++ /home/paulus/kernel/pmac-2.5/drivers/char/drm/r128_cce.c    2003-05-23 
07:51:33.000000000 +1000
@@ -240,7 +240,8 @@
        r128_do_wait_for_idle( dev_priv );
 
        R128_WRITE( R128_PM4_BUFFER_CNTL,
-                   dev_priv->cce_mode | dev_priv->ring.size_l2qw );
+                   dev_priv->cce_mode | dev_priv->ring.size_l2qw
+                   | R128_PM4_BUFFER_CNTL_NOUPDATE );
        R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */
        R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN );
 
@@ -266,7 +267,8 @@
 static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
 {
        R128_WRITE( R128_PM4_MICRO_CNTL, 0 );
-       R128_WRITE( R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 );
+       R128_WRITE( R128_PM4_BUFFER_CNTL,
+                   R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE );
 
        dev_priv->cce_running = 0;
 }
@@ -335,29 +337,6 @@
        R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
        R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
 
-       /* DL_RPTR_ADDR is a physical address in AGP space. */
-       SET_RING_HEAD( dev_priv, 0 );
-
-#if __REALLY_HAVE_AGP
-       if ( !dev_priv->is_pci ) {
-               R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-                           dev_priv->ring_rptr->offset - dev->agp->base );
-       } else
-#endif         
-       {
-               drm_sg_mem_t *entry = dev->sg;
-               unsigned long tmp_ofs, page_ofs;
-
-               tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
-               page_ofs = tmp_ofs >> PAGE_SHIFT;
-
-               R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-                           entry->busaddr[page_ofs]);
-               DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
-                          (unsigned long) entry->busaddr[page_ofs],
-                          entry->handle + tmp_ofs );
-       }
-
        /* Set watermark control */
        R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
                    ((R128_WATERMARK_L/4) << R128_WMA_SHIFT)
diff -urN shared/drm/kernel/r128_drv.h 
/home/paulus/kernel/pmac-2.5/drivers/char/drm/r128_drv.h
--- shared/drm/kernel/r128_drv.h        2003-05-21 20:05:00.000000000 +1000
+++ /home/paulus/kernel/pmac-2.5/drivers/char/drm/r128_drv.h    2003-05-23 
07:52:39.000000000 +1000
@@ -34,8 +34,8 @@
 #ifndef __R128_DRV_H__
 #define __R128_DRV_H__
 
-#define GET_RING_HEAD(dev_priv)                DRM_READ32(  (dev_priv)->ring_rptr, 0 )
-#define SET_RING_HEAD(dev_priv,val)    DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
+#define GET_RING_HEAD(dev_priv)                R128_READ( R128_PM4_BUFFER_DL_RPTR )
+#define SET_RING_HEAD(dev_priv, val)   do { } while (0)
 
 typedef struct drm_r128_freelist {
        unsigned int age;
@@ -130,15 +130,6 @@
 
 extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
 
-static __inline__ void
-r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
-{
-       drm_r128_ring_buffer_t *ring = &dev_priv->ring;
-       ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32);
-       if ( ring->space <= 0 )
-               ring->space += ring->size;
-}
-
 extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
 extern int r128_do_cleanup_cce( drm_device_t *dev );
 extern int r128_do_cleanup_pageflip( drm_device_t *dev );
@@ -277,6 +268,7 @@
 #      define R128_PM4_64PIO_64VCBM_64INDBM    (7  << 28)
 #      define R128_PM4_64BM_64VCBM_64INDBM     (8  << 28)
 #      define R128_PM4_64PIO_64VCPIO_64INDPIO  (15 << 28)
+#      define R128_PM4_BUFFER_CNTL_NOUPDATE    (1 << 27)
 
 #define R128_PM4_BUFFER_WM_CNTL                0x0708
 #      define R128_WMA_SHIFT                   0
@@ -394,6 +386,15 @@
                                         (pkt) | ((n) << 16))
 
 
+static __inline__ void
+r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
+{
+       drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+       ring->space = (GET_RING_HEAD( dev_priv ) - ring->tail) * sizeof(u32);
+       if ( ring->space <= 0 )
+               ring->space += ring->size;
+}
+
 /* ================================================================
  * Misc helper macros
  */
@@ -436,11 +437,7 @@
  * Ring control
  */
 
-#if defined(__powerpc__)
-#define r128_flush_write_combine()     (void) GET_RING_HEAD( dev_priv )
-#else
 #define r128_flush_write_combine()     DRM_WRITEMEMORYBARRIER()
-#endif
 
 
 #define R128_VERBOSE   0
@@ -496,7 +493,6 @@
        }                                                               \
        r128_flush_write_combine();                                     \
        DRM_MEMORYBARRIER();                                            \
-       GET_RING_HEAD( dev_priv );                                      \
        R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail );     \
        R128_READ( R128_PM4_BUFFER_DL_WPTR );                           \
 } while (0)


-------------------------------------------------------
This SF.net email is sponsored by: eBay
Get office equipment for less on eBay!
http://adfarm.mediaplex.com/ad/ck/711-11697-6916-5
_______________________________________________
Dri-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to