Skip to content

Commit

Permalink
Merge pull request #501 from bsmiles32/rdram
Browse files Browse the repository at this point in the history
Implement enough of RDRAM subsystem to remove rdram detection hack.
  • Loading branch information
richard42 authored Dec 16, 2017
2 parents 7d08811 + 28f7c86 commit 8ed7659
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 145 deletions.
2 changes: 0 additions & 2 deletions projects/VisualStudio2013/mupen64plus-core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@
<ClCompile Include="..\..\src\device\rcp\si\si_controller.c" />
<ClCompile Include="..\..\src\device\rcp\vi\vi_controller.c" />
<ClCompile Include="..\..\src\device\rdram\rdram.c" />
<ClCompile Include="..\..\src\device\rdram\rdram_detection_hack.c" />
<ClCompile Include="..\..\src\device\pif\cic.c" />
<ClCompile Include="..\..\src\device\pif\n64_cic_nus_6105.c" />
<ClCompile Include="..\..\src\device\pif\pif.c" />
Expand Down Expand Up @@ -449,7 +448,6 @@
<ClInclude Include="..\..\src\device\rcp\si\si_controller.h" />
<ClInclude Include="..\..\src\device\rcp\vi\vi_controller.h" />
<ClInclude Include="..\..\src\device\rdram\rdram.h" />
<ClInclude Include="..\..\src\device\rdram\rdram_detection_hack.h" />
<ClInclude Include="..\..\src\device\pif\cic.h" />
<ClInclude Include="..\..\src\device\pif\n64_cic_nus_6105.h" />
<ClInclude Include="..\..\src\device\pif\pif.h" />
Expand Down
6 changes: 0 additions & 6 deletions projects/VisualStudio2013/mupen64plus-core.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,6 @@
<ClCompile Include="..\..\src\device\rdram\rdram.c">
<Filter>device\rdram</Filter>
</ClCompile>
<ClCompile Include="..\..\src\device\rdram\rdram_detection_hack.c">
<Filter>device\rdram</Filter>
</ClCompile>
<ClCompile Include="..\..\src\device\rcp\ai\ai_controller.c">
<Filter>device\rcp\ai</Filter>
</ClCompile>
Expand Down Expand Up @@ -680,9 +677,6 @@
<ClInclude Include="..\..\src\device\rdram\rdram.h">
<Filter>device\rdram</Filter>
</ClInclude>
<ClInclude Include="..\..\src\device\rdram\rdram_detection_hack.h">
<Filter>device\rdram</Filter>
</ClInclude>
<ClInclude Include="..\..\src\device\rcp\ai\ai_controller.h">
<Filter>device\rcp\ai</Filter>
</ClInclude>
Expand Down
1 change: 0 additions & 1 deletion projects/unix/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ SOURCE = \
$(SRCDIR)/device/rcp/si/si_controller.c \
$(SRCDIR)/device/rcp/vi/vi_controller.c \
$(SRCDIR)/device/rdram/rdram.c \
$(SRCDIR)/device/rdram/rdram_detection_hack.c \
$(SRCDIR)/main/main.c \
$(SRCDIR)/main/util.c \
$(SRCDIR)/main/cheat.c \
Expand Down
6 changes: 3 additions & 3 deletions src/device/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void init_device(struct device* dev,
{ 0x00000000, 0xffffffff, M64P_MEM_NOTHING, { NULL, RW(open_bus) } },
/* memory map */
{ A(MM_RDRAM_DRAM, dram_size-1), M64P_MEM_RDRAM, { &dev->rdram, RW(rdram_dram) } },
{ A(MM_RDRAM_REGS, 0xffff), M64P_MEM_RDRAMREG, { &dev->rdram, RW(rdram_regs) } },
{ A(MM_RDRAM_REGS, 0xfffff), M64P_MEM_RDRAMREG, { &dev->rdram, RW(rdram_regs) } },
{ A(MM_RSP_MEM, 0xffff), M64P_MEM_RSPMEM, { &dev->sp, RW(rsp_mem) } },
{ A(MM_RSP_REGS, 0xffff), M64P_MEM_RSPREG, { &dev->sp, RW(rsp_regs) } },
{ A(MM_RSP_REGS2, 0xffff), M64P_MEM_RSP, { &dev->sp, RW(rsp_regs2) } },
Expand All @@ -163,7 +163,7 @@ void init_device(struct device* dev,

init_memory(&dev->mem, mappings, ARRAY_SIZE(mappings), base, &dbg_handler);

init_rdram(&dev->rdram, mem_base_u32(base, MM_RDRAM_DRAM), dram_size);
init_rdram(&dev->rdram, mem_base_u32(base, MM_RDRAM_DRAM), dram_size, &dev->r4300);

init_r4300(&dev->r4300, &dev->mem, &dev->mi, &dev->rdram, interrupt_handlers,
emumode, count_per_op, no_compiled_jump, randomize_interrupt);
Expand All @@ -173,7 +173,7 @@ void init_device(struct device* dev,
init_mi(&dev->mi, &dev->r4300);
init_pi(&dev->pi,
dev, get_pi_dma_handler,
&dev->mi, &dev->ri, &dev->pif.cic, &dev->dp);
&dev->mi, &dev->ri, &dev->dp);
init_ri(&dev->ri, &dev->rdram);
init_si(&dev->si, &dev->mi, &dev->pif, &dev->ri);
init_vi(&dev->vi, vi_clock, expected_refresh_rate, &dev->mi, &dev->dp);
Expand Down
10 changes: 0 additions & 10 deletions src/device/rcp/pi/pi_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include "device/rcp/mi/mi_controller.h"
#include "device/rcp/rdp/rdp_core.h"
#include "device/rcp/ri/ri_controller.h"
#include "device/rdram/rdram_detection_hack.h"

#define __STDC_FORMAT_MACROS
#include <inttypes.h>
Expand Down Expand Up @@ -101,13 +100,6 @@ static void dma_pi_write(struct pi_controller* pi)

post_framebuffer_write(&pi->dp->fb, dram_addr, length);

/* HACK: monitor PI DMA to trigger RDRAM size detection
* hack just before initial cart ROM loading. */
if ((cart_addr & 0x1fffffff) == (MM_CART_ROM + 0x1000))
{
force_detected_rdram_size_hack(pi->ri->rdram, pi->cic);
}

/* Mark DMA as busy */
pi->regs[PI_STATUS_REG] |= PI_STATUS_DMA_BUSY;

Expand All @@ -121,14 +113,12 @@ void init_pi(struct pi_controller* pi,
struct device* dev, pi_dma_handler_getter get_pi_dma_handler,
struct mi_controller* mi,
struct ri_controller* ri,
const struct cic* cic,
struct rdp_core* dp)
{
pi->dev = dev;
pi->get_pi_dma_handler = get_pi_dma_handler;
pi->mi = mi;
pi->ri = ri;
pi->cic = cic;
pi->dp = dp;
}

Expand Down
2 changes: 0 additions & 2 deletions src/device/rcp/pi/pi_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ struct pi_controller

struct mi_controller* mi;
struct ri_controller* ri;
const struct cic* cic;
struct rdp_core* dp;
};

Expand All @@ -82,7 +81,6 @@ void init_pi(struct pi_controller* pi,
struct device* dev, pi_dma_handler_getter get_pi_dma_handler,
struct mi_controller* mi,
struct ri_controller* ri,
const struct cic* cic,
struct rdp_core* dp);

void poweron_pi(struct pi_controller* pi);
Expand Down
10 changes: 10 additions & 0 deletions src/device/rcp/ri/ri_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ static osal_inline uint32_t ri_reg(uint32_t address)
return (address & 0xffff) >> 2;
}

