mcpcia_dma.c revision 1.1 1 /* $NetBSD: mcpcia_dma.c,v 1.1 1998/04/15 00:50:14 mjacob Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998 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 of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center. This code happens to have been written
10 * by Matthew Jacob for NASA/Ames.
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 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPEMCPCIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
42
43 __KERNEL_RCSID(0, "$NetBSD: mcpcia_dma.c,v 1.1 1998/04/15 00:50:14 mjacob Exp $");
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/device.h>
49 #include <sys/malloc.h>
50 #include <vm/vm.h>
51
52 #define _ALPHA_BUS_DMA_PRIVATE
53 #include <machine/bus.h>
54
55 #include <dev/pci/pcireg.h>
56 #include <dev/pci/pcivar.h>
57 #include <alpha/pci/mcpciareg.h>
58 #include <alpha/pci/mcpciavar.h>
59 #include <alpha/pci/pci_kn300.h>
60
61 bus_dma_tag_t mcpcia_dma_get_tag __P((bus_dma_tag_t, alpha_bus_t));
62
63 int mcpcia_bus_dmamap_create_sgmap __P((bus_dma_tag_t, bus_size_t, int,
64 bus_size_t, bus_size_t, int, bus_dmamap_t *));
65
66 void mcpcia_bus_dmamap_destroy_sgmap __P((bus_dma_tag_t, bus_dmamap_t));
67
68 int mcpcia_bus_dmamap_load_direct __P((bus_dma_tag_t, bus_dmamap_t, void *,
69 bus_size_t, struct proc *, int));
70
71 int mcpcia_bus_dmamap_load_sgmap __P((bus_dma_tag_t, bus_dmamap_t, void *,
72 bus_size_t, struct proc *, int));
73
74 int mcpcia_bus_dmamap_load_mbuf_direct __P((bus_dma_tag_t, bus_dmamap_t,
75 struct mbuf *, int));
76
77 int mcpcia_bus_dmamap_load_mbuf_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
78 struct mbuf *, int));
79
80 int mcpcia_bus_dmamap_load_uio_direct __P((bus_dma_tag_t, bus_dmamap_t,
81 struct uio *, int));
82 int mcpcia_bus_dmamap_load_uio_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
83 struct uio *, int));
84
85 int mcpcia_bus_dmamap_load_raw_direct __P((bus_dma_tag_t, bus_dmamap_t,
86 bus_dma_segment_t *, int, bus_size_t, int));
87 int mcpcia_bus_dmamap_load_raw_sgmap __P((bus_dma_tag_t, bus_dmamap_t,
88 bus_dma_segment_t *, int, bus_size_t, int));
89
90 void mcpcia_bus_dmamap_unload_sgmap __P((bus_dma_tag_t, bus_dmamap_t));
91
92 #define MCPCIA_DIRECT_MAPPED_BASE 0x80000000
93 #define MCPCIA_SG_MAPPED_BASE (8 << 20)
94
95 #define MCPCIA_SGTLB_INVALIDATE(mcp) \
96 alpha_mb(), \
97 REGVAL(MCPCIA_SG_TBIA(mcp)) = 0xdeadbeef, \
98 alpha_mb()
99
100 void
101 mcpcia_dma_init(ccp)
102 struct mcpcia_config *ccp;
103 {
104 bus_dma_tag_t t;
105
106 /*
107 * Initialize the DMA tag used for direct-mapped DMA.
108 */
109 t = &ccp->cc_dmat_direct;
110 t->_cookie = ccp;
111 t->_get_tag = mcpcia_dma_get_tag;
112 t->_dmamap_create = _bus_dmamap_create;
113 t->_dmamap_destroy = _bus_dmamap_destroy;
114 t->_dmamap_load = mcpcia_bus_dmamap_load_direct;
115 t->_dmamap_load_mbuf = mcpcia_bus_dmamap_load_mbuf_direct;
116 t->_dmamap_load_uio = mcpcia_bus_dmamap_load_uio_direct;
117 t->_dmamap_load_raw = mcpcia_bus_dmamap_load_raw_direct;
118 t->_dmamap_unload = _bus_dmamap_unload;
119 t->_dmamap_sync = _bus_dmamap_sync;
120
121 t->_dmamem_alloc = _bus_dmamem_alloc;
122 t->_dmamem_free = _bus_dmamem_free;
123 t->_dmamem_map = _bus_dmamem_map;
124 t->_dmamem_unmap = _bus_dmamem_unmap;
125 t->_dmamem_mmap = _bus_dmamem_mmap;
126
127 /*
128 * Initialize the DMA tag used for sgmap-mapped DMA.
129 */
130 t = &ccp->cc_dmat_sgmap;
131 t->_cookie = ccp;
132 t->_get_tag = mcpcia_dma_get_tag;
133 t->_dmamap_create = mcpcia_bus_dmamap_create_sgmap;
134 t->_dmamap_destroy = mcpcia_bus_dmamap_destroy_sgmap;
135 t->_dmamap_load = mcpcia_bus_dmamap_load_sgmap;
136 t->_dmamap_load_mbuf = mcpcia_bus_dmamap_load_mbuf_sgmap;
137 t->_dmamap_load_uio = mcpcia_bus_dmamap_load_uio_sgmap;
138 t->_dmamap_load_raw = mcpcia_bus_dmamap_load_raw_sgmap;
139 t->_dmamap_unload = mcpcia_bus_dmamap_unload_sgmap;
140 t->_dmamap_sync = _bus_dmamap_sync;
141
142 t->_dmamem_alloc = _bus_dmamem_alloc;
143 t->_dmamem_free = _bus_dmamem_free;
144 t->_dmamem_map = _bus_dmamem_map;
145 t->_dmamem_unmap = _bus_dmamem_unmap;
146 t->_dmamem_mmap = _bus_dmamem_mmap;
147
148 /*
149 * The SRM console is supposed to set up an 8MB direct mapped window
150 * at 8MB (window 0) and a 1MB direct mapped window at 1MB. Useless.
151 *
152 * The DU && OpenVMS convention is to have an 8MB S/G window
153 * at 8MB for window 0, a 1GB direct mapped window at 2GB
154 * for window 1, a 1 GB S/G window at window 2 and a 512 MB
155 * S/G window at window 3. This seems overkill.
156 *
157 * We'll just go with the 8MB S/G window and one 1GB direct window.
158 */
159
160 /*
161 * Initialize the SGMAP.
162 *
163 * Must align page table to its size.
164 */
165 alpha_sgmap_init(t, &ccp->cc_sgmap, "mcpcia_sgmap",
166 MCPCIA_SG_MAPPED_BASE, 0, (8 << 20),
167 sizeof(u_int64_t), NULL, 8 << 10);
168
169 if (ccp->cc_sgmap.aps_ptpa & (1024-1)) {
170 panic("mcpcia_dma_init: bad page table address %x",
171 ccp->cc_sgmap.aps_ptpa);
172 }
173
174 /*
175 * Disable windows first.
176 */
177
178 REGVAL(MCPCIA_W0_BASE(ccp->cc_sc)) = 0;
179 REGVAL(MCPCIA_W1_BASE(ccp->cc_sc)) = 0;
180 REGVAL(MCPCIA_W2_BASE(ccp->cc_sc)) = 0;
181 REGVAL(MCPCIA_W3_BASE(ccp->cc_sc)) = 0;
182 REGVAL(MCPCIA_T0_BASE(ccp->cc_sc)) = 0;
183 REGVAL(MCPCIA_T1_BASE(ccp->cc_sc)) = 0;
184 REGVAL(MCPCIA_T2_BASE(ccp->cc_sc)) = 0;
185 REGVAL(MCPCIA_T3_BASE(ccp->cc_sc)) = 0;
186 alpha_mb();
187
188 /*
189 * Set up window 0 as an 8MB SGMAP-mapped window starting at 8MB.
190 */
191 REGVAL(MCPCIA_W0_MASK(ccp->cc_sc)) = MCPCIA_WMASK_8M;
192 REGVAL(MCPCIA_T0_BASE(ccp->cc_sc)) =
193 ccp->cc_sgmap.aps_ptpa >> MCPCIA_TBASEX_SHIFT;
194 REGVAL(MCPCIA_W0_BASE(ccp->cc_sc)) =
195 MCPCIA_WBASE_EN | MCPCIA_WBASE_SG | MCPCIA_SG_MAPPED_BASE;
196 alpha_mb();
197
198 MCPCIA_SGTLB_INVALIDATE(ccp->cc_sc);
199
200 /*
201 * Set up window 1 as a 1 GB Direct-mapped window starting at 2GB.
202 */
203
204 REGVAL(MCPCIA_W0_MASK(ccp->cc_sc)) = MCPCIA_WMASK_1G;
205 REGVAL(MCPCIA_T0_BASE(ccp->cc_sc)) = 0;
206 REGVAL(MCPCIA_W0_BASE(ccp->cc_sc)) =
207 MCPCIA_DIRECT_MAPPED_BASE | MCPCIA_WBASE_EN;
208 alpha_mb();
209
210 /* XXX XXX BEGIN XXX XXX */
211 { /* XXX */
212 extern vm_offset_t alpha_XXX_dmamap_or; /* XXX */
213 alpha_XXX_dmamap_or = MCPCIA_DIRECT_MAPPED_BASE;/* XXX */
214 } /* XXX */
215 /* XXX XXX END XXX XXX */
216 }
217
218 /*
219 * Return the bus dma tag to be used for the specified bus type.
220 * INTERNAL USE ONLY!
221 */
222 bus_dma_tag_t
223 mcpcia_dma_get_tag(t, bustype)
224 bus_dma_tag_t t;
225 alpha_bus_t bustype;
226 {
227 struct mcpcia_config *ccp = t->_cookie;
228 extern int physmem;
229
230 switch (bustype) {
231 case ALPHA_BUS_PCI:
232 case ALPHA_BUS_EISA:
233 /*
234 * As best as I can tell from the DU source, you can't
235 * do DIRECT MAPPED and S/G at the same time.
236 */
237 return (&ccp->cc_dmat_direct);
238
239 case ALPHA_BUS_ISA:
240 /*
241 * ISA doesn't have enough address bits to use
242 * the direct-mapped DMA window, so we must use
243 * SGMAPs.
244 */
245 return (&ccp->cc_dmat_sgmap);
246
247 default:
248 panic("mcpcia_dma_get_tag: shouldn't be here, really...");
249 }
250 }
251
252 /*
253 * Create a MCPCIA SGMAP-mapped DMA map.
254 */
255 int
256 mcpcia_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary,
257 flags, dmamp)
258 bus_dma_tag_t t;
259 bus_size_t size;
260 int nsegments;
261 bus_size_t maxsegsz;
262 bus_size_t boundary;
263 int flags;
264 bus_dmamap_t *dmamp;
265 {
266 struct mcpcia_config *ccp = t->_cookie;
267 bus_dmamap_t map;
268 int error;
269
270 error = _bus_dmamap_create(t, size, nsegments, maxsegsz,
271 boundary, flags, dmamp);
272 if (error)
273 return (error);
274
275 map = *dmamp;
276
277 if (flags & BUS_DMA_ALLOCNOW) {
278 error = alpha_sgmap_alloc(map, round_page(size),
279 &ccp->cc_sgmap, flags);
280 if (error)
281 mcpcia_bus_dmamap_destroy_sgmap(t, map);
282 }
283
284 return (error);
285 }
286
287 /*
288 * Destroy a MCPCIA SGMAP-mapped DMA map.
289 */
290 void
291 mcpcia_bus_dmamap_destroy_sgmap(t, map)
292 bus_dma_tag_t t;
293 bus_dmamap_t map;
294 {
295 struct mcpcia_config *ccp = t->_cookie;
296
297 if (map->_dm_flags & DMAMAP_HAS_SGMAP)
298 alpha_sgmap_free(map, &ccp->cc_sgmap);
299
300 _bus_dmamap_destroy(t, map);
301 }
302
303 /*
304 * Load a MCPCIA direct-mapped DMA map with a linear buffer.
305 */
306 int
307 mcpcia_bus_dmamap_load_direct(t, map, buf, buflen, p, flags)
308 bus_dma_tag_t t;
309 bus_dmamap_t map;
310 void *buf;
311 bus_size_t buflen;
312 struct proc *p;
313 int flags;
314 {
315 return (_bus_dmamap_load_direct_common(t, map, buf, buflen, p,
316 flags, MCPCIA_DIRECT_MAPPED_BASE));
317 }
318
319 /*
320 * Load a MCPCIA SGMAP-mapped DMA map with a linear buffer.
321 */
322 int
323 mcpcia_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags)
324 bus_dma_tag_t t;
325 bus_dmamap_t map;
326 void *buf;
327 bus_size_t buflen;
328 struct proc *p;
329 int flags;
330 {
331 int error;
332 struct mcpcia_config *ccp = t->_cookie;
333
334 error = pci_sgmap_pte64_load(t, map, buf, buflen, p,
335 flags, &ccp->cc_sgmap);
336 if (error == 0)
337 MCPCIA_SGTLB_INVALIDATE(ccp->cc_sc);
338 return (error);
339 }
340
341 /*
342 * Load a MCPCIA direct-mapped DMA map with an mbuf chain.
343 */
344 int
345 mcpcia_bus_dmamap_load_mbuf_direct(t, map, m, flags)
346 bus_dma_tag_t t;
347 bus_dmamap_t map;
348 struct mbuf *m;
349 int flags;
350 {
351 return (_bus_dmamap_load_mbuf_direct_common(t, map, m,
352 flags, MCPCIA_DIRECT_MAPPED_BASE));
353 }
354
355 /*
356 * Load a MCPCIA SGMAP-mapped DMA map with an mbuf chain.
357 */
358 int
359 mcpcia_bus_dmamap_load_mbuf_sgmap(t, map, m, flags)
360 bus_dma_tag_t t;
361 bus_dmamap_t map;
362 struct mbuf *m;
363 int flags;
364 {
365 int error;
366 struct mcpcia_config *ccp = t->_cookie;
367
368 error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, &ccp->cc_sgmap);
369 if (error == 0)
370 MCPCIA_SGTLB_INVALIDATE(ccp->cc_sc);
371 return (error);
372 }
373
374 /*
375 * Load a MCPCIA direct-mapped DMA map with a uio.
376 */
377 int
378 mcpcia_bus_dmamap_load_uio_direct(t, map, uio, flags)
379 bus_dma_tag_t t;
380 bus_dmamap_t map;
381 struct uio *uio;
382 int flags;
383 {
384 return (_bus_dmamap_load_uio_direct_common(t, map, uio,
385 flags, MCPCIA_DIRECT_MAPPED_BASE));
386 }
387
388 /*
389 * Load a MCPCIA SGMAP-mapped DMA map with a uio.
390 */
391 int
392 mcpcia_bus_dmamap_load_uio_sgmap(t, map, uio, flags)
393 bus_dma_tag_t t;
394 bus_dmamap_t map;
395 struct uio *uio;
396 int flags;
397 {
398 int error;
399 struct mcpcia_config *ccp = t->_cookie;
400
401 error = pci_sgmap_pte64_load_uio(t, map, uio, flags, &ccp->cc_sgmap);
402 if (error == 0)
403 MCPCIA_SGTLB_INVALIDATE(ccp->cc_sc);
404 return (error);
405 }
406
407 /*
408 * Load a MCPCIA direct-mapped DMA map with raw memory.
409 */
410 int
411 mcpcia_bus_dmamap_load_raw_direct(t, map, segs, nsegs, size, flags)
412 bus_dma_tag_t t;
413 bus_dmamap_t map;
414 bus_dma_segment_t *segs;
415 int nsegs;
416 bus_size_t size;
417 int flags;
418 {
419 return (_bus_dmamap_load_raw_direct_common(t, map, segs, nsegs,
420 size, flags, MCPCIA_DIRECT_MAPPED_BASE));
421 }
422
423 /*
424 * Load a MCPCIA SGMAP-mapped DMA map with raw memory.
425 */
426 int
427 mcpcia_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags)
428 bus_dma_tag_t t;
429 bus_dmamap_t map;
430 bus_dma_segment_t *segs;
431 int nsegs;
432 bus_size_t size;
433 int flags;
434 {
435 int error;
436 struct mcpcia_config *ccp = t->_cookie;
437
438 error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs,
439 size, flags, &ccp->cc_sgmap);
440 if (error == 0)
441 MCPCIA_SGTLB_INVALIDATE(ccp->cc_sc);
442 return (error);
443 }
444
445 /*
446 * Unload a MCPCIA DMA map.
447 */
448 void
449 mcpcia_bus_dmamap_unload_sgmap(t, map)
450 bus_dma_tag_t t;
451 bus_dmamap_t map;
452 {
453 struct mcpcia_config *ccp = t->_cookie;
454
455 /*
456 * Invalidate any SGMAP page table entries used by this mapping.
457 */
458 pci_sgmap_pte64_unload(t, map, &ccp->cc_sgmap);
459 MCPCIA_SGTLB_INVALIDATE(ccp->cc_sc);
460
461 /*
462 * Do the generic bits of the unload.
463 */
464 _bus_dmamap_unload(t, map);
465 }
466