diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-07-06 05:35:54 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-07-06 05:35:54 +0000 |
commit | c3a60f6a2203e487a9cab88ae4892126da058e8f (patch) | |
tree | 4b002d2ac304e66b98c10514b46b7140b8241f9e /sys/arch/sparc64/dev/msi.c | |
parent | 04c2eb54a519692ed461b53c475f60e112f62e77 (diff) |
Split some generic MSI code out into its own file.
Diffstat (limited to 'sys/arch/sparc64/dev/msi.c')
-rw-r--r-- | sys/arch/sparc64/dev/msi.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/sys/arch/sparc64/dev/msi.c b/sys/arch/sparc64/dev/msi.c new file mode 100644 index 00000000000..1bd6cc9925d --- /dev/null +++ b/sys/arch/sparc64/dev/msi.c @@ -0,0 +1,86 @@ +/* $OpenBSD: msi.c,v 1.1 2011/07/06 05:35:53 kettenis Exp $ */ +/* + * Copyright (c) 2011 Mark Kettenis <kettenis@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#include <machine/bus.h> + +#include <sparc64/dev/msivar.h> + +struct msi_msg { + uint64_t mm_data[8]; +}; + +struct msi_eq * +msi_eq_alloc(bus_dma_tag_t t, int msi_eq_size) +{ + struct msi_eq *meq; + bus_size_t size; + caddr_t va; + int nsegs; + + meq = malloc(sizeof(struct msi_eq), M_DEVBUF, M_NOWAIT); + if (meq == NULL) + return NULL; + + size = roundup(msi_eq_size * sizeof(struct msi_msg), PAGE_SIZE); + + if (bus_dmamap_create(t, size, 1, size, 0, + BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &meq->meq_map) != 0) + return (NULL); + + if (bus_dmamem_alloc(t, size, PAGE_SIZE, 0, &meq->meq_seg, 1, + &nsegs, BUS_DMA_NOWAIT) != 0) + goto destroy; + + if (bus_dmamem_map(t, &meq->meq_seg, 1, size, &va, + BUS_DMA_NOWAIT) != 0) + goto free; + + if (bus_dmamap_load(t, meq->meq_map, va, size, NULL, + BUS_DMA_NOWAIT) != 0) + goto unmap; + + meq->meq_va = va; + meq->meq_nentries = msi_eq_size; + return (meq); + +unmap: + bus_dmamem_unmap(t, va, size); +free: + bus_dmamem_free(t, &meq->meq_seg, 1); +destroy: + bus_dmamap_destroy(t, meq->meq_map); + + return (NULL); +} + +void +msi_eq_free(bus_dma_tag_t t, struct msi_eq *meq) +{ + bus_size_t size; + + size = roundup(meq->meq_nentries * sizeof(struct msi_msg), PAGE_SIZE); + + bus_dmamap_unload(t, meq->meq_map); + bus_dmamem_unmap(t, meq->meq_va, size); + bus_dmamem_free(t, &meq->meq_seg, 1); + bus_dmamap_destroy(t, meq->meq_map); + free(meq, M_DEVBUF); +} |