static osal_inline uint16_t ri_address_to_id_field(uint32_t address)
{
/* XXX: pure guessing, need harware test */
return ((address >> 20) == 0x03f)
? (address & 0x0007fc00) >> 10 /* RDRAM registers id_field: [19..10] */
: (address & 0x00f00000) >> 20; /* RDRAM memory id_field: [23..20] */
}



void init_ri(struct ri_controller* ri, struct rdram* rdram);

void poweron_ri(struct ri_controller* ri);
Expand Down
180 changes: 173 additions & 7 deletions src/device/rdram/rdram.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,206 @@

#include "rdram.h"

#include "api/m64p_types.h"
#include "api/callbacks.h"
#include "device/device.h"
#include "device/memory/memory.h"
#include "device/r4300/r4300_core.h"
#include "device/rcp/ri/ri_controller.h"

#include <string.h>

#include "device/memory/memory.h"
#define RDRAM_BCAST_ADDRESS_MASK UINT32_C(0x00080000)


/* XXX: deduce # of RDRAM modules from it's total size
* Assume only 2Mo RDRAM modules.
* Proper way of doing it would be to declare in init_rdram
* what kind of modules we insert and deduce dram_size from
* that configuration.
*/
static size_t get_modules_count(const struct rdram* rdram)
{
return (rdram->dram_size) / 0x200000;
}

