summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar MerryMage2016-03-06 21:13:12 +0000
committerGravatar MerryMage2016-03-06 21:25:44 +0000
commit004991d79e991cf7825ab95fceecb4324d9b3c8c (patch)
tree066e17358e9debf470bd10f3bbc667631bfbbbd8 /src/core
parentMerge pull request #1463 from yuriks/non-app-region (diff)
downloadyuzu-004991d79e991cf7825ab95fceecb4324d9b3c8c.tar.gz
yuzu-004991d79e991cf7825ab95fceecb4324d9b3c8c.tar.xz
yuzu-004991d79e991cf7825ab95fceecb4324d9b3c8c.zip
DSP: Implement Pipe 2
Pipe 2 is a DSP pipe that is used to initialize both the DSP hardware (the application signals to the DSP to initialize) and the application (the DSP provides the memory location of structures in the shared memory region).
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/service/dsp_dsp.cpp194
1 files changed, 151 insertions, 43 deletions
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index 22e85cfc6..3ba24d466 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -58,10 +58,10 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
58 58
59 u32 addr = cmd_buff[1]; 59 u32 addr = cmd_buff[1];
60 60
61 cmd_buff[1] = 0; // No error 61 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
62 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); 62 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000);
63 63
64 LOG_TRACE(Service_DSP, "addr=0x%08X", addr); 64 LOG_DEBUG(Service_DSP, "addr=0x%08X", addr);
65} 65}
66 66
67/** 67/**
@@ -142,8 +142,7 @@ static void FlushDataCache(Service::Interface* self) {
142 142
143 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 143 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
144 144
145 LOG_DEBUG(Service_DSP, "(STUBBED) called address=0x%08X, size=0x%X, process=0x%08X", 145 LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process);
146 address, size, process);
147} 146}
148 147
149/** 148/**
@@ -167,14 +166,14 @@ static void RegisterInterruptEvents(Service::Interface* self) {
167 if (evt) { 166 if (evt) {
168 interrupt_events[std::make_pair(interrupt, channel)] = evt; 167 interrupt_events[std::make_pair(interrupt, channel)] = evt;
169 cmd_buff[1] = RESULT_SUCCESS.raw; 168 cmd_buff[1] = RESULT_SUCCESS.raw;
170 LOG_WARNING(Service_DSP, "Registered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); 169 LOG_INFO(Service_DSP, "Registered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
171 } else { 170 } else {
172 cmd_buff[1] = -1; 171 LOG_CRITICAL(Service_DSP, "Invalid event handle! interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
173 LOG_ERROR(Service_DSP, "Invalid event handle! interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); 172 ASSERT(false); // This should really be handled at a IPC translation layer.
174 } 173 }
175 } else { 174 } else {
176 interrupt_events.erase(std::make_pair(interrupt, channel)); 175 interrupt_events.erase(std::make_pair(interrupt, channel));
177 LOG_WARNING(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); 176 LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
178 } 177 }
179} 178}
180 179
@@ -188,7 +187,7 @@ static void RegisterInterruptEvents(Service::Interface* self) {
188static void SetSemaphore(Service::Interface* self) { 187static void SetSemaphore(Service::Interface* self) {
189 u32* cmd_buff = Kernel::GetCommandBuffer(); 188 u32* cmd_buff = Kernel::GetCommandBuffer();
190 189
191 cmd_buff[1] = 0; // No error 190 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
192 191
193 LOG_WARNING(Service_DSP, "(STUBBED) called"); 192 LOG_WARNING(Service_DSP, "(STUBBED) called");
194} 193}
@@ -207,21 +206,12 @@ static void SetSemaphore(Service::Interface* self) {
207static void WriteProcessPipe(Service::Interface* self) { 206static void WriteProcessPipe(Service::Interface* self) {
208 u32* cmd_buff = Kernel::GetCommandBuffer(); 207 u32* cmd_buff = Kernel::GetCommandBuffer();
209 208
210 u32 channel = cmd_buff[1]; 209 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
211 u32 size = cmd_buff[2]; 210 u32 size = cmd_buff[2];
212 u32 buffer = cmd_buff[4]; 211 u32 buffer = cmd_buff[4];
213 212
214 if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { 213 ASSERT_MSG(IPC::StaticBufferDesc(size, 1) == cmd_buff[3], "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe, size, buffer);
215 LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). channel=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], channel, size, buffer); 214 ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
216 cmd_buff[1] = -1; // TODO
217 return;
218 }
219
220 if (!Memory::GetPointer(buffer)) {
221 LOG_ERROR(Service_DSP, "Invalid Buffer: channel=%u, size=0x%X, buffer=0x%08X", channel, size, buffer);
222 cmd_buff[1] = -1; // TODO
223 return;
224 }
225 215
226 std::vector<u8> message(size); 216 std::vector<u8> message(size);
227 217
@@ -229,11 +219,11 @@ static void WriteProcessPipe(Service::Interface* self) {
229 message[i] = Memory::Read8(buffer + i); 219 message[i] = Memory::Read8(buffer + i);
230 } 220 }
231 221
232 DSP::HLE::PipeWrite(channel, message); 222 DSP::HLE::PipeWrite(pipe, message);
233 223
234 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 224 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
235 225
236 LOG_TRACE(Service_DSP, "channel=%u, size=0x%X, buffer=0x%08X", channel, size, buffer); 226 LOG_DEBUG(Service_DSP, "pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
237} 227}
238 228
239/** 229/**
@@ -245,7 +235,7 @@ static void WriteProcessPipe(Service::Interface* self) {
245 * 1 : Pipe Number 235 * 1 : Pipe Number
246 * 2 : Unknown 236 * 2 : Unknown
247 * 3 : Size in bytes of read (observed only lower half word used) 237 * 3 : Size in bytes of read (observed only lower half word used)
248 * 0x41 : Virtual address to read from DSP pipe to in memory 238 * 0x41 : Virtual address of memory buffer to write pipe contents to
249 * Outputs: 239 * Outputs:
250 * 1 : Result of function, 0 on success, otherwise error code 240 * 1 : Result of function, 0 on success, otherwise error code
251 * 2 : Number of bytes read from pipe 241 * 2 : Number of bytes read from pipe
@@ -253,25 +243,82 @@ static void WriteProcessPipe(Service::Interface* self) {
253static void ReadPipeIfPossible(Service::Interface* self) { 243static void ReadPipeIfPossible(Service::Interface* self) {
254 u32* cmd_buff = Kernel::GetCommandBuffer(); 244 u32* cmd_buff = Kernel::GetCommandBuffer();
255 245
256 u32 pipe = cmd_buff[1]; 246 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
257 u32 unk2 = cmd_buff[2]; 247 u32 unknown = cmd_buff[2];
258 u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size 248 u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size
259 VAddr addr = cmd_buff[0x41]; 249 VAddr addr = cmd_buff[0x41];
260 250
261 if (!Memory::GetPointer(addr)) { 251 ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
262 LOG_ERROR(Service_DSP, "Invalid addr: pipe=0x%08X, unk2=0x%08X, size=0x%X, buffer=0x%08X", pipe, unk2, size, addr); 252
263 cmd_buff[1] = -1; // TODO 253 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
264 return; 254 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
255 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
256
257 Memory::WriteBlock(addr, response.data(), response.size());
258
259 cmd_buff[2] = static_cast<u32>(response.size());
260 } else {
261 cmd_buff[2] = 0; // Return no data
265 } 262 }
266 263
267 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); 264 LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]);
265}
268 266
269 Memory::WriteBlock(addr, response.data(), response.size()); 267/**
268 * DSP_DSP::ReadPipe service function
269 * Inputs:
270 * 1 : Pipe Number
271 * 2 : Unknown
272 * 3 : Size in bytes of read (observed only lower half word used)
273 * 0x41 : Virtual address of memory buffer to write pipe contents to
274 * Outputs:
275 * 1 : Result of function, 0 on success, otherwise error code
276 * 2 : Number of bytes read from pipe
277 */
278static void ReadPipe(Service::Interface* self) {
279 u32* cmd_buff = Kernel::GetCommandBuffer();
280
281 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
282 u32 unknown = cmd_buff[2];
283 u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size
284 VAddr addr = cmd_buff[0x41];
270 285
271 cmd_buff[1] = 0; // No error 286 ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
272 cmd_buff[2] = (u32)response.size();
273 287
274 LOG_TRACE(Service_DSP, "pipe=0x%08X, unk2=0x%08X, size=0x%X, buffer=0x%08X", pipe, unk2, size, addr); 288 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
289 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
290
291 Memory::WriteBlock(addr, response.data(), response.size());
292
293 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
294 cmd_buff[2] = static_cast<u32>(response.size());
295 } else {
296 // No more data is in pipe. Hardware hangs in this case; this should never happen.
297 UNREACHABLE();
298 }
299
300 LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]);
301}
302
303/**
304 * DSP_DSP::GetPipeReadableSize service function
305 * Inputs:
306 * 1 : Pipe Number
307 * 2 : Unknown
308 * Outputs:
309 * 1 : Result of function, 0 on success, otherwise error code
310 * 2 : Number of bytes readable from pipe
311 */
312static void GetPipeReadableSize(Service::Interface* self) {
313 u32* cmd_buff = Kernel::GetCommandBuffer();
314
315 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
316 u32 unknown = cmd_buff[2];
317
318 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
319 cmd_buff[2] = DSP::HLE::GetPipeReadableSize(pipe);
320
321 LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, cmd_buff[2]);
275} 322}
276 323
277/** 324/**
@@ -306,12 +353,73 @@ static void GetHeadphoneStatus(Service::Interface* self) {
306 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 353 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
307 cmd_buff[2] = 0; // Not using headphones? 354 cmd_buff[2] = 0; // Not using headphones?
308 355
309 LOG_DEBUG(Service_DSP, "(STUBBED) called"); 356 LOG_WARNING(Service_DSP, "(STUBBED) called");
357}
358
359/**
360 * DSP_DSP::RecvData service function
361 * This function reads a value out of a DSP register.
362 * Inputs:
363 * 1 : Register Number
364 * Outputs:
365 * 1 : Result of function, 0 on success, otherwise error code
366 * 2 : Value in the register
367 * Notes:
368 * This function has only been observed being called with a register number of 0.
369 */
370static void RecvData(Service::Interface* self) {
371 u32* cmd_buff = Kernel::GetCommandBuffer();
372
373 u32 register_number = cmd_buff[1];
374
375 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
376
377 // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept.
378
379 cmd_buff[1] = RESULT_SUCCESS.raw;
380 switch (DSP::HLE::GetDspState()) {
381 case DSP::HLE::DspState::On:
382 cmd_buff[2] = 0;
383 break;
384 case DSP::HLE::DspState::Off:
385 case DSP::HLE::DspState::Sleeping:
386 cmd_buff[2] = 1;
387 break;
388 default:
389 UNREACHABLE();
390 break;
391 }
392
393 LOG_DEBUG(Service_DSP, "register_number=%u", register_number);
394}
395
396/**
397 * DSP_DSP::RecvDataIsReady service function
398 * This function checks whether a DSP register is ready to be read.
399 * Inputs:
400 * 1 : Register Number
401 * Outputs:
402 * 1 : Result of function, 0 on success, otherwise error code
403 * 2 : non-zero == ready
404 * Note:
405 * This function has only been observed being called with a register number of 0.
406 */
407static void RecvDataIsReady(Service::Interface* self) {
408 u32* cmd_buff = Kernel::GetCommandBuffer();
409
410 u32 register_number = cmd_buff[1];
411
412 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
413
414 cmd_buff[1] = RESULT_SUCCESS.raw;
415 cmd_buff[2] = 1; // Ready to read
416
417 LOG_DEBUG(Service_DSP, "register_number=%u", register_number);
310} 418}
311 419
312const Interface::FunctionInfo FunctionTable[] = { 420const Interface::FunctionInfo FunctionTable[] = {
313 {0x00010040, nullptr, "RecvData"}, 421 {0x00010040, RecvData, "RecvData"},
314 {0x00020040, nullptr, "RecvDataIsReady"}, 422 {0x00020040, RecvDataIsReady, "RecvDataIsReady"},
315 {0x00030080, nullptr, "SendData"}, 423 {0x00030080, nullptr, "SendData"},
316 {0x00040040, nullptr, "SendDataIsEmpty"}, 424 {0x00040040, nullptr, "SendDataIsEmpty"},
317 {0x000500C2, nullptr, "SendFifoEx"}, 425 {0x000500C2, nullptr, "SendFifoEx"},
@@ -323,8 +431,8 @@ const Interface::FunctionInfo FunctionTable[] = {
323 {0x000B0000, nullptr, "CheckSemaphoreRequest"}, 431 {0x000B0000, nullptr, "CheckSemaphoreRequest"},
324 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"}, 432 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
325 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"}, 433 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"},
326 {0x000E00C0, nullptr, "ReadPipe"}, 434 {0x000E00C0, ReadPipe, "ReadPipe"},
327 {0x000F0080, nullptr, "GetPipeReadableSize"}, 435 {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"},
328 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"}, 436 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"},
329 {0x001100C2, LoadComponent, "LoadComponent"}, 437 {0x001100C2, LoadComponent, "LoadComponent"},
330 {0x00120000, nullptr, "UnloadComponent"}, 438 {0x00120000, nullptr, "UnloadComponent"},