# HG changeset patch # User Michael Pavone # Date 1498279718 25200 # Node ID d9485508052969d270d76d234bf832e5d86f3b59 # Parent 3d7f668dce3d594192ff7043da6ba88cbe10ee18 Move I2C EEPROM and NOR Flash functions out of romdb.c into new files diff -r 3d7f668dce3d -r d94855080529 Makefile --- a/Makefile Thu Jun 22 23:40:05 2017 -0700 +++ b/Makefile Fri Jun 23 21:48:38 2017 -0700 @@ -127,7 +127,7 @@ AUDIOOBJS=ym2612.o psg.o wave.o CONFIGOBJS=config.o tern.o util.o -MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS) +MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o i2c.o nor.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS) ifeq ($(CPU),x86_64) CFLAGS+=-DX86_64 -m64 diff -r 3d7f668dce3d -r d94855080529 genesis.c --- a/genesis.c Thu Jun 22 23:40:05 2017 -0700 +++ b/genesis.c Fri Jun 23 21:48:38 2017 -0700 @@ -5,6 +5,7 @@ */ #include "genesis.h" #include "blastem.h" +#include "nor.h" #include #include #include diff -r 3d7f668dce3d -r d94855080529 genesis.h --- a/genesis.h Thu Jun 22 23:40:05 2017 -0700 +++ b/genesis.h Fri Jun 23 21:48:38 2017 -0700 @@ -16,6 +16,7 @@ #include "io.h" #include "romdb.h" #include "arena.h" +#include "i2c.h" typedef struct genesis_context genesis_context; diff -r 3d7f668dce3d -r d94855080529 i2c.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i2c.c Fri Jun 23 21:48:38 2017 -0700 @@ -0,0 +1,250 @@ +#include "genesis.h" +#include "util.h" + +enum { + I2C_IDLE, + I2C_START, + I2C_DEVICE_ACK, + I2C_ADDRESS_HI, + I2C_ADDRESS_HI_ACK, + I2C_ADDRESS, + I2C_ADDRESS_ACK, + I2C_READ, + I2C_READ_ACK, + I2C_WRITE, + I2C_WRITE_ACK +}; + +char * i2c_states[] = { + "idle", + "start", + "device ack", + "address hi", + "address hi ack", + "address", + "address ack", + "read", + "read_ack", + "write", + "write_ack" +}; + +void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size) +{ + state->slave_sda = 1; + state->host_sda = state->scl = 0; + state->buffer = buffer; + state->size = size; + state->state = I2C_IDLE; +} + +void set_host_sda(eeprom_state *state, uint8_t val) +{ + if (state->scl) { + if (val & ~state->host_sda) { + //low to high, stop condition + state->state = I2C_IDLE; + state->slave_sda = 1; + } else if (~val & state->host_sda) { + //high to low, start condition + state->state = I2C_START; + state->slave_sda = 1; + state->counter = 8; + } + } + state->host_sda = val; +} + +void set_scl(eeprom_state *state, uint8_t val) +{ + if (val & ~state->scl) { + //low to high transition + switch (state->state) + { + case I2C_START: + case I2C_ADDRESS_HI: + case I2C_ADDRESS: + case I2C_WRITE: + state->latch = state->host_sda | state->latch << 1; + state->counter--; + if (!state->counter) { + switch (state->state & 0x7F) + { + case I2C_START: + state->state = I2C_DEVICE_ACK; + break; + case I2C_ADDRESS_HI: + state->address = state->latch << 8; + state->state = I2C_ADDRESS_HI_ACK; + break; + case I2C_ADDRESS: + state->address |= state->latch; + state->state = I2C_ADDRESS_ACK; + break; + case I2C_WRITE: + state->buffer[state->address] = state->latch; + state->state = I2C_WRITE_ACK; + break; + } + } + break; + case I2C_DEVICE_ACK: + if (state->latch & 1) { + state->state = I2C_READ; + state->counter = 8; + if (state->size < 256) { + state->address = state->latch >> 1; + } + state->latch = state->buffer[state->address]; + } else { + if (state->size < 256) { + state->address = state->latch >> 1; + state->state = I2C_WRITE; + } else if (state->size < 4096) { + state->address = (state->latch & 0xE) << 7; + state->state = I2C_ADDRESS; + } else { + state->state = I2C_ADDRESS_HI; + } + state->counter = 8; + } + break; + case I2C_ADDRESS_HI_ACK: + state->state = I2C_ADDRESS; + state->counter = 8; + break; + case I2C_ADDRESS_ACK: + state->state = I2C_WRITE; + state->address &= state->size-1; + state->counter = 8; + break; + case I2C_READ: + state->counter--; + if (!state->counter) { + state->state = I2C_READ_ACK; + } + break; + case I2C_READ_ACK: + state->state = I2C_READ; + state->counter = 8; + state->address++; + //TODO: page mask + state->address &= state->size-1; + state->latch = state->buffer[state->address]; + break; + case I2C_WRITE_ACK: + state->state = I2C_WRITE; + state->counter = 8; + state->address++; + //TODO: page mask + state->address &= state->size-1; + break; + } + } else if (~val & state->scl) { + //high to low transition + switch (state->state & 0x7F) + { + case I2C_DEVICE_ACK: + case I2C_ADDRESS_HI_ACK: + case I2C_ADDRESS_ACK: + case I2C_READ_ACK: + case I2C_WRITE_ACK: + state->slave_sda = 0; + break; + case I2C_READ: + state->slave_sda = state->latch >> 7; + state->latch = state->latch << 1; + break; + default: + state->slave_sda = 1; + break; + } + } + state->scl = val; +} + +uint8_t get_sda(eeprom_state *state) +{ + return state->host_sda & state->slave_sda; +} + +eeprom_map *find_eeprom_map(uint32_t address, genesis_context *gen) +{ + for (int i = 0; i < gen->num_eeprom; i++) + { + if (address >= gen->eeprom_map[i].start && address <= gen->eeprom_map[i].end) { + return gen->eeprom_map + i; + } + } + return NULL; +} + +void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fatal_error("Could not find EEPROM map for address %X\n", address); + } + if (map->scl_mask) { + set_scl(&gen->eeprom, (value & map->scl_mask) != 0); + } + if (map->sda_write_mask) { + set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); + } + return context; +} + +void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fatal_error("Could not find EEPROM map for address %X\n", address); + } + + uint16_t expanded, mask; + if (address & 1) { + expanded = value; + mask = 0xFF; + } else { + expanded = value << 8; + mask = 0xFF00; + } + if (map->scl_mask & mask) { + set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); + } + if (map->sda_write_mask & mask) { + set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); + } + return context; +} + +uint16_t read_eeprom_i2c_w(uint32_t address, void * context) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fatal_error("Could not find EEPROM map for address %X\n", address); + } + uint16_t ret = 0; + if (map->sda_read_bit < 16) { + ret = get_sda(&gen->eeprom) << map->sda_read_bit; + } + return ret; +} + +uint8_t read_eeprom_i2c_b(uint32_t address, void * context) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fatal_error("Could not find EEPROM map for address %X\n", address); + } + uint8_t bit = address & 1 ? map->sda_read_bit : map->sda_read_bit - 8; + uint8_t ret = 0; + if (bit < 8) { + ret = get_sda(&gen->eeprom) << bit; + } + return ret; +} diff -r 3d7f668dce3d -r d94855080529 i2c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/i2c.h Fri Jun 23 21:48:38 2017 -0700 @@ -0,0 +1,22 @@ +#ifndef I2C_H_ +#define I2C_H_ + +typedef struct { + char *buffer; + uint32_t size; + uint16_t address; + uint8_t host_sda; + uint8_t slave_sda; + uint8_t scl; + uint8_t state; + uint8_t counter; + uint8_t latch; +} eeprom_state; + +void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size); +void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value); +void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value); +uint16_t read_eeprom_i2c_w(uint32_t address, void * context); +uint8_t read_eeprom_i2c_b(uint32_t address, void * context); + +#endif //I2C_H_ diff -r 3d7f668dce3d -r d94855080529 nor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nor.c Fri Jun 23 21:48:38 2017 -0700 @@ -0,0 +1,204 @@ +#include "genesis.h" +#include +#include + +enum { + NOR_NORMAL, + NOR_PRODUCTID, + NOR_BOOTBLOCK +}; + +enum { + NOR_CMD_IDLE, + NOR_CMD_AA, + NOR_CMD_55 +}; + +//Technically this value shoudl be slightly different between NTSC and PAL +//as it's defined as 200 micro-seconds, not in clock cycles +#define NOR_WRITE_PAUSE 10690 + +void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags) +{ + state->buffer = buffer; + state->page_buffer = malloc(page_size); + memset(state->page_buffer, 0xFF, page_size); + state->size = size; + state->page_size = page_size; + state->product_id = product_id; + state->last_write_cycle = 0xFFFFFFFF; + state->mode = NOR_NORMAL; + state->cmd_state = NOR_CMD_IDLE; + state->alt_cmd = 0; + state->bus_flags = bus_flags; +} + +void nor_run(nor_state *state, uint32_t cycle) +{ + if (state->last_write_cycle == 0xFFFFFFFF) { + return; + } + if (cycle - state->last_write_cycle >= NOR_WRITE_PAUSE) { + state->last_write_cycle = 0xFFFFFFFF; + for (uint32_t i = 0; i < state->page_size; i++) { + state->buffer[state->current_page + i] = state->page_buffer[i]; + } + memset(state->page_buffer, 0xFF, state->page_size); + } +} + +uint8_t nor_flash_read_b(uint32_t address, void *vcontext) +{ + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + nor_state *state = &gen->nor; + if ( + ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) || + (!(address & 1) && state->bus_flags == RAM_FLAG_ODD) + ) { + return 0xFF; + } + if (state->bus_flags != RAM_FLAG_BOTH) { + address = address >> 1; + } + + nor_run(state, m68k->current_cycle); + switch (state->mode) + { + case NOR_NORMAL: + return state->buffer[address & (state->size-1)]; + break; + case NOR_PRODUCTID: + switch (address & (state->size - 1)) + { + case 0: + return state->product_id >> 8; + case 1: + return state->product_id; + case 2: + //TODO: Implement boot block protection + return 0xFE; + default: + return 0xFE; + } + break; + case NOR_BOOTBLOCK: + break; + } + return 0xFF; +} + +uint16_t nor_flash_read_w(uint32_t address, void *context) +{ + uint16_t value = nor_flash_read_b(address, context) << 8; + value |= nor_flash_read_b(address+1, context); + return value; +} + +void nor_write_byte(nor_state *state, uint32_t address, uint8_t value, uint32_t cycle) +{ + switch(state->mode) + { + case NOR_NORMAL: + if (state->last_write_cycle != 0xFFFFFFFF) { + state->current_page = address & (state->size - 1) & ~(state->page_size - 1); + } + state->page_buffer[address & (state->page_size - 1)] = value; + break; + case NOR_PRODUCTID: + break; + case NOR_BOOTBLOCK: + //TODO: Implement boot block protection + state->mode = NOR_NORMAL; + break; + } +} + +void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value) +{ + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + nor_state *state = &gen->nor; + if ( + ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) || + (!(address & 1) && state->bus_flags == RAM_FLAG_ODD) + ) { + return vcontext; + } + if (state->bus_flags != RAM_FLAG_BOTH) { + address = address >> 1; + } + + nor_run(state, m68k->current_cycle); + switch (state->cmd_state) + { + case NOR_CMD_IDLE: + if (value == 0xAA && (address & (state->size - 1)) == 0x5555) { + state->cmd_state = NOR_CMD_AA; + } else { + nor_write_byte(state, address, value, m68k->current_cycle); + state->cmd_state = NOR_CMD_IDLE; + } + break; + case NOR_CMD_AA: + if (value == 0x55 && (address & (state->size - 1)) == 0x2AAA) { + state->cmd_state = NOR_CMD_55; + } else { + nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle); + nor_write_byte(state, address, value, m68k->current_cycle); + state->cmd_state = NOR_CMD_IDLE; + } + break; + case NOR_CMD_55: + if ((address & (state->size - 1)) == 0x5555) { + if (state->alt_cmd) { + switch(value) + { + case 0x10: + puts("UNIMPLEMENTED: NOR flash erase"); + break; + case 0x20: + puts("UNIMPLEMENTED: NOR flash disable protection"); + break; + case 0x40: + state->mode = NOR_BOOTBLOCK; + break; + case 0x60: + state->mode = NOR_PRODUCTID; + break; + } + } else { + switch(value) + { + case 0x80: + state->alt_cmd = 1; + break; + case 0x90: + state->mode = NOR_PRODUCTID; + break; + case 0xA0: + puts("UNIMPLEMENTED: NOR flash enable protection"); + break; + case 0xF0: + state->mode = NOR_NORMAL; + break; + default: + printf("Unrecognized unshifted NOR flash command %X\n", value); + } + } + } else { + nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle); + nor_write_byte(state, 0x2AAA, 0x55, m68k->current_cycle); + nor_write_byte(state, address, value, m68k->current_cycle); + } + state->cmd_state = NOR_CMD_IDLE; + break; + } + return vcontext; +} + +void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value) +{ + nor_flash_write_b(address, vcontext, value >> 8); + return nor_flash_write_b(address + 1, vcontext, value); +} diff -r 3d7f668dce3d -r d94855080529 nor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nor.h Fri Jun 23 21:48:38 2017 -0700 @@ -0,0 +1,10 @@ +#ifndef NOR_H_ +#define NOR_H_ + +void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags); +uint8_t nor_flash_read_b(uint32_t address, void *vcontext); +uint16_t nor_flash_read_w(uint32_t address, void *context); +void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value); +void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value); + +#endif //NOR_H_ diff -r 3d7f668dce3d -r d94855080529 romdb.c --- a/romdb.c Thu Jun 22 23:40:05 2017 -0700 +++ b/romdb.c Fri Jun 23 21:48:38 2017 -0700 @@ -8,6 +8,7 @@ #include "menu.h" #include "xband.h" #include "realtec.h" +#include "nor.h" #define DOM_TITLE_START 0x120 #define DOM_TITLE_END 0x150 @@ -30,374 +31,6 @@ return "SRAM"; } -enum { - I2C_IDLE, - I2C_START, - I2C_DEVICE_ACK, - I2C_ADDRESS_HI, - I2C_ADDRESS_HI_ACK, - I2C_ADDRESS, - I2C_ADDRESS_ACK, - I2C_READ, - I2C_READ_ACK, - I2C_WRITE, - I2C_WRITE_ACK -}; - -char * i2c_states[] = { - "idle", - "start", - "device ack", - "address hi", - "address hi ack", - "address", - "address ack", - "read", - "read_ack", - "write", - "write_ack" -}; - -void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size) -{ - state->slave_sda = 1; - state->host_sda = state->scl = 0; - state->buffer = buffer; - state->size = size; - state->state = I2C_IDLE; -} - -void set_host_sda(eeprom_state *state, uint8_t val) -{ - if (state->scl) { - if (val & ~state->host_sda) { - //low to high, stop condition - state->state = I2C_IDLE; - state->slave_sda = 1; - } else if (~val & state->host_sda) { - //high to low, start condition - state->state = I2C_START; - state->slave_sda = 1; - state->counter = 8; - } - } - state->host_sda = val; -} - -void set_scl(eeprom_state *state, uint8_t val) -{ - if (val & ~state->scl) { - //low to high transition - switch (state->state) - { - case I2C_START: - case I2C_ADDRESS_HI: - case I2C_ADDRESS: - case I2C_WRITE: - state->latch = state->host_sda | state->latch << 1; - state->counter--; - if (!state->counter) { - switch (state->state & 0x7F) - { - case I2C_START: - state->state = I2C_DEVICE_ACK; - break; - case I2C_ADDRESS_HI: - state->address = state->latch << 8; - state->state = I2C_ADDRESS_HI_ACK; - break; - case I2C_ADDRESS: - state->address |= state->latch; - state->state = I2C_ADDRESS_ACK; - break; - case I2C_WRITE: - state->buffer[state->address] = state->latch; - state->state = I2C_WRITE_ACK; - break; - } - } - break; - case I2C_DEVICE_ACK: - if (state->latch & 1) { - state->state = I2C_READ; - state->counter = 8; - if (state->size < 256) { - state->address = state->latch >> 1; - } - state->latch = state->buffer[state->address]; - } else { - if (state->size < 256) { - state->address = state->latch >> 1; - state->state = I2C_WRITE; - } else if (state->size < 4096) { - state->address = (state->latch & 0xE) << 7; - state->state = I2C_ADDRESS; - } else { - state->state = I2C_ADDRESS_HI; - } - state->counter = 8; - } - break; - case I2C_ADDRESS_HI_ACK: - state->state = I2C_ADDRESS; - state->counter = 8; - break; - case I2C_ADDRESS_ACK: - state->state = I2C_WRITE; - state->address &= state->size-1; - state->counter = 8; - break; - case I2C_READ: - state->counter--; - if (!state->counter) { - state->state = I2C_READ_ACK; - } - break; - case I2C_READ_ACK: - state->state = I2C_READ; - state->counter = 8; - state->address++; - //TODO: page mask - state->address &= state->size-1; - state->latch = state->buffer[state->address]; - break; - case I2C_WRITE_ACK: - state->state = I2C_WRITE; - state->counter = 8; - state->address++; - //TODO: page mask - state->address &= state->size-1; - break; - } - } else if (~val & state->scl) { - //high to low transition - switch (state->state & 0x7F) - { - case I2C_DEVICE_ACK: - case I2C_ADDRESS_HI_ACK: - case I2C_ADDRESS_ACK: - case I2C_READ_ACK: - case I2C_WRITE_ACK: - state->slave_sda = 0; - break; - case I2C_READ: - state->slave_sda = state->latch >> 7; - state->latch = state->latch << 1; - break; - default: - state->slave_sda = 1; - break; - } - } - state->scl = val; -} - -uint8_t get_sda(eeprom_state *state) -{ - return state->host_sda & state->slave_sda; -} - -enum { - NOR_NORMAL, - NOR_PRODUCTID, - NOR_BOOTBLOCK -}; - -enum { - NOR_CMD_IDLE, - NOR_CMD_AA, - NOR_CMD_55 -}; - -//Technically this value shoudl be slightly different between NTSC and PAL -//as it's defined as 200 micro-seconds, not in clock cycles -#define NOR_WRITE_PAUSE 10690 - -void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags) -{ - state->buffer = buffer; - state->page_buffer = malloc(page_size); - memset(state->page_buffer, 0xFF, page_size); - state->size = size; - state->page_size = page_size; - state->product_id = product_id; - state->last_write_cycle = 0xFFFFFFFF; - state->mode = NOR_NORMAL; - state->cmd_state = NOR_CMD_IDLE; - state->alt_cmd = 0; - state->bus_flags = bus_flags; -} - -void nor_run(nor_state *state, uint32_t cycle) -{ - if (state->last_write_cycle == 0xFFFFFFFF) { - return; - } - if (cycle - state->last_write_cycle >= NOR_WRITE_PAUSE) { - state->last_write_cycle = 0xFFFFFFFF; - for (uint32_t i = 0; i < state->page_size; i++) { - state->buffer[state->current_page + i] = state->page_buffer[i]; - } - memset(state->page_buffer, 0xFF, state->page_size); - } -} - -uint8_t nor_flash_read_b(uint32_t address, void *vcontext) -{ - m68k_context *m68k = vcontext; - genesis_context *gen = m68k->system; - nor_state *state = &gen->nor; - if ( - ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) || - (!(address & 1) && state->bus_flags == RAM_FLAG_ODD) - ) { - return 0xFF; - } - if (state->bus_flags != RAM_FLAG_BOTH) { - address = address >> 1; - } - - nor_run(state, m68k->current_cycle); - switch (state->mode) - { - case NOR_NORMAL: - return state->buffer[address & (state->size-1)]; - break; - case NOR_PRODUCTID: - switch (address & (state->size - 1)) - { - case 0: - return state->product_id >> 8; - case 1: - return state->product_id; - case 2: - //TODO: Implement boot block protection - return 0xFE; - default: - return 0xFE; - } - break; - case NOR_BOOTBLOCK: - break; - } - return 0xFF; -} - -uint16_t nor_flash_read_w(uint32_t address, void *context) -{ - uint16_t value = nor_flash_read_b(address, context) << 8; - value |= nor_flash_read_b(address+1, context); - return value; -} - -void nor_write_byte(nor_state *state, uint32_t address, uint8_t value, uint32_t cycle) -{ - switch(state->mode) - { - case NOR_NORMAL: - if (state->last_write_cycle != 0xFFFFFFFF) { - state->current_page = address & (state->size - 1) & ~(state->page_size - 1); - } - state->page_buffer[address & (state->page_size - 1)] = value; - break; - case NOR_PRODUCTID: - break; - case NOR_BOOTBLOCK: - //TODO: Implement boot block protection - state->mode = NOR_NORMAL; - break; - } -} - -void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value) -{ - m68k_context *m68k = vcontext; - genesis_context *gen = m68k->system; - nor_state *state = &gen->nor; - if ( - ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) || - (!(address & 1) && state->bus_flags == RAM_FLAG_ODD) - ) { - return vcontext; - } - if (state->bus_flags != RAM_FLAG_BOTH) { - address = address >> 1; - } - - nor_run(state, m68k->current_cycle); - switch (state->cmd_state) - { - case NOR_CMD_IDLE: - if (value == 0xAA && (address & (state->size - 1)) == 0x5555) { - state->cmd_state = NOR_CMD_AA; - } else { - nor_write_byte(state, address, value, m68k->current_cycle); - state->cmd_state = NOR_CMD_IDLE; - } - break; - case NOR_CMD_AA: - if (value == 0x55 && (address & (state->size - 1)) == 0x2AAA) { - state->cmd_state = NOR_CMD_55; - } else { - nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle); - nor_write_byte(state, address, value, m68k->current_cycle); - state->cmd_state = NOR_CMD_IDLE; - } - break; - case NOR_CMD_55: - if ((address & (state->size - 1)) == 0x5555) { - if (state->alt_cmd) { - switch(value) - { - case 0x10: - puts("UNIMPLEMENTED: NOR flash erase"); - break; - case 0x20: - puts("UNIMPLEMENTED: NOR flash disable protection"); - break; - case 0x40: - state->mode = NOR_BOOTBLOCK; - break; - case 0x60: - state->mode = NOR_PRODUCTID; - break; - } - } else { - switch(value) - { - case 0x80: - state->alt_cmd = 1; - break; - case 0x90: - state->mode = NOR_PRODUCTID; - break; - case 0xA0: - puts("UNIMPLEMENTED: NOR flash enable protection"); - break; - case 0xF0: - state->mode = NOR_NORMAL; - break; - default: - printf("Unrecognized unshifted NOR flash command %X\n", value); - } - } - } else { - nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle); - nor_write_byte(state, 0x2AAA, 0x55, m68k->current_cycle); - nor_write_byte(state, address, value, m68k->current_cycle); - } - state->cmd_state = NOR_CMD_IDLE; - break; - } - return vcontext; -} - -void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value) -{ - nor_flash_write_b(address, vcontext, value >> 8); - return nor_flash_write_b(address + 1, vcontext, value); -} - uint16_t read_sram_w(uint32_t address, m68k_context * context) { genesis_context * gen = context->system; @@ -531,86 +164,6 @@ } return context; } -eeprom_map *find_eeprom_map(uint32_t address, genesis_context *gen) -{ - for (int i = 0; i < gen->num_eeprom; i++) - { - if (address >= gen->eeprom_map[i].start && address <= gen->eeprom_map[i].end) { - return gen->eeprom_map + i; - } - } - return NULL; -} - -void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value) -{ - genesis_context *gen = ((m68k_context *)context)->system; - eeprom_map *map = find_eeprom_map(address, gen); - if (!map) { - fatal_error("Could not find EEPROM map for address %X\n", address); - } - if (map->scl_mask) { - set_scl(&gen->eeprom, (value & map->scl_mask) != 0); - } - if (map->sda_write_mask) { - set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); - } - return context; -} - -void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) -{ - genesis_context *gen = ((m68k_context *)context)->system; - eeprom_map *map = find_eeprom_map(address, gen); - if (!map) { - fatal_error("Could not find EEPROM map for address %X\n", address); - } - - uint16_t expanded, mask; - if (address & 1) { - expanded = value; - mask = 0xFF; - } else { - expanded = value << 8; - mask = 0xFF00; - } - if (map->scl_mask & mask) { - set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); - } - if (map->sda_write_mask & mask) { - set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); - } - return context; -} - -uint16_t read_eeprom_i2c_w(uint32_t address, void * context) -{ - genesis_context *gen = ((m68k_context *)context)->system; - eeprom_map *map = find_eeprom_map(address, gen); - if (!map) { - fatal_error("Could not find EEPROM map for address %X\n", address); - } - uint16_t ret = 0; - if (map->sda_read_bit < 16) { - ret = get_sda(&gen->eeprom) << map->sda_read_bit; - } - return ret; -} - -uint8_t read_eeprom_i2c_b(uint32_t address, void * context) -{ - genesis_context *gen = ((m68k_context *)context)->system; - eeprom_map *map = find_eeprom_map(address, gen); - if (!map) { - fatal_error("Could not find EEPROM map for address %X\n", address); - } - uint8_t bit = address & 1 ? map->sda_read_bit : map->sda_read_bit - 8; - uint8_t ret = 0; - if (bit < 8) { - ret = get_sda(&gen->eeprom) << bit; - } - return ret; -} tern_node *load_rom_db() { diff -r 3d7f668dce3d -r d94855080529 romdb.h --- a/romdb.h Thu Jun 22 23:40:05 2017 -0700 +++ b/romdb.h Fri Jun 23 21:48:38 2017 -0700 @@ -24,18 +24,6 @@ } eeprom_map; typedef struct { - char *buffer; - uint32_t size; - uint16_t address; - uint8_t host_sda; - uint8_t slave_sda; - uint8_t scl; - uint8_t state; - uint8_t counter; - uint8_t latch; -} eeprom_state; - -typedef struct { uint8_t *buffer; uint8_t *page_buffer; uint32_t size; @@ -83,8 +71,6 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks); rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks); uint8_t translate_region_char(uint8_t c); -void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size); -void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags); char const *save_type_name(uint8_t save_type); //Note: free_rom_info only frees things pointed to by a rom_info struct, not the struct itself //this is because rom_info structs are typically stack allocated