1 /* $NetBSD: g2bus_bus_mem.c,v 1.16 2011/07/19 15:52:29 dyoung 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 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Bus space implementation for the SEGA G2 bus.
34 *
35 * NOTE: We only implement a small subset of what the bus_space(9)
36 * API specifies. Right now, the GAPS PCI bridge is only used for
37 * the Dreamcast Broadband Adatper, so we only provide what the
38 * pci(4) and rtk(4) drivers need.
39 */
40
41 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
42 __KERNEL_RCSID(0, "$NetBSD: g2bus_bus_mem.c,v 1.16 2011/07/19 15:52:29 dyoung Exp $");
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/device.h>
47 #include <sys/bus.h>
48
49 #include <machine/cpu.h>
50
51 #include <dreamcast/dev/g2/g2busvar.h>
52
53 int g2bus_bus_mem_map(void *, bus_addr_t, bus_size_t, int,
54 bus_space_handle_t *);
55 void g2bus_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t);
56 paddr_t g2bus_bus_mem_mmap(void *, bus_addr_t, off_t, int, int);
57
58 uint8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
59 uint16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
60 uint32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
61
62 void g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
63 uint8_t);
64 void g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
65 uint16_t);
66 void g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
67 uint32_t);
68
69 void g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t,
70 uint8_t *, bus_size_t);
71 void g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t,
72 uint16_t *, bus_size_t);
73 void g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t,
74 uint32_t *, bus_size_t);
75
76 void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t,
77 const uint8_t *, bus_size_t);
78 void g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t,
79 const uint16_t *, bus_size_t);
80 void g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t,
81 const uint32_t *, bus_size_t);
82
83 void g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t,
84 uint32_t, bus_size_t);
85
86 uint8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
87 uint16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
88 uint32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
89
90 void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
91 uint8_t);
92 void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
93 uint16_t);
94 void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
95 uint32_t);
96
97 void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t,
98 bus_size_t, uint8_t *, bus_size_t);
99
100 void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t,
101 bus_size_t, const uint8_t *, bus_size_t);
102
103 void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t,
104 bus_size_t, uint8_t *, bus_size_t);
105
106 void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t,
107 bus_size_t, const uint8_t *, bus_size_t);
108
109 void
110 g2bus_bus_mem_init(struct g2bus_softc *sc)
111 {
112 bus_space_tag_t t = &sc->sc_memt;
113
114 memset(t, 0, sizeof(*t));
115
116 t->dbs_map = g2bus_bus_mem_map;
117 t->dbs_unmap = g2bus_bus_mem_unmap;
118 t->dbs_mmap = g2bus_bus_mem_mmap;
119
120 t->dbs_r_1 = g2bus_bus_mem_read_1;
121 t->dbs_r_2 = g2bus_bus_mem_read_2;
122 t->dbs_r_4 = g2bus_bus_mem_read_4;
123
124 t->dbs_w_1 = g2bus_bus_mem_write_1;
125 t->dbs_w_2 = g2bus_bus_mem_write_2;
126 t->dbs_w_4 = g2bus_bus_mem_write_4;
127
128 t->dbs_rr_1 = g2bus_bus_mem_read_region_1;
129 t->dbs_rr_2 = g2bus_bus_mem_read_region_2;
130 t->dbs_rr_4 = g2bus_bus_mem_read_region_4;
131
132 t->dbs_wr_1 = g2bus_bus_mem_write_region_1;
133 t->dbs_wr_2 = g2bus_bus_mem_write_region_2;
134 t->dbs_wr_4 = g2bus_bus_mem_write_region_4;
135
136 t->dbs_sr_4 = g2bus_bus_mem_set_region_4;
137 }
138
139 int
140 g2bus_bus_mem_map(void *v, bus_addr_t addr, bus_size_t size, int flags,
141 bus_space_handle_t *shp)
142 {
143
144 KASSERT((addr & SH3_PHYS_MASK) == addr);
145 *shp = SH3_PHYS_TO_P2SEG(addr);
146
147 return 0;
148 }
149
150 void
151 g2bus_bus_mem_unmap(void *v, bus_space_handle_t sh, bus_size_t size)
152 {
153
154 KASSERT(sh >= SH3_P2SEG_BASE && sh <= SH3_P2SEG_END);
155 /* Nothing to do. */
156 }
157
158 paddr_t
159 g2bus_bus_mem_mmap(void *v, bus_addr_t addr, off_t offset, int prot, int flags)
160 {
161
162 /* XXX not implemented */
163 return -1;
164 }
165
166 /*
167 * G2 bus cycles must not be interrupted by IRQs or G2 DMA.
168 * The following paired macros will take the necessary precautions.
169 */
170
171 #define G2LOCK_DECL \
172 int __s
173
174 #define G2_LOCK() \
175 do { \
176 __s = _cpu_intr_suspend(); \
177 /* suspend any G2 DMA here... */ \
178 while ((*(volatile uint32_t *)0xa05f688c) & 0x20) \
179 ; \
180 } while (/*CONSTCOND*/0)
181
182 #define G2_UNLOCK() \
183 do { \
184 /* resume any G2 DMA here... */ \
185 _cpu_intr_resume(__s); \
186 } while (/*CONSTCOND*/0)
187
188 uint8_t
189 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
190 {
191 G2LOCK_DECL;
192 uint8_t rv;
193
194 G2_LOCK();
195
196 rv = *(volatile uint8_t *)(sh + off);
197
198 G2_UNLOCK();
199
200 return rv;
201 }
202
203 uint16_t
204 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
205 {
206 G2LOCK_DECL;
207 uint16_t rv;
208
209 G2_LOCK();
210
211 rv = *(volatile uint16_t *)(sh + off);
212
213 G2_UNLOCK();
214
215 return rv;
216 }
217
218 uint32_t
219 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
220 {
221 G2LOCK_DECL;
222 uint32_t rv;
223
224 G2_LOCK();
225
226 rv = *(volatile uint32_t *)(sh + off);
227
228 G2_UNLOCK();
229
230 return rv;
231 }
232
233 void
234 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
235 uint8_t val)
236 {
237 G2LOCK_DECL;
238
239 G2_LOCK();
240
241 *(volatile uint8_t *)(sh + off) = val;
242
243 G2_UNLOCK();
244 }
245
246 void
247 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
248 uint16_t val)
249 {
250 G2LOCK_DECL;
251
252 G2_LOCK();
253
254 *(volatile uint16_t *)(sh + off) = val;
255
256 G2_UNLOCK();
257 }
258
259 void
260 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
261 uint32_t val)
262 {
263 G2LOCK_DECL;
264
265 G2_LOCK();
266
267 *(volatile uint32_t *)(sh + off) = val;
268
269 G2_UNLOCK();
270 }
271
272 void
273 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
274 uint8_t *addr, bus_size_t len)
275 {
276 G2LOCK_DECL;
277 volatile const uint8_t *baddr = (uint8_t *)(sh + off);
278
279 G2_LOCK();
280
281 while (len--)
282 *addr++ = *baddr++;
283
284 G2_UNLOCK();
285 }
286
287 void
288 g2bus_bus_mem_read_region_2(void *v, bus_space_handle_t sh, bus_size_t off,
289 uint16_t *addr, bus_size_t len)
290 {
291 G2LOCK_DECL;
292 volatile const uint16_t *baddr = (uint16_t *)(sh + off);
293
294 G2_LOCK();
295
296 while (len--)
297 *addr++ = *baddr++;
298
299 G2_UNLOCK();
300 }
301
302 void
303 g2bus_bus_mem_read_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
304 uint32_t *addr, bus_size_t len)
305 {
306 G2LOCK_DECL;
307 volatile const uint32_t *baddr = (uint32_t *)(sh + off);
308
309 G2_LOCK();
310
311 while (len--)
312 *addr++ = *baddr++;
313
314 G2_UNLOCK();
315 }
316
317 void
318 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
319 const uint8_t *addr, bus_size_t len)
320 {
321 G2LOCK_DECL;
322 volatile uint8_t *baddr = (uint8_t *)(sh + off);
323
324 G2_LOCK();
325
326 while (len--)
327 *baddr++ = *addr++;
328
329 G2_UNLOCK();
330 }
331
332 void
333 g2bus_bus_mem_write_region_2(void *v, bus_space_handle_t sh, bus_size_t off,
334 const uint16_t *addr, bus_size_t len)
335 {
336 G2LOCK_DECL;
337 volatile uint16_t *baddr = (uint16_t *)(sh + off);
338
339 G2_LOCK();
340
341 while (len--)
342 *baddr++ = *addr++;
343
344 G2_UNLOCK();
345 }
346
347 void
348 g2bus_bus_mem_write_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
349 const uint32_t *addr, bus_size_t len)
350 {
351 G2LOCK_DECL;
352 volatile uint32_t *baddr = (uint32_t *)(sh + off);
353
354 G2_LOCK();
355
356 while (len--)
357 *baddr++ = *addr++;
358
359 G2_UNLOCK();
360 }
361
362 void
363 g2bus_bus_mem_set_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
364 uint32_t val, bus_size_t len)
365 {
366 G2LOCK_DECL;
367 volatile uint32_t *baddr = (uint32_t *)(sh + off);
368
369 G2_LOCK();
370
371 while (len--)
372 *baddr++ = val;
373
374 G2_UNLOCK();
375 }
376
377 void
378 g2bus_set_bus_mem_sparse(bus_space_tag_t memt)
379 {
380
381 memt->dbs_r_1 = g2bus_sparse_bus_mem_read_1;
382 memt->dbs_r_2 = g2bus_sparse_bus_mem_read_2;
383 memt->dbs_r_4 = g2bus_sparse_bus_mem_read_4;
384
385 memt->dbs_w_1 = g2bus_sparse_bus_mem_write_1;
386 memt->dbs_w_2 = g2bus_sparse_bus_mem_write_2;
387 memt->dbs_w_4 = g2bus_sparse_bus_mem_write_4;
388
389 memt->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1;
390
391 memt->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1;
392
393 memt->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1;
394
395 memt->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1;
396 }
397
398 uint8_t
399 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
400 {
401 G2LOCK_DECL;
402 uint8_t rv;
403
404 G2_LOCK();
405
406 rv = *(volatile uint8_t *)(sh + (off * 4));
407
408 G2_UNLOCK();
409
410 return rv;
411 }
412
413 uint16_t
414 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
415 {
416 G2LOCK_DECL;
417 uint16_t rv;
418
419 G2_LOCK();
420
421 rv = *(volatile uint16_t *)(sh + (off * 4));
422
423 G2_UNLOCK();
424
425 return rv;
426 }
427
428 uint32_t
429 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
430 {
431 G2LOCK_DECL;
432 uint32_t rv;
433
434 G2_LOCK();
435
436 rv = *(volatile uint32_t *)(sh + (off * 4));
437
438 G2_UNLOCK();
439
440 return rv;
441 }
442
443 void
444 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
445 uint8_t val)
446 {
447 G2LOCK_DECL;
448
449 G2_LOCK();
450
451 *(volatile uint8_t *)(sh + (off * 4)) = val;
452
453 G2_UNLOCK();
454 }
455
456 void
457 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
458 uint16_t val)
459 {
460 G2LOCK_DECL;
461
462 G2_LOCK();
463
464 *(volatile uint16_t *)(sh + (off * 4)) = val;
465
466 G2_UNLOCK();
467 }
468
469 void
470 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
471 uint32_t val)
472 {
473 G2LOCK_DECL;
474
475 G2_LOCK();
476
477 *(volatile uint32_t *)(sh + (off * 4)) = val;
478
479 G2_UNLOCK();
480 }
481
482 void
483 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
484 bus_size_t off, uint8_t *addr, bus_size_t len)
485 {
486 G2LOCK_DECL;
487 volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4));
488
489 G2_LOCK();
490
491 while (len--) {
492 *addr++ = *baddr;
493 baddr += 4;
494 }
495
496 G2_UNLOCK();
497 }
498
499 void
500 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
501 bus_size_t off, const uint8_t *addr, bus_size_t len)
502 {
503 G2LOCK_DECL;
504 volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4));
505
506 G2_LOCK();
507
508 while (len--) {
509 *baddr = *addr++;
510 baddr += 4;
511 }
512
513 G2_UNLOCK();
514 }
515
516 void
517 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
518 bus_size_t off, uint8_t *addr, bus_size_t len)
519 {
520 G2LOCK_DECL;
521 volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4));
522
523 G2_LOCK();
524
525 while (len--)
526 *addr++ = *baddr;
527
528 G2_UNLOCK();
529 }
530
531 void
532 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
533 bus_size_t off, const uint8_t *addr, bus_size_t len)
534 {
535 G2LOCK_DECL;
536 volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4));
537
538 G2_LOCK();
539
540 while (len--)
541 *baddr = *addr++;
542
543 G2_UNLOCK();
544 }
Cache object: 1ec805e9acb6c19834715023fa895dd6
|