dsp_dsp.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <cinttypes>
  5. #include "audio_core/hle/pipe.h"
  6. #include "common/hash.h"
  7. #include "common/logging/log.h"
  8. #include "core/hle/kernel/event.h"
  9. #include "core/hle/service/dsp_dsp.h"
  10. ////////////////////////////////////////////////////////////////////////////////////////////////////
  11. // Namespace DSP_DSP
  12. namespace DSP_DSP {
  13. static u32 read_pipe_count;
  14. static Kernel::SharedPtr<Kernel::Event> semaphore_event;
  15. struct PairHash {
  16. template <typename T, typename U>
  17. std::size_t operator()(const std::pair<T, U> &x) const {
  18. // TODO(yuriks): Replace with better hash combining function.
  19. return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
  20. }
  21. };
  22. /// Map of (audio interrupt number, channel number) to Kernel::Events. See: RegisterInterruptEvents
  23. static std::unordered_map<std::pair<u32, u32>, Kernel::SharedPtr<Kernel::Event>, PairHash> interrupt_events;
  24. // DSP Interrupts:
  25. // Interrupt #2 occurs every frame tick. Userland programs normally have a thread that's waiting
  26. // for an interrupt event. Immediately after this interrupt event, userland normally updates the
  27. // state in the next region and increments the relevant frame counter by two.
  28. void SignalAllInterrupts() {
  29. // HACK: The other interrupts have currently unknown purpose, we trigger them each tick in any case.
  30. for (auto& interrupt_event : interrupt_events)
  31. interrupt_event.second->Signal();
  32. }
  33. void SignalInterrupt(u32 interrupt, u32 channel) {
  34. interrupt_events[std::make_pair(interrupt, channel)]->Signal();
  35. }
  36. /**
  37. * DSP_DSP::ConvertProcessAddressFromDspDram service function
  38. * Inputs:
  39. * 1 : Address
  40. * Outputs:
  41. * 1 : Result of function, 0 on success, otherwise error code
  42. * 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address)
  43. */
  44. static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
  45. u32* cmd_buff = Kernel::GetCommandBuffer();
  46. u32 addr = cmd_buff[1];
  47. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  48. cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000);
  49. LOG_DEBUG(Service_DSP, "addr=0x%08X", addr);
  50. }
  51. /**
  52. * DSP_DSP::LoadComponent service function
  53. * Inputs:
  54. * 1 : Size
  55. * 2 : Program mask (observed only half word used)
  56. * 3 : Data mask (observed only half word used)
  57. * 4 : (size << 4) | 0xA
  58. * 5 : Buffer address
  59. * Outputs:
  60. * 1 : Result of function, 0 on success, otherwise error code
  61. * 2 : Component loaded, 0 on not loaded, 1 on loaded
  62. */
  63. static void LoadComponent(Service::Interface* self) {
  64. u32* cmd_buff = Kernel::GetCommandBuffer();
  65. u32 size = cmd_buff[1];
  66. u32 prog_mask = cmd_buff[2];
  67. u32 data_mask = cmd_buff[3];
  68. u32 desc = cmd_buff[4];
  69. u32 buffer = cmd_buff[5];
  70. cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2);
  71. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  72. cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
  73. cmd_buff[3] = desc;
  74. cmd_buff[4] = buffer;
  75. // TODO(bunnei): Implement real DSP firmware loading
  76. ASSERT(Memory::GetPointer(buffer) != nullptr);
  77. ASSERT(size > 0x37C);
  78. LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer), size));
  79. // Some versions of the firmware have the location of DSP structures listed here.
  80. LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer) + 0x340, 60));
  81. LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X",
  82. size, prog_mask, data_mask, buffer);
  83. }
  84. /**
  85. * DSP_DSP::GetSemaphoreEventHandle service function
  86. * Outputs:
  87. * 1 : Result of function, 0 on success, otherwise error code
  88. * 3 : Semaphore event handle
  89. */
  90. static void GetSemaphoreEventHandle(Service::Interface* self) {
  91. u32* cmd_buff = Kernel::GetCommandBuffer();
  92. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  93. cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle
  94. LOG_WARNING(Service_DSP, "(STUBBED) called");
  95. }
  96. /**
  97. * DSP_DSP::FlushDataCache service function
  98. *
  99. * This Function is a no-op, We aren't emulating the CPU cache any time soon.
  100. *
  101. * Inputs:
  102. * 1 : Address
  103. * 2 : Size
  104. * 3 : Value 0, some descriptor for the KProcess Handle
  105. * 4 : KProcess handle
  106. * Outputs:
  107. * 1 : Result of function, 0 on success, otherwise error code
  108. */
  109. static void FlushDataCache(Service::Interface* self) {
  110. u32* cmd_buff = Kernel::GetCommandBuffer();
  111. u32 address = cmd_buff[1];
  112. u32 size = cmd_buff[2];
  113. u32 process = cmd_buff[4];
  114. // TODO(purpasmart96): Verify return header on HW
  115. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  116. LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process);
  117. }
  118. /**
  119. * DSP_DSP::RegisterInterruptEvents service function
  120. * Inputs:
  121. * 1 : Interrupt Number
  122. * 2 : Channel Number
  123. * 4 : Interrupt event handle
  124. * Outputs:
  125. * 1 : Result of function, 0 on success, otherwise error code
  126. */
  127. static void RegisterInterruptEvents(Service::Interface* self) {
  128. u32* cmd_buff = Kernel::GetCommandBuffer();
  129. u32 interrupt = cmd_buff[1];
  130. u32 channel = cmd_buff[2];
  131. u32 event_handle = cmd_buff[4];
  132. if (event_handle) {
  133. auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
  134. if (evt) {
  135. interrupt_events[std::make_pair(interrupt, channel)] = evt;
  136. cmd_buff[1] = RESULT_SUCCESS.raw;
  137. LOG_INFO(Service_DSP, "Registered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
  138. } else {
  139. LOG_CRITICAL(Service_DSP, "Invalid event handle! interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
  140. ASSERT(false); // This should really be handled at a IPC translation layer.
  141. }
  142. } else {
  143. interrupt_events.erase(std::make_pair(interrupt, channel));
  144. LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
  145. }
  146. }
  147. /**
  148. * DSP_DSP::SetSemaphore service function
  149. * Inputs:
  150. * 1 : Unknown (observed only half word used)
  151. * Outputs:
  152. * 1 : Result of function, 0 on success, otherwise error code
  153. */
  154. static void SetSemaphore(Service::Interface* self) {
  155. u32* cmd_buff = Kernel::GetCommandBuffer();
  156. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  157. LOG_WARNING(Service_DSP, "(STUBBED) called");
  158. }
  159. /**
  160. * DSP_DSP::WriteProcessPipe service function
  161. * Inputs:
  162. * 1 : Channel
  163. * 2 : Size
  164. * 3 : (size << 14) | 0x402
  165. * 4 : Buffer
  166. * Outputs:
  167. * 0 : Return header
  168. * 1 : Result of function, 0 on success, otherwise error code
  169. */
  170. static void WriteProcessPipe(Service::Interface* self) {
  171. u32* cmd_buff = Kernel::GetCommandBuffer();
  172. DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
  173. u32 size = cmd_buff[2];
  174. u32 buffer = cmd_buff[4];
  175. 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);
  176. ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
  177. std::vector<u8> message(size);
  178. for (size_t i = 0; i < size; i++) {
  179. message[i] = Memory::Read8(buffer + i);
  180. }
  181. DSP::HLE::PipeWrite(pipe, message);
  182. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  183. LOG_DEBUG(Service_DSP, "pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
  184. }
  185. /**
  186. * DSP_DSP::ReadPipeIfPossible service function
  187. * A pipe is a means of communication between the ARM11 and DSP that occurs on
  188. * hardware by writing to/reading from the DSP registers at 0x10203000.
  189. * Pipes are used for initialisation. See also DSP::HLE::PipeRead.
  190. * Inputs:
  191. * 1 : Pipe Number
  192. * 2 : Unknown
  193. * 3 : Size in bytes of read (observed only lower half word used)
  194. * 0x41 : Virtual address of memory buffer to write pipe contents to
  195. * Outputs:
  196. * 1 : Result of function, 0 on success, otherwise error code
  197. * 2 : Number of bytes read from pipe
  198. */
  199. static void ReadPipeIfPossible(Service::Interface* self) {
  200. u32* cmd_buff = Kernel::GetCommandBuffer();
  201. DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
  202. u32 unknown = cmd_buff[2];
  203. u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size
  204. VAddr addr = cmd_buff[0x41];
  205. ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
  206. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  207. if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
  208. std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
  209. Memory::WriteBlock(addr, response.data(), response.size());
  210. cmd_buff[2] = static_cast<u32>(response.size());
  211. } else {
  212. cmd_buff[2] = 0; // Return no data
  213. }
  214. 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]);
  215. }
  216. /**
  217. * DSP_DSP::ReadPipe service function
  218. * Inputs:
  219. * 1 : Pipe Number
  220. * 2 : Unknown
  221. * 3 : Size in bytes of read (observed only lower half word used)
  222. * 0x41 : Virtual address of memory buffer to write pipe contents to
  223. * Outputs:
  224. * 1 : Result of function, 0 on success, otherwise error code
  225. * 2 : Number of bytes read from pipe
  226. */
  227. static void ReadPipe(Service::Interface* self) {
  228. u32* cmd_buff = Kernel::GetCommandBuffer();
  229. DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
  230. u32 unknown = cmd_buff[2];
  231. u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size
  232. VAddr addr = cmd_buff[0x41];
  233. ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
  234. if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
  235. std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
  236. Memory::WriteBlock(addr, response.data(), response.size());
  237. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  238. cmd_buff[2] = static_cast<u32>(response.size());
  239. } else {
  240. // No more data is in pipe. Hardware hangs in this case; this should never happen.
  241. UNREACHABLE();
  242. }
  243. 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]);
  244. }
  245. /**
  246. * DSP_DSP::GetPipeReadableSize service function
  247. * Inputs:
  248. * 1 : Pipe Number
  249. * 2 : Unknown
  250. * Outputs:
  251. * 1 : Result of function, 0 on success, otherwise error code
  252. * 2 : Number of bytes readable from pipe
  253. */
  254. static void GetPipeReadableSize(Service::Interface* self) {
  255. u32* cmd_buff = Kernel::GetCommandBuffer();
  256. DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(cmd_buff[1]);
  257. u32 unknown = cmd_buff[2];
  258. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  259. cmd_buff[2] = DSP::HLE::GetPipeReadableSize(pipe);
  260. LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, cmd_buff[2]);
  261. }
  262. /**
  263. * DSP_DSP::SetSemaphoreMask service function
  264. * Inputs:
  265. * 1 : Mask
  266. * Outputs:
  267. * 1 : Result of function, 0 on success, otherwise error code
  268. */
  269. static void SetSemaphoreMask(Service::Interface* self) {
  270. u32* cmd_buff = Kernel::GetCommandBuffer();
  271. u32 mask = cmd_buff[1];
  272. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  273. LOG_WARNING(Service_DSP, "(STUBBED) called mask=0x%08X", mask);
  274. }
  275. /**
  276. * DSP_DSP::GetHeadphoneStatus service function
  277. * Inputs:
  278. * 1 : None
  279. * Outputs:
  280. * 1 : Result of function, 0 on success, otherwise error code
  281. * 2 : The headphone status response, 0 = Not using headphones?,
  282. * 1 = using headphones?
  283. */
  284. static void GetHeadphoneStatus(Service::Interface* self) {
  285. u32* cmd_buff = Kernel::GetCommandBuffer();
  286. cmd_buff[1] = RESULT_SUCCESS.raw; // No error
  287. cmd_buff[2] = 0; // Not using headphones?
  288. LOG_WARNING(Service_DSP, "(STUBBED) called");
  289. }
  290. /**
  291. * DSP_DSP::RecvData service function
  292. * This function reads a value out of a DSP register.
  293. * Inputs:
  294. * 1 : Register Number
  295. * Outputs:
  296. * 1 : Result of function, 0 on success, otherwise error code
  297. * 2 : Value in the register
  298. * Notes:
  299. * This function has only been observed being called with a register number of 0.
  300. */
  301. static void RecvData(Service::Interface* self) {
  302. u32* cmd_buff = Kernel::GetCommandBuffer();
  303. u32 register_number = cmd_buff[1];
  304. ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
  305. // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept.
  306. cmd_buff[1] = RESULT_SUCCESS.raw;
  307. switch (DSP::HLE::GetDspState()) {
  308. case DSP::HLE::DspState::On:
  309. cmd_buff[2] = 0;
  310. break;
  311. case DSP::HLE::DspState::Off:
  312. case DSP::HLE::DspState::Sleeping:
  313. cmd_buff[2] = 1;
  314. break;
  315. default:
  316. UNREACHABLE();
  317. break;
  318. }
  319. LOG_DEBUG(Service_DSP, "register_number=%u", register_number);
  320. }
  321. /**
  322. * DSP_DSP::RecvDataIsReady service function
  323. * This function checks whether a DSP register is ready to be read.
  324. * Inputs:
  325. * 1 : Register Number
  326. * Outputs:
  327. * 1 : Result of function, 0 on success, otherwise error code
  328. * 2 : non-zero == ready
  329. * Note:
  330. * This function has only been observed being called with a register number of 0.
  331. */
  332. static void RecvDataIsReady(Service::Interface* self) {
  333. u32* cmd_buff = Kernel::GetCommandBuffer();
  334. u32 register_number = cmd_buff[1];
  335. ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
  336. cmd_buff[1] = RESULT_SUCCESS.raw;
  337. cmd_buff[2] = 1; // Ready to read
  338. LOG_DEBUG(Service_DSP, "register_number=%u", register_number);
  339. }
  340. const Interface::FunctionInfo FunctionTable[] = {
  341. {0x00010040, RecvData, "RecvData"},
  342. {0x00020040, RecvDataIsReady, "RecvDataIsReady"},
  343. {0x00030080, nullptr, "SendData"},
  344. {0x00040040, nullptr, "SendDataIsEmpty"},
  345. {0x000500C2, nullptr, "SendFifoEx"},
  346. {0x000600C0, nullptr, "RecvFifoEx"},
  347. {0x00070040, SetSemaphore, "SetSemaphore"},
  348. {0x00080000, nullptr, "GetSemaphore"},
  349. {0x00090040, nullptr, "ClearSemaphore"},
  350. {0x000A0040, nullptr, "MaskSemaphore"},
  351. {0x000B0000, nullptr, "CheckSemaphoreRequest"},
  352. {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
  353. {0x000D0082, WriteProcessPipe, "WriteProcessPipe"},
  354. {0x000E00C0, ReadPipe, "ReadPipe"},
  355. {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"},
  356. {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"},
  357. {0x001100C2, LoadComponent, "LoadComponent"},
  358. {0x00120000, nullptr, "UnloadComponent"},
  359. {0x00130082, FlushDataCache, "FlushDataCache"},
  360. {0x00140082, nullptr, "InvalidateDCache"},
  361. {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"},
  362. {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"},
  363. {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"},
  364. {0x00180040, nullptr, "GetPhysicalAddress"},
  365. {0x00190040, nullptr, "GetVirtualAddress"},
  366. {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
  367. {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
  368. {0x001C0082, nullptr, "SetIirFilterEQ"},
  369. {0x001D00C0, nullptr, "ReadMultiEx_SPI2"},
  370. {0x001E00C2, nullptr, "WriteMultiEx_SPI2"},
  371. {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"},
  372. {0x00200040, nullptr, "ForceHeadphoneOut"},
  373. {0x00210000, nullptr, "GetIsDspOccupied"},
  374. };
  375. ////////////////////////////////////////////////////////////////////////////////////////////////////
  376. // Interface class
  377. Interface::Interface() {
  378. semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event");
  379. read_pipe_count = 0;
  380. Register(FunctionTable);
  381. }
  382. Interface::~Interface() {
  383. semaphore_event = nullptr;
  384. interrupt_events.clear();
  385. }
  386. } // namespace