diff options
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 14 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_bufs.c | 32 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_scatter.c | 104 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_vm.c | 16 |
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. */ |