Mercurial > repos > blastem
diff romdb.c @ 1414:d94855080529
Move I2C EEPROM and NOR Flash functions out of romdb.c into new files
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 23 Jun 2017 21:48:38 -0700 |
parents | 3d7f668dce3d |
children | f7d653bb8899 |
line wrap: on
line diff
--- 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() {