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