diff options
| -rw-r--r-- | linux-core/ati_pcigart.c | 84 | ||||
| -rw-r--r-- | linux-core/drmP.h | 17 | ||||
| -rw-r--r-- | shared-core/r128_cce.c | 15 | ||||
| -rw-r--r-- | shared-core/r128_drv.h | 3 | ||||
| -rw-r--r-- | shared-core/radeon_cp.c | 45 | ||||
| -rw-r--r-- | shared-core/radeon_drm.h | 1 | ||||
| -rw-r--r-- | shared-core/radeon_drv.h | 14 | ||||
| -rw-r--r-- | shared-core/radeon_state.c | 3 | 
8 files changed, 117 insertions, 65 deletions
| diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index c9ace516..1dde5ab3 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -91,9 +91,7 @@ static void drm_ati_free_pcigart_table(unsigned long address)  	free_pages(address, ATI_PCIGART_TABLE_ORDER);  } -int drm_ati_pcigart_init(drm_device_t * dev, -			 unsigned long *addr, dma_addr_t * bus_addr, -			int is_pcie) +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; @@ -106,25 +104,36 @@ int drm_ati_pcigart_init(drm_device_t * dev,  		goto done;  	} -	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 (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; +		} +		 +		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; @@ -142,7 +151,7 @@ int drm_ati_pcigart_init(drm_device_t * dev,  						   PAGE_SIZE, 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; @@ -150,11 +159,8 @@ int drm_ati_pcigart_init(drm_device_t * dev,  		page_base = (u32) entry->busaddr[i];  		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { -			if (is_pcie) -			{ +			if (gart_info->is_pcie)  				*pci_gart = (cpu_to_le32(page_base)>>8) | 0xc; -//				DRM_DEBUG("PCIE: %d %08X %08X to %p\n", i, page_base, (cpu_to_le32(page_base)>>8)|0xc, pci_gart); -			}  			else  				*pci_gart = cpu_to_le32(page_base);  			pci_gart++; @@ -171,14 +177,13 @@ int drm_ati_pcigart_init(drm_device_t * dev,  #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); -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; @@ -190,10 +195,12 @@ int drm_ati_pcigart_cleanup(drm_device_t * dev,  		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; @@ -204,10 +211,15 @@ int drm_ati_pcigart_cleanup(drm_device_t * dev,  			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; diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 8b1728bb..81c542dc 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -523,6 +523,17 @@ typedef struct drm_vbl_sig {  	struct task_struct *task;  } drm_vbl_sig_t; +/* location of GART table */ +#define DRM_ATI_GART_MAIN 1 +#define DRM_ATI_GART_FB   2 + +typedef struct ati_pcigart_info { +	int gart_table_location; +	int is_pcie; +	unsigned long addr; +	dma_addr_t bus_addr; +} drm_ati_pcigart_info; +  /**   * DRM driver structure. This structure represent the common code for   * a family of cards. There will one drm_device for each card present @@ -978,10 +989,8 @@ extern int drm_sg_free(struct inode *inode, struct file *filp,  		       unsigned int cmd, unsigned long arg);  			       /* ATI PCIGART support (ati_pcigart.h) */ -extern int drm_ati_pcigart_init(drm_device_t * dev, -				unsigned long *addr, dma_addr_t * bus_addr, int is_pcie); -extern int drm_ati_pcigart_cleanup(drm_device_t * dev, -				   unsigned long addr, dma_addr_t bus_addr); +extern int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info *gart_info); +extern int drm_ati_pcigart_cleanup(drm_device_t * dev, drm_ati_pcigart_info *gart_info);  extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,  			   size_t align, dma_addr_t maxaddr); diff --git a/shared-core/r128_cce.c b/shared-core/r128_cce.c index 33553670..cb84fa84 100644 --- a/shared-core/r128_cce.c +++ b/shared-core/r128_cce.c @@ -558,14 +558,16 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)  #if __OS_HAS_AGP  	if (dev_priv->is_pci) {  #endif -		if (!drm_ati_pcigart_init(dev, &dev_priv->phys_pci_gart, -					  &dev_priv->bus_pci_gart, 0)) { +		dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; +		dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0; +		dev_priv->gart_info.is_pcie = 0; +		if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {  			DRM_ERROR("failed to init PCI GART!\n");  			dev->dev_private = (void *)dev_priv;  			r128_do_cleanup_cce(dev);  			return DRM_ERR(ENOMEM);  		} -		R128_WRITE(R128_PCI_GART_PAGE, dev_priv->bus_pci_gart); +		R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);  #if __OS_HAS_AGP  	}  #endif @@ -606,10 +608,9 @@ int r128_do_cleanup_cce(drm_device_t * 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"); +			if (dev_priv->gart_info.bus_addr) +				if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) +					DRM_ERROR("failed to cleanup PCI GART!\n");  		}  		drm_free(dev->dev_private, sizeof(drm_r128_private_t), diff --git a/shared-core/r128_drv.h b/shared-core/r128_drv.h index c6bdf563..34724fde 100644 --- a/shared-core/r128_drv.h +++ b/shared-core/r128_drv.h @@ -87,8 +87,6 @@ typedef struct drm_r128_private {  	int usec_timeout;  	int is_pci; -	unsigned long phys_pci_gart; -	dma_addr_t bus_pci_gart;  	unsigned long cce_buffers_offset;  	atomic_t idle_count; @@ -119,6 +117,7 @@ typedef struct drm_r128_private {  	drm_local_map_t *cce_ring;  	drm_local_map_t *ring_rptr;  	drm_local_map_t *agp_textures; +	drm_ati_pcigart_info gart_info;  } drm_r128_private_t;  typedef struct drm_r128_buf_priv { diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 09a473d7..b7e0ec0c 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1246,17 +1246,17 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)  	if (on) {  		DRM_DEBUG("programming pcie %08X %08lX %08X\n", -			  dev_priv->gart_vm_start, (long)dev_priv->bus_pci_gart, +			  dev_priv->gart_vm_start, (long)dev_priv->gart_info.bus_addr,  			  dev_priv->gart_size);  		RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, dev_priv->gart_vm_start); -		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, dev_priv->bus_pci_gart); +		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, dev_priv->gart_info.bus_addr);  		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO, dev_priv->gart_vm_start);  		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO, dev_priv->gart_vm_start  			     + dev_priv->gart_size - 1);  		RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);	/* ?? */ -		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, RADEON_PCIE_TX_GART_EN | RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD | RADEON_PCIE_TX_GART_CHK_RW_VALID_EN); +		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, RADEON_PCIE_TX_GART_EN);  	} else {  		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);  	} @@ -1279,7 +1279,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)  		/* set PCI GART page-table base address  		 */ -		RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart); +		RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);  		/* set address range for PCI address translate  		 */ @@ -1526,8 +1526,28 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)  	} else  #endif  	{ -		if (!drm_ati_pcigart_init(dev, &dev_priv->phys_pci_gart, -					  &dev_priv->bus_pci_gart, (dev_priv->flags & CHIP_IS_PCIE))) { +		/* if we have an offset set from userspace */ +		if (dev_priv->pcigart_offset) { +			dev_priv->gart_info.bus_addr = dev_priv->pcigart_offset + dev_priv->fb_location; +			dev_priv->gart_info.addr = (unsigned long)drm_ioremap(dev_priv->gart_info.bus_addr, RADEON_PCIGART_TABLE_SIZE, dev); + +			dev_priv->gart_info.is_pcie = !!(dev_priv->flags & CHIP_IS_PCIE); +			dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB; +			 +			DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n", dev_priv->gart_info.addr, dev_priv->pcigart_offset); +		} +		else { +			dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; +			dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr= 0; +			if (dev_priv->flags & CHIP_IS_PCIE) +			{ +				DRM_ERROR("Cannot use PCI Express without GART in FB memory\n"); +				radeon_do_cleanup_cp(dev); +				return DRM_ERR(EINVAL); +			} +		} + +		if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {  			DRM_ERROR("failed to init PCI GART!\n");  			radeon_do_cleanup_cp(dev);  			return DRM_ERR(ENOMEM); @@ -1576,10 +1596,15 @@ static int radeon_do_cleanup_cp(drm_device_t * 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"); +		if (dev_priv->gart_info.bus_addr) +			if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) +				DRM_ERROR("failed to cleanup PCI GART!\n"); + +		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) +		{ +			drm_ioremapfree((void *)dev_priv->gart_info.addr, RADEON_PCIGART_TABLE_SIZE, dev); +			dev_priv->gart_info.addr = 0; +		}  	}  	/* only clear to the start of flags */  	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 64b96939..60656741 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -690,6 +690,7 @@ typedef struct drm_radeon_setparam {  #define RADEON_SETPARAM_FB_LOCATION    1	/* determined framebuffer location */  #define RADEON_SETPARAM_SWITCH_TILING  2	/* enable/disable color tiling */ +#define RADEON_SETPARAM_PCIGART_LOCATION 3      /* PCI Gart Location */  /* 1.14: Clients can allocate/free a surface   */ diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 58e4c17a..265697c7 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -38,7 +38,7 @@  #define DRIVER_NAME		"radeon"  #define DRIVER_DESC		"ATI Radeon" -#define DRIVER_DATE		"20050905" +#define DRIVER_DATE		"20050911"  /* Interface history:   * @@ -86,10 +86,11 @@   * 1.18- Add support for GL_ATI_fragment_shader, new packets R200_EMIT_PP_AFS_0/1,           R200_EMIT_PP_TXCTLALL_0-5 (replaces R200_EMIT_PP_TXFILTER_0-5, 2 more regs)           and R200_EMIT_ATF_TFACTOR (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6) + * 1.19- Add support for gart table in FB memory and PCIE r300   */  #define DRIVER_MAJOR		1 -#define DRIVER_MINOR		18 +#define DRIVER_MINOR		19  #define DRIVER_PATCHLEVEL	0  enum radeon_family { @@ -211,9 +212,6 @@ typedef struct drm_radeon_private {  	int microcode_version; -	unsigned long phys_pci_gart; -	dma_addr_t bus_pci_gart; -  	struct {  		u32 boxes;  		int freelist_timeouts; @@ -265,7 +263,9 @@ typedef struct drm_radeon_private {  	struct radeon_surface surfaces[RADEON_MAX_SURFACES];  	struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES]; -	 + +	unsigned long pcigart_offset; +	drm_ati_pcigart_info gart_info;  	/* starting from here on, data is preserved accross an open */  	uint32_t flags;		/* see radeon_chip_flags */ @@ -920,6 +920,8 @@ extern int r300_do_cp_cmdbuf( drm_device_t* dev,  #define RADEON_RING_HIGH_MARK		128 +#define RADEON_PCIGART_TABLE_SIZE      (32*1024) +  #define RADEON_READ(reg)	DRM_READ32(  dev_priv->mmio, (reg) )  #define RADEON_WRITE(reg,val)	DRM_WRITE32( dev_priv->mmio, (reg), (val) )  #define RADEON_READ8(reg)	DRM_READ8(  dev_priv->mmio, (reg) ) diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 8b3317b2..91fc9f2d 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3007,6 +3007,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)  			dev_priv->sarea_priv->tiling_enabled = 1;  		}  		break; +	case RADEON_SETPARAM_PCIGART_LOCATION: +		dev_priv->pcigart_offset = sp.value; +		break;  	default:  		DRM_DEBUG("Invalid parameter %d\n", sp.param);  		return DRM_ERR(EINVAL); | 
