g2bus_bus_mem.c revision 1.8 1 /* $NetBSD: g2bus_bus_mem.c,v 1.8 2003/07/15 01:31:38 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 2001 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 /*
40 * Bus space implementation for the SEGA G2 bus.
41 *
42 * NOTE: We only implement a small subset of what the bus_space(9)
43 * API specifies. Right now, the GAPS PCI bridge is only used for
44 * the Dreamcast Broadband Adatper, so we only provide what the
45 * pci(4) and rtk(4) drivers need.
46 */
47
48 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
49 __KERNEL_RCSID(0, "$NetBSD: g2bus_bus_mem.c,v 1.8 2003/07/15 01:31:38 lukem Exp $");
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/device.h>
54
55 #include <machine/cpu.h>
56 #include <machine/bus.h>
57
58 #include <dreamcast/dev/g2/g2busvar.h>
59
60 int g2bus_bus_mem_map(void *, bus_addr_t, bus_size_t, int,
61 bus_space_handle_t *);
62 void g2bus_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t);
63
64 u_int8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
65 u_int16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
66 u_int32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
67
68 void g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
69 u_int8_t);
70 void g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
71 u_int16_t);
72 void g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
73 u_int32_t);
74
75 void g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t,
76 u_int8_t *, bus_size_t);
77
78 void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t,
79 const u_int8_t *, bus_size_t);
80
81 u_int8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
82 u_int16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
83 u_int32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
84
85 void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
86 u_int8_t);
87 void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
88 u_int16_t);
89 void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
90 u_int32_t);
91
92 void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t,
93 bus_size_t, u_int8_t *, bus_size_t);
94
95 void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t,
96 bus_size_t, const u_int8_t *, bus_size_t);
97
98 void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t,
99 bus_size_t, u_int8_t *, bus_size_t);
100
101 void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t,
102 bus_size_t, const u_int8_t *, bus_size_t);
103
104 void
105 g2bus_bus_mem_init(struct g2bus_softc *sc)
106 {
107 bus_space_tag_t t = &sc->sc_memt;
108
109 memset(t, 0, sizeof(*t));
110
111 t->dbs_map = g2bus_bus_mem_map;
112 t->dbs_unmap = g2bus_bus_mem_unmap;
113
114 t->dbs_r_1 = g2bus_bus_mem_read_1;
115 t->dbs_r_2 = g2bus_bus_mem_read_2;
116 t->dbs_r_4 = g2bus_bus_mem_read_4;
117
118 t->dbs_w_1 = g2bus_bus_mem_write_1;
119 t->dbs_w_2 = g2bus_bus_mem_write_2;
120 t->dbs_w_4 = g2bus_bus_mem_write_4;
121
122 t->dbs_rr_1 = g2bus_bus_mem_read_region_1;
123
124 t->dbs_wr_1 = g2bus_bus_mem_write_region_1;
125 }
126
127 int
128 g2bus_bus_mem_map(void *v, bus_addr_t addr, bus_size_t size, int flags,
129 bus_space_handle_t *shp)
130 {
131
132 KASSERT((addr & SH3_PHYS_MASK) == addr);
133 *shp = SH3_PHYS_TO_P2SEG(addr);
134
135 return (0);
136 }
137
138 void
139 g2bus_bus_mem_unmap(void *v, bus_space_handle_t sh, bus_size_t size)
140 {
141
142 KASSERT(sh >= SH3_P2SEG_BASE && sh <= SH3_P2SEG_END);
143 /* Nothing to do. */
144 }
145
146 /*
147 * G2 bus cycles must not be interrupted by IRQs or G2 DMA.
148 * The following paired macros will take the necessary precautions.
149 */
150
151 #define G2LOCK_DECL \
152 int __s
153
154 #define G2_LOCK() \
155 do { \
156 __s = _cpu_intr_suspend(); \
157 /* suspend any G2 DMA here... */ \
158 while ((*(__volatile u_int32_t *)0xa05f688c) & 0x20) \
159 ; \
160 } while (/*CONSTCOND*/0)
161
162 #define G2_UNLOCK() \
163 do { \
164 /* resume any G2 DMA here... */ \
165 _cpu_intr_resume(__s); \
166 } while (/*CONSTCOND*/0)
167
168 u_int8_t
169 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
170 {
171 G2LOCK_DECL;
172 u_int8_t rv;
173
174 G2_LOCK();
175
176 rv = *(__volatile u_int8_t *)(sh + off);
177
178 G2_UNLOCK();
179
180 return (rv);
181 }
182
183 u_int16_t
184 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
185 {
186 G2LOCK_DECL;
187 u_int16_t rv;
188
189 G2_LOCK();
190
191 rv = *(__volatile u_int16_t *)(sh + off);
192
193 G2_UNLOCK();
194
195 return (rv);
196 }
197
198 u_int32_t
199 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
200 {
201 G2LOCK_DECL;
202 u_int32_t rv;
203
204 G2_LOCK();
205
206 rv = *(__volatile u_int32_t *)(sh + off);
207
208 G2_UNLOCK();
209
210 return (rv);
211 }
212
213 void
214 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
215 u_int8_t val)
216 {
217 G2LOCK_DECL;
218
219 G2_LOCK();
220
221 *(__volatile u_int8_t *)(sh + off) = val;
222
223 G2_UNLOCK();
224 }
225
226 void
227 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
228 u_int16_t val)
229 {
230 G2LOCK_DECL;
231
232 G2_LOCK();
233
234 *(__volatile u_int16_t *)(sh + off) = val;
235
236 G2_UNLOCK();
237 }
238
239 void
240 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
241 u_int32_t val)
242 {
243 G2LOCK_DECL;
244
245 G2_LOCK();
246
247 *(__volatile u_int32_t *)(sh + off) = val;
248
249 G2_UNLOCK();
250 }
251
252 void
253 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
254 u_int8_t *addr, bus_size_t len)
255 {
256 G2LOCK_DECL;
257 __volatile const u_int8_t *baddr = (u_int8_t *)(sh + off);
258
259 G2_LOCK();
260
261 while (len--)
262 *addr++ = *baddr++;
263
264 G2_UNLOCK();
265 }
266
267 void
268 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
269 const u_int8_t *addr, bus_size_t len)
270 {
271 G2LOCK_DECL;
272 __volatile u_int8_t *baddr = (u_int8_t *)(sh + off);
273
274 G2_LOCK();
275
276 while (len--)
277 *baddr++ = *addr++;
278
279 G2_UNLOCK();
280 }
281
282 void
283 g2bus_set_bus_mem_sparse(bus_space_tag_t memt)
284 {
285
286 memt->dbs_r_1 = g2bus_sparse_bus_mem_read_1;
287 memt->dbs_r_2 = g2bus_sparse_bus_mem_read_2;
288 memt->dbs_r_4 = g2bus_sparse_bus_mem_read_4;
289
290 memt->dbs_w_1 = g2bus_sparse_bus_mem_write_1;
291 memt->dbs_w_2 = g2bus_sparse_bus_mem_write_2;
292 memt->dbs_w_4 = g2bus_sparse_bus_mem_write_4;
293
294 memt->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1;
295
296 memt->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1;
297
298 memt->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1;
299
300 memt->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1;
301 }
302
303 u_int8_t
304 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
305 {
306 G2LOCK_DECL;
307 u_int8_t rv;
308
309 G2_LOCK();
310
311 rv = *(__volatile u_int8_t *)(sh + (off * 4));
312
313 G2_UNLOCK();
314
315 return (rv);
316 }
317
318 u_int16_t
319 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
320 {
321 G2LOCK_DECL;
322 u_int16_t rv;
323
324 G2_LOCK();
325
326 rv = *(__volatile u_int16_t *)(sh + (off * 4));
327
328 G2_UNLOCK();
329
330 return (rv);
331 }
332
333 u_int32_t
334 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
335 {
336 G2LOCK_DECL;
337 u_int32_t rv;
338
339 G2_LOCK();
340
341 rv = *(__volatile u_int32_t *)(sh + (off * 4));
342
343 G2_UNLOCK();
344
345 return (rv);
346 }
347
348 void
349 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
350 u_int8_t val)
351 {
352 G2LOCK_DECL;
353
354 G2_LOCK();
355
356 *(__volatile u_int8_t *)(sh + (off * 4)) = val;
357
358 G2_UNLOCK();
359 }
360
361 void
362 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
363 u_int16_t val)
364 {
365 G2LOCK_DECL;
366
367 G2_LOCK();
368
369 *(__volatile u_int16_t *)(sh + (off * 4)) = val;
370
371 G2_UNLOCK();
372 }
373
374 void
375 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
376 u_int32_t val)
377 {
378 G2LOCK_DECL;
379
380 G2_LOCK();
381
382 *(__volatile u_int32_t *)(sh + (off * 4)) = val;
383
384 G2_UNLOCK();
385 }
386
387 void
388 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
389 bus_size_t off, u_int8_t *addr, bus_size_t len)
390 {
391 G2LOCK_DECL;
392 __volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
393
394 G2_LOCK();
395
396 while (len--) {
397 *addr++ = *baddr;
398 baddr += 4;
399 }
400
401 G2_UNLOCK();
402 }
403
404 void
405 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
406 bus_size_t off, const u_int8_t *addr, bus_size_t len)
407 {
408 G2LOCK_DECL;
409 __volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
410
411 G2_LOCK();
412
413 while (len--) {
414 *baddr = *addr++;
415 baddr += 4;
416 }
417
418 G2_UNLOCK();
419 }
420
421 void
422 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
423 bus_size_t off, u_int8_t *addr, bus_size_t len)
424 {
425 G2LOCK_DECL;
426 __volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
427
428 G2_LOCK();
429
430 while (len--)
431 *addr++ = *baddr;
432
433 G2_UNLOCK();
434 }
435
436 void
437 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
438 bus_size_t off, const u_int8_t *addr, bus_size_t len)
439 {
440 G2LOCK_DECL;
441 __volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
442
443 G2_LOCK();
444
445 while (len--)
446 *baddr = *addr++;
447
448 G2_UNLOCK();
449 }
450