1 /* $OpenBSD: sgmap_common.c,v 1.15 2019/05/13 21:27:59 mpi Exp $ */ 2 /* $NetBSD: sgmap_common.c,v 1.13 2000/06/29 09:02:57 mrg Exp $ */ 3 4 /*- 5 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #define _ALPHA_BUS_DMA_PRIVATE 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/malloc.h> 40 #include <sys/proc.h> 41 42 #include <uvm/uvm_extern.h> 43 44 #include <machine/bus.h> 45 46 #include <alpha/dev/sgmapvar.h> 47 48 /* 49 * Some systems will prefetch the next page during a memory -> device DMA. 50 * This can cause machine checks if there is not a spill page after the 51 * last page of the DMA (thus avoiding hitting an invalid SGMAP PTE). 52 */ 53 vaddr_t alpha_sgmap_prefetch_spill_page_va; 54 bus_addr_t alpha_sgmap_prefetch_spill_page_pa; 55 56 void 57 alpha_sgmap_init(t, sgmap, name, wbase, sgvabase, sgvasize, ptesize, ptva, 58 minptalign) 59 bus_dma_tag_t t; 60 struct alpha_sgmap *sgmap; 61 const char *name; 62 bus_addr_t wbase; 63 bus_addr_t sgvabase; 64 bus_size_t sgvasize; 65 size_t ptesize; 66 void *ptva; 67 bus_size_t minptalign; 68 { 69 bus_dma_segment_t seg; 70 size_t ptsize; 71 int rseg; 72 73 if (sgvasize & PGOFSET) { 74 printf("size botch for sgmap `%s'\n", name); 75 goto die; 76 } 77 78 sgmap->aps_wbase = wbase; 79 sgmap->aps_sgvabase = sgvabase; 80 sgmap->aps_sgvasize = sgvasize; 81 82 if (ptva != NULL) { 83 /* 84 * We already have a page table; this may be a system 85 * where the page table resides in bridge-resident SRAM. 86 */ 87 sgmap->aps_pt = ptva; 88 sgmap->aps_ptpa = 0; 89 } else { 90 /* 91 * Compute the page table size and allocate it. At minimum, 92 * this must be aligned to the page table size. However, 93 * some platforms have more strict alignment requirements. 94 */ 95 ptsize = (sgvasize / PAGE_SIZE) * ptesize; 96 if (minptalign != 0) { 97 if (minptalign < ptsize) 98 minptalign = ptsize; 99 } else 100 minptalign = ptsize; 101 if (bus_dmamem_alloc(t, ptsize, minptalign, 0, &seg, 1, &rseg, 102 BUS_DMA_NOWAIT)) { 103 panic("unable to allocate page table for sgmap `%s'", 104 name); 105 goto die; 106 } 107 sgmap->aps_ptpa = seg.ds_addr; 108 sgmap->aps_pt = (caddr_t)ALPHA_PHYS_TO_K0SEG(sgmap->aps_ptpa); 109 } 110 111 /* 112 * Create the extent map used to manage the virtual address 113 * space. 114 */ 115 sgmap->aps_ex = extent_create((char *)name, sgvabase, sgvasize - 1, 116 M_DEVBUF, NULL, 0, EX_NOWAIT|EX_NOCOALESCE); 117 if (sgmap->aps_ex == NULL) { 118 printf("unable to create extent map for sgmap `%s'\n", 119 name); 120 goto die; 121 } 122 mtx_init(&sgmap->aps_mtx, IPL_HIGH); 123 124 /* 125 * Allocate a spill page if that hasn't already been done. 126 */ 127 if (alpha_sgmap_prefetch_spill_page_va == 0) { 128 if (bus_dmamem_alloc(t, PAGE_SIZE, 0, 0, &seg, 1, &rseg, 129 BUS_DMA_NOWAIT)) { 130 printf("unable to allocate spill page for sgmap `%s'\n", 131 name); 132 goto die; 133 } 134 alpha_sgmap_prefetch_spill_page_pa = seg.ds_addr; 135 alpha_sgmap_prefetch_spill_page_va = 136 ALPHA_PHYS_TO_K0SEG(alpha_sgmap_prefetch_spill_page_pa); 137 bzero((caddr_t)alpha_sgmap_prefetch_spill_page_va, PAGE_SIZE); 138 } 139 140 return; 141 die: 142 panic("alpha_sgmap_init"); 143 } 144 145 int 146 alpha_sgmap_dmamap_setup(map, nsegments, flags) 147 bus_dmamap_t map; 148 int nsegments; 149 int flags; 150 { 151 map->_dm_cookie = mallocarray(nsegments, sizeof(struct extent_region), 152 M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK); 153 if (map->_dm_cookie != NULL) 154 map->_dm_cookiesize = nsegments * sizeof(struct extent_region); 155 return (map->_dm_cookie == NULL); 156 } 157 158 int 159 alpha_sgmap_dmamap_create(t, size, nsegments, maxsegsz, boundary, 160 flags, dmamp) 161 bus_dma_tag_t t; 162 bus_size_t size; 163 int nsegments; 164 bus_size_t maxsegsz; 165 bus_size_t boundary; 166 int flags; 167 bus_dmamap_t *dmamp; 168 { 169 bus_dmamap_t map; 170 int error; 171 172 error = _bus_dmamap_create(t, size, nsegments, maxsegsz, 173 boundary, flags, dmamp); 174 if (error) 175 return (error); 176 177 map = *dmamp; 178 if (alpha_sgmap_dmamap_setup(map, nsegments, flags)) { 179 _bus_dmamap_destroy(t, map); 180 return (ENOMEM); 181 } 182 183 /* XXX BUS_DMA_ALLOCNOW */ 184 185 return (0); 186 } 187 188 void 189 alpha_sgmap_dmamap_teardown(map) 190 bus_dmamap_t map; 191 { 192 free(map->_dm_cookie, M_DEVBUF, map->_dm_cookiesize); 193 } 194 195 void 196 alpha_sgmap_dmamap_destroy(t, map) 197 bus_dma_tag_t t; 198 bus_dmamap_t map; 199 { 200 KASSERT(map->dm_mapsize == 0); 201 202 alpha_sgmap_dmamap_teardown(map); 203 _bus_dmamap_destroy(t, map); 204 } 205