mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #558 from kevinhartman/gsp-writereg-mask
Implemented WriteHWRegsWithMask for GSP
This commit is contained in:
		
						commit
						0200414ef9
					
				
					 1 changed files with 91 additions and 6 deletions
				
			
		|  | @ -48,20 +48,42 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { | ||||||
|     return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr)); |     return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | /**
 | ||||||
|  |  * Checks if the parameters in a register write call are valid and logs in the case that | ||||||
|  |  * they are not | ||||||
|  |  * @param base_address The first address in the sequence of registers that will be written | ||||||
|  |  * @param size_in_bytes The number of registers that will be written | ||||||
|  |  * @return true if the parameters are valid, false otherwise | ||||||
|  |  */ | ||||||
|  | static bool CheckWriteParameters(u32 base_address, u32 size_in_bytes) { | ||||||
|     // TODO: Return proper error codes
 |     // TODO: Return proper error codes
 | ||||||
|     if (base_address + size_in_bytes >= 0x420000) { |     if (base_address + size_in_bytes >= 0x420000) { | ||||||
|         LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)", |         LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)", | ||||||
|                   base_address, size_in_bytes); |                   base_address, size_in_bytes); | ||||||
|         return; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // size should be word-aligned
 |     // size should be word-aligned
 | ||||||
|     if ((size_in_bytes % 4) != 0) { |     if ((size_in_bytes % 4) != 0) { | ||||||
|         LOG_ERROR(Service_GSP, "Invalid size 0x%08x", size_in_bytes); |         LOG_ERROR(Service_GSP, "Invalid size 0x%08x", size_in_bytes); | ||||||
|         return; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Writes sequential GSP GPU hardware registers using an array of source data | ||||||
|  |  * | ||||||
|  |  * @param base_address The address of the first register in the sequence | ||||||
|  |  * @param size_in_bytes The number of registers to update (size of data) | ||||||
|  |  * @param data A pointer to the source data | ||||||
|  |  */ | ||||||
|  | static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | ||||||
|  |     // TODO: Return proper error codes
 | ||||||
|  |     if (!CheckWriteParameters(base_address, size_in_bytes)) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     while (size_in_bytes > 0) { |     while (size_in_bytes > 0) { | ||||||
|         GPU::Write<u32>(base_address + 0x1EB00000, *data); |         GPU::Write<u32>(base_address + 0x1EB00000, *data); | ||||||
| 
 | 
 | ||||||
|  | @ -71,17 +93,80 @@ static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Write a GSP GPU hardware register
 | /**
 | ||||||
|  |  * GSP_GPU::WriteHWRegs service function | ||||||
|  |  * | ||||||
|  |  * Writes sequential GSP GPU hardware registers | ||||||
|  |  * | ||||||
|  |  *  Inputs: | ||||||
|  |  *      1 : address of first GPU register | ||||||
|  |  *      2 : number of registers to write sequentially | ||||||
|  |  *      4 : pointer to source data array | ||||||
|  |  */ | ||||||
| static void WriteHWRegs(Service::Interface* self) { | static void WriteHWRegs(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
|     u32 reg_addr = cmd_buff[1]; |     u32 reg_addr = cmd_buff[1]; | ||||||
|     u32 size = cmd_buff[2]; |     u32 size = cmd_buff[2]; | ||||||
| 
 | 
 | ||||||
|     u32* src = (u32*)Memory::GetPointer(cmd_buff[0x4]); |     u32* src = (u32*)Memory::GetPointer(cmd_buff[4]); | ||||||
| 
 | 
 | ||||||
|     WriteHWRegs(reg_addr, size, src); |     WriteHWRegs(reg_addr, size, src); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Updates sequential GSP GPU hardware registers using parallel arrays of source data and masks. | ||||||
|  |  * For each register, the value is updated only where the mask is high | ||||||
|  |  * | ||||||
|  |  * @param base_address The address of the first register in the sequence | ||||||
|  |  * @param size_in_bytes The number of registers to update (size of data) | ||||||
|  |  * @param data A pointer to the source data to use for updates | ||||||
|  |  * @param masks A pointer to the masks | ||||||
|  |  */ | ||||||
|  | static void WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { | ||||||
|  |     // TODO: Return proper error codes
 | ||||||
|  |     if (!CheckWriteParameters(base_address, size_in_bytes)) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     while (size_in_bytes > 0) { | ||||||
|  |         const u32 reg_address = base_address + 0x1EB00000; | ||||||
|  | 
 | ||||||
|  |         u32 reg_value; | ||||||
|  |         GPU::Read<u32>(reg_value, reg_address); | ||||||
|  | 
 | ||||||
|  |         // Update the current value of the register only for set mask bits
 | ||||||
|  |         reg_value = (reg_value & ~*masks) | (*data | *masks); | ||||||
|  | 
 | ||||||
|  |         GPU::Write<u32>(reg_address, reg_value); | ||||||
|  | 
 | ||||||
|  |         size_in_bytes -= 4; | ||||||
|  |         ++data; | ||||||
|  |         ++masks; | ||||||
|  |         base_address += 4; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * GSP_GPU::WriteHWRegsWithMask service function | ||||||
|  |  * | ||||||
|  |  * Updates sequential GSP GPU hardware registers using masks | ||||||
|  |  * | ||||||
|  |  *  Inputs: | ||||||
|  |  *      1 : address of first GPU register | ||||||
|  |  *      2 : number of registers to update sequentially | ||||||
|  |  *      4 : pointer to source data array | ||||||
|  |  *      6 : pointer to mask array | ||||||
|  |  */ | ||||||
|  | static void WriteHWRegsWithMask(Service::Interface* self) { | ||||||
|  |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
|  |     u32 reg_addr = cmd_buff[1]; | ||||||
|  |     u32 size = cmd_buff[2]; | ||||||
|  |      | ||||||
|  |     u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); | ||||||
|  |     u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); | ||||||
|  | 
 | ||||||
|  |     WriteHWRegsWithMask(reg_addr, size, src_data, mask_data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// Read a GSP GPU hardware register
 | /// Read a GSP GPU hardware register
 | ||||||
| static void ReadHWRegs(Service::Interface* self) { | static void ReadHWRegs(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||||
|  | @ -350,7 +435,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x00010082, WriteHWRegs,                   "WriteHWRegs"}, |     {0x00010082, WriteHWRegs,                   "WriteHWRegs"}, | ||||||
|     {0x00020084, nullptr,                       "WriteHWRegsWithMask"}, |     {0x00020084, WriteHWRegsWithMask,           "WriteHWRegsWithMask"}, | ||||||
|     {0x00030082, nullptr,                       "WriteHWRegRepeat"}, |     {0x00030082, nullptr,                       "WriteHWRegRepeat"}, | ||||||
|     {0x00040080, ReadHWRegs,                    "ReadHWRegs"}, |     {0x00040080, ReadHWRegs,                    "ReadHWRegs"}, | ||||||
|     {0x00050200, SetBufferSwap,                 "SetBufferSwap"}, |     {0x00050200, SetBufferSwap,                 "SetBufferSwap"}, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue