summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2008-05-06 19:24:57 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2008-05-06 19:24:57 +0000
commit1eed9bf6c704ac401ae8e0657f2ca1d96647174d (patch)
tree4da41d2b4ec815b7a1074b9bfe30b41916a6a242 /sys/dev
parent0d12c3f56a9965c9c1fbab7d8a961c9e121bc885 (diff)
Kill vtophys in drm.
The code we inherited from FreeBSD used vtophys is a fair few places, nuke that and replace with bus_dma. technically _DRM_SHM should be managed with uao_create(), but until we move away from mmap and into an ioctl to map, this will do. This also paves the way for amd64 support (it lacks vtophys). ok kettenis, miod looked at it a while back too.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/drm/drmP.h14
-rw-r--r--sys/dev/pci/drm/drm_bufs.c32
-rw-r--r--sys/dev/pci/drm/drm_scatter.c104
-rw-r--r--sys/dev/pci/drm/drm_vm.c16
4 files changed, 156 insertions, 10 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h
index f93246c0e93..2b0cc8e7f64 100644
--- a/sys/dev/pci/drm/drmP.h
+++ b/sys/dev/pci/drm/drmP.h
@@ -668,12 +668,26 @@ typedef struct drm_agp_head {
unsigned long page_mask;
} drm_agp_head_t;
+#ifdef __OpenBSD__
+struct drm_sg_dmamem {
+ bus_dma_tag_t sg_tag;
+ bus_dmamap_t sg_map;
+ bus_dma_segment_t *sg_segs;
+ int sg_nsegs;
+ size_t sg_size;
+ caddr_t sg_kva;
+};
+#endif
+
typedef struct drm_sg_mem {
unsigned long handle;
void *virtual;
int pages;
dma_addr_t *busaddr;
drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */
+#ifdef __OpenBSD__
+ struct drm_sg_dmamem *mem;
+#endif
} drm_sg_mem_t;
typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
diff --git a/sys/dev/pci/drm/drm_bufs.c b/sys/dev/pci/drm/drm_bufs.c
index 3451b7c63f1..e98da50ceb6 100644
--- a/sys/dev/pci/drm/drm_bufs.c
+++ b/sys/dev/pci/drm/drm_bufs.c
@@ -207,6 +207,7 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
map->mtrr = 1;
#endif
break;
+#ifndef __OpenBSD__
case _DRM_SHM:
map->handle = malloc(map->size, M_DRM, M_NOWAIT);
DRM_DEBUG( "%lu %d %p\n",
@@ -224,12 +225,14 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
DRM_UNLOCK();
free(map->handle, M_DRM);
free(map, M_DRM);
+ DRM_LOCK();
return EBUSY;
}
dev->lock.hw_lock = map->handle; /* Pointer to lock */
DRM_UNLOCK();
}
break;
+#endif
case _DRM_AGP:
/*valid = 0;*/
/* In some cases (i810 driver), user space may have already
@@ -276,6 +279,9 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
}
map->offset = map->offset + dev->sg->handle;
break;
+#ifdef __OpenBSD__
+ case _DRM_SHM:
+#endif
case _DRM_CONSISTENT:
/* Unfortunately, we don't get any alignment specification from
* the caller, so we have to guess. drm_pci_alloc requires
@@ -294,6 +300,22 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
}
map->handle = map->dmah->vaddr;
map->offset = map->dmah->busaddr;
+#ifdef __OpenBSD__
+ if (map->type == _DRM_SHM &&
+ map->flags & _DRM_CONTAINS_LOCK) {
+ DRM_LOCK();
+ /* Prevent a 2nd X Server from creating a 2nd lock */
+ if (dev->lock.hw_lock != NULL) {
+ DRM_UNLOCK();
+ drm_pci_free(dev, map->dmah);
+ free(map, M_DRM);
+ DRM_LOCK();
+ return EBUSY;
+ }
+ dev->lock.hw_lock = map->handle;
+ DRM_UNLOCK();
+ }
+#endif
break;
default:
DRM_ERROR("Bad map type %d\n", map->type);
@@ -343,9 +365,10 @@ drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
request->mtrr = map->mtrr;
request->handle = map->handle;
- if (request->type != _DRM_SHM) {
+#ifndef __OpenBSD__
+ if (request->type != _DRM_SHM)
+#endif
request->handle = (void *)request->offset;
- }
return 0;
}
@@ -375,12 +398,17 @@ drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
}
#endif
break;
+#ifndef __OpenBSD__
case _DRM_SHM:
free(map->handle, M_DRM);
break;
+#endif
case _DRM_AGP:
case _DRM_SCATTER_GATHER:
break;
+#ifdef __OpenBSD__
+ case _DRM_SHM:
+#endif
case _DRM_CONSISTENT:
drm_pci_free(dev, map->dmah);
break;
diff --git a/sys/dev/pci/drm/drm_scatter.c b/sys/dev/pci/drm/drm_scatter.c
index 5ce642fb5d2..3f9a691b610 100644
--- a/sys/dev/pci/drm/drm_scatter.c
+++ b/sys/dev/pci/drm/drm_scatter.c
@@ -36,13 +36,24 @@
#include "drmP.h"
#define DEBUG_SCATTER 0
+struct drm_sg_dmamem *drm_sg_dmamem_alloc(drm_device_t *, size_t);
+void drm_sg_dmamem_free(struct drm_sg_dmamem *);
void
drm_sg_cleanup(drm_sg_mem_t *entry)
{
- free((void *)entry->handle, M_DRM);
- free(entry->busaddr, M_DRM);
- free(entry, M_DRM);
+ if (entry) {
+#ifdef __OpenBSD__
+ if (entry->mem)
+ drm_sg_dmamem_free(entry->mem);
+#else
+ if (entry->handle)
+ free((void *)entry->handle, M_DRM);
+#endif
+ if (entry->busaddr)
+ free(entry->busaddr, M_DRM);
+ free(entry, M_DRM);
+ }
}
int
@@ -71,9 +82,20 @@ drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)
return ENOMEM;
}
+#ifdef __OpenBSD__
+ if ((entry->mem = drm_sg_dmamem_alloc(dev, pages)) == NULL) {
+ drm_sg_cleanup(entry);
+ return ENOMEM;
+ }
+
+ entry->handle = (unsigned long)entry->mem->sg_kva;
+
+ for (i = 0; i < pages; i++)
+ entry->busaddr[i] = entry->mem->sg_map->dm_segs[i].ds_addr;
+#else
entry->handle = (long)malloc(pages << PAGE_SHIFT, M_DRM,
M_WAITOK | M_ZERO);
- if (entry->handle == 0) {
+ if (entry->handle == NULL) {
drm_sg_cleanup(entry);
return ENOMEM;
}
@@ -81,6 +103,7 @@ drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)
for (i = 0; i < pages; i++) {
entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE);
}
+#endif
DRM_DEBUG( "sg alloc handle = %08lx\n", entry->handle );
@@ -131,3 +154,76 @@ drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv)
return 0;
}
+
+/*
+ * allocate `pages' pages of dma memory for use in
+ * scatter/gather
+ */
+struct drm_sg_dmamem*
+drm_sg_dmamem_alloc(drm_device_t *dev, size_t pages)
+{
+ struct drm_sg_dmamem *dsd = NULL;
+ bus_size_t size = pages << PAGE_SHIFT;
+ int ret = 0;
+
+ printf("size = %d\n", size);
+
+ dsd = malloc(sizeof(*dsd), M_DRM, M_NOWAIT | M_ZERO);
+ if (dsd == NULL)
+ return (NULL);
+
+ dsd->sg_segs = malloc(sizeof(*dsd->sg_segs) * pages, M_DRM,
+ M_NOWAIT | M_ZERO);
+ if (dsd->sg_segs == NULL)
+ goto dsdfree;
+
+ dsd->sg_tag = dev->pa.pa_dmat;
+ dsd->sg_size = size;
+
+ if (bus_dmamap_create(dev->pa.pa_dmat, size, pages, PAGE_SIZE, 0,
+ BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &dsd->sg_map) != 0)
+ goto segsfree;
+
+ if ((ret = bus_dmamem_alloc(dev->pa.pa_dmat, size, PAGE_SIZE, 0,
+ dsd->sg_segs, pages, &dsd->sg_nsegs, BUS_DMA_NOWAIT)) != 0) {
+ printf("alloc failed, value= %d\n",ret);
+ goto destroy;
+ }
+
+ if (bus_dmamem_map(dev->pa.pa_dmat, dsd->sg_segs, dsd->sg_nsegs, size,
+ &dsd->sg_kva, BUS_DMA_NOWAIT) != 0)
+ goto free;
+
+ if (bus_dmamap_load(dev->pa.pa_dmat, dsd->sg_map, dsd->sg_kva, size,
+ NULL, BUS_DMA_NOWAIT) != 0)
+ goto unmap;
+
+ bzero(dsd->sg_kva, size);
+
+ return (dsd);
+
+unmap:
+ bus_dmamem_unmap(dev->pa.pa_dmat, dsd->sg_kva, size);
+free:
+ bus_dmamem_free(dev->pa.pa_dmat, dsd->sg_segs, dsd->sg_nsegs);
+destroy:
+ bus_dmamap_destroy(dev->pa.pa_dmat, dsd->sg_map);
+segsfree:
+ free(dsd->sg_segs, M_DRM);
+
+dsdfree:
+ free(dsd, M_DRM);
+
+ return (NULL);
+}
+
+void
+drm_sg_dmamem_free(struct drm_sg_dmamem *mem)
+{
+ bus_dmamap_unload(mem->sg_tag, mem->sg_map);
+ bus_dmamem_unmap(mem->sg_tag, mem->sg_kva, mem->sg_size);
+ bus_dmamem_free(mem->sg_tag, mem->sg_segs, mem->sg_nsegs);
+ bus_dmamap_destroy(mem->sg_tag, mem->sg_map);
+ free(mem->sg_segs, M_DRM);
+ free(mem, M_DRM);
+}
diff --git a/sys/dev/pci/drm/drm_vm.c b/sys/dev/pci/drm/drm_vm.c
index cbc3039f3ea..550f7b9a14f 100644
--- a/sys/dev/pci/drm/drm_vm.c
+++ b/sys/dev/pci/drm/drm_vm.c
@@ -118,17 +118,25 @@ drm_mmap(dev_t kdev, off_t offset, int prot)
case _DRM_AGP:
phys = offset;
break;
- case _DRM_CONSISTENT:
#ifdef __FreeBSD__
+ case _DRM_CONSISTENT:
phys = vtophys((char *)map->handle + (offset - map->offset));
-#else
- phys = vtophys((paddr_t)map->handle + (offset - map->offset));
-#endif
break;
case _DRM_SCATTER_GATHER:
case _DRM_SHM:
phys = vtophys(offset);
break;
+#else
+ /* XXX unify all the bus_dmamem_mmap bits */
+ case _DRM_SCATTER_GATHER:
+ return bus_dmamem_mmap(dev->pa.pa_dmat, dev->sg->mem->sg_segs,
+ dev->sg->mem->sg_nsegs, offset - dev->sg->handle, prot,
+ BUS_DMA_NOWAIT);
+ case _DRM_SHM:
+ case _DRM_CONSISTENT:
+ return bus_dmamem_mmap(dev->pa.pa_dmat, &map->dmah->seg, 1,
+ offset - map->offset, prot, BUS_DMA_NOWAIT);
+#endif
default:
DRM_ERROR("bad map type %d\n", type);
return -1; /* This should never happen. */