trunk/src/mame/drivers/nexus3d.c
| r23602 | r23603 | |
| 14 | 14 | #include "emu.h" |
| 15 | 15 | #include "cpu/arm7/arm7.h" |
| 16 | 16 | #include "cpu/arm7/arm7core.h" |
| 17 | #include "machine/serflash.h" |
| 18 | |
| 17 | 19 | //#include "machine/i2cmem.h" |
| 18 | 20 | |
| 19 | 21 | |
| 20 | | #define FLASH_PAGE_SIZE (2048+64) |
| 21 | 22 | |
| 22 | 23 | class nexus3d_state : public driver_device |
| 23 | 24 | { |
| r23602 | r23603 | |
| 25 | 26 | nexus3d_state(const machine_config &mconfig, device_type type, const char *tag) |
| 26 | 27 | : driver_device(mconfig, type, tag), |
| 27 | 28 | m_mainram(*this, "mainram"), |
| 28 | | m_maincpu(*this, "maincpu") { } |
| 29 | m_maincpu(*this, "maincpu"), |
| 30 | m_serflash(*this, "flash") |
| 31 | { } |
| 29 | 32 | |
| 30 | 33 | required_shared_ptr<UINT32> m_mainram; |
| 34 | required_device<cpu_device> m_maincpu; |
| 35 | required_device<serflash_device> m_serflash; |
| 31 | 36 | |
| 32 | | // |
| 33 | | UINT8 m_last_flash_cmd; |
| 34 | | |
| 35 | | int m_flash_addr_seq; |
| 36 | | UINT32 m_flash_addr; |
| 37 | | |
| 38 | | int m_flash_page_addr; |
| 39 | | UINT8 flash_page_data[FLASH_PAGE_SIZE]; |
| 40 | | |
| 41 | | UINT8* m_flash_region; |
| 42 | | |
| 43 | 37 | DECLARE_READ32_MEMBER(nexus3d_unk_r); |
| 44 | 38 | // DECLARE_READ32_MEMBER(nexus3d_unk2_r); |
| 45 | 39 | // DECLARE_READ32_MEMBER(nexus3d_unk3_r); |
| 46 | 40 | // DECLARE_WRITE32_MEMBER(nexus3d_unk2_w); |
| 47 | 41 | // DECLARE_WRITE32_MEMBER(nexus3d_unk3_w); |
| 48 | | DECLARE_READ8_MEMBER(n3d_flash_r); |
| 49 | | DECLARE_WRITE8_MEMBER(n3d_flash_cmd_w); |
| 50 | | DECLARE_WRITE8_MEMBER(n3d_flash_addr_w); |
| 42 | |
| 51 | 43 | DECLARE_DRIVER_INIT(nexus3d); |
| 52 | 44 | virtual void machine_reset(); |
| 53 | 45 | virtual void video_start(); |
| 54 | 46 | UINT32 screen_update_nexus3d(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 55 | | void nexus3d_flash_reset(); |
| 56 | | required_device<cpu_device> m_maincpu; |
| 57 | 47 | }; |
| 58 | 48 | |
| 59 | 49 | |
| r23602 | r23603 | |
| 61 | 51 | |
| 62 | 52 | |
| 63 | 53 | |
| 64 | | // Flash handling is very similar (but not 100% identical) to the stuff used in cavesh3 (command structure seems very slightly different, probably due to larger size) |
| 65 | | // this is just a skeleton implementation |
| 66 | | |
| 67 | | void nexus3d_state::nexus3d_flash_reset() |
| 68 | | { |
| 69 | | m_last_flash_cmd = 0x00; |
| 70 | | m_flash_addr_seq = 0; |
| 71 | | m_flash_addr = 0; |
| 72 | | |
| 73 | | m_flash_page_addr = 0; |
| 74 | | } |
| 75 | | |
| 76 | | READ8_MEMBER(nexus3d_state::n3d_flash_r) |
| 77 | | { |
| 78 | | if (m_last_flash_cmd==0x70) return 0xe0; |
| 79 | | |
| 80 | | if (m_last_flash_cmd==0x00) |
| 81 | | { |
| 82 | | UINT8 retdat = flash_page_data[m_flash_page_addr]; |
| 83 | | |
| 84 | | //logerror("n3d_flash_r %02x %04x\n", offset, m_flash_page_addr); |
| 85 | | |
| 86 | | m_flash_page_addr++; |
| 87 | | return retdat; |
| 88 | | } |
| 89 | | |
| 90 | | |
| 91 | | logerror("n3d_flash_r %02x\n", offset); |
| 92 | | return 0x00; |
| 93 | | |
| 94 | | } |
| 95 | | |
| 96 | | |
| 97 | | WRITE8_MEMBER(nexus3d_state::n3d_flash_cmd_w) |
| 98 | | { |
| 99 | | logerror("n3d_flash_cmd_w %02x %02x\n", offset, data); |
| 100 | | m_last_flash_cmd = data; |
| 101 | | |
| 102 | | if (data==0x00) |
| 103 | | { |
| 104 | | memcpy(flash_page_data, m_flash_region + m_flash_addr * FLASH_PAGE_SIZE, FLASH_PAGE_SIZE); |
| 105 | | |
| 106 | | } |
| 107 | | |
| 108 | | } |
| 109 | | |
| 110 | | WRITE8_MEMBER(nexus3d_state::n3d_flash_addr_w) |
| 111 | | { |
| 112 | | // logerror("n3d_flash_addr_w %02x %02x\n", offset, data); |
| 113 | | |
| 114 | | m_flash_addr_seq++; |
| 115 | | |
| 116 | | if (m_flash_addr_seq==3) |
| 117 | | m_flash_addr = (m_flash_addr & 0xffff00) | data; |
| 118 | | |
| 119 | | if (m_flash_addr_seq==4) |
| 120 | | m_flash_addr = (m_flash_addr & 0xff00ff) | data << 8; |
| 121 | | |
| 122 | | if (m_flash_addr_seq==5) |
| 123 | | m_flash_addr = (m_flash_addr & 0x00ffff) | data << 16; |
| 124 | | |
| 125 | | if (m_flash_addr_seq==5) |
| 126 | | { |
| 127 | | m_flash_addr_seq = 0; |
| 128 | | m_flash_page_addr = 0; |
| 129 | | logerror("set flash block to %08x\n", m_flash_addr); |
| 130 | | } |
| 131 | | |
| 132 | | } |
| 133 | | |
| 134 | 54 | READ32_MEMBER(nexus3d_state::nexus3d_unk_r) |
| 135 | 55 | { |
| 136 | 56 | return machine().rand() ^ (machine().rand() << 16); |
| r23602 | r23603 | |
| 162 | 82 | AM_RANGE(0x00400000, 0x01ffffff) AM_RAM // ?? uploads various data, + pointers to data in the 0x01ffxxxx range, might be video system related |
| 163 | 83 | |
| 164 | 84 | // flash |
| 165 | | AM_RANGE(0x9C000000, 0x9C000003) AM_READ8(n3d_flash_r, 0xffffffff) |
| 166 | | AM_RANGE(0x9C000010, 0x9C000013) AM_WRITE8(n3d_flash_cmd_w, 0xffffffff) |
| 167 | | AM_RANGE(0x9C000018, 0x9C00001b) AM_WRITE8(n3d_flash_addr_w, 0xffffffff) |
| 85 | AM_RANGE(0x9C000000, 0x9C000003) AM_DEVREAD8( "flash", serflash_device, n3d_flash_r, 0xffffffff) |
| 86 | AM_RANGE(0x9C000010, 0x9C000013) AM_DEVWRITE8("flash", serflash_device, n3d_flash_cmd_w, 0xffffffff) |
| 87 | AM_RANGE(0x9C000018, 0x9C00001b) AM_DEVWRITE8("flash", serflash_device, n3d_flash_addr_w, 0xffffffff) |
| 168 | 88 | |
| 169 | 89 | // lots of accesses in this range |
| 170 | 90 | // AM_RANGE(0xC0000F44, 0xC0000F47) AM_READWRITE(nexus3d_unk2_r, nexus3d_unk2_w ) // often |
| r23602 | r23603 | |
| 191 | 111 | |
| 192 | 112 | void nexus3d_state::machine_reset() |
| 193 | 113 | { |
| 194 | | nexus3d_flash_reset(); |
| 195 | 114 | } |
| 196 | 115 | |
| 197 | 116 | static MACHINE_CONFIG_START( nexus3d, nexus3d_state ) |
| r23602 | r23603 | |
| 209 | 128 | |
| 210 | 129 | MCFG_PALETTE_LENGTH(256) |
| 211 | 130 | |
| 131 | MCFG_SERFLASH_ADD("flash") |
| 212 | 132 | |
| 213 | 133 | MACHINE_CONFIG_END |
| 214 | 134 | |
| 215 | 135 | |
| 216 | 136 | |
| 217 | 137 | ROM_START( acheart ) |
| 218 | | ROM_REGION( 0x10800898, "user1", 0 ) /* ARM 32 bit code */ |
| 138 | ROM_REGION( 0x10800898, "flash", 0 ) /* ARM 32 bit code */ |
| 219 | 139 | ROM_LOAD( "arcanaheart.u1", 0x000000, 0x10800898, CRC(109bf439) SHA1(33fd39355923ef384d5eaeec8ae3f296509bde93) ) |
| 220 | 140 | |
| 221 | 141 | ROM_REGION( 0x200000, "user2", 0 ) // QDSP stuff |
| r23602 | r23603 | |
| 231 | 151 | |
| 232 | 152 | |
| 233 | 153 | ROM_START( acheartf ) |
| 234 | | ROM_REGION( 0x10800898, "user1", 0 ) /* ARM 32 bit code */ |
| 154 | ROM_REGION( 0x10800898, "flash", 0 ) /* ARM 32 bit code */ |
| 235 | 155 | ROM_LOAD( "arcanaheartfull.u1", 0x000000, 0x10800898, CRC(54b57a9d) SHA1(dee5a43b3aea854d2b98869dca74c57b66fb06eb)) |
| 236 | 156 | |
| 237 | 157 | ROM_REGION( 0x200000, "user2", 0 ) // QDSP stuff |
| r23602 | r23603 | |
| 248 | 168 | DRIVER_INIT_MEMBER(nexus3d_state,nexus3d) |
| 249 | 169 | { |
| 250 | 170 | // the first part of the flash ROM automatically gets copied to RAM |
| 251 | | memcpy( m_mainram, memregion("user1")->base(), 4 * 1024); |
| 252 | | m_flash_region = memregion("user1")->base(); |
| 171 | memcpy( m_mainram, memregion("flash")->base(), 4 * 1024); |
| 253 | 172 | } |
| 254 | 173 | |
| 255 | 174 | GAME( 2005, acheart, 0, nexus3d, nexus3d, nexus3d_state, nexus3d, ROT0, "Examu", "Arcana Heart",GAME_IS_SKELETON ) |
trunk/src/emu/machine/serflash.c
| r0 | r23603 | |
| 1 | /* Serial Flash Device */ |
| 2 | |
| 3 | /* todo: cleanup, refactor etc. */ |
| 4 | /* ghosteo.c is similar? */ |
| 5 | |
| 6 | #include "emu.h" |
| 7 | #include "machine/serflash.h" |
| 8 | |
| 9 | |
| 10 | |
| 11 | //************************************************************************** |
| 12 | // LIVE DEVICE |
| 13 | //************************************************************************** |
| 14 | |
| 15 | // device type definition |
| 16 | const device_type SERFLASH = &device_creator<serflash_device>; |
| 17 | |
| 18 | //------------------------------------------------- |
| 19 | // serflash_device - constructor |
| 20 | //------------------------------------------------- |
| 21 | |
| 22 | serflash_device::serflash_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 23 | : device_t(mconfig, SERFLASH, "SERFLASH", tag, owner, clock), |
| 24 | device_nvram_interface(mconfig, *this), |
| 25 | m_length(0) |
| 26 | { |
| 27 | } |
| 28 | |
| 29 | |
| 30 | |
| 31 | //------------------------------------------------- |
| 32 | // device_start - device-specific startup |
| 33 | //------------------------------------------------- |
| 34 | |
| 35 | void serflash_device::device_start() |
| 36 | { |
| 37 | m_length = machine().root_device().memregion( tag() )->bytes(); |
| 38 | m_region = machine().root_device().memregion( tag() )->base(); |
| 39 | |
| 40 | printf("bytes %d\n", m_length); |
| 41 | |
| 42 | m_flashwritemap = auto_alloc_array(machine(), UINT8, m_length / FLASH_PAGE_SIZE); |
| 43 | memset(m_flashwritemap, 0, m_length / FLASH_PAGE_SIZE); |
| 44 | |
| 45 | } |
| 46 | |
| 47 | void serflash_device::device_reset() |
| 48 | { |
| 49 | m_flash_enab = 0; |
| 50 | flash_hard_reset(machine()); |
| 51 | |
| 52 | m_last_flash_cmd = 0x00; |
| 53 | m_flash_addr_seq = 0; |
| 54 | m_flash_addr = 0; |
| 55 | |
| 56 | m_flash_page_addr = 0; |
| 57 | } |
| 58 | |
| 59 | //------------------------------------------------- |
| 60 | // serflash_default - called to initialize SERFLASH to |
| 61 | // its default state |
| 62 | //------------------------------------------------- |
| 63 | |
| 64 | void serflash_device::nvram_default() |
| 65 | { |
| 66 | |
| 67 | } |
| 68 | |
| 69 | |
| 70 | //------------------------------------------------- |
| 71 | // nvram_read - called to read SERFLASH from the |
| 72 | // .nv file |
| 73 | //------------------------------------------------- |
| 74 | |
| 75 | void serflash_device::nvram_read(emu_file &file) |
| 76 | { |
| 77 | if (m_length % FLASH_PAGE_SIZE) return; // region size must be multiple of flash page size |
| 78 | int size = m_length /= FLASH_PAGE_SIZE; |
| 79 | |
| 80 | |
| 81 | if (file) |
| 82 | { |
| 83 | UINT32 page; |
| 84 | file.read(&page, 4); |
| 85 | while (page < size) |
| 86 | { |
| 87 | m_flashwritemap[page] = 1; |
| 88 | file.read(m_region + page * FLASH_PAGE_SIZE, FLASH_PAGE_SIZE); |
| 89 | file.read(&page, 4); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | } |
| 94 | |
| 95 | |
| 96 | //------------------------------------------------- |
| 97 | // nvram_write - called to write SERFLASH to the |
| 98 | // .nv file |
| 99 | //------------------------------------------------- |
| 100 | |
| 101 | void serflash_device::nvram_write(emu_file &file) |
| 102 | { |
| 103 | |
| 104 | if (m_length % FLASH_PAGE_SIZE) return; // region size must be multiple of flash page size |
| 105 | int size = m_length /= FLASH_PAGE_SIZE; |
| 106 | |
| 107 | UINT32 page = 0; |
| 108 | while (page < size) |
| 109 | { |
| 110 | if (m_flashwritemap[page]) |
| 111 | { |
| 112 | file.write(&page, 4); |
| 113 | file.write(m_region + page * FLASH_PAGE_SIZE, FLASH_PAGE_SIZE); |
| 114 | } |
| 115 | page++; |
| 116 | } |
| 117 | file.write(&page, 4); |
| 118 | } |
| 119 | |
| 120 | void serflash_device::flash_hard_reset(running_machine &machine) |
| 121 | { |
| 122 | // logerror("%08x FLASH: RESET\n", cpuexec_describe_context(machine)); |
| 123 | |
| 124 | m_flash_state = STATE_READ; |
| 125 | |
| 126 | m_flash_cmd_prev = -1; |
| 127 | m_flash_cmd_seq = 0; |
| 128 | |
| 129 | m_flash_addr_seq = 0; |
| 130 | m_flash_read_seq = 0; |
| 131 | |
| 132 | m_flash_row = 0; |
| 133 | m_flash_col = 0; |
| 134 | |
| 135 | memset(m_flash_page_data, 0, FLASH_PAGE_SIZE); |
| 136 | m_flash_page_addr = 0; |
| 137 | m_flash_page_index = 0; |
| 138 | } |
| 139 | |
| 140 | WRITE8_MEMBER( serflash_device::flash_enab_w ) |
| 141 | { |
| 142 | //logerror("%08x FLASH: enab = %02X\n", m_maincpu->pc(), data); |
| 143 | m_flash_enab = data; |
| 144 | } |
| 145 | |
| 146 | void serflash_device::flash_change_state(running_machine &machine, flash_state_t state) |
| 147 | { |
| 148 | m_flash_state = state; |
| 149 | |
| 150 | m_flash_cmd_prev = -1; |
| 151 | m_flash_cmd_seq = 0; |
| 152 | |
| 153 | m_flash_read_seq = 0; |
| 154 | m_flash_addr_seq = 0; |
| 155 | |
| 156 | //logerror("flash_change_state - FLASH: state = %s\n", m_flash_state_name[state]); |
| 157 | } |
| 158 | |
| 159 | WRITE8_MEMBER( serflash_device::flash_cmd_w ) |
| 160 | { |
| 161 | if (!m_flash_enab) |
| 162 | return; |
| 163 | |
| 164 | //logerror("%08x FLASH: cmd = %02X (prev = %02X)\n", m_maincpu->pc(), data, m_flash_cmd_prev); |
| 165 | |
| 166 | if (m_flash_cmd_prev == -1) |
| 167 | { |
| 168 | m_flash_cmd_prev = data; |
| 169 | |
| 170 | switch (data) |
| 171 | { |
| 172 | case 0x00: // READ |
| 173 | m_flash_addr_seq = 0; |
| 174 | break; |
| 175 | |
| 176 | case 0x60: // BLOCK ERASE |
| 177 | m_flash_addr_seq = 0; |
| 178 | break; |
| 179 | |
| 180 | case 0x70: // READ STATUS |
| 181 | flash_change_state( space.machine(), STATE_READ_STATUS ); |
| 182 | break; |
| 183 | |
| 184 | case 0x80: // PAGE / CACHE PROGRAM |
| 185 | m_flash_addr_seq = 0; |
| 186 | // this actually seems to be set with the next 2 writes? |
| 187 | m_flash_page_addr = 0; |
| 188 | break; |
| 189 | |
| 190 | case 0x90: // READ ID |
| 191 | flash_change_state( space.machine(), STATE_READ_ID ); |
| 192 | break; |
| 193 | |
| 194 | case 0xff: // RESET |
| 195 | flash_change_state( space.machine(), STATE_IDLE ); |
| 196 | break; |
| 197 | |
| 198 | default: |
| 199 | { |
| 200 | //logerror("%08x FLASH: unknown cmd1 = %02X\n", cpu_get_pc(space.device()), data); |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | else |
| 205 | { |
| 206 | switch (m_flash_cmd_prev) |
| 207 | { |
| 208 | case 0x00: // READ |
| 209 | if (data == 0x30) |
| 210 | { |
| 211 | |
| 212 | |
| 213 | memcpy(m_flash_page_data, m_region + m_flash_row * FLASH_PAGE_SIZE, FLASH_PAGE_SIZE); |
| 214 | m_flash_page_addr = m_flash_col; |
| 215 | m_flash_page_index = m_flash_row; |
| 216 | |
| 217 | flash_change_state( space.machine(), STATE_READ ); |
| 218 | |
| 219 | //logerror("%08x FLASH: caching page = %04X\n", m_maincpu->pc(), m_flash_row); |
| 220 | } |
| 221 | break; |
| 222 | |
| 223 | case 0x60: // BLOCK ERASE |
| 224 | if (data==0xd0) |
| 225 | { |
| 226 | flash_change_state( space.machine(), STATE_BLOCK_ERASE ); |
| 227 | m_flashwritemap[m_flash_col] |= 1; |
| 228 | memset(m_region + m_flash_col * FLASH_PAGE_SIZE, 0xff, FLASH_PAGE_SIZE); |
| 229 | //logerror("erased block %04x (%08x - %08x)\n", m_flash_col, m_flash_col * FLASH_PAGE_SIZE, ((m_flash_col+1) * FLASH_PAGE_SIZE)-1); |
| 230 | } |
| 231 | else |
| 232 | { |
| 233 | //logerror("unexpected 2nd command after BLOCK ERASE\n"); |
| 234 | } |
| 235 | break; |
| 236 | case 0x80: |
| 237 | if (data==0x10) |
| 238 | { |
| 239 | flash_change_state( space.machine(), STATE_PAGE_PROGRAM ); |
| 240 | m_flashwritemap[m_flash_row] |= (memcmp(m_region + m_flash_row * FLASH_PAGE_SIZE, m_flash_page_data, FLASH_PAGE_SIZE) != 0); |
| 241 | memcpy(m_region + m_flash_row * FLASH_PAGE_SIZE, m_flash_page_data, FLASH_PAGE_SIZE); |
| 242 | //logerror("re-written block %04x (%08x - %08x)\n", m_flash_row, m_flash_row * FLASH_PAGE_SIZE, ((m_flash_row+1) * FLASH_PAGE_SIZE)-1); |
| 243 | |
| 244 | } |
| 245 | else |
| 246 | { |
| 247 | //logerror("unexpected 2nd command after SPAGE PROGRAM\n"); |
| 248 | } |
| 249 | break; |
| 250 | |
| 251 | |
| 252 | default: |
| 253 | { |
| 254 | //logerror("%08x FLASH: unknown cmd2 = %02X (cmd1 = %02X)\n", m_maincpu->pc(), data, m_flash_cmd_prev); |
| 255 | } |
| 256 | } |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | WRITE8_MEMBER( serflash_device::flash_data_w ) |
| 261 | { |
| 262 | if (!m_flash_enab) |
| 263 | return; |
| 264 | |
| 265 | //logerror("flash data write %04x\n", m_flash_page_addr); |
| 266 | m_flash_page_data[m_flash_page_addr] = data; |
| 267 | m_flash_page_addr++; |
| 268 | } |
| 269 | |
| 270 | WRITE8_MEMBER( serflash_device::flash_addr_w ) |
| 271 | { |
| 272 | if (!m_flash_enab) |
| 273 | return; |
| 274 | |
| 275 | //logerror("%08x FLASH: addr = %02X (seq = %02X)\n", m_maincpu->pc(), data, m_flash_addr_seq); |
| 276 | |
| 277 | switch( m_flash_addr_seq++ ) |
| 278 | { |
| 279 | case 0: |
| 280 | m_flash_col = (m_flash_col & 0xff00) | data; |
| 281 | break; |
| 282 | case 1: |
| 283 | m_flash_col = (m_flash_col & 0x00ff) | (data << 8); |
| 284 | break; |
| 285 | case 2: |
| 286 | m_flash_row = (m_flash_row & 0xff00) | data; |
| 287 | break; |
| 288 | case 3: |
| 289 | m_flash_row = (m_flash_row & 0x00ff) | (data << 8); |
| 290 | m_flash_addr_seq = 0; |
| 291 | break; |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | READ8_MEMBER( serflash_device::flash_io_r ) |
| 296 | { |
| 297 | UINT8 data = 0x00; |
| 298 | // UINT32 old; |
| 299 | |
| 300 | if (!m_flash_enab) |
| 301 | return 0xff; |
| 302 | |
| 303 | switch (m_flash_state) |
| 304 | { |
| 305 | case STATE_READ_ID: |
| 306 | //old = m_flash_read_seq; |
| 307 | |
| 308 | switch( m_flash_read_seq++ ) |
| 309 | { |
| 310 | case 0: |
| 311 | data = 0xEC; // Manufacturer |
| 312 | break; |
| 313 | case 1: |
| 314 | data = 0xF1; // Device |
| 315 | break; |
| 316 | case 2: |
| 317 | data = 0x00; // XX |
| 318 | break; |
| 319 | case 3: |
| 320 | data = 0x15; // Flags |
| 321 | m_flash_read_seq = 0; |
| 322 | break; |
| 323 | } |
| 324 | |
| 325 | //logerror("%08x FLASH: read %02X from id(%02X)\n", m_maincpu->pc(), data, old); |
| 326 | break; |
| 327 | |
| 328 | case STATE_READ: |
| 329 | if (m_flash_page_addr > FLASH_PAGE_SIZE-1) |
| 330 | m_flash_page_addr = FLASH_PAGE_SIZE-1; |
| 331 | |
| 332 | //old = m_flash_page_addr; |
| 333 | |
| 334 | data = m_flash_page_data[m_flash_page_addr++]; |
| 335 | |
| 336 | //logerror("%08x FLASH: read data %02X from addr %03X (page %04X)\n", m_maincpu->pc(), data, old, m_flash_page_index); |
| 337 | break; |
| 338 | |
| 339 | case STATE_READ_STATUS: |
| 340 | // bit 7 = writeable, bit 6 = ready, bit 5 = ready/true ready, bit 1 = fail(N-1), bit 0 = fail |
| 341 | data = 0xe0; |
| 342 | //logerror("%08x FLASH: read status %02X\n", m_maincpu->pc(), data); |
| 343 | break; |
| 344 | |
| 345 | default: |
| 346 | { |
| 347 | // logerror("%08x FLASH: unknown read in state %s\n",0x00/*m_maincpu->pc()*/, m_flash_state_name[m_flash_state]); |
| 348 | } |
| 349 | } |
| 350 | |
| 351 | return data; |
| 352 | } |
| 353 | |
| 354 | READ8_MEMBER( serflash_device::flash_ready_r ) |
| 355 | { |
| 356 | return 1; |
| 357 | } |
| 358 | |
| 359 | |
| 360 | |
| 361 | READ8_MEMBER(serflash_device::n3d_flash_r) |
| 362 | { |
| 363 | if (m_last_flash_cmd==0x70) return 0xe0; |
| 364 | |
| 365 | if (m_last_flash_cmd==0x00) |
| 366 | { |
| 367 | UINT8 retdat = m_flash_page_data[m_flash_page_addr]; |
| 368 | |
| 369 | //logerror("n3d_flash_r %02x %04x\n", offset, m_flash_page_addr); |
| 370 | |
| 371 | m_flash_page_addr++; |
| 372 | return retdat; |
| 373 | } |
| 374 | |
| 375 | |
| 376 | logerror("n3d_flash_r %02x\n", offset); |
| 377 | return 0x00; |
| 378 | |
| 379 | } |
| 380 | |
| 381 | |
| 382 | WRITE8_MEMBER(serflash_device::n3d_flash_cmd_w) |
| 383 | { |
| 384 | logerror("n3d_flash_cmd_w %02x %02x\n", offset, data); |
| 385 | m_last_flash_cmd = data; |
| 386 | |
| 387 | if (data==0x00) |
| 388 | { |
| 389 | memcpy(m_flash_page_data, m_region + m_flash_addr * FLASH_PAGE_SIZE, FLASH_PAGE_SIZE); |
| 390 | |
| 391 | } |
| 392 | |
| 393 | } |
| 394 | |
| 395 | WRITE8_MEMBER(serflash_device::n3d_flash_addr_w) |
| 396 | { |
| 397 | // logerror("n3d_flash_addr_w %02x %02x\n", offset, data); |
| 398 | |
| 399 | m_flash_addr_seq++; |
| 400 | |
| 401 | if (m_flash_addr_seq==3) |
| 402 | m_flash_addr = (m_flash_addr & 0xffff00) | data; |
| 403 | |
| 404 | if (m_flash_addr_seq==4) |
| 405 | m_flash_addr = (m_flash_addr & 0xff00ff) | data << 8; |
| 406 | |
| 407 | if (m_flash_addr_seq==5) |
| 408 | m_flash_addr = (m_flash_addr & 0x00ffff) | data << 16; |
| 409 | |
| 410 | if (m_flash_addr_seq==5) |
| 411 | { |
| 412 | m_flash_addr_seq = 0; |
| 413 | m_flash_page_addr = 0; |
| 414 | logerror("set flash block to %08x\n", m_flash_addr); |
| 415 | } |
| 416 | } |
| 417 | |
trunk/src/emu/machine/serflash.h
| r0 | r23603 | |
| 1 | /* Serial Flash */ |
| 2 | |
| 3 | #pragma once |
| 4 | |
| 5 | #ifndef __SERFLASH_H__ |
| 6 | #define __SERFLASH_H__ |
| 7 | |
| 8 | |
| 9 | #define FLASH_PAGE_SIZE (2048+64) |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | //************************************************************************** |
| 17 | // INTERFACE CONFIGURATION MACROS |
| 18 | //************************************************************************** |
| 19 | |
| 20 | #define MCFG_SERFLASH_ADD(_tag) \ |
| 21 | MCFG_DEVICE_ADD(_tag, SERFLASH, 0) \ |
| 22 | |
| 23 | //************************************************************************** |
| 24 | // TYPE DEFINITIONS |
| 25 | //************************************************************************** |
| 26 | |
| 27 | class serflash_device; |
| 28 | |
| 29 | typedef enum { STATE_IDLE = 0, STATE_READ, STATE_READ_ID, STATE_READ_STATUS, STATE_BLOCK_ERASE, STATE_PAGE_PROGRAM } flash_state_t; |
| 30 | //const char *m_flash_state_name[] = { "IDLE", "READ", "READ_ID", "READ_STATUS", "BLOCK ERASE", "PAGE PROGRAM" }; |
| 31 | |
| 32 | // custom initialization for default state |
| 33 | typedef device_delegate<void (serflash_device &, void *, size_t)> serflash_init_delegate; |
| 34 | |
| 35 | |
| 36 | // ======================> serflash_device |
| 37 | |
| 38 | class serflash_device : public device_t, |
| 39 | public device_nvram_interface |
| 40 | { |
| 41 | public: |
| 42 | |
| 43 | // construction/destruction |
| 44 | serflash_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 45 | |
| 46 | DECLARE_READ8_MEMBER( flash_ready_r ); |
| 47 | DECLARE_READ8_MEMBER( flash_io_r ); |
| 48 | DECLARE_WRITE8_MEMBER( flash_addr_w ); |
| 49 | DECLARE_WRITE8_MEMBER( flash_data_w ); |
| 50 | DECLARE_WRITE8_MEMBER( flash_cmd_w ); |
| 51 | DECLARE_WRITE8_MEMBER( flash_enab_w ); |
| 52 | void flash_hard_reset(running_machine &machine); |
| 53 | |
| 54 | DECLARE_READ8_MEMBER(n3d_flash_r); |
| 55 | DECLARE_WRITE8_MEMBER(n3d_flash_cmd_w); |
| 56 | DECLARE_WRITE8_MEMBER(n3d_flash_addr_w); |
| 57 | |
| 58 | protected: |
| 59 | // device-level overrides |
| 60 | virtual void device_start(); |
| 61 | virtual void device_reset(); |
| 62 | |
| 63 | // device_nvram_interface overrides |
| 64 | virtual void nvram_default(); |
| 65 | virtual void nvram_read(emu_file &file); |
| 66 | virtual void nvram_write(emu_file &file); |
| 67 | |
| 68 | void flash_change_state(running_machine &machine, flash_state_t state); |
| 69 | |
| 70 | // runtime state |
| 71 | size_t m_length; |
| 72 | UINT8* m_region; |
| 73 | |
| 74 | |
| 75 | flash_state_t m_flash_state; |
| 76 | |
| 77 | UINT8 m_flash_enab; |
| 78 | |
| 79 | UINT8 m_flash_cmd_seq; |
| 80 | UINT32 m_flash_cmd_prev; |
| 81 | |
| 82 | UINT8 m_flash_addr_seq; |
| 83 | UINT8 m_flash_read_seq; |
| 84 | |
| 85 | UINT16 m_flash_row, m_flash_col; |
| 86 | int m_flash_page_addr; |
| 87 | UINT16 m_flash_page_index; |
| 88 | |
| 89 | |
| 90 | UINT8* m_flashwritemap; |
| 91 | |
| 92 | UINT8 m_last_flash_cmd; |
| 93 | |
| 94 | UINT32 m_flash_addr; |
| 95 | |
| 96 | UINT8 m_flash_page_data[FLASH_PAGE_SIZE]; |
| 97 | |
| 98 | |
| 99 | |
| 100 | }; |
| 101 | |
| 102 | |
| 103 | // device type definition |
| 104 | extern const device_type SERFLASH; |
| 105 | |
| 106 | |
| 107 | #endif |
| 108 | |