1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#include "ultra64.h"
#include "ultra64/bcp.h"
s32 __osEPiRawStartDma(OSPiHandle* handle, s32 direction, u32 cartAddr, void* dramAddr, size_t size) {
#ifdef BBPLAYER
u64 dummybuf[2];
#endif
u32 status;
OSPiHandle* curHandle;
#ifdef BBPLAYER
u32 buffer;
u32 pgsize;
u16* adr;
u32 i;
#endif
status = IO_READ(PI_STATUS_REG);
while (status & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) {
status = IO_READ(PI_STATUS_REG);
}
if (__osCurrentHandle[handle->domain]->type != handle->type) {
curHandle = __osCurrentHandle[handle->domain];
if (handle->domain == 0) {
if (curHandle->latency != handle->latency) {
IO_WRITE(PI_BSD_DOM1_LAT_REG, handle->latency);
}
if (curHandle->pageSize != handle->pageSize) {
IO_WRITE(PI_BSD_DOM1_PGS_REG, handle->pageSize);
}
if (curHandle->relDuration != handle->relDuration) {
IO_WRITE(PI_BSD_DOM1_RLS_REG, handle->relDuration);
}
if (curHandle->pulse != handle->pulse) {
IO_WRITE(PI_BSD_DOM1_PWD_REG, handle->pulse);
}
} else {
if (curHandle->latency != handle->latency) {
IO_WRITE(PI_BSD_DOM2_LAT_REG, handle->latency);
}
if (curHandle->pageSize != handle->pageSize) {
IO_WRITE(PI_BSD_DOM2_PGS_REG, handle->pageSize);
}
if (curHandle->relDuration != handle->relDuration) {
IO_WRITE(PI_BSD_DOM2_RLS_REG, handle->relDuration);
}
if (curHandle->pulse != handle->pulse) {
IO_WRITE(PI_BSD_DOM2_PWD_REG, handle->pulse);
}
}
curHandle->type = handle->type;
curHandle->latency = handle->latency;
curHandle->pageSize = handle->pageSize;
curHandle->relDuration = handle->relDuration;
curHandle->pulse = handle->pulse;
}
#ifdef BBPLAYER
if (direction == OS_READ) {
// Device page size in bytes
pgsize = 1;
for (i = 1; i <= (u32)handle->pageSize + 2; i++) {
pgsize *= 2;
}
// If the initial cart address mod pgsize is at the last u16 in the page,
// need to do some manual DMAs?
if ((cartAddr & (pgsize - 1)) == pgsize - sizeof(u16)) {
// Read 32 bits starting 2 bytes before the target DMA address,
// so that the lower 16 bits of the result are the first 2 bytes
// of the requested data.
__osEPiRawReadIo(handle, cartAddr - sizeof(u16), &buffer);
// Poke the lower 16 bits into the destination address
adr = (u16*)PHYS_TO_K1(dramAddr);
*(adr++) = (u16)buffer;
// Update DMA parameters
cartAddr += sizeof(u16);
dramAddr = adr;
size -= sizeof(u16);
// If the remaining size is >= 4
if (size >= sizeof(u32)) {
// Read another 32 bits at the cart addr
__osEPiRawReadIo(handle, cartAddr, &buffer);
// Store all 32 bits to RAM
adr = (u16*)dramAddr;
*(adr++) = buffer >> 16;
*(adr++) = (u16)buffer;
// Update DMA parameters again
cartAddr += sizeof(u32);
dramAddr = adr;
size -= sizeof(u32);
// If we're not at the end of the DMA
if (size != 0) {
// Read 32 bits again
__osEPiRawReadIo(handle, cartAddr, &buffer);
// Store just the upper 16 bits
adr = (u16*)PHYS_TO_K1(dramAddr);
*(adr++) = buffer >> 16;
// Update DMA parameters once more
cartAddr += sizeof(u16);
dramAddr = adr;
size -= sizeof(u16);
}
}
}
// If the end cart address mod pgsize is just 2 bytes into a page or the remaining data size is just 1x u16
if (((((cartAddr + size) & (pgsize - 1)) == sizeof(u16)) | (size == sizeof(u16))) != 0) {
if ((cartAddr + size) & 2) {
// Read 32 bits at end - 2, store the upper 16 bits
__osEPiRawReadIo(handle, cartAddr + size - sizeof(u16), &buffer);
adr = (u16*)PHYS_TO_K1(dramAddr) + (size - sizeof(u16)) / sizeof(u16);
*adr = buffer >> 16;
} else {
// Read 32 bits at end - 4, store the lower 16 bits
__osEPiRawReadIo(handle, cartAddr + size - sizeof(u32), &buffer);
adr = (u16*)PHYS_TO_K1(dramAddr) + (size - sizeof(u16)) / sizeof(u16);
*adr = (u16)buffer;
}
size -= sizeof(u16);
}
if (size == 0) {
// If size ended up 0 following the adjustments, run an 8-byte dummy DMA anyway
size = 8;
dramAddr = (void*)dummybuf;
cartAddr = 0;
}
}
#endif
IO_WRITE(PI_DRAM_ADDR_REG, osVirtualToPhysical(dramAddr));
IO_WRITE(PI_CART_ADDR_REG, K1_TO_PHYS(handle->baseAddress | cartAddr));
#ifdef BBPLAYER
if (direction != OS_READ && direction != OS_WRITE) {
return -1;
}
if ((handle->baseAddress | cartAddr) <= 0x400) {
IO_WRITE((direction == OS_READ) ? PI_EX_WR_LEN_REG : PI_EX_RD_LEN_REG, size - 1);
} else {
IO_WRITE((direction == OS_READ) ? PI_WR_LEN_REG : PI_RD_LEN_REG, size - 1);
}
#else
switch (direction) {
case OS_READ:
IO_WRITE(PI_WR_LEN_REG, size - 1);
break;
case OS_WRITE:
IO_WRITE(PI_RD_LEN_REG, size - 1);
break;
default:
return -1;
}
#endif
return 0;
}
|