1 /* $NetBSD: mcpcia_dma.c,v 1.18 2009/03/14 15:35:59 dsl Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe and Matthew Jacob of the Numerical Aerospace Simulation 9 * Facility, NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 34 35 __KERNEL_RCSID(0, "$NetBSD: mcpcia_dma.c,v 1.18 2009/03/14 15:35:59 dsl Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/device.h> 41 #include <sys/malloc.h> 42 43 #include <uvm/uvm_extern.h> 44 45 #define _ALPHA_BUS_DMA_PRIVATE 46 #include <machine/bus.h> 47 48 #include <dev/pci/pcireg.h> 49 #include <dev/pci/pcivar.h> 50 #include <alpha/pci/mcpciareg.h> 51 #include <alpha/pci/mcpciavar.h> 52 #include <alpha/pci/pci_kn300.h> 53 54 bus_dma_tag_t mcpcia_dma_get_tag(bus_dma_tag_t, alpha_bus_t); 55 56 int mcpcia_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *, 57 bus_size_t, struct proc *, int); 58 59 int mcpcia_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t, 60 struct mbuf *, int); 61 62 int mcpcia_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t, 63 struct uio *, int); 64 65 int mcpcia_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t, 66 bus_dma_segment_t *, int, bus_size_t, int); 67 68 void mcpcia_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t); 69 70 /* 71 * Direct-mapped window: 2G at 2G 72 */ 73 #define MCPCIA_DIRECT_MAPPED_BASE (2UL*1024UL*1024UL*1024UL) 74 #define MCPCIA_DIRECT_MAPPED_SIZE (2UL*1024UL*1024UL*1024UL) 75 76 /* 77 * SGMAP window for PCI: 1G at 1G 78 */ 79 #define MCPCIA_PCI_SG_MAPPED_BASE (1UL*1024UL*1024UL*1024UL) 80 #define MCPCIA_PCI_SG_MAPPED_SIZE (1UL*1024UL*1024UL*1024UL) 81 82 /* 83 * SGMAP window for ISA: 8M at 8M 84 */ 85 #define MCPCIA_ISA_SG_MAPPED_BASE (8*1024*1024) 86 #define MCPCIA_ISA_SG_MAPPED_SIZE (8*1024*1024) 87 88 /* MCPCIA has a 256-byte out-bound DMA prefetch threshold. */ 89 #define MCPCIA_SG_MAPPED_PFTHRESH 256 90 91 #define MCPCIA_SGTLB_INVALIDATE(ccp) \ 92 do { \ 93 alpha_mb(); \ 94 REGVAL(MCPCIA_SG_TBIA(ccp)) = 0xdeadbeef; \ 95 alpha_mb(); \ 96 } while (0) 97 98 void 99 mcpcia_dma_init(struct mcpcia_config *ccp) 100 { 101 bus_dma_tag_t t; 102 103 /* 104 * Initialize the DMA tag used for direct-mapped DMA. 105 */ 106 t = &ccp->cc_dmat_direct; 107 t->_cookie = ccp; 108 t->_wbase = MCPCIA_DIRECT_MAPPED_BASE; 109 t->_wsize = MCPCIA_DIRECT_MAPPED_SIZE; 110 t->_next_window = &ccp->cc_dmat_pci_sgmap; 111 t->_boundary = 0; 112 t->_sgmap = NULL; 113 t->_get_tag = mcpcia_dma_get_tag; 114 t->_dmamap_create = _bus_dmamap_create; 115 t->_dmamap_destroy = _bus_dmamap_destroy; 116 t->_dmamap_load = _bus_dmamap_load_direct; 117 t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct; 118 t->_dmamap_load_uio = _bus_dmamap_load_uio_direct; 119 t->_dmamap_load_raw = _bus_dmamap_load_raw_direct; 120 t->_dmamap_unload = _bus_dmamap_unload; 121 t->_dmamap_sync = _bus_dmamap_sync; 122 123 t->_dmamem_alloc = _bus_dmamem_alloc; 124 t->_dmamem_free = _bus_dmamem_free; 125 t->_dmamem_map = _bus_dmamem_map; 126 t->_dmamem_unmap = _bus_dmamem_unmap; 127 t->_dmamem_mmap = _bus_dmamem_mmap; 128 129 /* 130 * Initialize the DMA tag used for sgmap-mapped PCI DMA. 131 */ 132 t = &ccp->cc_dmat_pci_sgmap; 133 t->_cookie = ccp; 134 t->_wbase = MCPCIA_PCI_SG_MAPPED_BASE; 135 t->_wsize = MCPCIA_PCI_SG_MAPPED_SIZE; 136 t->_next_window = NULL; 137 t->_boundary = 0; 138 t->_sgmap = &ccp->cc_pci_sgmap; 139 t->_pfthresh = MCPCIA_SG_MAPPED_PFTHRESH; 140 t->_get_tag = mcpcia_dma_get_tag; 141 t->_dmamap_create = alpha_sgmap_dmamap_create; 142 t->_dmamap_destroy = alpha_sgmap_dmamap_destroy; 143 t->_dmamap_load = mcpcia_bus_dmamap_load_sgmap; 144 t->_dmamap_load_mbuf = mcpcia_bus_dmamap_load_mbuf_sgmap; 145 t->_dmamap_load_uio = mcpcia_bus_dmamap_load_uio_sgmap; 146 t->_dmamap_load_raw = mcpcia_bus_dmamap_load_raw_sgmap; 147 t->_dmamap_unload = mcpcia_bus_dmamap_unload_sgmap; 148 t->_dmamap_sync = _bus_dmamap_sync; 149 150 t->_dmamem_alloc = _bus_dmamem_alloc; 151 t->_dmamem_free = _bus_dmamem_free; 152 t->_dmamem_map = _bus_dmamem_map; 153 t->_dmamem_unmap = _bus_dmamem_unmap; 154 t->_dmamem_mmap = _bus_dmamem_mmap; 155 156 /* 157 * Initialize the DMA tag used for sgmap-mapped ISA DMA. 158 */ 159 t = &ccp->cc_dmat_isa_sgmap; 160 t->_cookie = ccp; 161 t->_wbase = MCPCIA_ISA_SG_MAPPED_BASE; 162 t->_wsize = MCPCIA_ISA_SG_MAPPED_SIZE; 163 t->_next_window = NULL; 164 t->_boundary = 0; 165 t->_sgmap = &ccp->cc_isa_sgmap; 166 t->_pfthresh = MCPCIA_SG_MAPPED_PFTHRESH; 167 t->_get_tag = mcpcia_dma_get_tag; 168 t->_dmamap_create = alpha_sgmap_dmamap_create; 169 t->_dmamap_destroy = alpha_sgmap_dmamap_destroy; 170 t->_dmamap_load = mcpcia_bus_dmamap_load_sgmap; 171 t->_dmamap_load_mbuf = mcpcia_bus_dmamap_load_mbuf_sgmap; 172 t->_dmamap_load_uio = mcpcia_bus_dmamap_load_uio_sgmap; 173 t->_dmamap_load_raw = mcpcia_bus_dmamap_load_raw_sgmap; 174 t->_dmamap_unload = mcpcia_bus_dmamap_unload_sgmap; 175 t->_dmamap_sync = _bus_dmamap_sync; 176 177 t->_dmamem_alloc = _bus_dmamem_alloc; 178 t->_dmamem_free = _bus_dmamem_free; 179 t->_dmamem_map = _bus_dmamem_map; 180 t->_dmamem_unmap = _bus_dmamem_unmap; 181 t->_dmamem_mmap = _bus_dmamem_mmap; 182 183 /* 184 * Initialize the SGMAPs. 185 */ 186 alpha_sgmap_init(&ccp->cc_dmat_pci_sgmap, &ccp->cc_pci_sgmap, 187 "mcpcia pci sgmap", 188 MCPCIA_PCI_SG_MAPPED_BASE, 0, MCPCIA_PCI_SG_MAPPED_SIZE, 189 sizeof(u_int64_t), NULL, 0); 190 191 alpha_sgmap_init(&ccp->cc_dmat_isa_sgmap, &ccp->cc_isa_sgmap, 192 "mcpcia isa sgmap", 193 MCPCIA_ISA_SG_MAPPED_BASE, 0, MCPCIA_ISA_SG_MAPPED_SIZE, 194 sizeof(u_int64_t), NULL, 0); 195 196 /* 197 * Disable windows first. 198 */ 199 200 REGVAL(MCPCIA_W0_BASE(ccp)) = 0; 201 REGVAL(MCPCIA_W1_BASE(ccp)) = 0; 202 REGVAL(MCPCIA_W2_BASE(ccp)) = 0; 203 REGVAL(MCPCIA_W3_BASE(ccp)) = 0; 204 REGVAL(MCPCIA_T0_BASE(ccp)) = 0; 205 REGVAL(MCPCIA_T1_BASE(ccp)) = 0; 206 REGVAL(MCPCIA_T2_BASE(ccp)) = 0; 207 REGVAL(MCPCIA_T3_BASE(ccp)) = 0; 208 alpha_mb(); 209 210 /* 211 * Set up window 0 as an 8MB SGMAP-mapped window starting at 8MB. 212 */ 213 REGVAL(MCPCIA_W0_MASK(ccp)) = MCPCIA_WMASK_8M; 214 REGVAL(MCPCIA_T0_BASE(ccp)) = 215 ccp->cc_isa_sgmap.aps_ptpa >> MCPCIA_TBASEX_SHIFT; 216 alpha_mb(); 217 REGVAL(MCPCIA_W0_BASE(ccp)) = 218 MCPCIA_WBASE_EN | MCPCIA_WBASE_SG | MCPCIA_ISA_SG_MAPPED_BASE; 219 alpha_mb(); 220 221 MCPCIA_SGTLB_INVALIDATE(ccp); 222 223 /* 224 * Set up window 1 as a 2 GB Direct-mapped window starting at 2GB. 225 */ 226 227 REGVAL(MCPCIA_W1_MASK(ccp)) = MCPCIA_WMASK_2G; 228 REGVAL(MCPCIA_T1_BASE(ccp)) = 0; 229 alpha_mb(); 230 REGVAL(MCPCIA_W1_BASE(ccp)) = 231 MCPCIA_DIRECT_MAPPED_BASE | MCPCIA_WBASE_EN; 232 alpha_mb(); 233 234 /* 235 * Set up window 2 as a 1G SGMAP-mapped window starting at 1G. 236 */ 237 238 REGVAL(MCPCIA_W2_MASK(ccp)) = MCPCIA_WMASK_1G; 239 REGVAL(MCPCIA_T2_BASE(ccp)) = 240 ccp->cc_pci_sgmap.aps_ptpa >> MCPCIA_TBASEX_SHIFT; 241 alpha_mb(); 242 REGVAL(MCPCIA_W2_BASE(ccp)) = 243 MCPCIA_WBASE_EN | MCPCIA_WBASE_SG | MCPCIA_PCI_SG_MAPPED_BASE; 244 alpha_mb(); 245 246 /* XXX XXX BEGIN XXX XXX */ 247 { /* XXX */ 248 extern paddr_t alpha_XXX_dmamap_or; /* XXX */ 249 alpha_XXX_dmamap_or = MCPCIA_DIRECT_MAPPED_BASE;/* XXX */ 250 } /* XXX */ 251 /* XXX XXX END XXX XXX */ 252 } 253 254 /* 255 * Return the bus dma tag to be used for the specified bus type. 256 * INTERNAL USE ONLY! 257 */ 258 bus_dma_tag_t 259 mcpcia_dma_get_tag(bus_dma_tag_t t, alpha_bus_t bustype) 260 { 261 struct mcpcia_config *ccp = t->_cookie; 262 263 switch (bustype) { 264 case ALPHA_BUS_PCI: 265 case ALPHA_BUS_EISA: 266 /* 267 * Start off using the direct-mapped window. We will 268 * automatically fall backed onto the chained PCI SGMAP 269 * window if necessary. 270 */ 271 return (&ccp->cc_dmat_direct); 272 273 case ALPHA_BUS_ISA: 274 /* 275 * ISA doesn't have enough address bits to use 276 * the direct-mapped DMA window, so we must use 277 * SGMAPs. 278 */ 279 return (&ccp->cc_dmat_isa_sgmap); 280 281 default: 282 panic("mcpcia_dma_get_tag: shouldn't be here, really..."); 283 } 284 } 285 286 /* 287 * Load a MCPCIA SGMAP-mapped DMA map with a linear buffer. 288 */ 289 int 290 mcpcia_bus_dmamap_load_sgmap(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen, struct proc *p, int flags) 291 { 292 int error; 293 struct mcpcia_config *ccp = t->_cookie; 294 295 error = pci_sgmap_pte64_load(t, map, buf, buflen, p, flags, 296 t->_sgmap); 297 if (error == 0) 298 MCPCIA_SGTLB_INVALIDATE(ccp); 299 return (error); 300 } 301 302 /* 303 * Load a MCPCIA SGMAP-mapped DMA map with an mbuf chain. 304 */ 305 int 306 mcpcia_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m, int flags) 307 { 308 int error; 309 struct mcpcia_config *ccp = t->_cookie; 310 311 error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, t->_sgmap); 312 if (error == 0) 313 MCPCIA_SGTLB_INVALIDATE(ccp); 314 return (error); 315 } 316 317 /* 318 * Load a MCPCIA SGMAP-mapped DMA map with a uio. 319 */ 320 int 321 mcpcia_bus_dmamap_load_uio_sgmap(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags) 322 { 323 int error; 324 struct mcpcia_config *ccp = t->_cookie; 325 326 error = pci_sgmap_pte64_load_uio(t, map, uio, flags, t->_sgmap); 327 if (error == 0) 328 MCPCIA_SGTLB_INVALIDATE(ccp); 329 return (error); 330 } 331 332 /* 333 * Load a MCPCIA SGMAP-mapped DMA map with raw memory. 334 */ 335 int 336 mcpcia_bus_dmamap_load_raw_sgmap(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) 337 { 338 int error; 339 struct mcpcia_config *ccp = t->_cookie; 340 341 error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs, size, flags, 342 t->_sgmap); 343 if (error == 0) 344 MCPCIA_SGTLB_INVALIDATE(ccp); 345 return (error); 346 } 347 348 /* 349 * Unload a MCPCIA DMA map. 350 */ 351 void 352 mcpcia_bus_dmamap_unload_sgmap(bus_dma_tag_t t, bus_dmamap_t map) 353 { 354 struct mcpcia_config *ccp = t->_cookie; 355 356 /* 357 * Invalidate any SGMAP page table entries used by this mapping. 358 */ 359 pci_sgmap_pte64_unload(t, map, t->_sgmap); 360 MCPCIA_SGTLB_INVALIDATE(ccp); 361 362 /* 363 * Do the generic bits of the unload. 364 */ 365 _bus_dmamap_unload(t, map); 366 } 367