ttwoga_dma.c revision 1.3 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