static uint8_t cc_value(uint32_t mode_reg)
{
return ((mode_reg & 0x00000040) >> 6)
| ((mode_reg & 0x00004000) >> 13)
| ((mode_reg & 0x00400000) >> 20)
| ((mode_reg & 0x00000080) >> 4)
| ((mode_reg & 0x00008000) >> 11)
| ((mode_reg & 0x00800000) >> 18);
}


static osal_inline uint16_t idfield_value(uint32_t device_id)
{
return ((((device_id >> 26) & 0x3f) << 0)
| (((device_id >> 23) & 0x01) << 6)
| (((device_id >> 16) & 0xff) << 7)
| (((device_id >> 7) & 0x01) << 15));
}

static size_t get_module(const struct rdram* rdram, uint32_t address)
{
size_t module;
size_t modules = get_modules_count(rdram);
uint16_t id_field = ri_address_to_id_field(address);


for (module = 0; module < modules; ++module) {
if (id_field == idfield_value(rdram->regs[module][RDRAM_DEVICE_ID_REG])) {
return module;
}
}

/* can happen during memory detection because
* it probes potentialy non present RDRAM */
return RDRAM_MAX_MODULES_COUNT;
}

static void read_rdram_dram_corrupted(void* opaque, uint32_t address, uint32_t* value)
{
struct rdram* rdram = (struct rdram*)opaque;
uint32_t addr = rdram_dram_address(address);
size_t module;

*value = rdram->dram[addr];

module = get_module(rdram, address);
if (module == RDRAM_MAX_MODULES_COUNT) {
*value = 0;
return;
}

/* corrupt read value if CC value is not calibrated */
uint32_t mode = rdram->regs[module][RDRAM_MODE_REG] ^ UINT32_C(0xc0c0c0c0);
if ((mode & 0x80000000) && (cc_value(mode) == 0)) {
*value = 0;
}
}

static void map_corrupt_rdram(struct rdram* rdram, int corrupt)
{
struct mem_mapping mapping;

mapping.begin = MM_RDRAM_DRAM;
mapping.end = MM_RDRAM_DRAM + rdram->dram_size - 1;
mapping.type = M64P_MEM_RDRAM;
mapping.handler.opaque = rdram;
mapping.handler.read32 = (corrupt)
? read_rdram_dram_corrupted
: read_rdram_dram;
mapping.handler.write32 = write_rdram_dram;

apply_mem_mapping(rdram->r4300->mem, &mapping);
rdram->r4300->recomp.fast_memory = (corrupt) ? 0 : 1;
invalidate_r4300_cached_code(rdram->r4300, 0, 0);
}


void init_rdram(struct rdram* rdram,
uint32_t* dram,
size_t dram_size)
size_t dram_size,
struct r4300_core* r4300)
{
rdram->dram = dram;
rdram->dram_size = dram_size;
rdram->r4300 = r4300;
}

void poweron_rdram(struct rdram* rdram)
{
memset(rdram->regs, 0, RDRAM_REGS_COUNT*sizeof(uint32_t));
size_t module;
size_t modules = get_modules_count(rdram);
memset(rdram->regs, 0, RDRAM_MAX_MODULES_COUNT*RDRAM_REGS_COUNT*sizeof(uint32_t));
memset(rdram->dram, 0, rdram->dram_size);

DebugMessage(M64MSG_INFO, "Initializing %u RDRAM modules for a total of %u MB",
modules, rdram->dram_size / (1024*1024));

for (module = 0; module < modules; ++module) {
rdram->regs[module][RDRAM_CONFIG_REG] = UINT32_C(0xb5190010);
rdram->regs[module][RDRAM_DEVICE_ID_REG] = UINT32_C(0x00000000);
rdram->regs[module][RDRAM_DELAY_REG] = UINT32_C(0x230b0223);
rdram->regs[module][RDRAM_MODE_REG] = UINT32_C(0xc4c0c0c0);
rdram->regs[module][RDRAM_REF_ROW_REG] = UINT32_C(0x00000000);
rdram->regs[module][RDRAM_MIN_INTERVAL_REG] = UINT32_C(0x0040c0e0);
rdram->regs[module][RDRAM_ADDR_SELECT_REG] = UINT32_C(0x00000000);
rdram->regs[module][RDRAM_DEVICE_MANUF_REG] = UINT32_C(0x00000500);
}
}


