diff options
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 11 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_drv.c | 61 |
2 files changed, 72 insertions, 0 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h index 7b50ea58ab5..c75f60b2fc0 100644 --- a/sys/dev/pci/drm/drmP.h +++ b/sys/dev/pci/drm/drmP.h @@ -304,6 +304,14 @@ typedef struct drm_dma_handle { size_t size; } drm_dma_handle_t; +struct drm_dmamem { + bus_dmamap_t map; + caddr_t kva; + bus_size_t size; + int nsegs; + bus_dma_segment_t segs[1]; +}; + typedef struct drm_buf_entry { int buf_size; int buf_count; @@ -570,6 +578,9 @@ dev_type_open(drmopen); dev_type_close(drmclose); dev_type_mmap(drmmmap); extern drm_local_map_t *drm_getsarea(struct drm_device *); +struct drm_dmamem *drm_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + int, bus_size_t, int, int); +void drm_dmamem_free(bus_dma_tag_t, struct drm_dmamem *); drm_pci_id_list_t *drm_find_description(int , int , drm_pci_id_list_t *); diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c index e948965dd93..97f9708872a 100644 --- a/sys/dev/pci/drm/drm_drv.c +++ b/sys/dev/pci/drm/drm_drv.c @@ -856,3 +856,64 @@ drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv) return 0; } + +struct drm_dmamem * +drm_dmamem_alloc(bus_dma_tag_t dmat, bus_size_t size, bus_size_t alignment, + int nsegments, bus_size_t maxsegsz, int mapflags, int loadflags) +{ + struct drm_dmamem *mem; + size_t strsize; + /* + * segs is the last member of the struct since we modify the size + * to allow extra segments if more than one are allowed. + */ + strsize = sizeof(*mem) + (sizeof(bus_dma_segment_t) * (nsegments - 1)); + mem = malloc(strsize, M_DRM, M_NOWAIT | M_ZERO); + if (mem == NULL) + return (NULL); + + mem->size = size; + + if (bus_dmamap_create(dmat, size, nsegments, maxsegsz, 0, + BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mem->map) != 0) + goto strfree; + + if (bus_dmamem_alloc(dmat, size, alignment, 0, + mem->segs, nsegments, &mem->nsegs, BUS_DMA_NOWAIT) != 0) + goto destroy; + + if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, size, + &mem->kva, BUS_DMA_NOWAIT | mapflags) != 0) + goto free; + + if (bus_dmamap_load(dmat, mem->map, mem->kva, size, + NULL, BUS_DMA_NOWAIT | loadflags) != 0) + goto unmap; + bzero(mem->kva, size); + + return (mem); + +unmap: + bus_dmamem_unmap(dmat, mem->kva, size); +free: + bus_dmamem_free(dmat, mem->segs, mem->nsegs); +destroy: + bus_dmamap_destroy(dmat, mem->map); +strfree: + free(mem, M_DRM); + + return (NULL); +} + +void +drm_dmamem_free(bus_dma_tag_t dmat, struct drm_dmamem *mem) +{ + if (mem == NULL) + return; + + bus_dmamap_unload(dmat, mem->map); + bus_dmamem_unmap(dmat, mem->kva, mem->size); + bus_dmamem_free(dmat, mem->segs, mem->nsegs); + bus_dmamap_destroy(dmat, mem->map); + free(mem, M_DRM); +} |