si: implement EEPROM read/write

This code does not handle saving or loading of EEPROM data from a save
file. Any save data will be lost once cen64 quits.
This commit is contained in:
Mike Ryan 2016-01-23 02:26:07 -08:00
parent adf46db9df
commit 30a2303a4a
2 changed files with 42 additions and 4 deletions

View file

@ -32,6 +32,9 @@ static void pif_process(struct si_controller *si);
static int pif_perform_command(struct si_controller *si, unsigned channel,
uint8_t *send_buf, uint8_t send_bytes, uint8_t *recv_buf, uint8_t recv_bytes);
static int eeprom_read(struct eeprom *eeprom, uint8_t *send_buf, uint8_t send_bytes, uint8_t *recv_buf, uint8_t recv_bytes);
static int eeprom_write(struct eeprom *eeprom, uint8_t *send_buf, uint8_t send_bytes, uint8_t *recv_buf, uint8_t recv_bytes);
// Initializes the SI.
int si_init(struct si_controller *si, struct bus_controller *bus,
const uint8_t *pif_rom, const uint8_t *cart_rom, bool dd_present) {
@ -66,6 +69,10 @@ int si_init(struct si_controller *si, struct bus_controller *bus,
else if (si->ram[0x26] == 0x91 && si->ram[0x27] == 0x3F)
bus_write_word(si, 0x3F0, 0x800000, ~0U);
// initialize EEPROM
si->eeprom.size = EEPROM_SIZE;
// TODO zero memory?
return 0;
}
@ -150,15 +157,13 @@ int pif_perform_command(struct si_controller *si,
case 0x04:
if (channel != 4)
assert(0 && "Invalid channel for EEPROM read");
// TODO
return 1;
return eeprom_read(&si->eeprom, send_buf, send_bytes, recv_buf, recv_bytes);
// EEPROM write
case 0x05:
if (channel != 4)
assert(0 && "Invalid channel for EEPROM write");
// TODO
return 1;
return eeprom_write(&si->eeprom, send_buf, send_bytes, recv_buf, recv_bytes);
// RTC status
case 0x06:
@ -345,3 +350,29 @@ int write_si_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
return 0;
}
int eeprom_read(struct eeprom *eeprom, uint8_t *send_buf, uint8_t send_bytes, uint8_t *recv_buf, uint8_t recv_bytes) {
assert(send_bytes == 2 && recv_bytes == 8);
uint16_t address = send_buf[1] << 3;
if (address <= eeprom->size - 8) {
memcpy(recv_buf, &eeprom->data[address], 8);
return 0;
}
return 1;
}
static int eeprom_write(struct eeprom *eeprom, uint8_t *send_buf, uint8_t send_bytes, uint8_t *recv_buf, uint8_t recv_bytes) {
assert(send_bytes == 10);
uint16_t address = send_buf[1] << 3;
if (address <= eeprom->size - 8) {
memcpy(&eeprom->data[address], send_buf + 2, 8);
return 0;
}
return 1;
}

View file

@ -25,6 +25,12 @@ enum si_register {
extern const char *si_register_mnemonics[NUM_SI_REGISTERS];
#endif
#define EEPROM_SIZE 0x800
struct eeprom {
uint8_t data[EEPROM_SIZE];
size_t size;
};
struct si_controller {
struct bus_controller *bus;
const uint8_t *rom;
@ -34,6 +40,7 @@ struct si_controller {
uint32_t regs[NUM_SI_REGISTERS];
uint32_t pif_status;
uint8_t input[4];
struct eeprom eeprom;
};
cen64_cold int si_init(struct si_controller *si, struct bus_controller *bus,