void read_rdram_regs(void* opaque, uint32_t address, uint32_t* value)
{
struct rdram* rdram = (struct rdram*)opaque;
uint32_t reg = rdram_reg(address);
size_t module;

if (address & RDRAM_BCAST_ADDRESS_MASK) {
DebugMessage(M64MSG_WARNING, "Reading from broadcast address is unsupported %08x", address);
return;
}

*value = rdram->regs[reg];
module = get_module(rdram, address);
if (module == RDRAM_MAX_MODULES_COUNT) {
*value = 0;
return;
}

*value = rdram->regs[module][reg];

/* some bits are inverted when read */
if (reg == RDRAM_MODE_REG) {
*value ^= UINT32_C(0xc0c0c0c0);
}
}

void write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
{
struct rdram* rdram = (struct rdram*)opaque;
uint32_t reg = rdram_reg(address);

masked_write(&rdram->regs[reg], value, mask);
size_t module;
size_t modules = get_modules_count(rdram);

/* HACK: Detect when current Control calibration is about to start,
* so we can set corrupted rdram_dram handler
*/
if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_DELAY_REG) {
map_corrupt_rdram(rdram, 1);
}

/* HACK: Detect when current Control calibration is over,
* so we can restore the original rdram_dram handler
* and let dynarec have it's fast_memory enabled.
*/
if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_MODE_REG) {
map_corrupt_rdram(rdram, 0);

/* HACK: In the IPL3 procedure, at this point,
* the amount of detected memory can be found in s4 */
size_t ipl3_rdram_size = rdram->r4300->regs[20] & UINT32_C(0x0fffffff);
if (ipl3_rdram_size != rdram->dram_size) {
DebugMessage(M64MSG_ERROR, "IPL3 detected %u MB of RDRAM != %u MB",
ipl3_rdram_size / (1024*1024), rdram->dram_size / (1024*1024));
}
}


if (address & RDRAM_BCAST_ADDRESS_MASK) {
for (module = 0; module < modules; ++module) {
masked_write(&rdram->regs[module][reg], value, mask);
}
}
else {
module = get_module(rdram, address);
if (module != RDRAM_MAX_MODULES_COUNT) {
masked_write(&rdram->regs[module][reg], value, mask);
}
}
}


Expand All @@ -72,4 +239,3 @@ void write_rdram_dram(void* opaque, uint32_t address, uint32_t value, uint32_t m

masked_write(&rdram->dram[addr], value, mask);
}

13 changes: 11 additions & 2 deletions src/device/rdram/rdram.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

#include "osal/preproc.h"

struct r4300_core;

enum rdram_registers
{
RDRAM_CONFIG_REG,
Expand All @@ -42,11 +44,17 @@ enum rdram_registers
RDRAM_REGS_COUNT
};

/* IPL3 rdram initialization accepts up to 8 RDRAM modules */
enum { RDRAM_MAX_MODULES_COUNT = 8 };

struct rdram
{
uint32_t regs[RDRAM_REGS_COUNT];
uint32_t regs[RDRAM_MAX_MODULES_COUNT][RDRAM_REGS_COUNT];

uint32_t* dram;
size_t dram_size;

struct r4300_core* r4300;
};

static osal_inline uint32_t rdram_reg(uint32_t address)
Expand All @@ -61,7 +69,8 @@ static osal_inline uint32_t rdram_dram_address(uint32_t address)

void init_rdram(struct rdram* rdram,
uint32_t* dram,
size_t dram_size);
size_t dram_size,
struct r4300_core* r4300);

void poweron_rdram(struct rdram* rdram);

Expand Down
Loading

0 comments on commit 8ed7659

Please sign in to comment.