diff options
Diffstat (limited to 'sys/dev/pci/if_tht.c')
-rw-r--r-- | sys/dev/pci/if_tht.c | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/sys/dev/pci/if_tht.c b/sys/dev/pci/if_tht.c index 3780f52558a..46cffd67c7f 100644 --- a/sys/dev/pci/if_tht.c +++ b/sys/dev/pci/if_tht.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tht.c,v 1.24 2007/04/18 07:17:44 dlg Exp $ */ +/* $OpenBSD: if_tht.c,v 1.25 2007/04/18 11:19:35 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -252,7 +252,9 @@ struct cfdriver thtc_cd = { NULL, "thtc", DV_DULL }; + /* port autoconf glue */ +struct tht_dmamem; struct tht_softc { struct device sc_dev; @@ -302,6 +304,22 @@ void tht_watchdog(struct ifnet *); int tht_media_change(struct ifnet *); void tht_media_status(struct ifnet *, struct ifmediareq *); +/* wrapper around dma memory */ +struct tht_dmamem { + bus_dmamap_t tdm_map; + bus_dma_segment_t tdm_seg; + size_t tdm_size; + caddr_t tdm_kva; +}; +#define THT_DMA_MAP(_tdm) ((_tdm)->tdm_map) +#define THT_DMA_DVA(_tdm) ((_tdm)->tdm_map->dm_segs[0].ds_addr) +#define THT_DMA_KVA(_tdm) ((void *)(_tdm)->tdm_kva) + +struct tht_dmamem *tht_dmamem_alloc(struct tht_softc *, bus_size_t, + bus_size_t); +void tht_dmamem_free(struct tht_softc *, + struct tht_dmamem *); + /* bus space operations */ u_int32_t tht_read(struct tht_softc *, bus_size_t); void tht_write(struct tht_softc *, bus_size_t, u_int32_t); @@ -674,3 +692,58 @@ tht_wait_ne(struct tht_softc *sp, bus_size_t r, u_int32_t m, u_int32_t v, return (1); } + +struct tht_dmamem * +tht_dmamem_alloc(struct tht_softc *sc, bus_size_t size, bus_size_t align) +{ + bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat; + struct tht_dmamem *tdm; + int nsegs; + + tdm = malloc(sizeof(struct tht_dmamem), M_DEVBUF, M_WAITOK); + bzero(tdm, sizeof(struct tht_dmamem)); + tdm->tdm_size = size; + + if (bus_dmamap_create(dmat, size, 1, size, 0, + BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tdm->tdm_map) != 0) + goto tdmfree; + + if (bus_dmamem_alloc(dmat, size, align, 0, &tdm->tdm_seg, 1, &nsegs, + BUS_DMA_WAITOK) != 0) + goto destroy; + + if (bus_dmamem_map(dmat, &tdm->tdm_seg, nsegs, size, &tdm->tdm_kva, + BUS_DMA_WAITOK) != 0) + goto free; + + if (bus_dmamap_load(dmat, tdm->tdm_map, tdm->tdm_kva, size, + NULL, BUS_DMA_WAITOK) != 0) + goto unmap; + + bzero(tdm->tdm_kva, size); + + return (tdm); + +unmap: + bus_dmamem_unmap(dmat, tdm->tdm_kva, size); +free: + bus_dmamem_free(dmat, &tdm->tdm_seg, 1); +destroy: + bus_dmamap_destroy(dmat, tdm->tdm_map); +tdmfree: + free(tdm, M_DEVBUF); + + return (NULL); +} + +void +tht_dmamem_free(struct tht_softc *sc, struct tht_dmamem *tdm) +{ + bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat; + + bus_dmamap_unload(dmat, tdm->tdm_map); + bus_dmamem_unmap(dmat, tdm->tdm_kva, tdm->tdm_size); + bus_dmamem_free(dmat, &tdm->tdm_seg, 1); + bus_dmamap_destroy(dmat, tdm->tdm_map); + free(tdm, M_DEVBUF); +} |