Implemented WriteHWRegsWithMask for GSP.
This commit is contained in:
		
							parent
							
								
									54de697084
								
							
						
					
					
						commit
						a56f3f290e
					
				@ -48,20 +48,42 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
 | 
			
		||||
    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
 | 
			
		||||
    if (base_address + size_in_bytes >= 0x420000) {
 | 
			
		||||
        LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)",
 | 
			
		||||
                  base_address, size_in_bytes);
 | 
			
		||||
        return;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // size should be word-aligned
 | 
			
		||||
    if ((size_in_bytes % 4) != 0) {
 | 
			
		||||
        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) {
 | 
			
		||||
        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) {
 | 
			
		||||
    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
			
		||||
    u32 reg_addr = cmd_buff[1];
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
static void ReadHWRegs(Service::Interface* self) {
 | 
			
		||||
    u32* cmd_buff = Kernel::GetCommandBuffer();
 | 
			
		||||
@ -350,7 +435,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) {
 | 
			
		||||
 | 
			
		||||
const Interface::FunctionInfo FunctionTable[] = {
 | 
			
		||||
    {0x00010082, WriteHWRegs,                   "WriteHWRegs"},
 | 
			
		||||
    {0x00020084, nullptr,                       "WriteHWRegsWithMask"},
 | 
			
		||||
    {0x00020084, WriteHWRegsWithMask,           "WriteHWRegsWithMask"},
 | 
			
		||||
    {0x00030082, nullptr,                       "WriteHWRegRepeat"},
 | 
			
		||||
    {0x00040080, ReadHWRegs,                    "ReadHWRegs"},
 | 
			
		||||
    {0x00050200, SetBufferSwap,                 "SetBufferSwap"},
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user