diff options
Diffstat (limited to 'linux/r128_cce.c')
-rw-r--r-- | linux/r128_cce.c | 95 |
1 files changed, 78 insertions, 17 deletions
diff --git a/linux/r128_cce.c b/linux/r128_cce.c index c0e20c213..1ced05fe9 100644 --- a/linux/r128_cce.c +++ b/linux/r128_cce.c @@ -178,6 +178,8 @@ static void r128_cce_load_microcode( drm_r128_private_t *dev_priv ) { int i; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + r128_do_wait_for_idle( dev_priv ); R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 ); @@ -208,7 +210,7 @@ int r128_do_cce_idle( drm_r128_private_t *dev_priv ) int i; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - if ( *dev_priv->ring.head == dev_priv->ring.tail ) { + if ( GET_RING_HEAD( &dev_priv->ring ) == dev_priv->ring.tail ) { int pm4stat = R128_READ( R128_PM4_STAT ); if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size ) && @@ -249,7 +251,7 @@ static void r128_do_cce_reset( drm_r128_private_t *dev_priv ) { R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 ); R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 ); - *dev_priv->ring.head = 0; + SET_RING_HEAD( &dev_priv->ring, 0 ); dev_priv->ring.tail = 0; } @@ -312,19 +314,43 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev ) u32 ring_start; u32 tmp; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + /* The manual (p. 2) says this address is in "VM space". This * means it's an offset from the start of AGP space. */ - ring_start = dev_priv->cce_ring->offset - dev->agp->base; +#if __REALLY_HAVE_AGP + if ( !dev_priv->is_pci ) + ring_start = dev_priv->cce_ring->offset - dev->agp->base; + else +#endif + ring_start = dev_priv->cce_ring->offset - dev->sg->handle; + R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET ); 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. */ - *dev_priv->ring.head = 0; - R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, - dev_priv->ring_rptr->offset ); + SET_RING_HEAD( &dev_priv->ring, 0 ); + + if ( !dev_priv->is_pci ) { + R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, + dev_priv->ring_rptr->offset ); + } else { + 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, + virt_to_bus(entry->pagelist[page_ofs]->virtual)); + + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + virt_to_bus(entry->pagelist[page_ofs]->virtual), + entry->handle + tmp_ofs ); + } /* Set watermark control */ R128_WRITE( R128_PM4_BUFFER_WM_CNTL, @@ -346,6 +372,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) drm_r128_private_t *dev_priv; struct list_head *list; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); if ( dev_priv == NULL ) return -ENOMEM; @@ -355,11 +383,9 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) dev_priv->is_pci = init->is_pci; - /* GH: We don't support PCI cards until PCI GART is implemented. - * Fail here so we can remove all checks for PCI cards around - * the CCE ring code. - */ - if ( dev_priv->is_pci ) { + if ( dev_priv->is_pci && !dev->sg ) { + DRM_DEBUG( "PCI GART memory not allocated!\n" ); + DRM_ERROR( "PCI GART memory not allocated!\n" ); DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); dev->dev_private = NULL; return -EINVAL; @@ -368,6 +394,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) dev_priv->usec_timeout = init->usec_timeout; if ( dev_priv->usec_timeout < 1 || dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) { + DRM_DEBUG( "TIMEOUT problem!\n" ); DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); dev->dev_private = NULL; return -EINVAL; @@ -387,6 +414,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) ( init->cce_mode != R128_PM4_128BM_64INDBM ) && ( init->cce_mode != R128_PM4_64BM_128INDBM ) && ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) { + DRM_DEBUG( "Bad cce_mode!\n" ); DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); dev->dev_private = NULL; return -EINVAL; @@ -476,9 +504,24 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + init->sarea_priv_offset); - DRM_IOREMAP( dev_priv->cce_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + if ( !dev_priv->is_pci ) { + DRM_IOREMAP( dev_priv->cce_ring ); + DRM_IOREMAP( dev_priv->ring_rptr ); + DRM_IOREMAP( dev_priv->buffers ); + } else { + dev_priv->cce_ring->handle = + (void *)dev_priv->cce_ring->offset; + dev_priv->ring_rptr->handle = + (void *)dev_priv->ring_rptr->offset; + dev_priv->buffers->handle = (void *)dev_priv->buffers->offset; + } + +#if __REALLY_HAVE_AGP + if ( !dev_priv->is_pci ) + dev_priv->cce_buffers_offset = dev->agp->base; + else +#endif + dev_priv->cce_buffers_offset = dev->sg->handle; dev_priv->ring.head = ((__volatile__ u32 *) dev_priv->ring_rptr->handle); @@ -501,6 +544,20 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) R128_WRITE( R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch ); + if ( dev_priv->is_pci ) { + dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev ); + if ( !dev_priv->phys_pci_gart ) { + DRM_DEBUG( "failed to init PCI GART!\n" ); + DRM_ERROR( "failed to init PCI GART!\n" ); + DRM(free)( dev_priv, sizeof(*dev_priv), + DRM_MEM_DRIVER ); + dev->dev_private = NULL; + return -EINVAL; + } + R128_WRITE( R128_PCI_GART_PAGE, + virt_to_bus( (void *)dev_priv->phys_pci_gart ) ); + } + r128_cce_init_ring_buffer( dev ); r128_cce_load_microcode( dev_priv ); r128_do_engine_reset( dev ); @@ -513,9 +570,11 @@ int r128_do_cleanup_cce( drm_device_t *dev ) if ( dev->dev_private ) { drm_r128_private_t *dev_priv = dev->dev_private; - DRM_IOREMAPFREE( dev_priv->cce_ring ); - DRM_IOREMAPFREE( dev_priv->ring_rptr ); - DRM_IOREMAPFREE( dev_priv->buffers ); + if ( !dev_priv->is_pci ) { + DRM_IOREMAPFREE( dev_priv->cce_ring ); + DRM_IOREMAPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPFREE( dev_priv->buffers ); + } DRM(free)( dev->dev_private, sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); @@ -532,6 +591,8 @@ int r128_cce_init( struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_r128_init_t init; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) ) return -EFAULT; |