g2bus_bus_mem.c revision 1.10 1 /* $NetBSD: g2bus_bus_mem.c,v 1.10 2005/02/19 15:37:34 tsutsui 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.10 2005/02/19 15:37:34 tsutsui 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 uint8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
65 uint16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
66 uint32_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 uint8_t);
70 void g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
71 uint16_t);
72 void g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
73 uint32_t);
74
75 void g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t,
76 uint8_t *, bus_size_t);
77 void g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t,
78 uint16_t *, bus_size_t);
79 void g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t,
80 uint32_t *, bus_size_t);
81
82 void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t,
83 const uint8_t *, bus_size_t);
84 void g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t,
85 const uint16_t *, bus_size_t);
86 void g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t,
87 const uint32_t *, bus_size_t);
88
89 void g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t,
90 uint32_t, bus_size_t);
91
92 uint8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
93 uint16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
94 uint32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
95
96 void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
97 uint8_t);
98 void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
99 uint16_t);
100 void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
101 uint32_t);
102
103 void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t,
104 bus_size_t, uint8_t *, bus_size_t);
105
106 void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t,
107 bus_size_t, const uint8_t *, bus_size_t);
108
109 void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t,
110 bus_size_t, uint8_t *, bus_size_t);
111
112 void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t,
113 bus_size_t, const uint8_t *, bus_size_t);
114
115 void
116 g2bus_bus_mem_init(struct g2bus_softc *sc)
117 {
118 bus_space_tag_t t = &sc->sc_memt;
119
120 memset(t, 0, sizeof(*t));
121
122 t->dbs_map = g2bus_bus_mem_map;
123 t->dbs_unmap = g2bus_bus_mem_unmap;
124
125 t->dbs_r_1 = g2bus_bus_mem_read_1;
126 t->dbs_r_2 = g2bus_bus_mem_read_2;
127 t->dbs_r_4 = g2bus_bus_mem_read_4;
128
129 t->dbs_w_1 = g2bus_bus_mem_write_1;
130 t->dbs_w_2 = g2bus_bus_mem_write_2;
131 t->dbs_w_4 = g2bus_bus_mem_write_4;
132
133 t->dbs_rr_1 = g2bus_bus_mem_read_region_1;
134 t->dbs_rr_2 = g2bus_bus_mem_read_region_2;
135 t->dbs_rr_4 = g2bus_bus_mem_read_region_4;
136
137 t->dbs_wr_1 = g2bus_bus_mem_write_region_1;
138 t->dbs_wr_2 = g2bus_bus_mem_write_region_2;
139 t->dbs_wr_4 = g2bus_bus_mem_write_region_4;
140
141 t->dbs_sr_4 = g2bus_bus_mem_set_region_4;
142 }
143
144 int
145 g2bus_bus_mem_map(void *v, bus_addr_t addr, bus_size_t size, int flags,
146 bus_space_handle_t *shp)
147 {
148
149 KASSERT((addr & SH3_PHYS_MASK) == addr);
150 *shp = SH3_PHYS_TO_P2SEG(addr);
151
152 return 0;
153 }
154
155 void
156 g2bus_bus_mem_unmap(void *v, bus_space_handle_t sh, bus_size_t size)
157 {
158
159 KASSERT(sh >= SH3_P2SEG_BASE && sh <= SH3_P2SEG_END);
160 /* Nothing to do. */
161 }
162
163 /*
164 * G2 bus cycles must not be interrupted by IRQs or G2 DMA.
165 * The following paired macros will take the necessary precautions.
166 */
167
168 #define G2LOCK_DECL \
169 int __s
170
171 #define G2_LOCK() \
172 do { \
173 __s = _cpu_intr_suspend(); \
174 /* suspend any G2 DMA here... */ \
175 while ((*(__volatile uint32_t *)0xa05f688c) & 0x20) \
176 ; \
177 } while (/*CONSTCOND*/0)
178
179 #define G2_UNLOCK() \
180 do { \
181 /* resume any G2 DMA here... */ \
182 _cpu_intr_resume(__s); \
183 } while (/*CONSTCOND*/0)
184
185 uint8_t
186 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
187 {
188 G2LOCK_DECL;
189 uint8_t rv;
190
191 G2_LOCK();
192
193 rv = *(__volatile uint8_t *)(sh + off);
194
195 G2_UNLOCK();
196
197 return rv;
198 }
199
200 uint16_t
201 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
202 {
203 G2LOCK_DECL;
204 uint16_t rv;
205
206 G2_LOCK();
207
208 rv = *(__volatile uint16_t *)(sh + off);
209
210 G2_UNLOCK();
211
212 return rv;
213 }
214
215 uint32_t
216 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
217 {
218 G2LOCK_DECL;
219 uint32_t rv;
220
221 G2_LOCK();
222
223 rv = *(__volatile uint32_t *)(sh + off);
224
225 G2_UNLOCK();
226
227 return rv;
228 }
229
230 void
231 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
232 uint8_t val)
233 {
234 G2LOCK_DECL;
235
236 G2_LOCK();
237
238 *(__volatile uint8_t *)(sh + off) = val;
239
240 G2_UNLOCK();
241 }
242
243 void
244 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
245 uint16_t val)
246 {
247 G2LOCK_DECL;
248
249 G2_LOCK();
250
251 *(__volatile uint16_t *)(sh + off) = val;
252
253 G2_UNLOCK();
254 }
255
256 void
257 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
258 uint32_t val)
259 {
260 G2LOCK_DECL;
261
262 G2_LOCK();
263
264 *(__volatile uint32_t *)(sh + off) = val;
265
266 G2_UNLOCK();
267 }
268
269 void
270 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
271 uint8_t *addr, bus_size_t len)
272 {
273 G2LOCK_DECL;
274 __volatile const uint8_t *baddr = (uint8_t *)(sh + off);
275
276 G2_LOCK();
277
278 while (len--)
279 *addr++ = *baddr++;
280
281 G2_UNLOCK();
282 }
283
284 void
285 g2bus_bus_mem_read_region_2(void *v, bus_space_handle_t sh, bus_size_t off,
286 uint16_t *addr, bus_size_t len)
287 {
288 G2LOCK_DECL;
289 __volatile const uint16_t *baddr = (uint16_t *)(sh + off);
290
291 G2_LOCK();
292
293 while (len--)
294 *addr++ = *baddr++;
295
296 G2_UNLOCK();
297 }
298
299 void
300 g2bus_bus_mem_read_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
301 uint32_t *addr, bus_size_t len)
302 {
303 G2LOCK_DECL;
304 __volatile const uint32_t *baddr = (uint32_t *)(sh + off);
305
306 G2_LOCK();
307
308 while (len--)
309 *addr++ = *baddr++;
310
311 G2_UNLOCK();
312 }
313
314 void
315 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
316 const uint8_t *addr, bus_size_t len)
317 {
318 G2LOCK_DECL;
319 __volatile uint8_t *baddr = (uint8_t *)(sh + off);
320
321 G2_LOCK();
322
323 while (len--)
324 *baddr++ = *addr++;
325
326 G2_UNLOCK();
327 }
328
329 void
330 g2bus_bus_mem_write_region_2(void *v, bus_space_handle_t sh, bus_size_t off,
331 const uint16_t *addr, bus_size_t len)
332 {
333 G2LOCK_DECL;
334 __volatile uint16_t *baddr = (uint16_t *)(sh + off);
335
336 G2_LOCK();
337
338 while (len--)
339 *baddr++ = *addr++;
340
341 G2_UNLOCK();
342 }
343
344 void
345 g2bus_bus_mem_write_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
346 const uint32_t *addr, bus_size_t len)
347 {
348 G2LOCK_DECL;
349 __volatile uint32_t *baddr = (uint32_t *)(sh + off);
350
351 G2_LOCK();
352
353 while (len--)
354 *baddr++ = *addr++;
355
356 G2_UNLOCK();
357 }
358
359 void
360 g2bus_bus_mem_set_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
361 uint32_t val, bus_size_t len)
362 {
363 G2LOCK_DECL;
364 __volatile uint32_t *baddr = (uint32_t *)(sh + off);
365
366 G2_LOCK();
367
368 while (len--)
369 *baddr++ = val;
370
371 G2_UNLOCK();
372 }
373
374 void
375 g2bus_set_bus_mem_sparse(bus_space_tag_t memt)
376 {
377
378 memt->dbs_r_1 = g2bus_sparse_bus_mem_read_1;
379 memt->dbs_r_2 = g2bus_sparse_bus_mem_read_2;
380 memt->dbs_r_4 = g2bus_sparse_bus_mem_read_4;
381
382 memt->dbs_w_1 = g2bus_sparse_bus_mem_write_1;
383 memt->dbs_w_2 = g2bus_sparse_bus_mem_write_2;
384 memt->dbs_w_4 = g2bus_sparse_bus_mem_write_4;
385
386 memt->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1;
387
388 memt->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1;
389
390 memt->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1;
391
392 memt->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1;
393 }
394
395 uint8_t
396 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
397 {
398 G2LOCK_DECL;
399 uint8_t rv;
400
401 G2_LOCK();
402
403 rv = *(__volatile uint8_t *)(sh + (off * 4));
404
405 G2_UNLOCK();
406
407 return rv;
408 }
409
410 uint16_t
411 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
412 {
413 G2LOCK_DECL;
414 uint16_t rv;
415
416 G2_LOCK();
417
418 rv = *(__volatile uint16_t *)(sh + (off * 4));
419
420 G2_UNLOCK();
421
422 return rv;
423 }
424
425 uint32_t
426 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
427 {
428 G2LOCK_DECL;
429 uint32_t rv;
430
431 G2_LOCK();
432
433 rv = *(__volatile uint32_t *)(sh + (off * 4));
434
435 G2_UNLOCK();
436
437 return rv;
438 }
439
440 void
441 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
442 uint8_t val)
443 {
444 G2LOCK_DECL;
445
446 G2_LOCK();
447
448 *(__volatile uint8_t *)(sh + (off * 4)) = val;
449
450 G2_UNLOCK();
451 }
452
453 void
454 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
455 uint16_t val)
456 {
457 G2LOCK_DECL;
458
459 G2_LOCK();
460
461 *(__volatile uint16_t *)(sh + (off * 4)) = val;
462
463 G2_UNLOCK();
464 }
465
466 void
467 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
468 uint32_t val)
469 {
470 G2LOCK_DECL;
471
472 G2_LOCK();
473
474 *(__volatile uint32_t *)(sh + (off * 4)) = val;
475
476 G2_UNLOCK();
477 }
478
479 void
480 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
481 bus_size_t off, uint8_t *addr, bus_size_t len)
482 {
483 G2LOCK_DECL;
484 __volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4));
485
486 G2_LOCK();
487
488 while (len--) {
489 *addr++ = *baddr;
490 baddr += 4;
491 }
492
493 G2_UNLOCK();
494 }
495
496 void
497 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
498 bus_size_t off, const uint8_t *addr, bus_size_t len)
499 {
500 G2LOCK_DECL;
501 __volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4));
502
503 G2_LOCK();
504
505 while (len--) {
506 *baddr = *addr++;
507 baddr += 4;
508 }
509
510 G2_UNLOCK();
511 }
512
513 void
514 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
515 bus_size_t off, uint8_t *addr, bus_size_t len)
516 {
517 G2LOCK_DECL;
518 __volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4));
519
520 G2_LOCK();
521
522 while (len--)
523 *addr++ = *baddr;
524
525 G2_UNLOCK();
526 }
527
528 void
529 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
530 bus_size_t off, const uint8_t *addr, bus_size_t len)
531 {
532 G2LOCK_DECL;
533 __volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4));
534
535 G2_LOCK();
536
537 while (len--)
538 *baddr = *addr++;
539
540 G2_UNLOCK();
541 }
542