summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm/drm_memory.c
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2008-05-06 19:19:03 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2008-05-06 19:19:03 +0000
commit0d12c3f56a9965c9c1fbab7d8a961c9e121bc885 (patch)
tree1b8da77e839c5cdd95bbfe014dc6f76d6d8f5d4c /sys/dev/pci/drm/drm_memory.c
parent6326e66a01c7b4d7ac0ec2d749c33423122e90bd (diff)
currently agp_i810 needs to map the same BAR as inteldrm, this obviously
fails. In order to allow this, implement an API so that drm and agp can share mappings for the BARs. Now it works as it should. tested by many. ok kettenis, miod said he'd look at it when it's in tree.
Diffstat (limited to 'sys/dev/pci/drm/drm_memory.c')
-rw-r--r--sys/dev/pci/drm/drm_memory.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/sys/dev/pci/drm/drm_memory.c b/sys/dev/pci/drm/drm_memory.c
index 8d3ae1d4a5f..5900b431d17 100644
--- a/sys/dev/pci/drm/drm_memory.c
+++ b/sys/dev/pci/drm/drm_memory.c
@@ -97,13 +97,48 @@ drm_ioremap(drm_device_t *dev, drm_local_map_t *map)
#ifdef __FreeBSD__
return pmap_mapdev(map->offset, map->size);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
- int ret;
- if (!map->bst)
- map->bst = dev->pa.pa_memt;
- if ((ret = bus_space_map(map->bst, map->offset, map->size,
- BUS_SPACE_MAP_LINEAR, &map->bsh))) {
- return NULL;
+ struct vga_pci_bar *bar = NULL;
+ int i;
+
+ DRM_DEBUG("offset: 0x%x size: 0x%x type: %d\n", map->offset, map->size,
+ map->type);
+
+ if (map->type == _DRM_AGP || map->type == _DRM_FRAME_BUFFER) {
+ /*
+ * there can be multiple agp maps in the same BAR, agp also
+ * quite possibly isn't the same as the vga device, just try
+ * to map it.
+ */
+ DRM_DEBUG("AGP map\n");
+ map->bst = dev->pa.pa_memt;
+ if (bus_space_map(map->bst, map->offset,
+ map->size, BUS_SPACE_MAP_LINEAR, &map->bsh)) {
+ DRM_ERROR("ioremap fail\n");
+ return (NULL);
+ }
+ goto done;
+ } else {
+ for (i = 0 ; i < DRM_MAX_PCI_RESOURCE; ++i) {
+ bar = vga_pci_bar_info(dev->vga_softc, i);
+ if (bar == NULL)
+ continue;
+
+ if (bar->base == map->offset) {
+ DRM_DEBUG("REGISTERS map\n");
+ map->bsr = vga_pci_bar_map(dev->vga_softc,
+ bar->addr, map->size, BUS_SPACE_MAP_LINEAR);
+ if (map->bsr == NULL) {
+ DRM_ERROR("ioremap fail\n");
+ return (NULL);
+ }
+ map->bst = map->bsr->bst;
+ map->bsh = map->bsr->bsh;
+ goto done;
+ }
+ }
}
+done:
+ /* handles are still supposed to be kernel virtual addresses */
return bus_space_vaddr(map->bst, map->bsh);
#endif
}
@@ -114,7 +149,10 @@ drm_ioremapfree(drm_local_map_t *map)
#ifdef __FreeBSD__
pmap_unmapdev((vm_offset_t) map->handle, map->size);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
- bus_space_unmap(map->bst, map->bsh, map->size);
+ if (map != NULL && map->bsr != NULL)
+ vga_pci_bar_unmap(map->bsr);
+ else
+ bus_space_unmap(map->bst, map->bsh, map->size);
#endif
}