PI: name constants and fixed DMA/reset controller behaviour (#134)

* PI: name constants and fixed DMA/reset controller behaviour.

When a reset controller request is performed, only busy and error bits are cleared.
When DMAs begin, the DMA busy bit is set, but the interrupt bit shouldn't be touched yet.

* Ignore PI register write and flag error when busy.
This commit is contained in:
Nabile Rahmani 2019-11-03 17:46:44 +01:00 committed by Simon Eriksson
parent fd4cb9be51
commit 30f17b2e20
2 changed files with 30 additions and 14 deletions

View file

@ -38,14 +38,12 @@ void pi_cycle_(struct pi_controller *pi) {
// XXX: Defer actual movement of bytes until... now.
// This is a giant hack; bytes should be DMA'd slowly.
// Also, why the heck does the OR do? I know the &
// clears the busy bit, but...
pi->is_dma_read ? pi_dma_read(pi) : pi_dma_write(pi);
pi->regs[PI_DRAM_ADDR_REG] += bytes;
pi->regs[PI_CART_ADDR_REG] += bytes;
pi->regs[PI_STATUS_REG] &= ~0x1;
pi->regs[PI_STATUS_REG] |= 0x8;
pi->regs[PI_STATUS_REG] &= ~PI_STATUS_DMA_BUSY;
pi->regs[PI_STATUS_REG] |= PI_STATUS_INTERRUPT;
signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
@ -219,16 +217,21 @@ int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
debug_mmio_write(pi, pi_register_mnemonics[reg], word, dqm);
if (reg == PI_STATUS_REG) {
if (word & 0x1)
pi->regs[reg] = 0;
if (word & PI_STATUS_RESET_CONTROLLER)
pi->regs[reg] &= ~(PI_STATUS_IS_BUSY | PI_STATUS_ERROR);
if (word & 0x2) {
if (word & PI_STATUS_CLEAR_INTERRUPT) {
clear_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
pi->regs[reg] &= ~0x8;
pi->regs[reg] &= ~PI_STATUS_INTERRUPT;
}
}
else {
if (pi->regs[PI_STATUS_REG] & PI_STATUS_IS_BUSY) {
pi->regs[PI_STATUS_REG] |= PI_STATUS_ERROR;
return 0;
}
pi->regs[reg] &= ~dqm;
pi->regs[reg] |= word;
@ -237,8 +240,8 @@ int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
else if (reg == PI_WR_LEN_REG) {
if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
pi->regs[PI_STATUS_REG] &= ~0x1;
pi->regs[PI_STATUS_REG] |= 0x8;
pi->regs[PI_STATUS_REG] &= ~PI_STATUS_DMA_BUSY;
pi->regs[PI_STATUS_REG] |= PI_STATUS_INTERRUPT;
signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
return 0;
@ -246,14 +249,14 @@ int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
pi->bytes_to_copy = (pi->regs[PI_WR_LEN_REG] & 0xFFFFFF) + 1;
pi->counter = pi->bytes_to_copy / 2 + 100; // Assume ~2 bytes/clock?
pi->regs[PI_STATUS_REG] |= 0x9; // I'm busy!
pi->regs[PI_STATUS_REG] |= PI_STATUS_DMA_BUSY; // I'm busy!
pi->is_dma_read = false;
}
else if (reg == PI_RD_LEN_REG) {
if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
pi->regs[PI_STATUS_REG] &= ~0x1;
pi->regs[PI_STATUS_REG] |= 0x8;
pi->regs[PI_STATUS_REG] &= ~PI_STATUS_DMA_BUSY;
pi->regs[PI_STATUS_REG] |= PI_STATUS_INTERRUPT;
signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
return 0;
@ -261,7 +264,7 @@ int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
pi->bytes_to_copy = (pi->regs[PI_RD_LEN_REG] & 0xFFFFFF) + 1;
pi->counter = pi->bytes_to_copy / 2 + 100; // Assume ~2 bytes/clock?
pi->regs[PI_STATUS_REG] |= 0x9; // I'm busy!
pi->regs[PI_STATUS_REG] |= PI_STATUS_DMA_BUSY; // I'm busy!
pi->is_dma_read = true;
}
}

View file

@ -26,6 +26,19 @@ enum pi_register {
extern const char *pi_register_mnemonics[NUM_PI_REGISTERS];
#endif
enum pi_status {
PI_STATUS_DMA_BUSY = 1 << 0,
PI_STATUS_IO_BUSY = 1 << 1,
PI_STATUS_ERROR = 1 << 2,
PI_STATUS_INTERRUPT = 1 << 3,
PI_STATUS_IS_BUSY = PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY
};
enum pi_status_write {
PI_STATUS_RESET_CONTROLLER = 1 << 0,
PI_STATUS_CLEAR_INTERRUPT = 1 << 1
};
#define FLASHRAM_SIZE 0x20000
enum flashram_mode {