// // rdp/interface.c: RDP interface. // // CEN64: Cycle-Accurate Nintendo 64 Emulator. // Copyright (C) 2015, Tyler J. Stachecki. // // This file is subject to the terms and conditions defined in // 'LICENSE', which is part of this source code package. // #include "common.h" #include "bus/address.h" #include "bus/controller.h" #include "rdp/cpu.h" #include "rdp/interface.h" #include "rsp/cpu.h" #include "thread.h" #define DP_XBUS_DMEM_DMA 0x00000001 #define DP_FREEZE 0x00000002 #define DP_FLUSH 0x00000004 #define DP_CLEAR_XBUS_DMEM_DMA 0x00000001 #define DP_SET_XBUS_DMEM_DMA 0x00000002 #define DP_CLEAR_FREEZE 0x00000004 #define DP_SET_FREEZE 0x00000008 #define DP_CLEAR_FLUSH 0x00000010 #define DP_SET_FLUSH 0x00000020 unsigned rdp_process_list(struct rdp *rdp); // Reads a word from the DP MMIO register space. int read_dp_regs(void *opaque, uint32_t address, uint32_t *word) { struct rdp *rdp = (struct rdp *) opaque; uint32_t offset = address - DP_REGS_BASE_ADDRESS; enum dp_register reg = (offset >> 2); cen64_mutex_lock(&rdp->rdp_mutex); *word = rdp->regs[reg]; cen64_mutex_unlock(&rdp->rdp_mutex); debug_mmio_read(dp, dp_register_mnemonics[reg], *word); return 0; } // Writes a word to the DP MMIO register space. int write_dp_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) { struct rdp *rdp = (struct rdp *) opaque; uint32_t offset = address - DP_REGS_BASE_ADDRESS; enum dp_register reg = (offset >> 2); unsigned dl_length; debug_mmio_write(dp, dp_register_mnemonics[reg], word, dqm); cen64_mutex_lock(&rdp->rdp_mutex); switch (reg) { case DPC_START_REG: rdp->regs[DPC_CURRENT_REG] = word & ~0x7; rdp->regs[DPC_START_REG] = word & ~0x7; break; case DPC_END_REG: rdp->regs[DPC_END_REG] = word & ~0x7; if ((dl_length = rdp_process_list(rdp))) { cen64_cv_signal(&rdp->rdp_signal); cen64_mutex_unlock(&rdp->rdp_mutex); rdp->bus->rsp->rdp_has_pending_dl = 1; return 0; } break; case DPC_STATUS_REG: if (word & DP_CLEAR_XBUS_DMEM_DMA) rdp->regs[DPC_STATUS_REG] &= ~DP_XBUS_DMEM_DMA; else if (word & DP_SET_XBUS_DMEM_DMA) rdp->regs[DPC_STATUS_REG] |= DP_XBUS_DMEM_DMA; if (word & DP_CLEAR_FREEZE) rdp->regs[DPC_STATUS_REG] &= ~DP_FREEZE; // else if (word & DP_SET_FREEZE) // rdp->regs[DPC_STATUS_REG] |= DP_FREEZE; if (word & DP_CLEAR_FLUSH) rdp->regs[DPC_STATUS_REG] &= ~DP_FLUSH; else if (word & DP_SET_FLUSH) rdp->regs[DPC_STATUS_REG] |= DP_FLUSH; break; default: rdp->regs[reg] &= ~dqm; rdp->regs[reg] |= word; break; } cen64_mutex_unlock(&rdp->rdp_mutex); return 0; }