1 1.18 thorpej /* $NetBSD: vsbus_dma.c,v 1.18 2023/12/20 15:34:46 thorpej Exp $ */ 2 1.1 matt 3 1.1 matt /*- 4 1.1 matt * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 1.1 matt * All rights reserved. 6 1.1 matt * 7 1.1 matt * This code is derived from software contributed to The NetBSD Foundation 8 1.1 matt * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.1 matt * NASA Ames Research Center. 10 1.1 matt * 11 1.1 matt * Redistribution and use in source and binary forms, with or without 12 1.1 matt * modification, are permitted provided that the following conditions 13 1.1 matt * are met: 14 1.1 matt * 1. Redistributions of source code must retain the above copyright 15 1.1 matt * notice, this list of conditions and the following disclaimer. 16 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 matt * notice, this list of conditions and the following disclaimer in the 18 1.1 matt * documentation and/or other materials provided with the distribution. 19 1.1 matt * 20 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 matt * POSSIBILITY OF SUCH DAMAGE. 31 1.1 matt */ 32 1.1 matt 33 1.9 lukem #include <sys/cdefs.h> 34 1.18 thorpej __KERNEL_RCSID(0, "$NetBSD: vsbus_dma.c,v 1.18 2023/12/20 15:34:46 thorpej Exp $"); 35 1.16 matt 36 1.16 matt #define _VAX_BUS_DMA_PRIVATE 37 1.1 matt 38 1.1 matt #include <sys/param.h> 39 1.1 matt #include <sys/systm.h> 40 1.16 matt #include <sys/bus.h> 41 1.16 matt #include <sys/cpu.h> 42 1.16 matt 43 1.6 mrg #include <uvm/uvm_extern.h> 44 1.1 matt 45 1.4 matt #include <machine/sid.h> 46 1.1 matt #include <machine/sgmap.h> 47 1.1 matt #include <machine/vsbus.h> 48 1.1 matt 49 1.13 matt static int sgmap_bus_dmamap_create_sgmap(bus_dma_tag_t, bus_size_t, int, 50 1.7 matt bus_size_t, bus_size_t, int, bus_dmamap_t *); 51 1.1 matt 52 1.13 matt static void sgmap_bus_dmamap_destroy_sgmap(bus_dma_tag_t, bus_dmamap_t); 53 1.1 matt 54 1.13 matt static int sgmap_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *, 55 1.7 matt bus_size_t, struct proc *, int); 56 1.1 matt 57 1.13 matt static int sgmap_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t, 58 1.7 matt struct mbuf *, int); 59 1.1 matt 60 1.13 matt static int sgmap_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t, 61 1.7 matt struct uio *, int); 62 1.1 matt 63 1.13 matt static int sgmap_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t, 64 1.7 matt bus_dma_segment_t *, int, bus_size_t, int); 65 1.1 matt 66 1.13 matt static void sgmap_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t); 67 1.1 matt 68 1.13 matt static void sgmap_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 69 1.7 matt bus_size_t, int); 70 1.1 matt 71 1.1 matt void 72 1.13 matt vax_sgmap_dmatag_init(bus_dma_tag_t t, void *cookie, size_t ptecnt) 73 1.1 matt { 74 1.1 matt /* 75 1.1 matt * Initialize the DMA tag used for sgmap-mapped DMA. 76 1.1 matt */ 77 1.13 matt t->_cookie = cookie; 78 1.1 matt t->_wbase = 0; 79 1.4 matt t->_wsize = ptecnt * VAX_NBPG; 80 1.1 matt t->_boundary = 0; 81 1.13 matt t->_dmamap_create = sgmap_bus_dmamap_create_sgmap; 82 1.13 matt t->_dmamap_destroy = sgmap_bus_dmamap_destroy_sgmap; 83 1.13 matt t->_dmamap_load = sgmap_bus_dmamap_load_sgmap; 84 1.13 matt t->_dmamap_load_mbuf = sgmap_bus_dmamap_load_mbuf_sgmap; 85 1.13 matt t->_dmamap_load_uio = sgmap_bus_dmamap_load_uio_sgmap; 86 1.13 matt t->_dmamap_load_raw = sgmap_bus_dmamap_load_raw_sgmap; 87 1.13 matt t->_dmamap_unload = sgmap_bus_dmamap_unload_sgmap; 88 1.13 matt t->_dmamap_sync = sgmap_bus_dmamap_sync; 89 1.1 matt 90 1.1 matt t->_dmamem_alloc = _bus_dmamem_alloc; 91 1.1 matt t->_dmamem_free = _bus_dmamem_free; 92 1.1 matt t->_dmamem_map = _bus_dmamem_map; 93 1.1 matt t->_dmamem_unmap = _bus_dmamem_unmap; 94 1.1 matt t->_dmamem_mmap = _bus_dmamem_mmap; 95 1.13 matt } 96 1.13 matt 97 1.13 matt void 98 1.13 matt vsbus_dma_init(struct vsbus_softc *sc, unsigned ptecnt) 99 1.13 matt { 100 1.13 matt bus_dma_tag_t t = &sc->sc_dmatag; 101 1.13 matt bus_dma_segment_t segs[1]; 102 1.13 matt struct pte *pte; 103 1.13 matt int nsegs; 104 1.13 matt int error; 105 1.13 matt size_t mapsize = ptecnt * sizeof(struct pte); 106 1.13 matt 107 1.13 matt vax_sgmap_dmatag_init(t, sc, ptecnt); 108 1.13 matt 109 1.13 matt t->_sgmap = &sc->sc_sgmap; 110 1.1 matt 111 1.4 matt if (vax_boardtype == VAX_BTYP_46 || vax_boardtype == VAX_BTYP_48) { 112 1.4 matt /* 113 1.4 matt * Allocate and map the VS4000 scatter gather map. 114 1.4 matt */ 115 1.4 matt error = bus_dmamem_alloc(t, mapsize, mapsize, mapsize, 116 1.4 matt segs, 1, &nsegs, BUS_DMA_NOWAIT); 117 1.4 matt if (error) { 118 1.4 matt panic("vsbus_dma_init: error allocating memory for " 119 1.4 matt "hw sgmap: error=%d", error); 120 1.4 matt } 121 1.4 matt 122 1.4 matt error = bus_dmamem_map(t, segs, nsegs, mapsize, 123 1.12 christos (void **)(void *) &pte, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 124 1.4 matt if (error) { 125 1.4 matt panic("vsbus_dma_init: error mapping memory for " 126 1.4 matt "hw sgmap: error=%d", error); 127 1.4 matt } 128 1.4 matt memset(pte, 0, mapsize); 129 1.17 jakllsch *(volatile int *) (sc->sc_vsregs + 8) = segs->ds_addr; /* set MAP BASE 0x2008008 */ 130 1.4 matt } else { 131 1.4 matt pte = (struct pte *) vax_map_physmem(KA49_SCSIMAP, mapsize / VAX_NBPG); 132 1.5 matt for (nsegs = ptecnt; nsegs > 0; ) { 133 1.14 matt ((uint32_t *) pte)[--nsegs] = 0; 134 1.4 matt } 135 1.4 matt segs->ds_addr = KA49_SCSIMAP; 136 1.2 matt } 137 1.14 matt aprint_normal_dev(sc->sc_dev, 138 1.14 matt "%uK entry DMA SGMAP at PA 0x%lx (VA %p)\n", 139 1.14 matt ptecnt / 1024, segs->ds_addr, pte); 140 1.1 matt 141 1.1 matt /* 142 1.1 matt * Initialize the SGMAP. 143 1.1 matt */ 144 1.1 matt vax_sgmap_init(t, &sc->sc_sgmap, "vsbus_sgmap", t->_wbase, t->_wsize, pte, 0); 145 1.1 matt 146 1.1 matt } 147 1.1 matt 148 1.1 matt /* 149 1.1 matt * Create a VSBUS SGMAP-mapped DMA map. 150 1.1 matt */ 151 1.1 matt int 152 1.14 matt sgmap_bus_dmamap_create_sgmap(bus_dma_tag_t t, bus_size_t size, int nsegments, 153 1.14 matt bus_size_t maxsegsz, bus_size_t boundary, int flags, 154 1.14 matt bus_dmamap_t *dmamp) 155 1.1 matt { 156 1.1 matt bus_dmamap_t map; 157 1.1 matt int error; 158 1.1 matt 159 1.1 matt error = _bus_dmamap_create(t, size, nsegments, maxsegsz, 160 1.1 matt boundary, flags, dmamp); 161 1.1 matt if (error) 162 1.1 matt return (error); 163 1.1 matt 164 1.1 matt map = *dmamp; 165 1.1 matt 166 1.1 matt if (flags & BUS_DMA_ALLOCNOW) { 167 1.1 matt error = vax_sgmap_alloc(map, vax_round_page(size), 168 1.1 matt t->_sgmap, flags); 169 1.1 matt if (error) 170 1.13 matt sgmap_bus_dmamap_destroy_sgmap(t, map); 171 1.1 matt } 172 1.1 matt 173 1.1 matt return (error); 174 1.1 matt } 175 1.1 matt 176 1.1 matt /* 177 1.1 matt * Destroy a VSBUS SGMAP-mapped DMA map. 178 1.1 matt */ 179 1.1 matt static void 180 1.14 matt sgmap_bus_dmamap_destroy_sgmap(bus_dma_tag_t t, bus_dmamap_t map) 181 1.1 matt { 182 1.1 matt 183 1.1 matt if (map->_dm_flags & DMAMAP_HAS_SGMAP) 184 1.1 matt vax_sgmap_free(map, t->_sgmap); 185 1.1 matt 186 1.1 matt _bus_dmamap_destroy(t, map); 187 1.1 matt } 188 1.1 matt 189 1.1 matt /* 190 1.1 matt * Load a VSBUS SGMAP-mapped DMA map with a linear buffer. 191 1.1 matt */ 192 1.1 matt static int 193 1.14 matt sgmap_bus_dmamap_load_sgmap(bus_dma_tag_t t, bus_dmamap_t map, void *buf, 194 1.14 matt bus_size_t buflen, struct proc *p, int flags) 195 1.1 matt { 196 1.1 matt return vax_sgmap_load(t, map, buf, buflen, p, flags, t->_sgmap); 197 1.1 matt } 198 1.1 matt 199 1.1 matt /* 200 1.1 matt * Load a VSBUS SGMAP-mapped DMA map with an mbuf chain. 201 1.1 matt */ 202 1.1 matt static int 203 1.14 matt sgmap_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t t, bus_dmamap_t map, 204 1.14 matt struct mbuf *m, int flags) 205 1.1 matt { 206 1.1 matt return vax_sgmap_load_mbuf(t, map, m, flags, t->_sgmap); 207 1.1 matt } 208 1.1 matt 209 1.1 matt /* 210 1.1 matt * Load a VSBUS SGMAP-mapped DMA map with a uio. 211 1.1 matt */ 212 1.1 matt static int 213 1.14 matt sgmap_bus_dmamap_load_uio_sgmap(bus_dma_tag_t t, bus_dmamap_t map, 214 1.14 matt struct uio *uio, int flags) 215 1.1 matt { 216 1.1 matt return vax_sgmap_load_uio(t, map, uio, flags, t->_sgmap); 217 1.1 matt } 218 1.1 matt 219 1.1 matt /* 220 1.1 matt * Load a VSBUS SGMAP-mapped DMA map with raw memory. 221 1.1 matt */ 222 1.1 matt static int 223 1.14 matt sgmap_bus_dmamap_load_raw_sgmap(bus_dma_tag_t t, bus_dmamap_t map, 224 1.14 matt bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) 225 1.1 matt { 226 1.1 matt return vax_sgmap_load_raw(t, map, segs, nsegs, size, flags, t->_sgmap); 227 1.1 matt } 228 1.1 matt 229 1.1 matt /* 230 1.1 matt * Unload a VSBUS DMA map. 231 1.1 matt */ 232 1.1 matt static void 233 1.14 matt sgmap_bus_dmamap_unload_sgmap(bus_dma_tag_t t, bus_dmamap_t map) 234 1.1 matt { 235 1.1 matt /* 236 1.1 matt * Invalidate any SGMAP page table entries used by this 237 1.1 matt * mapping. 238 1.1 matt */ 239 1.1 matt vax_sgmap_unload(t, map, t->_sgmap); 240 1.1 matt 241 1.1 matt /* 242 1.1 matt * Do the generic bits of the unload. 243 1.1 matt */ 244 1.1 matt _bus_dmamap_unload(t, map); 245 1.1 matt } 246 1.1 matt 247 1.1 matt /* 248 1.1 matt * Sync the bus map. 249 1.1 matt */ 250 1.1 matt static void 251 1.14 matt sgmap_bus_dmamap_sync(bus_dma_tag_t tag, bus_dmamap_t dmam, bus_addr_t offset, 252 1.14 matt bus_size_t len, int ops) 253 1.1 matt { 254 1.1 matt /* not needed */ 255 1.1 matt } 256