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