src/emu/machine/intelfsh.c
| r8142 | r8143 | |
| 39 | 39 | int bits; |
| 40 | 40 | int status; |
| 41 | 41 | int erase_sector; |
| 42 | int sector_is_4k; |
| 42 | 43 | INT32 flash_mode; |
| 43 | 44 | INT32 flash_master_lock; |
| 44 | 45 | int device_id; |
| r8142 | r8143 | |
| 89 | 90 | c = &chips[ chip ]; |
| 90 | 91 | |
| 91 | 92 | c->type = type; |
| 93 | c->sector_is_4k = 0; |
| 92 | 94 | switch( c->type ) |
| 93 | 95 | { |
| 94 | 96 | case FLASH_INTEL_28F016S5: |
| r8142 | r8143 | |
| 135 | 137 | c->maker_id = 0xc2; |
| 136 | 138 | c->device_id = 0x51; |
| 137 | 139 | break; |
| 140 | |
| 141 | case FLASH_PANASONIC_MN63F805MNP: |
| 142 | c->bits = 8; |
| 143 | c->size = 0x10000; |
| 144 | c->maker_id = 0x32; |
| 145 | c->device_id = 0x1b; |
| 146 | c->sector_is_4k = 1; |
| 147 | break; |
| 148 | |
| 149 | case FLASH_SANYO_LE26FV10N1TS: |
| 150 | c->bits = 8; |
| 151 | c->size = 0x20000; |
| 152 | c->maker_id = 0x62; |
| 153 | c->device_id = 0x13; |
| 154 | c->sector_is_4k = 1; |
| 155 | break; |
| 138 | 156 | } |
| 139 | 157 | if( data == NULL ) |
| 140 | 158 | { |
| r8142 | r8143 | |
| 248 | 266 | break; |
| 249 | 267 | } |
| 250 | 268 | |
| 251 | | // logerror( "%s: intelflash_read( %d, %08x ) %08x\n", cpuexec_describe_context(machine), chip, address, data ); |
| 269 | // logerror( "intelflash_read( %d, %08x ) %08x\n", chip, address, data ); |
| 252 | 270 | |
| 253 | 271 | return data; |
| 254 | 272 | } |
| r8142 | r8143 | |
| 263 | 281 | } |
| 264 | 282 | c = &chips[ chip ]; |
| 265 | 283 | |
| 266 | | // logerror( "%s: intelflash_write( %d, %08x, %08x )\n", cpuexec_describe_context(machine), chip, address, data ); |
| 284 | // logerror( "intelflash_write( %d, %08x, %08x )\n", chip, address, data ); |
| 267 | 285 | |
| 268 | 286 | switch( c->flash_mode ) |
| 269 | 287 | { |
| r8142 | r8143 | |
| 298 | 316 | c->flash_mode = FM_READSTATUS; |
| 299 | 317 | break; |
| 300 | 318 | case 0xaa: // AMD ID select part 1 |
| 301 | | if( ( address & 0xffff ) == 0x555 ) |
| 319 | if( ( address & 0xfff ) == 0x555 ) |
| 302 | 320 | { |
| 303 | 321 | c->flash_mode = FM_READAMDID1; |
| 304 | 322 | } |
| r8142 | r8143 | |
| 313 | 331 | { |
| 314 | 332 | c->flash_mode = FM_READAMDID2; |
| 315 | 333 | } |
| 334 | else if( ( address & 0xffff ) == 0x2aaa && ( data & 0xff ) == 0x55 ) |
| 335 | { |
| 336 | c->flash_mode = FM_READAMDID2; |
| 337 | } |
| 316 | 338 | else |
| 317 | 339 | { |
| 318 | 340 | logerror( "unexpected %08x=%02x in FM_READAMDID1\n", address, data & 0xff ); |
| r8142 | r8143 | |
| 324 | 346 | { |
| 325 | 347 | c->flash_mode = FM_READAMDID3; |
| 326 | 348 | } |
| 349 | else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0x90 ) |
| 350 | { |
| 351 | c->flash_mode = FM_READAMDID3; |
| 352 | } |
| 327 | 353 | else if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0x80 ) |
| 328 | 354 | { |
| 329 | 355 | c->flash_mode = FM_ERASEAMD1; |
| 330 | 356 | } |
| 357 | else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0x80 ) |
| 358 | { |
| 359 | c->flash_mode = FM_ERASEAMD1; |
| 360 | } |
| 331 | 361 | else if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0xa0 ) |
| 332 | 362 | { |
| 333 | 363 | c->flash_mode = FM_BYTEPROGRAM; |
| 334 | 364 | } |
| 365 | else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0xa0 ) |
| 366 | { |
| 367 | c->flash_mode = FM_BYTEPROGRAM; |
| 368 | } |
| 335 | 369 | else if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0xf0 ) |
| 336 | 370 | { |
| 337 | 371 | c->flash_mode = FM_NORMAL; |
| 338 | 372 | } |
| 373 | else if( ( address & 0xffff ) == 0x5555 && ( data & 0xff ) == 0xf0 ) |
| 374 | { |
| 375 | c->flash_mode = FM_NORMAL; |
| 376 | } |
| 339 | 377 | else |
| 340 | 378 | { |
| 341 | 379 | logerror( "unexpected %08x=%02x in FM_READAMDID2\n", address, data & 0xff ); |
| r8142 | r8143 | |
| 343 | 381 | } |
| 344 | 382 | break; |
| 345 | 383 | case FM_ERASEAMD1: |
| 346 | | if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0xaa ) |
| 384 | if( ( address & 0xfff ) == 0x555 && ( data & 0xff ) == 0xaa ) |
| 347 | 385 | { |
| 348 | 386 | c->flash_mode = FM_ERASEAMD2; |
| 349 | 387 | } |
| r8142 | r8143 | |
| 357 | 395 | { |
| 358 | 396 | c->flash_mode = FM_ERASEAMD3; |
| 359 | 397 | } |
| 398 | else if( ( address & 0xffff ) == 0x2aaa && ( data & 0xff ) == 0x55 ) |
| 399 | { |
| 400 | c->flash_mode = FM_ERASEAMD3; |
| 401 | } |
| 360 | 402 | else |
| 361 | 403 | { |
| 362 | 404 | logerror( "unexpected %08x=%02x in FM_ERASEAMD2\n", address, data & 0xff ); |
| 363 | 405 | } |
| 364 | 406 | break; |
| 365 | 407 | case FM_ERASEAMD3: |
| 366 | | if( ( address & 0xffff ) == 0x555 && ( data & 0xff ) == 0x10 ) |
| 408 | if( ( address & 0xfff ) == 0x555 && ( data & 0xff ) == 0x10 ) |
| 367 | 409 | { |
| 368 | 410 | // chip erase |
| 369 | 411 | memset( c->flash_memory, 0xff, c->size); |
| r8142 | r8143 | |
| 376 | 418 | else if( ( data & 0xff ) == 0x30 ) |
| 377 | 419 | { |
| 378 | 420 | // sector erase |
| 379 | | // clear the 64k block containing the current address to all 0xffs |
| 421 | // clear the 4k/64k block containing the current address to all 0xffs |
| 380 | 422 | switch( c->bits ) |
| 381 | 423 | { |
| 382 | 424 | case 8: |
| 383 | 425 | { |
| 384 | 426 | UINT8 *flash_memory = (UINT8 *)c->flash_memory; |
| 385 | | memset( &flash_memory[ address & ~0xffff ], 0xff, 64 * 1024 ); |
| 386 | | c->erase_sector = address & ~0xffff; |
| 427 | if (c->sector_is_4k) |
| 428 | { |
| 429 | memset( &flash_memory[ address & ~0xfff ], 0xff, 4 * 1024 ); |
| 430 | c->erase_sector = address & ~0xfff; |
| 431 | } |
| 432 | else |
| 433 | { |
| 434 | memset( &flash_memory[ address & ~0xffff ], 0xff, 64 * 1024 ); |
| 435 | c->erase_sector = address & ~0xffff; |
| 436 | } |
| 387 | 437 | } |
| 388 | 438 | break; |
| 389 | 439 | case 16: |
| 390 | 440 | { |
| 391 | 441 | UINT16 *flash_memory = (UINT16 *)c->flash_memory; |
| 392 | | memset( &flash_memory[ address & ~0x7fff ], 0xff, 64 * 1024 ); |
| 393 | | c->erase_sector = address & ~0x7fff; |
| 442 | if (c->sector_is_4k) |
| 443 | { |
| 444 | memset( &flash_memory[ address & ~0x7ff ], 0xff, 4 * 1024 ); |
| 445 | c->erase_sector = address & ~0x7ff; |
| 446 | } |
| 447 | else |
| 448 | { |
| 449 | memset( &flash_memory[ address & ~0x7fff ], 0xff, 64 * 1024 ); |
| 450 | c->erase_sector = address & ~0x7fff; |
| 451 | } |
| 394 | 452 | } |
| 395 | 453 | break; |
| 396 | 454 | } |
src/mess/drivers/gba.c
| r8142 | r8143 | |
| 23 | 23 | #include "includes/gba.h" |
| 24 | 24 | #include "includes/gb.h" |
| 25 | 25 | #include "sound/dac.h" |
| 26 | #include "machine/intelfsh.h" |
| 26 | 27 | |
| 27 | | #define VERBOSE_LEVEL (2) |
| 28 | #define VERBOSE_LEVEL (0) |
| 28 | 29 | |
| 29 | 30 | INLINE void verboselog(running_machine *machine, int n_level, const char *s_fmt, ...) |
| 30 | 31 | { |
| r8142 | r8143 | |
| 2010 | 2011 | |
| 2011 | 2012 | memset(state, 0, sizeof(state)); |
| 2012 | 2013 | state->SOUNDBIAS = 0x0200; |
| 2013 | | state->flash_state = FLASH_IDLEBYTE0; |
| 2014 | 2014 | state->eeprom_state = EEP_IDLE; |
| 2015 | 2015 | state->SIOMULTI0 = 0xffff; |
| 2016 | 2016 | state->SIOMULTI1 = 0xffff; |
| r8142 | r8143 | |
| 2107 | 2107 | COMBINE_DATA(&state->gba_sram[offset]); |
| 2108 | 2108 | } |
| 2109 | 2109 | |
| 2110 | | /*static const char *flash_states[] = |
| 2111 | | { |
| 2112 | | "IDLEBYTE0", "IDLEBYTE1", "IDLEBYTE2", "IDENT", |
| 2113 | | "ERASEBYTE0", "ERASEBYTE1", "ERASEBYTE2", "ERASE_ALL", "ERASE_4K", "WRITE" |
| 2114 | | };*/ |
| 2115 | | |
| 2116 | 2110 | static READ32_HANDLER( flash_r ) |
| 2117 | 2111 | { |
| 2118 | | UINT32 rv; |
| 2119 | | |
| 2120 | 2112 | gba_state *state = (gba_state *)space->machine->driver_data; |
| 2113 | UINT32 rv; |
| 2121 | 2114 | |
| 2122 | | switch (state->flash_state) |
| 2123 | | { |
| 2124 | | case FLASH_IDENT: |
| 2125 | | if (offset == 0) |
| 2126 | | rv = (state->gba_flash[0] & 0xffff0000) | state->flash_id; |
| 2127 | | else |
| 2128 | | rv = state->gba_flash[offset]; |
| 2129 | | break; |
| 2115 | rv = 0; |
| 2116 | offset &= state->flash_mask; |
| 2117 | if (mem_mask & 0xff) rv |= intelflash_read(0, offset*4); |
| 2118 | if (mem_mask & 0xff00) rv |= intelflash_read(0, (offset*4)+1)<<8; |
| 2119 | if (mem_mask & 0xff0000) rv |= intelflash_read(0, (offset*4)+2)<<16; |
| 2120 | if (mem_mask & 0xff000000) rv |= intelflash_read(0, (offset*4)+3)<<24; |
| 2130 | 2121 | |
| 2131 | | default: |
| 2132 | | rv = state->gba_flash[offset]; |
| 2133 | | break; |
| 2134 | | } |
| 2135 | | |
| 2136 | | // printf("flash_r: @ %x (mask %x) (state %s) (PC=%x) = %x\n", offset, mem_mask, flash_states[state->flash_state], cpu_get_pc(space->cpu), rv&mem_mask); |
| 2137 | | |
| 2138 | 2122 | return rv; |
| 2139 | 2123 | } |
| 2140 | 2124 | |
| r8142 | r8143 | |
| 2142 | 2126 | { |
| 2143 | 2127 | gba_state *state = (gba_state *)space->machine->driver_data; |
| 2144 | 2128 | |
| 2145 | | // printf("flash_w: %x @ %x (mask %x) (state=%s) (PC=%x)\n", data, offset, mem_mask, flash_states[state->flash_state], cpu_get_pc(space->cpu)); |
| 2146 | | |
| 2147 | | switch (state->flash_state) |
| 2129 | offset &= state->flash_mask; |
| 2130 | switch (mem_mask) |
| 2148 | 2131 | { |
| 2149 | | case FLASH_IDLEBYTE0: |
| 2150 | | case FLASH_ERASEBYTE0: |
| 2151 | | if (offset == 0x5555/4 && mem_mask == 0xff00) |
| 2152 | | { |
| 2153 | | if ((data & mem_mask) == 0x0000aa00) |
| 2154 | | { |
| 2155 | | if (state->flash_state == FLASH_ERASEBYTE0) |
| 2156 | | { |
| 2157 | | state->flash_state = FLASH_ERASEBYTE1; |
| 2158 | | } |
| 2159 | | else |
| 2160 | | { |
| 2161 | | state->flash_state = FLASH_IDLEBYTE1; |
| 2162 | | } |
| 2163 | | } |
| 2164 | | } |
| 2132 | case 0xff: |
| 2133 | intelflash_write(0, offset*4, data&0xff); |
| 2165 | 2134 | break; |
| 2166 | | case FLASH_IDLEBYTE1: |
| 2167 | | case FLASH_ERASEBYTE1: |
| 2168 | | if (offset == 0x2aaa/4 && mem_mask == 0xff0000) |
| 2169 | | { |
| 2170 | | if ((data & mem_mask) == 0x00550000) |
| 2171 | | { |
| 2172 | | if (state->flash_state == FLASH_IDLEBYTE1) |
| 2173 | | state->flash_state = FLASH_IDLEBYTE2; |
| 2174 | | else if (state->flash_state == FLASH_ERASEBYTE1) |
| 2175 | | state->flash_state = FLASH_ERASEBYTE2; |
| 2176 | | } |
| 2177 | | } |
| 2135 | case 0xff00: |
| 2136 | intelflash_write(0, (offset*4)+1, (data>>8)&0xff); |
| 2178 | 2137 | break; |
| 2179 | | case FLASH_IDLEBYTE2: |
| 2180 | | case FLASH_ERASEBYTE2: |
| 2181 | | if (offset == 0x5555/4 && mem_mask == 0xff00) |
| 2182 | | { |
| 2183 | | if (state->flash_state == FLASH_IDLEBYTE2) |
| 2184 | | { |
| 2185 | | switch ((data & mem_mask) >> 8) |
| 2186 | | { |
| 2187 | | case 0x80: |
| 2188 | | state->flash_state = FLASH_ERASEBYTE0; |
| 2189 | | break; |
| 2190 | | case 0x90: |
| 2191 | | state->flash_state = FLASH_IDENT; |
| 2192 | | break; |
| 2193 | | case 0xa0: |
| 2194 | | state->flash_state = FLASH_WRITE; |
| 2195 | | break; |
| 2196 | | } |
| 2197 | | } |
| 2198 | | else if (state->flash_state == FLASH_ERASEBYTE2) |
| 2199 | | { |
| 2200 | | if ((data & mem_mask) == 0x00001000) |
| 2201 | | { |
| 2202 | | UINT32 flashWord; |
| 2203 | | for (flashWord = 0; flashWord < state->flash_size/4; flashWord++) |
| 2204 | | { |
| 2205 | | state->gba_flash[flashWord] = 0xffffffff; |
| 2206 | | } |
| 2207 | | state->flash_state = FLASH_ERASE_ALL; |
| 2208 | | } |
| 2209 | | } |
| 2210 | | } |
| 2211 | | else if ((offset & 0xffffc3ff) == 0 && (data & mem_mask) == 0x00000030) |
| 2212 | | { |
| 2213 | | UINT32 flashWord; |
| 2214 | | state->flash_page = offset >> 10; |
| 2215 | | for (flashWord = offset; flashWord < offset + 0x1000/4; flashWord++) |
| 2216 | | { |
| 2217 | | state->gba_flash[flashWord] = 0xffffffff; |
| 2218 | | } |
| 2219 | | state->flash_state = FLASH_ERASE_4K; |
| 2220 | | } |
| 2138 | case 0xff0000: |
| 2139 | intelflash_write(0, (offset*4)+2, (data>>16)&0xff); |
| 2221 | 2140 | break; |
| 2222 | | case FLASH_IDENT: |
| 2223 | | // Hack; any sensibly-written game should follow up with the relevant read, which will reset the state to FLASH_IDLEBYTE0. |
| 2224 | | state->flash_state = FLASH_IDLEBYTE0; |
| 2225 | | flash_w(space, offset, data, mem_mask); |
| 2141 | case 0xff000000: |
| 2142 | intelflash_write(0, (offset*4)+3, (data>>24)&0xff); |
| 2226 | 2143 | break; |
| 2227 | | case FLASH_ERASE_4K: |
| 2228 | | // Hack; any sensibly-written game should follow up with the relevant read, which will reset the state to FLASH_IDLEBYTE0. |
| 2229 | | state->flash_state = FLASH_IDLEBYTE0; |
| 2230 | | flash_w(space, offset, data, mem_mask); |
| 2144 | default: |
| 2145 | fatalerror("Unknown mem_mask for GBA flash_w %x\n", mem_mask); |
| 2231 | 2146 | break; |
| 2232 | | case FLASH_ERASE_ALL: |
| 2233 | | // Hack; any sensibly-written game should follow up with the relevant read, which will reset the state to FLASH_IDLEBYTE0. |
| 2234 | | state->flash_state = FLASH_IDLEBYTE0; |
| 2235 | | flash_w(space, offset, data, mem_mask); |
| 2236 | | break; |
| 2237 | | case FLASH_WRITE: |
| 2238 | | COMBINE_DATA(&state->gba_flash[offset]); |
| 2239 | | state->flash_state = FLASH_IDLEBYTE0; |
| 2240 | | break; |
| 2241 | 2147 | } |
| 2242 | 2148 | } |
| 2243 | 2149 | |
| r8142 | r8143 | |
| 2393 | 2299 | gba_state *state = (gba_state *)image->machine->driver_data; |
| 2394 | 2300 | |
| 2395 | 2301 | state->nvsize = 0; |
| 2302 | state->flash_size = 0; |
| 2396 | 2303 | state->nvptr = (UINT8 *)NULL; |
| 2397 | 2304 | |
| 2398 | 2305 | if (image_software_entry(image) == NULL) |
| r8142 | r8143 | |
| 2439 | 2346 | state->nvptr = (UINT8 *)&state->gba_flash; |
| 2440 | 2347 | state->nvsize = 0x20000; |
| 2441 | 2348 | state->flash_size = 0x20000; |
| 2442 | | state->flash_id = 0x1362; |
| 2349 | state->flash_mask = 0x1ffff/4; |
| 2443 | 2350 | |
| 2444 | 2351 | memory_install_read32_handler(cpu_get_address_space(devtag_get_device(image->machine, "maincpu"), ADDRESS_SPACE_PROGRAM), 0xe000000, 0xe01ffff, 0, 0, flash_r); |
| 2445 | 2352 | memory_install_write32_handler(cpu_get_address_space(devtag_get_device(image->machine, "maincpu"), ADDRESS_SPACE_PROGRAM), 0xe000000, 0xe01ffff, 0, 0, flash_w); |
| r8142 | r8143 | |
| 2450 | 2357 | state->nvptr = (UINT8 *)&state->gba_flash; |
| 2451 | 2358 | state->nvsize = 0x10000; |
| 2452 | 2359 | state->flash_size = 0x10000; |
| 2453 | | state->flash_id = 0x1b32; |
| 2360 | state->flash_mask = 0xffff/4; |
| 2454 | 2361 | |
| 2455 | | memory_install_read32_handler(cpu_get_address_space(devtag_get_device(image->machine, "maincpu"), ADDRESS_SPACE_PROGRAM), 0xe000000, 0xe007fff, 0, 0, flash_r); |
| 2456 | | memory_install_write32_handler(cpu_get_address_space(devtag_get_device(image->machine, "maincpu"), ADDRESS_SPACE_PROGRAM), 0xe000000, 0xe007fff, 0, 0, flash_w); |
| 2362 | memory_install_read32_handler(cpu_get_address_space(devtag_get_device(image->machine, "maincpu"), ADDRESS_SPACE_PROGRAM), 0xe000000, 0xe00ffff, 0, 0, flash_r); |
| 2363 | memory_install_write32_handler(cpu_get_address_space(devtag_get_device(image->machine, "maincpu"), ADDRESS_SPACE_PROGRAM), 0xe000000, 0xe00ffff, 0, 0, flash_w); |
| 2457 | 2364 | break; |
| 2458 | 2365 | } |
| 2459 | 2366 | else if (!memcmp(&ROM[i], "SIIRTC_V", 8)) |
| r8142 | r8143 | |
| 2475 | 2382 | state->nvsize = 0; |
| 2476 | 2383 | } |
| 2477 | 2384 | |
| 2385 | // init the flash here so it gets the contents from the battery_load above |
| 2386 | if (state->flash_size > 0) |
| 2387 | { |
| 2388 | if (state->flash_size == 0x10000) |
| 2389 | { |
| 2390 | intelflash_init(image->machine, 0, FLASH_PANASONIC_MN63F805MNP, &state->gba_flash); |
| 2391 | } |
| 2392 | else |
| 2393 | { |
| 2394 | intelflash_init(image->machine, 0, FLASH_SANYO_LE26FV10N1TS, &state->gba_flash); |
| 2395 | } |
| 2396 | } |
| 2397 | |
| 2478 | 2398 | // mirror the ROM |
| 2479 | 2399 | switch (cart_size) |
| 2480 | 2400 | { |