bus_dma_jazz.c revision 1.3.2.2 1 1.3.2.2 bouyer /* $NetBSD: bus_dma_jazz.c,v 1.3.2.2 2000/11/20 20:00:40 bouyer Exp $ */
2 1.3.2.2 bouyer
3 1.3.2.2 bouyer /*-
4 1.3.2.2 bouyer * Copyright (C) 2000 Shuichiro URATA. All rights reserved.
5 1.3.2.2 bouyer *
6 1.3.2.2 bouyer * Redistribution and use in source and binary forms, with or without
7 1.3.2.2 bouyer * modification, are permitted provided that the following conditions
8 1.3.2.2 bouyer * are met:
9 1.3.2.2 bouyer * 1. Redistributions of source code must retain the above copyright
10 1.3.2.2 bouyer * notice, this list of conditions and the following disclaimer.
11 1.3.2.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
12 1.3.2.2 bouyer * notice, this list of conditions and the following disclaimer in the
13 1.3.2.2 bouyer * documentation and/or other materials provided with the distribution.
14 1.3.2.2 bouyer * 3. The name of the author may not be used to endorse or promote products
15 1.3.2.2 bouyer * derived from this software without specific prior written permission.
16 1.3.2.2 bouyer *
17 1.3.2.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 1.3.2.2 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 1.3.2.2 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.3.2.2 bouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 1.3.2.2 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 1.3.2.2 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 1.3.2.2 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 1.3.2.2 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 1.3.2.2 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 1.3.2.2 bouyer * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 1.3.2.2 bouyer */
28 1.3.2.2 bouyer
29 1.3.2.2 bouyer #include <sys/param.h>
30 1.3.2.2 bouyer #include <sys/systm.h>
31 1.3.2.2 bouyer #include <sys/mbuf.h>
32 1.3.2.2 bouyer #include <sys/device.h>
33 1.3.2.2 bouyer
34 1.3.2.2 bouyer #include <uvm/uvm_extern.h>
35 1.3.2.2 bouyer
36 1.3.2.2 bouyer #define _ARC_BUS_DMA_PRIVATE
37 1.3.2.2 bouyer #include <machine/bus.h>
38 1.3.2.2 bouyer
39 1.3.2.2 bouyer #include <arc/jazz/jazzdmatlbreg.h>
40 1.3.2.2 bouyer #include <arc/jazz/jazzdmatlbvar.h>
41 1.3.2.2 bouyer
42 1.3.2.2 bouyer static int jazz_bus_dmamap_alloc_sgmap __P((bus_dma_tag_t,
43 1.3.2.2 bouyer bus_dma_segment_t *, int, bus_size_t, struct proc *, int));
44 1.3.2.2 bouyer static void jazz_bus_dmamap_free_sgmap __P((bus_dma_tag_t,
45 1.3.2.2 bouyer bus_dma_segment_t *, int));
46 1.3.2.2 bouyer
47 1.3.2.2 bouyer int jazz_bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
48 1.3.2.2 bouyer bus_size_t, struct proc *, int));
49 1.3.2.2 bouyer int jazz_bus_dmamap_load_mbuf __P((bus_dma_tag_t, bus_dmamap_t,
50 1.3.2.2 bouyer struct mbuf *, int));
51 1.3.2.2 bouyer int jazz_bus_dmamap_load_uio __P((bus_dma_tag_t, bus_dmamap_t,
52 1.3.2.2 bouyer struct uio *, int));
53 1.3.2.2 bouyer int jazz_bus_dmamap_load_raw __P((bus_dma_tag_t, bus_dmamap_t,
54 1.3.2.2 bouyer bus_dma_segment_t *, int, bus_size_t, int));
55 1.3.2.2 bouyer void jazz_bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
56 1.3.2.2 bouyer void jazz_mips1_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t,
57 1.3.2.2 bouyer bus_addr_t, bus_size_t, int));
58 1.3.2.2 bouyer void jazz_mips3_bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t,
59 1.3.2.2 bouyer bus_addr_t, bus_size_t, int));
60 1.3.2.2 bouyer
61 1.3.2.2 bouyer void
62 1.3.2.2 bouyer jazz_bus_dma_tag_init(t)
63 1.3.2.2 bouyer bus_dma_tag_t t;
64 1.3.2.2 bouyer {
65 1.3.2.2 bouyer _bus_dma_tag_init(t);
66 1.3.2.2 bouyer
67 1.3.2.2 bouyer t->_dmamap_load = jazz_bus_dmamap_load;
68 1.3.2.2 bouyer t->_dmamap_load_mbuf = jazz_bus_dmamap_load_mbuf;
69 1.3.2.2 bouyer t->_dmamap_load_uio = jazz_bus_dmamap_load_uio;
70 1.3.2.2 bouyer t->_dmamap_load_raw = jazz_bus_dmamap_load_raw;
71 1.3.2.2 bouyer t->_dmamap_unload = jazz_bus_dmamap_unload;
72 1.3.2.2 bouyer #if defined(MIPS1) && defined(MIPS3)
73 1.3.2.2 bouyer t->_dmamap_sync = (CPUISMIPS3) ?
74 1.3.2.2 bouyer jazz_mips3_bus_dmamap_sync : jazz_mips1_bus_dmamap_sync;
75 1.3.2.2 bouyer #elif defined(MIPS1)
76 1.3.2.2 bouyer t->_dmamap_sync = jazz_mips1_bus_dmamap_sync;
77 1.3.2.2 bouyer #elif defined(MIPS3)
78 1.3.2.2 bouyer t->_dmamap_sync = jazz_mips3_bus_dmamap_sync;
79 1.3.2.2 bouyer #else
80 1.3.2.2 bouyer #error neither MIPS1 nor MIPS3 is defined
81 1.3.2.2 bouyer #endif
82 1.3.2.2 bouyer t->_dmamem_alloc = _bus_dmamem_alloc;
83 1.3.2.2 bouyer t->_dmamem_free = _bus_dmamem_free;
84 1.3.2.2 bouyer }
85 1.3.2.2 bouyer
86 1.3.2.2 bouyer static int
87 1.3.2.2 bouyer jazz_bus_dmamap_alloc_sgmap(t, segs, nsegs, boundary, p, flags)
88 1.3.2.2 bouyer bus_dma_tag_t t;
89 1.3.2.2 bouyer bus_dma_segment_t *segs;
90 1.3.2.2 bouyer int nsegs;
91 1.3.2.2 bouyer bus_size_t boundary;
92 1.3.2.2 bouyer struct proc *p;
93 1.3.2.2 bouyer int flags;
94 1.3.2.2 bouyer {
95 1.3.2.2 bouyer jazz_dma_pte_t *dmapte;
96 1.3.2.2 bouyer bus_addr_t addr;
97 1.3.2.2 bouyer bus_size_t off;
98 1.3.2.2 bouyer int i, npte;
99 1.3.2.2 bouyer
100 1.3.2.2 bouyer for (i = 0; i < nsegs; i++) {
101 1.3.2.2 bouyer off = jazz_dma_page_offs(segs[i]._ds_paddr);
102 1.3.2.2 bouyer npte = jazz_dma_page_round(segs[i].ds_len + off) /
103 1.3.2.2 bouyer JAZZ_DMA_PAGE_SIZE;
104 1.3.2.2 bouyer dmapte = jazz_dmatlb_alloc(npte, boundary, flags, &addr);
105 1.3.2.2 bouyer if (dmapte == NULL)
106 1.3.2.2 bouyer return (ENOMEM);
107 1.3.2.2 bouyer segs[i].ds_addr = addr + off;
108 1.3.2.2 bouyer
109 1.3.2.2 bouyer jazz_dmatlb_map_pa(segs[i]._ds_paddr, segs[i].ds_len, dmapte);
110 1.3.2.2 bouyer }
111 1.3.2.2 bouyer return (0);
112 1.3.2.2 bouyer }
113 1.3.2.2 bouyer
114 1.3.2.2 bouyer static void
115 1.3.2.2 bouyer jazz_bus_dmamap_free_sgmap(t, segs, nsegs)
116 1.3.2.2 bouyer bus_dma_tag_t t;
117 1.3.2.2 bouyer bus_dma_segment_t *segs;
118 1.3.2.2 bouyer int nsegs;
119 1.3.2.2 bouyer {
120 1.3.2.2 bouyer int i, npte;
121 1.3.2.2 bouyer bus_addr_t addr;
122 1.3.2.2 bouyer
123 1.3.2.2 bouyer for (i = 0; i < nsegs; i++) {
124 1.3.2.2 bouyer addr = (segs[i].ds_addr - t->dma_offset) & JAZZ_DMA_PAGE_NUM;
125 1.3.2.2 bouyer npte = jazz_dma_page_round(segs[i].ds_len +
126 1.3.2.2 bouyer jazz_dma_page_offs(segs[i].ds_addr)) / JAZZ_DMA_PAGE_SIZE;
127 1.3.2.2 bouyer jazz_dmatlb_free(addr, npte);
128 1.3.2.2 bouyer }
129 1.3.2.2 bouyer }
130 1.3.2.2 bouyer
131 1.3.2.2 bouyer /*
132 1.3.2.2 bouyer * function for loading a direct-mapped DMA map with a linear buffer.
133 1.3.2.2 bouyer */
134 1.3.2.2 bouyer int
135 1.3.2.2 bouyer jazz_bus_dmamap_load(t, map, buf, buflen, p, flags)
136 1.3.2.2 bouyer bus_dma_tag_t t;
137 1.3.2.2 bouyer bus_dmamap_t map;
138 1.3.2.2 bouyer void *buf;
139 1.3.2.2 bouyer bus_size_t buflen;
140 1.3.2.2 bouyer struct proc *p;
141 1.3.2.2 bouyer int flags;
142 1.3.2.2 bouyer {
143 1.3.2.2 bouyer int error = _bus_dmamap_load(t, map, buf, buflen, p, flags);
144 1.3.2.2 bouyer
145 1.3.2.2 bouyer if (error == 0) {
146 1.3.2.2 bouyer error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
147 1.3.2.2 bouyer map->dm_nsegs, map->_dm_boundary, p, flags);
148 1.3.2.2 bouyer }
149 1.3.2.2 bouyer return (error);
150 1.3.2.2 bouyer }
151 1.3.2.2 bouyer
152 1.3.2.2 bouyer /*
153 1.3.2.2 bouyer * Like jazz_bus_dmamap_load(), but for mbufs.
154 1.3.2.2 bouyer */
155 1.3.2.2 bouyer int
156 1.3.2.2 bouyer jazz_bus_dmamap_load_mbuf(t, map, m0, flags)
157 1.3.2.2 bouyer bus_dma_tag_t t;
158 1.3.2.2 bouyer bus_dmamap_t map;
159 1.3.2.2 bouyer struct mbuf *m0;
160 1.3.2.2 bouyer int flags;
161 1.3.2.2 bouyer {
162 1.3.2.2 bouyer int error = _bus_dmamap_load_mbuf(t, map, m0, flags);
163 1.3.2.2 bouyer
164 1.3.2.2 bouyer if (error == 0) {
165 1.3.2.2 bouyer error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
166 1.3.2.2 bouyer map->dm_nsegs, map->_dm_boundary, NULL, flags);
167 1.3.2.2 bouyer }
168 1.3.2.2 bouyer return (error);
169 1.3.2.2 bouyer }
170 1.3.2.2 bouyer
171 1.3.2.2 bouyer /*
172 1.3.2.2 bouyer * Like jazz_bus_dmamap_load(), but for uios.
173 1.3.2.2 bouyer */
174 1.3.2.2 bouyer int
175 1.3.2.2 bouyer jazz_bus_dmamap_load_uio(t, map, uio, flags)
176 1.3.2.2 bouyer bus_dma_tag_t t;
177 1.3.2.2 bouyer bus_dmamap_t map;
178 1.3.2.2 bouyer struct uio *uio;
179 1.3.2.2 bouyer int flags;
180 1.3.2.2 bouyer {
181 1.3.2.2 bouyer int error = jazz_bus_dmamap_load_uio(t, map, uio, flags);
182 1.3.2.2 bouyer
183 1.3.2.2 bouyer if (error == 0) {
184 1.3.2.2 bouyer error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
185 1.3.2.2 bouyer map->dm_nsegs, map->_dm_boundary,
186 1.3.2.2 bouyer uio->uio_segflg == UIO_USERSPACE ? uio->uio_procp : NULL,
187 1.3.2.2 bouyer flags);
188 1.3.2.2 bouyer }
189 1.3.2.2 bouyer return (error);
190 1.3.2.2 bouyer }
191 1.3.2.2 bouyer
192 1.3.2.2 bouyer /*
193 1.3.2.2 bouyer * Like _bus_dmamap_load(), but for raw memory.
194 1.3.2.2 bouyer */
195 1.3.2.2 bouyer int
196 1.3.2.2 bouyer jazz_bus_dmamap_load_raw(t, map, segs, nsegs, size, flags)
197 1.3.2.2 bouyer bus_dma_tag_t t;
198 1.3.2.2 bouyer bus_dmamap_t map;
199 1.3.2.2 bouyer bus_dma_segment_t *segs;
200 1.3.2.2 bouyer int nsegs;
201 1.3.2.2 bouyer bus_size_t size;
202 1.3.2.2 bouyer int flags;
203 1.3.2.2 bouyer {
204 1.3.2.2 bouyer int error = _bus_dmamap_load_raw(t, map, segs, nsegs, size, flags);
205 1.3.2.2 bouyer
206 1.3.2.2 bouyer if (error == 0) {
207 1.3.2.2 bouyer error = jazz_bus_dmamap_alloc_sgmap(t, map->dm_segs,
208 1.3.2.2 bouyer map->dm_nsegs, map->_dm_boundary, NULL, flags);
209 1.3.2.2 bouyer }
210 1.3.2.2 bouyer return (error);
211 1.3.2.2 bouyer }
212 1.3.2.2 bouyer
213 1.3.2.2 bouyer /*
214 1.3.2.2 bouyer * unload a DMA map.
215 1.3.2.2 bouyer */
216 1.3.2.2 bouyer void
217 1.3.2.2 bouyer jazz_bus_dmamap_unload(t, map)
218 1.3.2.2 bouyer bus_dma_tag_t t;
219 1.3.2.2 bouyer bus_dmamap_t map;
220 1.3.2.2 bouyer {
221 1.3.2.2 bouyer jazz_bus_dmamap_free_sgmap(t, map->dm_segs, map->dm_nsegs);
222 1.3.2.2 bouyer _bus_dmamap_unload(t, map);
223 1.3.2.2 bouyer }
224 1.3.2.2 bouyer
225 1.3.2.2 bouyer #ifdef MIPS1
226 1.3.2.2 bouyer /*
227 1.3.2.2 bouyer * Function for MIPS1 DMA map synchronization.
228 1.3.2.2 bouyer */
229 1.3.2.2 bouyer void
230 1.3.2.2 bouyer jazz_mips1_bus_dmamap_sync(t, map, offset, len, ops)
231 1.3.2.2 bouyer bus_dma_tag_t t;
232 1.3.2.2 bouyer bus_dmamap_t map;
233 1.3.2.2 bouyer bus_addr_t offset;
234 1.3.2.2 bouyer bus_size_t len;
235 1.3.2.2 bouyer int ops;
236 1.3.2.2 bouyer {
237 1.3.2.2 bouyer /* Flush DMA TLB */
238 1.3.2.2 bouyer if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0)
239 1.3.2.2 bouyer jazz_dmatlb_flush();
240 1.3.2.2 bouyer
241 1.3.2.2 bouyer return (_mips1_bus_dmamap_sync(t, map, offset, len, ops));
242 1.3.2.2 bouyer }
243 1.3.2.2 bouyer #endif /* MIPS1 */
244 1.3.2.2 bouyer
245 1.3.2.2 bouyer #ifdef MIPS3
246 1.3.2.2 bouyer /*
247 1.3.2.2 bouyer * Function for MIPS3 DMA map synchronization.
248 1.3.2.2 bouyer */
249 1.3.2.2 bouyer void
250 1.3.2.2 bouyer jazz_mips3_bus_dmamap_sync(t, map, offset, len, ops)
251 1.3.2.2 bouyer bus_dma_tag_t t;
252 1.3.2.2 bouyer bus_dmamap_t map;
253 1.3.2.2 bouyer bus_addr_t offset;
254 1.3.2.2 bouyer bus_size_t len;
255 1.3.2.2 bouyer int ops;
256 1.3.2.2 bouyer {
257 1.3.2.2 bouyer /* Flush DMA TLB */
258 1.3.2.2 bouyer if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0)
259 1.3.2.2 bouyer jazz_dmatlb_flush();
260 1.3.2.2 bouyer
261 1.3.2.2 bouyer return (_mips3_bus_dmamap_sync(t, map, offset, len, ops));
262 1.3.2.2 bouyer }
263 1.3.2.2 bouyer #endif /* MIPS3 */
264