summaryrefslogtreecommitdiff
path: root/shared/radeon_cp.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/radeon_cp.c')
-rw-r--r--shared/radeon_cp.c165
1 files changed, 113 insertions, 52 deletions
diff --git a/shared/radeon_cp.c b/shared/radeon_cp.c
index fc859825..f12e526e 100644
--- a/shared/radeon_cp.c
+++ b/shared/radeon_cp.c
@@ -859,7 +859,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
| ( dev_priv->fb_location >> 16 ) );
#if __REALLY_HAVE_AGP
- if ( !dev_priv->is_pci ) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
RADEON_WRITE( RADEON_MC_AGP_LOCATION,
(((dev_priv->gart_vm_start - 1 +
dev_priv->gart_size) & 0xffff0000) |
@@ -868,7 +868,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
ring_start = (dev_priv->cp_ring->offset
- dev->agp->base
+ dev_priv->gart_vm_start);
- } else
+ } else
#endif
ring_start = (dev_priv->cp_ring->offset
- dev->sg->handle
@@ -886,7 +886,9 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
dev_priv->ring.tail = cur_read_ptr;
#if __REALLY_HAVE_AGP
- if ( !dev_priv->is_pci ) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
+ /* set RADEON_AGP_BASE here instead of relying on X from user space */
+ RADEON_WRITE( RADEON_AGP_BASE, (unsigned int)dev->agp->base );
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
dev_priv->ring_rptr->offset
- dev->agp->base
@@ -1003,20 +1005,11 @@ static void radeon_set_pcigart( drm_radeon_private_t *dev_priv, int on )
static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
{
- drm_radeon_private_t *dev_priv;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
- dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
- if ( dev_priv == NULL )
- return DRM_ERR(ENOMEM);
-
- memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
-
- dev_priv->is_pci = init->is_pci;
-
- if ( dev_priv->is_pci && !dev->sg ) {
+ if ( (!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg ) {
DRM_ERROR( "PCI GART memory not allocated!\n" );
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1025,7 +1018,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
if ( dev_priv->usec_timeout < 1 ||
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
DRM_DEBUG( "TIMEOUT problem!\n" );
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1041,7 +1033,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1113,7 +1104,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
if(!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1121,28 +1111,24 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
if(!dev_priv->mmio) {
DRM_ERROR("could not find mmio region!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
if(!dev_priv->cp_ring) {
DRM_ERROR("could not find cp ring region!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
if(!dev_priv->ring_rptr) {
DRM_ERROR("could not find ring read pointer!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if(!dev->agp_buffer_map) {
DRM_ERROR("could not find dma buffer region!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1151,7 +1137,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset);
if ( !dev_priv->gart_textures ) {
DRM_ERROR("could not find GART texture region!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1162,7 +1147,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
init->sarea_priv_offset);
#if __REALLY_HAVE_AGP
- if ( !dev_priv->is_pci ) {
+ if ( dev_priv->flags & CHIP_IS_AGP ) {
drm_core_ioremap( dev_priv->cp_ring, dev );
drm_core_ioremap( dev_priv->ring_rptr, dev );
drm_core_ioremap( dev->agp_buffer_map, dev );
@@ -1170,7 +1155,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
!dev_priv->ring_rptr->handle ||
!dev->agp_buffer_map->handle) {
DRM_ERROR("could not find ioremap agp regions!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1212,7 +1196,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
+ RADEON_READ( RADEON_CONFIG_APER_SIZE );
#if __REALLY_HAVE_AGP
- if ( !dev_priv->is_pci )
+ if (dev_priv->flags & CHIP_IS_AGP)
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- dev->agp->base
+ dev_priv->gart_vm_start);
@@ -1241,7 +1225,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
#if __REALLY_HAVE_AGP
- if ( !dev_priv->is_pci ) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart( dev_priv, 0 );
} else
@@ -1250,7 +1234,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
&dev_priv->bus_pci_gart)) {
DRM_ERROR( "failed to init PCI GART!\n" );
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(ENOMEM);
}
@@ -1264,8 +1247,6 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
dev_priv->last_buf = 0;
- dev->dev_private = (void *)dev_priv;
-
radeon_do_engine_reset( dev );
return 0;
@@ -1273,6 +1254,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
int radeon_do_cleanup_cp( drm_device_t *dev )
{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
#if __HAVE_IRQ
@@ -1283,29 +1265,27 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
#endif
- if ( dev->dev_private ) {
- drm_radeon_private_t *dev_priv = dev->dev_private;
-
#if __REALLY_HAVE_AGP
- if ( !dev_priv->is_pci ) {
- if ( dev_priv->cp_ring != NULL )
- drm_core_ioremapfree( dev_priv->cp_ring, dev );
- if ( dev_priv->ring_rptr != NULL )
- drm_core_ioremapfree( dev_priv->ring_rptr, dev );
- if ( dev->agp_buffer_map != NULL )
- drm_core_ioremapfree( dev->agp_buffer_map, dev );
- } else
+ if (dev_priv->flags & CHIP_IS_AGP) {
+ if ( dev_priv->cp_ring != NULL )
+ drm_core_ioremapfree( dev_priv->cp_ring, dev );
+ if ( dev_priv->ring_rptr != NULL )
+ drm_core_ioremapfree( dev_priv->ring_rptr, dev );
+ if ( dev->agp_buffer_map != NULL )
+ drm_core_ioremapfree( dev->agp_buffer_map, dev );
+ } else
#endif
- {
- if (!DRM(ati_pcigart_cleanup)( dev,
- dev_priv->phys_pci_gart,
- dev_priv->bus_pci_gart ))
- DRM_ERROR( "failed to cleanup PCI GART!\n" );
- }
-
- DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
- DRM_MEM_DRIVER );
- dev->dev_private = NULL;
+ {
+ if (!DRM(ati_pcigart_cleanup)( dev,
+ dev_priv->phys_pci_gart,
+ dev_priv->bus_pci_gart ))
+ DRM_ERROR( "failed to cleanup PCI GART!\n" );
+ }
+
+ {
+ int flags = dev_priv->flags;
+ memset(dev_priv, 0, sizeof(*dev_priv));
+ dev_priv->flags = flags;
}
return 0;
@@ -1330,7 +1310,7 @@ static int radeon_do_resume_cp( drm_device_t *dev )
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
#if __REALLY_HAVE_AGP
- if ( !dev_priv->is_pci ) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart( dev_priv, 0 );
} else
@@ -1444,8 +1424,10 @@ void radeon_do_release( drm_device_t *dev )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int ret;
+ DRM_DEBUG("dev_priv %ptr\n", dev_priv);
if (dev_priv) {
+
if (dev_priv->cp_running) {
/* Stop the cp */
while ((ret = radeon_do_cp_idle( dev_priv )) != 0) {
@@ -1461,7 +1443,8 @@ void radeon_do_release( drm_device_t *dev )
}
/* Disable *all* interrupts */
- RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
+ if (dev_priv->mmio) /* remove this after permanent addmaps */
+ RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
/* Free memory heap structures */
radeon_mem_takedown( &(dev_priv->gart_heap) );
@@ -1745,3 +1728,81 @@ int radeon_cp_buffers( DRM_IOCTL_ARGS )
return ret;
}
+
+static int radeon_register_regions(struct pci_dev *pdev) {
+ int retcode = -EINVAL;
+
+ /* request the mem regions */
+ if (!request_mem_region (pci_resource_start( pdev, 2 ),
+ pci_resource_len(pdev, 2), DRIVER_NAME)) {
+ printk(KERN_ERR DRIVER_NAME ": cannot reserve MMIO region\n");
+ return retcode;
+ }
+ if (!request_mem_region (pci_resource_start( pdev, 0 ),
+ pci_resource_len(pdev, 0), DRIVER_NAME)) {
+ printk(KERN_ERR DRIVER_NAME ": cannot reserve FB region\n");
+ return retcode;
+ }
+ return 0;
+}
+
+static void radeon_release_regions(struct pci_dev *pdev) {
+ release_mem_region (pci_resource_start( pdev, 2 ), pci_resource_len(pdev, 2));
+ release_mem_region (pci_resource_start( pdev, 0 ), pci_resource_len(pdev, 0));
+}
+
+/* Always create a map record for MMIO and FB memory, done from DRIVER_POSTINIT */
+int radeon_preinit( struct drm_device *dev, unsigned long flags )
+{
+ int retcode = -EINVAL;
+ u32 save, temp;
+ drm_radeon_private_t *dev_priv;
+
+ dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
+ if ( dev_priv == NULL )
+ return DRM_ERR(ENOMEM);
+ DRM_DEBUG("dev_priv %ptr\n", dev_priv);
+
+ memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
+ dev->dev_private = (void *)dev_priv;
+ dev_priv->flags = flags;
+
+ /* request the mem regions */
+ if (!DRM(fb_loaded))
+ if ((retcode = radeon_register_regions(dev->pdev)) != 0)
+ return retcode;
+
+ /* There are signatures in BIOS and PCI-SSID for a PCI card, but they are not very reliable.
+ Following detection method works for all cards tested so far.
+ Note, checking AGP_ENABLE bit after drmAgpEnable call can also give the correct result.
+ However, calling drmAgpEnable on a PCI card can cause some strange lockup when the server
+ restarts next time.
+ */
+ pci_read_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, &save);
+ pci_write_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, save | RADEON_AGP_ENABLE);
+ pci_read_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, &temp);
+ if (temp & RADEON_AGP_ENABLE)
+ dev_priv->flags |= CHIP_IS_AGP;
+ DRM_DEBUG("%s card detected\n", ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));
+ pci_write_config_dword(dev->pdev, RADEON_AGP_COMMAND_PCI_CONFIG, save);
+
+ return 0;
+}
+
+int radeon_postinit( struct drm_device *dev, unsigned long flags )
+{
+ return 0;
+}
+
+int radeon_postcleanup( struct drm_device *dev )
+{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+
+ DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+
+ if (!DRM(fb_loaded))
+ radeon_release_regions(dev->pdev);
+
+ dev->dev_private = NULL;
+ return 0;
+}