summaryrefslogtreecommitdiff
path: root/bsd-core
diff options
context:
space:
mode:
authorRobert Noland <rnoland@2hip.net>2008-09-06 21:08:33 -0400
committerRobert Noland <rnoland@2hip.net>2008-09-06 21:08:33 -0400
commit740f09bffde20d9207497bd107d50941ca21278a (patch)
tree67fb687214bacc8a2c0fbe9e2875ae3e6a1421c9 /bsd-core
parentbe5fad45ee4e81997784f258fcdfaf0a303dd666 (diff)
[FreeBSD] IGP gart needs to be un-cached.
Airlied inadvertently discovered that the IGP gart needs to be un-cached for radeon rs485 and rs690 to work. Initial tests by placing a wbinvd() after allocating the gart were successful. This is an attempt at a more appropriate method of achieving success.
Diffstat (limited to 'bsd-core')
-rw-r--r--bsd-core/ati_pcigart.c91
1 files changed, 73 insertions, 18 deletions
diff --git a/bsd-core/ati_pcigart.c b/bsd-core/ati_pcigart.c
index c4453ed5..5feeeba8 100644
--- a/bsd-core/ati_pcigart.c
+++ b/bsd-core/ati_pcigart.c
@@ -39,31 +39,86 @@
#define ATI_PCIE_WRITE 0x4
#define ATI_PCIE_READ 0x8
-static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
- struct drm_ati_pcigart_info *gart_info)
+static void
+drm_ati_alloc_pcigart_table_cb(void *arg, bus_dma_segment_t *segs,
+ int nsegs, int error)
{
- drm_dma_handle_t *dmah;
+ struct drm_dma_handle *dmah = arg;
+
+ if (error != 0)
+ return;
+
+ KASSERT(nsegs == 1,
+ ("drm_ati_alloc_pcigart_table_cb: bad dma segment count"));
+
+ dmah->busaddr = segs[0].ds_addr;
+}
+
+static int
+drm_ati_alloc_pcigart_table(struct drm_device *dev,
+ struct drm_ati_pcigart_info *gart_info)
+{
+ struct drm_dma_handle *dmah;
+ int flags, ret;
+
+ dmah = malloc(sizeof(struct drm_dma_handle), M_DRM, M_ZERO | M_NOWAIT);
+ if (dmah == NULL)
+ return ENOMEM;
DRM_UNLOCK();
- dmah = drm_pci_alloc(dev, gart_info->table_size, PAGE_SIZE,
- gart_info->table_mask);
+ ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */
+ gart_info->table_mask, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
+ NULL, NULL, /* filtfunc, filtfuncargs */
+ gart_info->table_size, 1, /* maxsize, nsegs */
+ gart_info->table_size, /* maxsegsize */
+ BUS_DMA_ALLOCNOW, NULL, NULL, /* flags, lockfunc, lockfuncargs */
+ &dmah->tag);
+ if (ret != 0) {
+ free(dmah, M_DRM);
+ return ENOMEM;
+ }
+
+ flags = BUS_DMA_NOWAIT | BUS_DMA_ZERO;
+ if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
+ flags |= BUS_DMA_NOCACHE;
+
+ ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, flags, &dmah->map);
+ if (ret != 0) {
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, M_DRM);
+ return ENOMEM;
+ }
DRM_LOCK();
- if (dmah == NULL)
+
+ ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
+ gart_info->table_size, drm_ati_alloc_pcigart_table_cb, dmah, 0);
+ if (ret != 0) {
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, M_DRM);
return ENOMEM;
+ }
dev->sg->dmah = dmah;
return 0;
}
-static void drm_ati_free_pcigart_table(struct drm_device *dev,
- struct drm_ati_pcigart_info *gart_info)
+static void
+drm_ati_free_pcigart_table(struct drm_device *dev,
+ struct drm_ati_pcigart_info *gart_info)
{
- drm_pci_free(dev, dev->sg->dmah);
+ struct drm_dma_handle *dmah = dev->sg->dmah;
+
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, M_DRM);
dev->sg->dmah = NULL;
}
-int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
+int
+drm_ati_pcigart_cleanup(struct drm_device *dev,
+ struct drm_ati_pcigart_info *gart_info)
{
/* we need to support large memory configurations */
if (dev->sg == NULL) {
@@ -82,17 +137,17 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
return 1;
}
-int drm_ati_pcigart_init(struct drm_device *dev,
- struct drm_ati_pcigart_info *gart_info)
+int
+drm_ati_pcigart_init(struct drm_device *dev,
+ struct drm_ati_pcigart_info *gart_info)
{
-
void *address = NULL;
unsigned long pages;
u32 *pci_gart, page_base;
dma_addr_t bus_address = 0;
+ dma_addr_t entry_addr;
int i, j, ret = 0;
int max_pages;
- dma_addr_t entry_addr;
/* we need to support large memory configurations */
if (dev->sg == NULL) {
@@ -134,12 +189,14 @@ int drm_ati_pcigart_init(struct drm_device *dev,
page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;
switch(gart_info->gart_reg_if) {
case DRM_ATI_GART_IGP:
- page_base |= (upper_32_bits(entry_addr) & 0xff) << 4;
+ page_base |=
+ (upper_32_bits(entry_addr) & 0xff) << 4;
page_base |= 0xc;
break;
case DRM_ATI_GART_PCIE:
page_base >>= 8;
- page_base |= (upper_32_bits(entry_addr) & 0xff) << 24;
+ page_base |=
+ (upper_32_bits(entry_addr) & 0xff) << 24;
page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
break;
default:
@@ -152,8 +209,6 @@ int drm_ati_pcigart_init(struct drm_device *dev,
}
}
- DRM_MEMORYBARRIER();
-
ret = 1;
done: