summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci')
-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. */