summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2009-05-11 00:06:40 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2009-05-11 00:06:40 +0000
commitc943cdb9e19d7789ca8cf02b4c9b0921bc9cc61b (patch)
tree4a64b010791e634de8f5cb98e429c186cfaf8075 /sys/dev/pci/drm
parentdcc04216edc250771b008004668abcdb51e19363 (diff)
Rework the pcigart stuff somewhat.
firstly: move the pcigart initialisation in radeon_cp.c into its own function to avoid the horrible nesting and make it more readable. secondly: make the pcigart code more intelligent depending on whether the gart table is in pci memory, or system memory. In the former case we use the bus_space functions and thus don't need BUS_SPACE_LINEAR, while i'm here, stop using the drm wrapper functions for mapping (which require a drm_local_map structure, which will die eventually) and just use bus_space_map itself. tested on pcie (in framebuffer memory) here on my x800. tested on an i386 agp card forced to pci mode by sthen. Doesn't make IGP chips worse, doesn't make them better either (tested on a rs690). basic idea from a commit "upstream" a while ago. All the code from yours truly.
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r--sys/dev/pci/drm/ati_pcigart.c48
-rw-r--r--sys/dev/pci/drm/drmP.h15
-rw-r--r--sys/dev/pci/drm/r128_cce.c1
-rw-r--r--sys/dev/pci/drm/radeon_cp.c119
-rw-r--r--sys/dev/pci/drm/radeon_drv.c1
-rw-r--r--sys/dev/pci/drm/radeon_drv.h1
6 files changed, 104 insertions, 81 deletions
diff --git a/sys/dev/pci/drm/ati_pcigart.c b/sys/dev/pci/drm/ati_pcigart.c
index 9290ef3327b..b9a5c4c55c9 100644
--- a/sys/dev/pci/drm/ati_pcigart.c
+++ b/sys/dev/pci/drm/ati_pcigart.c
@@ -33,17 +33,17 @@
#include "drmP.h"
-#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
-#define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1))
+#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
+#define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1))
-#define ATI_PCIE_WRITE 0x4
-#define ATI_PCIE_READ 0x8
+#define ATI_PCIE_WRITE 0x4
+#define ATI_PCIE_READ 0x8
-void pcigart_add_entry(struct drm_ati_pcigart_info *, u_int32_t *,
+void pcigart_add_entry(struct drm_ati_pcigart_info *, bus_size_t,
bus_addr_t);
void
-pcigart_add_entry(struct drm_ati_pcigart_info *gart_info, u_int32_t *pci_gart,
+pcigart_add_entry(struct drm_ati_pcigart_info *gart_info, bus_size_t offset,
bus_addr_t entry_addr)
{
u_int32_t page_base = (u_int32_t)entry_addr &
@@ -63,7 +63,11 @@ pcigart_add_entry(struct drm_ati_pcigart_info *gart_info, u_int32_t *pci_gart,
case DRM_ATI_GART_PCI:
break;
}
- *pci_gart = htole32(page_base);
+ if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+ gart_info->tbl.dma.addr[offset] = htole32(page_base);
+ else
+ bus_space_write_4(gart_info->tbl.fb.bst, gart_info->tbl.fb.bsh,
+ offset * sizeof(u_int32_t), page_base);
}
int
@@ -78,11 +82,10 @@ drm_ati_pcigart_cleanup(struct drm_device *dev,
if (gart_info->bus_addr) {
gart_info->bus_addr = 0;
- gart_info->addr = 0;
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN &&
- gart_info->mem != NULL) {
- drm_dmamem_free(dev->dmat, gart_info->mem);
- gart_info->mem = NULL;
+ gart_info->tbl.dma.mem != NULL) {
+ drm_dmamem_free(dev->dmat, gart_info->tbl.dma.mem);
+ gart_info->tbl.dma.mem = NULL;
}
}
@@ -94,8 +97,8 @@ drm_ati_pcigart_init(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info)
{
- u_int32_t *pci_gart;
bus_addr_t entry_addr;
+ bus_size_t gart_idx;
u_long pages, max_ati_pages, max_real_pages;
int i, j, ret;
@@ -114,38 +117,38 @@ drm_ati_pcigart_init(struct drm_device *dev,
if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
flags |= BUS_DMA_NOCACHE;
- gart_info->mem = drm_dmamem_alloc(dev->dmat,
+ gart_info->tbl.dma.mem = drm_dmamem_alloc(dev->dmat,
gart_info->table_size, PAGE_SIZE, 1,
gart_info->table_size, flags, 0);
- if (gart_info->mem == NULL) {
+ if (gart_info->tbl.dma.mem == NULL) {
DRM_ERROR("cannot allocate PCI GART page!\n");
ret = ENOMEM;
goto error;
}
- gart_info->addr = gart_info->mem->kva;
- gart_info->bus_addr = gart_info->mem->map->dm_segs[0].ds_addr;
+ gart_info->tbl.dma.addr =
+ (u_int32_t *)gart_info->tbl.dma.mem->kva;
+ gart_info->bus_addr =
+ gart_info->tbl.dma.mem->map->dm_segs[0].ds_addr;
} else {
DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
(unsigned int)bus_address, (unsigned long)address);
+ bus_space_set_region_1(gart_info->tbl.fb.bst,
+ gart_info->tbl.fb.bsh, 0, 0, gart_info->table_size);
}
- pci_gart = (u_int32_t *)gart_info->addr;
-
max_ati_pages = (gart_info->table_size / sizeof(u_int32_t));
max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE);
pages = (dev->sg->mem->map->dm_nsegs <= max_real_pages) ?
dev->sg->mem->map->dm_nsegs : max_real_pages;
- memset(pci_gart, 0, max_ati_pages * sizeof(u_int32_t));
-
KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE);
- for (i = 0; i < pages; i++) {
+ for (gart_idx = 0, i = 0; i < pages; i++) {
entry_addr = dev->sg->mem->map->dm_segs[i].ds_addr;
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE);
j++, entry_addr += ATI_PCIGART_PAGE_SIZE)
- pcigart_add_entry(gart_info, pci_gart++, entry_addr);
+ pcigart_add_entry(gart_info, gart_idx++, entry_addr);
}
DRM_MEMORYBARRIER();
@@ -153,7 +156,6 @@ drm_ati_pcigart_init(struct drm_device *dev,
return (0);
error:
- gart_info->addr = NULL;
gart_info->bus_addr = 0;
return (ret);
}
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h
index 877a6032b69..9cc5e9017df 100644
--- a/sys/dev/pci/drm/drmP.h
+++ b/sys/dev/pci/drm/drmP.h
@@ -332,14 +332,21 @@ struct drm_mem {
#define upper_32_bits(_val) ((u_int32_t)(((_val) >> 16) >> 16))
struct drm_ati_pcigart_info {
- struct drm_local_map mapping;
- struct drm_dmamem *mem;
- void *addr;
+ union pcigart_table {
+ struct fb_gart {
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ } fb;
+ struct mem_gart {
+ struct drm_dmamem *mem;
+ u_int32_t *addr;
+ } dma;
+ } tbl;
bus_addr_t bus_addr;
bus_addr_t table_mask;
+ bus_size_t table_size;
int gart_table_location;
int gart_reg_if;
- int table_size;
};
struct drm_driver_info {
diff --git a/sys/dev/pci/drm/r128_cce.c b/sys/dev/pci/drm/r128_cce.c
index 5f923c17c22..3a52f5c374e 100644
--- a/sys/dev/pci/drm/r128_cce.c
+++ b/sys/dev/pci/drm/r128_cce.c
@@ -541,7 +541,6 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
- dev_priv->gart_info.addr = NULL;
dev_priv->gart_info.bus_addr = 0;
dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
if (drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
diff --git a/sys/dev/pci/drm/radeon_cp.c b/sys/dev/pci/drm/radeon_cp.c
index 501c9345ac1..92fdea4b372 100644
--- a/sys/dev/pci/drm/radeon_cp.c
+++ b/sys/dev/pci/drm/radeon_cp.c
@@ -69,6 +69,7 @@ void radeon_test_writeback(drm_radeon_private_t *);
void radeon_set_igpgart(drm_radeon_private_t *, int);
void radeon_set_pciegart(drm_radeon_private_t *, int);
void radeon_set_pcigart(drm_radeon_private_t *, int);
+int radeondrm_setup_pcigart(struct drm_radeon_private *);
u32
@@ -751,6 +752,62 @@ radeon_test_writeback(drm_radeon_private_t *dev_priv)
}
}
+/*
+ * Set up the addresses for a pcigart table, then fill it.
+ */
+int
+radeondrm_setup_pcigart(struct drm_radeon_private *dev_priv)
+{
+ struct drm_ati_pcigart_info *agi = &dev_priv->gart_info;
+ struct drm_device *dev;
+ bus_addr_t gartaddr;
+ int ret;
+
+ dev = (struct drm_device *)dev_priv->drmdev;
+
+ agi->table_mask = DMA_BIT_MASK(32);
+
+ /* if we have an offset set from userspace */
+ if (dev_priv->pcigart_offset_set) {
+ gartaddr = dev_priv->fb_aper_offset + dev_priv->pcigart_offset;
+
+ agi->tbl.fb.bst = dev_priv->bst;
+ /* XXX write combining */
+ if (bus_space_map(agi->tbl.fb.bst, gartaddr, agi->table_size,
+ 0, &agi->tbl.fb.bsh) != 0)
+ return (ret);
+
+ /* this is a radeon virtual address */
+ agi->bus_addr = dev_priv->fb_location +
+ dev_priv->pcigart_offset;
+ agi->gart_reg_if = dev_priv->flags & RADEON_IS_PCIE ?
+ DRM_ATI_GART_PCIE : DRM_ATI_GART_PCI;
+ agi->gart_table_location = DRM_ATI_GART_FB;
+ } else {
+ if (dev_priv->flags & RADEON_IS_PCIE) {
+ DRM_ERROR("Cannot use PCI Express without GART "
+ "in FB memory\n");
+ return (EINVAL);
+ }
+ agi->gart_reg_if = dev_priv->flags & RADEON_IS_IGPGART ?
+ DRM_ATI_GART_IGP : DRM_ATI_GART_PCI;
+ agi->gart_table_location = DRM_ATI_GART_MAIN;
+
+ /* pcigart_init will allocate dma memory for us */
+ agi->bus_addr = 0;
+ }
+
+ if (drm_ati_pcigart_init(dev, agi)) {
+ DRM_ERROR("failed to init PCI GART!\n");
+ return (ENOMEM);
+ }
+
+ /* Turn on PCI GART */
+ radeon_set_pcigart(dev_priv, 1);
+
+ return (0);
+}
+
/* Enable or disable IGP GART on the chip */
void
radeon_set_igpgart(drm_radeon_private_t *dev_priv, int on)
@@ -1173,55 +1230,10 @@ radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init)
} else
#endif
{
- dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
- /* if we have an offset set from userspace */
- if (dev_priv->pcigart_offset_set) {
- dev_priv->gart_info.bus_addr =
- dev_priv->pcigart_offset + dev_priv->fb_location;
- dev_priv->gart_info.mapping.offset =
- dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
- dev_priv->gart_info.mapping.size =
- dev_priv->gart_info.table_size;
-
- drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
- dev_priv->gart_info.addr =
- dev_priv->gart_info.mapping.handle;
-
- if (dev_priv->flags & RADEON_IS_PCIE)
- dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
- else
- dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
- dev_priv->gart_info.gart_table_location =
- DRM_ATI_GART_FB;
-
- DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
- dev_priv->gart_info.addr,
- dev_priv->pcigart_offset);
- } else {
- if (dev_priv->flags & RADEON_IS_IGPGART)
- dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
- else
- dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
- dev_priv->gart_info.gart_table_location =
- DRM_ATI_GART_MAIN;
- dev_priv->gart_info.addr = NULL;
- dev_priv->gart_info.bus_addr = 0;
- if (dev_priv->flags & RADEON_IS_PCIE) {
- DRM_ERROR
- ("Cannot use PCI Express without GART in FB memory\n");
- radeon_do_cleanup_cp(dev);
- return EINVAL;
- }
- }
-
- if (drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
- DRM_ERROR("failed to init PCI GART!\n");
+ if (radeondrm_setup_pcigart(dev_priv) != 0) {
radeon_do_cleanup_cp(dev);
- return ENOMEM;
+ return EINVAL;
}
-
- /* Turn on PCI GART */
- radeon_set_pcigart(dev_priv, 1);
}
/* Start with assuming that writeback doesn't work */
@@ -1263,12 +1275,13 @@ radeon_do_cleanup_cp(struct drm_device *dev)
DRM_ERROR("failed to cleanup PCI GART!\n");
}
- if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
- {
- drm_core_ioremapfree(&dev_priv->gart_info.mapping);
- dev_priv->gart_info.addr = 0;
- dev_priv->gart_info.gart_table_location = 0;
- }
+ if (dev_priv->gart_info.gart_table_location ==
+ DRM_ATI_GART_FB && dev_priv->gart_info.tbl.fb.bst != 0)
+ bus_space_unmap(dev_priv->gart_info.tbl.fb.bst,
+ dev_priv->gart_info.tbl.fb.bsh,
+ dev_priv->gart_info.table_size);
+ memset(&dev_priv->gart_info.tbl, 0,
+ sizeof(dev_priv->gart_info.tbl));
}
dev_priv->cp_ring = NULL;
dev_priv->ring_rptr = NULL;
diff --git a/sys/dev/pci/drm/radeon_drv.c b/sys/dev/pci/drm/radeon_drv.c
index 3623862e8fe..b302470d9cf 100644
--- a/sys/dev/pci/drm/radeon_drv.c
+++ b/sys/dev/pci/drm/radeon_drv.c
@@ -528,6 +528,7 @@ radeondrm_attach(struct device *parent, struct device *self, void *aux)
PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist);
dev_priv->flags = id_entry->driver_private;
dev_priv->pc = pa->pa_pc;
+ dev_priv->bst = pa->pa_memt;
bar = vga_pci_bar_info((struct vga_pci_softc *)parent, 0);
if (bar == NULL) {
diff --git a/sys/dev/pci/drm/radeon_drv.h b/sys/dev/pci/drm/radeon_drv.h
index 8b18cf049a7..586c1595a92 100644
--- a/sys/dev/pci/drm/radeon_drv.h
+++ b/sys/dev/pci/drm/radeon_drv.h
@@ -212,6 +212,7 @@ typedef struct drm_radeon_private {
pci_chipset_tag_t pc;
pci_intr_handle_t ih;
+ bus_space_tag_t bst;
void *irqh;
struct vga_pci_bar *regs;