Home | History | Annotate | Line # | Download | only in g2
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