1 /* $NetBSD: ttwoga_dma.c,v 1.3 2001/07/19 18:50:25 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 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. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 40 41 __KERNEL_RCSID(0, "$NetBSD: ttwoga_dma.c,v 1.3 2001/07/19 18:50:25 thorpej Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/device.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #define _ALPHA_BUS_DMA_PRIVATE 51 #include <machine/bus.h> 52 53 #include <dev/pci/pcireg.h> 54 #include <dev/pci/pcivar.h> 55 56 #include <alpha/pci/ttwogareg.h> 57 #include <alpha/pci/ttwogavar.h> 58 59 bus_dma_tag_t ttwoga_dma_get_tag(bus_dma_tag_t, alpha_bus_t); 60 61 int ttwoga_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *, 62 bus_size_t, struct proc *, int); 63 64 int ttwoga_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t, 65 struct mbuf *, int); 66 67 int ttwoga_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t, 68 struct uio *, int); 69 70 int ttwoga_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t, 71 bus_dma_segment_t *, int, bus_size_t, int); 72 73 void ttwoga_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t); 74 75 /* 76 * Direct-mapped window: 1G at 1G 77 */ 78 #define TTWOGA_DIRECT_MAPPED_BASE (1UL*1024UL*1024UL*1024UL) 79 #define TTWOGA_DIRECT_MAPPED_SIZE (1UL*1024UL*1024UL*1024UL) 80 81 /* 82 * SGMAP window: 8M at 8M 83 */ 84 #define TTWOGA_SGMAP_MAPPED_BASE (8UL*1024UL*1024UL) 85 #define TTWOGA_SGMAP_MAPPED_SIZE (8UL*1024UL*1024UL) 86 87 /* T2 has a 256-byte out-bound DMA prefetch threshold. */ 88 #define TTWOGA_SGMAP_PFTHRESH 256 89 90 /* 91 * Macro to flush the T2 Gate Array scatter/gather TLB. 92 */ 93 #define TTWOGA_TLB_INVALIDATE(tcp) \ 94 do { \ 95 u_int64_t temp; \ 96 \ 97 alpha_mb(); \ 98 temp = T2GA((tcp), T2_IOCSR); \ 99 T2GA((tcp), T2_IOCSR) = temp | IOCSR_FTLB; \ 100 alpha_mb(); \ 101 alpha_mb(); /* MAGIC */ \ 102 T2GA((tcp), T2_IOCSR) = temp; \ 103 alpha_mb(); \ 104 alpha_mb(); /* MAGIC */ \ 105 } while (0) 106 107 void 108 ttwoga_dma_init(struct ttwoga_config *tcp) 109 { 110 bus_dma_tag_t t; 111 112 /* 113 * Initialize the DMA tag used for direct-mapped DMA. 114 */ 115 t = &tcp->tc_dmat_direct; 116 t->_cookie = tcp; 117 t->_wbase = TTWOGA_DIRECT_MAPPED_BASE; 118 t->_wsize = TTWOGA_DIRECT_MAPPED_SIZE; 119 t->_next_window = NULL; 120 t->_boundary = 0; 121 t->_sgmap = NULL; 122 t->_get_tag = ttwoga_dma_get_tag; 123 t->_dmamap_create = _bus_dmamap_create; 124 t->_dmamap_destroy = _bus_dmamap_destroy; 125 t->_dmamap_load = _bus_dmamap_load_direct; 126 t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct; 127 t->_dmamap_load_uio = _bus_dmamap_load_uio_direct; 128 t->_dmamap_load_raw = _bus_dmamap_load_raw_direct; 129 t->_dmamap_unload = _bus_dmamap_unload; 130 t->_dmamap_sync = _bus_dmamap_sync; 131 132 t->_dmamem_alloc = _bus_dmamem_alloc; 133 t->_dmamem_free = _bus_dmamem_free; 134 t->_dmamem_map = _bus_dmamem_map; 135 t->_dmamem_unmap = _bus_dmamem_unmap; 136 t->_dmamem_mmap = _bus_dmamem_mmap; 137 138 /* 139 * Initialize the DMA tag used for sgmap-mapped DMA. 140 */ 141 t = &tcp->tc_dmat_sgmap; 142 t->_cookie = tcp; 143 t->_wbase = TTWOGA_SGMAP_MAPPED_BASE; 144 t->_wsize = TTWOGA_SGMAP_MAPPED_SIZE; 145 t->_next_window = NULL; 146 t->_boundary = 0; 147 t->_sgmap = &tcp->tc_sgmap; 148 t->_pfthresh = TTWOGA_SGMAP_PFTHRESH; 149 t->_get_tag = ttwoga_dma_get_tag; 150 t->_dmamap_create = alpha_sgmap_dmamap_create; 151 t->_dmamap_destroy = alpha_sgmap_dmamap_destroy; 152 t->_dmamap_load = ttwoga_bus_dmamap_load_sgmap; 153 t->_dmamap_load_mbuf = ttwoga_bus_dmamap_load_mbuf_sgmap; 154 t->_dmamap_load_uio = ttwoga_bus_dmamap_load_uio_sgmap; 155 t->_dmamap_load_raw = ttwoga_bus_dmamap_load_raw_sgmap; 156 t->_dmamap_unload = ttwoga_bus_dmamap_unload_sgmap; 157 t->_dmamap_sync = _bus_dmamap_sync; 158 159 t->_dmamem_alloc = _bus_dmamem_alloc; 160 t->_dmamem_free = _bus_dmamem_free; 161 t->_dmamem_map = _bus_dmamem_map; 162 t->_dmamem_unmap = _bus_dmamem_unmap; 163 t->_dmamem_mmap = _bus_dmamem_mmap; 164 165 /* 166 * Disable the SGMAP TLB, and flush it. We reenable it if 167 * we have a Sable or a Gamma with T3 or T4; Gamma with T2 168 * has a TLB bug apparently severe enough to require disabling 169 * it. 170 */ 171 alpha_mb(); 172 T2GA(tcp, T2_IOCSR) &= ~IOCSR_ETLB; 173 alpha_mb(); 174 alpha_mb(); /* MAGIC */ 175 176 TTWOGA_TLB_INVALIDATE(tcp); 177 178 /* 179 * XXX We might want to make sure our DMA windows don't 180 * XXX overlap with PCI memory space! 181 */ 182 183 /* 184 * Set up window 1 as a 1G direct-mapped window 185 * starting at 1G. 186 */ 187 T2GA(tcp, T2_WBASE1) = 0; 188 alpha_mb(); 189 190 T2GA(tcp, T2_WMASK1) = (TTWOGA_DIRECT_MAPPED_SIZE - 1) & WMASKx_PWM; 191 alpha_mb(); 192 193 T2GA(tcp, T2_TBASE1) = 0; 194 alpha_mb(); 195 196 T2GA(tcp, T2_WBASE1) = TTWOGA_DIRECT_MAPPED_BASE | 197 ((TTWOGA_DIRECT_MAPPED_BASE + (TTWOGA_DIRECT_MAPPED_SIZE - 1)) >> 198 WBASEx_PWxA_SHIFT) | WBASEx_PWE; 199 alpha_mb(); 200 201 /* 202 * Initialize the SGMAP. 203 */ 204 alpha_sgmap_init(t, &tcp->tc_sgmap, "ttwoga_sgmap", 205 TTWOGA_SGMAP_MAPPED_BASE, 0, TTWOGA_SGMAP_MAPPED_SIZE, 206 sizeof(u_int64_t), NULL, 0); 207 208 /* 209 * Set up window 2 as an 8MB SGMAP-mapped window 210 * starting at 8MB. 211 */ 212 #ifdef DIAGNOSTIC 213 if ((TTWOGA_SGMAP_MAPPED_BASE & WBASEx_PWSA) != 214 TTWOGA_SGMAP_MAPPED_BASE) 215 panic("ttwoga_dma_init: SGMAP base inconsistency"); 216 #endif 217 T2GA(tcp, T2_WBASE2) = 0; 218 alpha_mb(); 219 220 T2GA(tcp, T2_WMASK2) = (TTWOGA_SGMAP_MAPPED_SIZE - 1) & WMASKx_PWM; 221 alpha_mb(); 222 223 T2GA(tcp, T2_TBASE2) = tcp->tc_sgmap.aps_ptpa >> 1; 224 alpha_mb(); 225 226 T2GA(tcp, T2_WBASE2) = TTWOGA_SGMAP_MAPPED_BASE | 227 ((TTWOGA_SGMAP_MAPPED_BASE + (TTWOGA_SGMAP_MAPPED_SIZE - 1)) >> 228 WBASEx_PWxA_SHIFT) | WBASEx_SGE | WBASEx_PWE; 229 alpha_mb(); 230 231 /* 232 * Enable SGMAP TLB on Sable or Gamma with T3 or T4; see above. 233 */ 234 if (alpha_implver() == ALPHA_IMPLVER_EV4 || 235 tcp->tc_rev >= TRN_T3) { 236 alpha_mb(); 237 T2GA(tcp, T2_IOCSR) |= IOCSR_ETLB; 238 alpha_mb(); 239 alpha_mb(); /* MAGIC */ 240 tcp->tc_use_tlb = 1; 241 } 242 243 /* XXX XXX BEGIN XXX XXX */ 244 { /* XXX */ 245 extern paddr_t alpha_XXX_dmamap_or; /* XXX */ 246 alpha_XXX_dmamap_or = TTWOGA_DIRECT_MAPPED_BASE;/* XXX */ 247 } /* XXX */ 248 /* XXX XXX END XXX XXX */ 249 } 250 251 /* 252 * Return the bus dma tag to be used for the specified bus type. 253 * INTERNAL USE ONLY! 254 */ 255 bus_dma_tag_t 256 ttwoga_dma_get_tag(bus_dma_tag_t t, alpha_bus_t bustype) 257 { 258 struct ttwoga_config *tcp = t->_cookie; 259 260 switch (bustype) { 261 case ALPHA_BUS_PCI: 262 case ALPHA_BUS_EISA: 263 /* 264 * Systems with a T2 Gate Array can have 2G 265 * of memory, but we only get a direct-mapped 266 * window of 1G! 267 * 268 * XXX FIX THIS SOMEDAY! 269 */ 270 return (&tcp->tc_dmat_direct); 271 272 case ALPHA_BUS_ISA: 273 /* 274 * ISA doesn't have enough address bits to use 275 * the direct-mapped DMA window, so we must use 276 * SGMAPs. 277 */ 278 return (&tcp->tc_dmat_sgmap); 279 280 default: 281 panic("ttwoga_dma_get_tag: shouldn't be here, really..."); 282 } 283 } 284 285 /* 286 * Load a T2 SGMAP-mapped DMA map with a liner buffer. 287 */ 288 int 289 ttwoga_bus_dmamap_load_sgmap(bus_dma_tag_t t, bus_dmamap_t map, void *buf, 290 bus_size_t buflen, struct proc *p, int flags) 291 { 292 struct ttwoga_config *tcp = t->_cookie; 293 int error; 294 295 error = pci_sgmap_pte64_load(t, map, buf, buflen, p, flags, 296 t->_sgmap); 297 if (error == 0 && tcp->tc_use_tlb) 298 TTWOGA_TLB_INVALIDATE(tcp); 299 300 return (error); 301 } 302 303 /* 304 * Load a T2 SGMAP-mapped DMA map with an mbuf chain. 305 */ 306 int 307 ttwoga_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t t, bus_dmamap_t map, 308 struct mbuf *m, int flags) 309 { 310 struct ttwoga_config *tcp = t->_cookie; 311 int error; 312 313 error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, t->_sgmap); 314 if (error == 0 && tcp->tc_use_tlb) 315 TTWOGA_TLB_INVALIDATE(tcp); 316 317 return (error); 318 } 319 320 /* 321 * Load a T2 SGMAP-mapped DMA map with a uio. 322 */ 323 int 324 ttwoga_bus_dmamap_load_uio_sgmap(bus_dma_tag_t t, bus_dmamap_t map, 325 struct uio *uio, int flags) 326 { 327 struct ttwoga_config *tcp = t->_cookie; 328 int error; 329 330 error = pci_sgmap_pte64_load_uio(t, map, uio, flags, t->_sgmap); 331 if (error == 0 && tcp->tc_use_tlb) 332 TTWOGA_TLB_INVALIDATE(tcp); 333 334 return (error); 335 } 336 337 /* 338 * Load a T2 SGMAP-mapped DMA map with raw memory. 339 */ 340 int 341 ttwoga_bus_dmamap_load_raw_sgmap(bus_dma_tag_t t, bus_dmamap_t map, 342 bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) 343 { 344 struct ttwoga_config *tcp = t->_cookie; 345 int error; 346 347 error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs, size, flags, 348 t->_sgmap); 349 if (error == 0 && tcp->tc_use_tlb) 350 TTWOGA_TLB_INVALIDATE(tcp); 351 352 return (error); 353 } 354 355 /* 356 * Unload an T2 DMA map. 357 */ 358 void 359 ttwoga_bus_dmamap_unload_sgmap(bus_dma_tag_t t, bus_dmamap_t map) 360 { 361 struct ttwoga_config *tcp = t->_cookie; 362 363 /* 364 * Invalidate any SGMAP page table entries used by this 365 * mapping. 366 */ 367 pci_sgmap_pte64_unload(t, map, t->_sgmap); 368 if (tcp->tc_use_tlb) 369 TTWOGA_TLB_INVALIDATE(tcp); 370 371 /* 372 * Do the generic bits of the unload. 373 */ 374 _bus_dmamap_unload(t, map); 375 } 376