Home | History | Annotate | Line # | Download | only in g2
g2bus_bus_mem.c revision 1.7
      1 /*	$NetBSD: g2bus_bus_mem.c,v 1.7 2003/03/02 04:23:16 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 
     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 G2LOCK_DECL							\
    151 	int __s
    152 
    153 #define G2_LOCK()							\
    154 	do {								\
    155 		__s = _cpu_intr_suspend();				\
    156 		/* suspend any G2 DMA here... */			\
    157 		while ((*(__volatile u_int32_t *)0xa05f688c) & 0x20)	\
    158 			;						\
    159 	} while (/*CONSTCOND*/0)
    160 
    161 #define G2_UNLOCK()							\
    162 	do {								\
    163 		/* resume any G2 DMA here... */				\
    164 		_cpu_intr_resume(__s);					\
    165 	} while (/*CONSTCOND*/0)
    166 
    167 u_int8_t
    168 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
    169 {
    170 	G2LOCK_DECL;
    171 	u_int8_t rv;
    172 
    173 	G2_LOCK();
    174 
    175 	rv = *(__volatile u_int8_t *)(sh + off);
    176 
    177 	G2_UNLOCK();
    178 
    179 	return (rv);
    180 }
    181 
    182 u_int16_t
    183 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
    184 {
    185 	G2LOCK_DECL;
    186 	u_int16_t rv;
    187 
    188 	G2_LOCK();
    189 
    190 	rv = *(__volatile u_int16_t *)(sh + off);
    191 
    192 	G2_UNLOCK();
    193 
    194 	return (rv);
    195 }
    196 
    197 u_int32_t
    198 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
    199 {
    200 	G2LOCK_DECL;
    201 	u_int32_t rv;
    202 
    203 	G2_LOCK();
    204 
    205 	rv = *(__volatile u_int32_t *)(sh + off);
    206 
    207 	G2_UNLOCK();
    208 
    209 	return (rv);
    210 }
    211 
    212 void
    213 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
    214     u_int8_t val)
    215 {
    216 	G2LOCK_DECL;
    217 
    218 	G2_LOCK();
    219 
    220 	*(__volatile u_int8_t *)(sh + off) = val;
    221 
    222 	G2_UNLOCK();
    223 }
    224 
    225 void
    226 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
    227     u_int16_t val)
    228 {
    229 	G2LOCK_DECL;
    230 
    231 	G2_LOCK();
    232 
    233 	*(__volatile u_int16_t *)(sh + off) = val;
    234 
    235 	G2_UNLOCK();
    236 }
    237 
    238 void
    239 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
    240     u_int32_t val)
    241 {
    242 	G2LOCK_DECL;
    243 
    244 	G2_LOCK();
    245 
    246 	*(__volatile u_int32_t *)(sh + off) = val;
    247 
    248 	G2_UNLOCK();
    249 }
    250 
    251 void
    252 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
    253     u_int8_t *addr, bus_size_t len)
    254 {
    255 	G2LOCK_DECL;
    256 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + off);
    257 
    258 	G2_LOCK();
    259 
    260 	while (len--)
    261 		*addr++ = *baddr++;
    262 
    263 	G2_UNLOCK();
    264 }
    265 
    266 void
    267 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
    268     const u_int8_t *addr, bus_size_t len)
    269 {
    270 	G2LOCK_DECL;
    271 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + off);
    272 
    273 	G2_LOCK();
    274 
    275 	while (len--)
    276 		*baddr++ = *addr++;
    277 
    278 	G2_UNLOCK();
    279 }
    280 
    281 void
    282 g2bus_set_bus_mem_sparse(bus_space_tag_t memt)
    283 {
    284 
    285 	memt->dbs_r_1 = g2bus_sparse_bus_mem_read_1;
    286 	memt->dbs_r_2 = g2bus_sparse_bus_mem_read_2;
    287 	memt->dbs_r_4 = g2bus_sparse_bus_mem_read_4;
    288 
    289 	memt->dbs_w_1 = g2bus_sparse_bus_mem_write_1;
    290 	memt->dbs_w_2 = g2bus_sparse_bus_mem_write_2;
    291 	memt->dbs_w_4 = g2bus_sparse_bus_mem_write_4;
    292 
    293 	memt->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1;
    294 
    295 	memt->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1;
    296 
    297 	memt->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1;
    298 
    299 	memt->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1;
    300 }
    301 
    302 u_int8_t
    303 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
    304 {
    305 	G2LOCK_DECL;
    306 	u_int8_t rv;
    307 
    308 	G2_LOCK();
    309 
    310 	rv = *(__volatile u_int8_t *)(sh + (off * 4));
    311 
    312 	G2_UNLOCK();
    313 
    314 	return (rv);
    315 }
    316 
    317 u_int16_t
    318 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
    319 {
    320 	G2LOCK_DECL;
    321 	u_int16_t rv;
    322 
    323 	G2_LOCK();
    324 
    325 	rv = *(__volatile u_int16_t *)(sh + (off * 4));
    326 
    327 	G2_UNLOCK();
    328 
    329 	return (rv);
    330 }
    331 
    332 u_int32_t
    333 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
    334 {
    335 	G2LOCK_DECL;
    336 	u_int32_t rv;
    337 
    338 	G2_LOCK();
    339 
    340 	rv = *(__volatile u_int32_t *)(sh + (off * 4));
    341 
    342 	G2_UNLOCK();
    343 
    344 	return (rv);
    345 }
    346 
    347 void
    348 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
    349     u_int8_t val)
    350 {
    351 	G2LOCK_DECL;
    352 
    353 	G2_LOCK();
    354 
    355 	*(__volatile u_int8_t *)(sh + (off * 4)) = val;
    356 
    357 	G2_UNLOCK();
    358 }
    359 
    360 void
    361 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
    362     u_int16_t val)
    363 {
    364 	G2LOCK_DECL;
    365 
    366 	G2_LOCK();
    367 
    368 	*(__volatile u_int16_t *)(sh + (off * 4)) = val;
    369 
    370 	G2_UNLOCK();
    371 }
    372 
    373 void
    374 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
    375     u_int32_t val)
    376 {
    377 	G2LOCK_DECL;
    378 
    379 	G2_LOCK();
    380 
    381 	*(__volatile u_int32_t *)(sh + (off * 4)) = val;
    382 
    383 	G2_UNLOCK();
    384 }
    385 
    386 void
    387 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
    388     bus_size_t off, u_int8_t *addr, bus_size_t len)
    389 {
    390 	G2LOCK_DECL;
    391 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
    392 
    393 	G2_LOCK();
    394 
    395 	while (len--) {
    396 		*addr++ = *baddr;
    397 		baddr += 4;
    398 	}
    399 
    400 	G2_UNLOCK();
    401 }
    402 
    403 void
    404 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
    405     bus_size_t off, const u_int8_t *addr, bus_size_t len)
    406 {
    407 	G2LOCK_DECL;
    408 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
    409 
    410 	G2_LOCK();
    411 
    412 	while (len--) {
    413 		*baddr = *addr++;
    414 		baddr += 4;
    415 	}
    416 
    417 	G2_UNLOCK();
    418 }
    419 
    420 void
    421 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
    422     bus_size_t off, u_int8_t *addr, bus_size_t len)
    423 {
    424 	G2LOCK_DECL;
    425 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
    426 
    427 	G2_LOCK();
    428 
    429 	while (len--)
    430 		*addr++ = *baddr;
    431 
    432 	G2_UNLOCK();
    433 }
    434 
    435 void
    436 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
    437     bus_size_t off, const u_int8_t *addr, bus_size_t len)
    438 {
    439 	G2LOCK_DECL;
    440 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
    441 
    442 	G2_LOCK();
    443 
    444 	while (len--)
    445 		*baddr = *addr++;
    446 
    447 	G2_UNLOCK();
    448 }
    449