drm: add radeon PCI express support

Add support for Radeon PCI Express cards (needs a new X.org DDX)
Also allows PCI GART table to be stored in VRAM for non PCIE cards

Signed-off-by: Dave Airlie <airlied@linux.ie>
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index 0aec5ef..957596c 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -91,9 +91,7 @@
 	free_pages( address, ATI_PCIGART_TABLE_ORDER );
 }
 
-int drm_ati_pcigart_cleanup( drm_device_t *dev,
-			      unsigned long addr,
-			      dma_addr_t bus_addr)
+int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
 {
 	drm_sg_mem_t *entry = dev->sg;
 	unsigned long pages;
@@ -105,10 +103,12 @@
 		return 0;
 	}
 
-	if ( bus_addr ) {
-		pci_unmap_single(dev->pdev, bus_addr,
-				 ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
-				 PCI_DMA_TODEVICE);
+	if (gart_info->bus_addr) {
+		if (gart_info->gart_table_location==DRM_ATI_GART_MAIN) {
+			pci_unmap_single(dev->pdev, gart_info->bus_addr,
+					 ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+					 PCI_DMA_TODEVICE);
+		}
 
 		pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
 		        ? entry->pages : ATI_MAX_PCIGART_PAGES;
@@ -118,19 +118,21 @@
 			pci_unmap_single(dev->pdev, entry->busaddr[i],
 					 PAGE_SIZE, PCI_DMA_TODEVICE);
 		}
+		
+ 		if (gart_info->gart_table_location==DRM_ATI_GART_MAIN)
+			gart_info->bus_addr=0;
 	}
 
-	if ( addr ) {
-		drm_ati_free_pcigart_table( addr );
+ 	if (gart_info->gart_table_location==DRM_ATI_GART_MAIN && gart_info->addr) {
+		drm_ati_free_pcigart_table(gart_info->addr);
+		gart_info->addr=0;
 	}
 
 	return 1;
 }
 EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
 
-int drm_ati_pcigart_init( drm_device_t *dev,
-			   unsigned long *addr,
-			   dma_addr_t *bus_addr)
+int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
 {
 	drm_sg_mem_t *entry = dev->sg;
 	unsigned long address = 0;
@@ -143,25 +145,36 @@
 		goto done;
 	}
 
-	address = drm_ati_alloc_pcigart_table();
-	if ( !address ) {
-		DRM_ERROR( "cannot allocate PCI GART page!\n" );
-		goto done;
-	}
+	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+	{
+		DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
+		
+		address = drm_ati_alloc_pcigart_table();
+		if ( !address ) {
+			DRM_ERROR( "cannot allocate PCI GART page!\n" );
+			goto done;
+		}
+		
+		if ( !dev->pdev ) {
+			DRM_ERROR( "PCI device unknown!\n" );
+			goto done;
+		}
 
-	if ( !dev->pdev ) {
-		DRM_ERROR( "PCI device unknown!\n" );
-		goto done;
+		bus_address = pci_map_single(dev->pdev, (void *)address,
+					     ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
+					     PCI_DMA_TODEVICE);
+		if (bus_address == 0) {
+			DRM_ERROR( "unable to map PCIGART pages!\n" );
+			drm_ati_free_pcigart_table( address );
+			address = 0;
+			goto done;
+		}
 	}
-
-	bus_address = pci_map_single(dev->pdev, (void *)address,
-				  ATI_PCIGART_TABLE_PAGES * PAGE_SIZE,
-				  PCI_DMA_TODEVICE);
-	if (bus_address == 0) {
-		DRM_ERROR( "unable to map PCIGART pages!\n" );
-		drm_ati_free_pcigart_table( address );
-		address = 0;
-		goto done;
+	else
+	{
+		address = gart_info->addr;
+		bus_address = gart_info->bus_addr;
+ 		DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n", bus_address, address);
 	}
 
 	pci_gart = (u32 *)address;
@@ -179,7 +192,7 @@
 					   PCI_DMA_TODEVICE);
 		if (entry->busaddr[i] == 0) {
 			DRM_ERROR( "unable to map PCIGART pages!\n" );
-			drm_ati_pcigart_cleanup( dev, address, bus_address );
+			drm_ati_pcigart_cleanup(dev, gart_info);
 			address = 0;
 			bus_address = 0;
 			goto done;
@@ -187,7 +200,10 @@
 		page_base = (u32) entry->busaddr[i];
 
 		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
-			*pci_gart++ = cpu_to_le32( page_base );
+			if (gart_info->is_pcie)
+				*pci_gart = (cpu_to_le32(page_base)>>8) | 0xc;
+			else
+				*pci_gart++ = cpu_to_le32( page_base );
 			page_base += ATI_PCIGART_PAGE_SIZE;
 		}
 	}
@@ -201,8 +217,8 @@
 #endif
 
 done:
-	*addr = address;
-	*bus_addr = bus_address;
+	gart_info->addr = address;
+ 	gart_info->bus_addr = bus_address;
 	return ret;
 }
 EXPORT_SYMBOL(drm_ati_pcigart_init);