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