Skip to content

Commit 778b543

Browse files
committed
Fix RDRAM initialization
1 parent e170c40 commit 778b543

File tree

3 files changed

+56
-32
lines changed

3 files changed

+56
-32
lines changed

src/device/rcp/ri/ri_controller.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ static osal_inline uint32_t ri_reg(uint32_t address)
5454
return (address & 0xffff) >> 2;
5555
}
5656

57+
static osal_inline uint32_t ri_address(uint32_t address)
58+
{
59+
/* https://n64brew.dev/wiki/RDRAM_Interface#Memory_addressing */
60+
return (((address >> 20) == 0x03f)
61+
? (((address & 0x3FF))) | /* Adr[10:0] */
62+
(((address >> 10) & 0x1FF) << 11) | /* Adr[19:11] */
63+
(((address >> 10) & 0x1FF) << 20) /* Adr[28:20] */
64+
: (((address & 0x7FF))) | /* Adr[10:0] */
65+
(((address >> 11) & 0x1FF) << 11) | /* Adr[19:11] */
66+
(((address >> 20) & 0x3F) << 20)); /* Adr[28:20] */
67+
}
68+
5769
static osal_inline uint16_t ri_address_to_id_field(uint32_t address)
5870
{
5971
/* XXX: pure guessing, need harware test */

src/device/rdram/rdram.c

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include <string.h>
3232

3333
#define RDRAM_BCAST_ADDRESS_MASK UINT32_C(0x00080000)
34-
34+
#define RDRAM_MODE_CE_MASK UINT32_C(0x80000000)
3535

3636
/* XXX: deduce # of RDRAM modules from it's total size
3737
* Assume only 2Mo RDRAM modules.
@@ -59,19 +59,32 @@ static osal_inline uint16_t idfield_value(uint32_t device_id)
5959
{
6060
return ((((device_id >> 26) & 0x3f) << 0)
6161
| (((device_id >> 23) & 0x01) << 6)
62-
| (((device_id >> 16) & 0xff) << 7)
62+
| (((device_id >> 8) & 0xff) << 7)
6363
| (((device_id >> 7) & 0x01) << 15));
6464
}
6565

66+
static osal_inline uint8_t swapfield_value(uint32_t address_select)
67+
{
68+
return ((((address_select >> 25) & 0x7F) << 0)
69+
| (((address_select >> 15) & 0x01) << 7));
70+
}
71+
72+
static osal_inline uint16_t ri_address_to_idfield(uint32_t address, uint8_t swapfield)
73+
{
74+
/* https://n64brew.dev/wiki/RDRAM#RDRAM_addressing */
75+
return (((swapfield & ((address >> 11) & 0x1FF)))
76+
| ((~swapfield & ((address >> 20) & 0x1FF)))); /* AdrS[28:20] */
77+
}
78+
6679
static size_t get_module(const struct rdram* rdram, uint32_t address)
6780
{
6881
size_t module;
6982
size_t modules = get_modules_count(rdram);
70-
uint16_t id_field = ri_address_to_id_field(address);
71-
83+
uint16_t id_field;
7284

7385
for (module = 0; module < modules; ++module) {
74-
if (id_field == idfield_value(rdram->regs[module][RDRAM_DEVICE_ID_REG])) {
86+
id_field = ri_address_to_idfield(ri_address(address), swapfield_value(rdram->regs[module][RDRAM_ADDR_SELECT_REG]));
87+
if ((id_field & 0xFFFE) == (idfield_value(rdram->regs[module][RDRAM_DEVICE_ID_REG]) & 0xFFFE)) {
7588
return module;
7689
}
7790
}
@@ -87,8 +100,6 @@ static void read_rdram_dram_corrupted(void* opaque, uint32_t address, uint32_t*
87100
uint32_t addr = rdram_dram_address(address);
88101
size_t module;
89102

90-
*value = rdram->dram[addr];
91-
92103
module = get_module(rdram, address);
93104
if (module == RDRAM_MAX_MODULES_COUNT) {
94105
*value = 0;
@@ -97,7 +108,14 @@ static void read_rdram_dram_corrupted(void* opaque, uint32_t address, uint32_t*
97108

98109
/* corrupt read value if CC value is not calibrated */
99110
uint32_t mode = rdram->regs[module][RDRAM_MODE_REG] ^ UINT32_C(0xc0c0c0c0);
100-
if ((mode & 0x80000000) && (cc_value(mode) == 0)) {
111+
if ((mode & RDRAM_MODE_CE_MASK) && (cc_value(mode) == 0)) {
112+
*value = 0;
113+
return;
114+
}
115+
116+
if (address < rdram->dram_size) {
117+
*value = rdram->dram[addr];
118+
} else {
101119
*value = 0;
102120
}
103121
}
@@ -131,6 +149,7 @@ void init_rdram(struct rdram* rdram,
131149
rdram->dram = dram;
132150
rdram->dram_size = dram_size;
133151
rdram->r4300 = r4300;
152+
rdram->corrupted_handler = 0;
134153
}
135154

136155
void poweron_rdram(struct rdram* rdram)
@@ -185,33 +204,11 @@ void write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t m
185204
{
186205
struct rdram* rdram = (struct rdram*)opaque;
187206
uint32_t reg = rdram_reg(address);
207+
uint32_t mode;
208+
uint8_t corrupted_handler = 0;
188209
size_t module;
189210
size_t modules = get_modules_count(rdram);
190211

191-
/* HACK: Detect when current Control calibration is about to start,
192-
* so we can set corrupted rdram_dram handler
193-
*/
194-
if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_DELAY_REG) {
195-
map_corrupt_rdram(rdram, 1);
196-
}
197-
198-
/* HACK: Detect when current Control calibration is over,
199-
* so we can restore the original rdram_dram handler
200-
* and let dynarec have it's fast_memory enabled.
201-
*/
202-
if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_MODE_REG) {
203-
map_corrupt_rdram(rdram, 0);
204-
205-
/* HACK: In the IPL3 procedure, at this point,
206-
* the amount of detected memory can be found in s4 */
207-
size_t ipl3_rdram_size = r4300_regs(rdram->r4300)[20] & UINT32_C(0x0fffffff);
208-
if (ipl3_rdram_size != rdram->dram_size) {
209-
DebugMessage(M64MSG_WARNING, "IPL3 detected %u MB of RDRAM != %u MB",
210-
(uint32_t) ipl3_rdram_size / (1024*1024), (uint32_t) rdram->dram_size / (1024*1024));
211-
}
212-
}
213-
214-
215212
if (address & RDRAM_BCAST_ADDRESS_MASK) {
216213
for (module = 0; module < modules; ++module) {
217214
masked_write(&rdram->regs[module][reg], value, mask);
@@ -223,6 +220,19 @@ void write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t m
223220
masked_write(&rdram->regs[module][reg], value, mask);
224221
}
225222
}
223+
224+
/* toggle corrupt handler based on CC value for all modules,
225+
* only check values when writing to the mode register */
226+
if (reg == RDRAM_MODE_REG) {
227+
for (module = 0; module < modules; ++module) {
228+
mode = rdram->regs[module][RDRAM_MODE_REG] ^ UINT32_C(0xc0c0c0c0);
229+
corrupted_handler |= ((mode & RDRAM_MODE_CE_MASK) && (cc_value(mode) == 0));
230+
}
231+
if (rdram->corrupted_handler != corrupted_handler) {
232+
map_corrupt_rdram(rdram, corrupted_handler);
233+
rdram->corrupted_handler = corrupted_handler;
234+
}
235+
}
226236
}
227237

228238

src/device/rdram/rdram.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ struct rdram
5454
uint32_t* dram;
5555
size_t dram_size;
5656

57+
uint8_t corrupted_handler;
58+
5759
struct r4300_core* r4300;
5860
};
5961

0 commit comments

Comments
 (0)