📄 syncregio.cpp
字号:
writeDword(DL_CTL, dl_control);
//Note: Evidently the firmware upload succeeds only if I read the values back
// after every write.
DWORD value;
readDword(DL_CTL, &value);
DWORD retries = 0;
const DWORD MAX_RETRIES = 5;
//The upper bits of the address byte are ignored, so we don't care
// what is in them.
while((value & 0xFFFF3FFF) != (dl_control & 0xFFFF3FFF))
{
if(retries >= MAX_RETRIES)
{
DbgLogError((
"Failed to write Merlin firmware byte. written = %x, read = %x",
dl_control, value));
status = STATUS_UNSUCCESSFUL;
}
//Check if we can correct the byte by changing the address. We can
// only write the lower byte of the address.
if((value & 0x3F00) == (dl_control & 0x3F00))
{
//Write again
writeDword(DL_CTL, dl_control);
//Read back to see if it is accurate.
readDword(DL_CTL, &value);
retries++;
}
else
{
status = STATUS_UNSUCCESSFUL;
}
if(!NT_SUCCESS(status))
{
//Break if we failed.
break;
}
}
}
}
//We were successful if we dropped out of the loop at the end of the file.
if(status == STATUS_END_OF_FILE) status = STATUS_SUCCESS;
if(status == STATUS_SUCCESS)
{
if(!_firmware_stop_reasons)
{
//Take the 8051 out of reset and enable firmware execution
writeDword(DL_CTL, 0x13000000 | address);
_firmware_state = FIRMWARE_STATE_ENABLED;
}
else
{
_firmware_state = FIRMWARE_STATE_STOPPED;
}
}
unlock();
return status;
}
*/
NTSTATUS SyncRegIo::writeAudioFirmware(HANDLE file_handle,DWORD rev_id)
{
lock();
LARGE_INTEGER start;
LARGE_INTEGER end;
RtlZeroMemory((PVOID)&start, sizeof(start));
RtlZeroMemory((PVOID)&end, sizeof(end));
KeQuerySystemTime(&start);
//Put the 8051 in reset and enable firmware upload
writeByte(DL_CTL_CONTROL, 0xB);
//Turn off Mako's auto increment feature so we can write to the same register
// multiple times.
BYTE value;
readByte(HOST_REG1, &value);
writeByte(HOST_REG1, value | 0x20);
//Write the address of zero to the firmware upload register
writeByte(DL_CTL_ADDRESS_HIGH, 0);
writeByte(DL_CTL_ADDRESS_LOW, 0);
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS i2cstatus = STATUS_SUCCESS;
IO_STATUS_BLOCK status_block;
ULONG write_size =0;
if(rev_id >=POLARIS_REVID_A0)
{
write_size = TRANSFER_SIZE_A0;
}
else if(rev_id == POLARIS_REVID_T0)
{
write_size = TRANSFER_SIZE_T0;
}
else
{
status = STATUS_UNSUCCESSFUL;
unlock();
return status;
}
DWORD address = 0;
DWORD data=0;
//ALLOCATED_BUFFER_SIZE should be multiples of 4B.
const DWORD ALLOCATED_BUFFER_SIZE = 256;
BYTE* p_buffer=NULL;
BYTE* p_data=NULL;
p_buffer = new BYTE[ALLOCATED_BUFFER_SIZE];
if(p_buffer==NULL)
{
unlock();
return STATUS_INSUFFICIENT_RESOURCES;
}
BOOLEAN first_write=TRUE;
ULONG last_data=0;
ULONG write_byte =0;
while(status == STATUS_SUCCESS)
{
RtlZeroMemory((PVOID)p_buffer,ALLOCATED_BUFFER_SIZE);
status = ZwReadFile(
file_handle, //file handle
NULL, //event
NULL, //apc routine
NULL, //apc context
&status_block, // io status block
p_buffer, //buffer
ALLOCATED_BUFFER_SIZE, //Size of buffer
NULL, //Offset in the file to read
NULL); //key
if(NT_SUCCESS(status))
{
ULONG_PTR buffer_size = status_block.Information;
p_data = p_buffer;
ULONG buffer_byte = (ULONG)buffer_size;
while(buffer_size >= write_size)
{
if(rev_id >=POLARIS_REVID_A0)
{
if(first_write==TRUE)
{
first_write=FALSE;
i2cstatus = setCommandFormat(TRUE,FALSE);//first time write to the address
}
else
{
last_data = (ULONG)buffer_size-write_size;
if(last_data==0&&buffer_byte<ALLOCATED_BUFFER_SIZE)
{
i2cstatus = setCommandFormat(FALSE,TRUE);//the last time write to the address
}
else
{
i2cstatus = setCommandFormat(FALSE,FALSE);//middle time write to the address
}
}
}
if(!NT_SUCCESS(i2cstatus))
{
status = STATUS_UNSUCCESSFUL;
}
else
{
if (!NT_SUCCESS(writeMultiByte(DL_CTL_DATA, p_data,write_size)))
{
if(rev_id >=POLARIS_REVID_A0)//change to common format
{
setCommandFormat(TRUE,TRUE);
}
DbgLogError(("I2C transcation failed. Bailing out !!!\n"));
//we failed I2C transaction - no point in writing any further. Bail out
status = STATUS_UNSUCCESSFUL;
}
}
write_byte+=write_size;
buffer_size-=write_size;
p_data+=write_size;
}
while((buffer_size<write_size) && (buffer_size>0))
{
if(rev_id >=POLARIS_REVID_A0)
{
if(buffer_size==1)
{
i2cstatus = setCommandFormat(FALSE,TRUE);// the last time write to the address
}
else
{
i2cstatus = setCommandFormat(FALSE,FALSE); //middle time
}
}
if(!NT_SUCCESS(i2cstatus))
{
status = STATUS_UNSUCCESSFUL;
}
else
{
if (!NT_SUCCESS(writeByte(DL_CTL_DATA, *p_data)))
{
if(rev_id >=POLARIS_REVID_A0)
{
setCommandFormat(TRUE,TRUE);
}
DbgLogError(("I2C transcation failed. Bailing out !!!\n"));
//we failed I2C transaction - no point in writing any further. Bail out
status = STATUS_UNSUCCESSFUL;
}
}
write_byte+=1;
buffer_size--;
p_data++;
}
}
}
delete [] p_buffer;
//We were successful if we dropped out of the loop at the end of the file.
if(status == STATUS_END_OF_FILE)
{
status = STATUS_SUCCESS;
}
else
{
DbgLogError(("writeAudioFirmware failed, status = %lx\n",status));
}
DbgLog(("merlin firmware have load %0x\n",write_byte));
if(rev_id >=POLARIS_REVID_A0)
{
i2cstatus = setCommandFormat(TRUE,TRUE);//change to common format
}
if(!NT_SUCCESS(i2cstatus))
{
status = STATUS_UNSUCCESSFUL;
unlock();
return status;
}
//Turn on Mako's auto increment feature
readByte(HOST_REG1, &value);
writeByte(HOST_REG1, value & 0xDF);
DWORD dl_ctrl = 0xFF;
readDword(DL_CTL, &dl_ctrl);
dl_ctrl &= 0x00FFFFFF;
dl_ctrl |= 0x3000000;
//do not enable 8051 but disable auto increment on read and disable download
writeDword(DL_CTL, dl_ctrl);
// Default to firmware stopped, Only enable firmware based on crossbar switching to tuner
_firmware_state = FIRMWARE_STATE_STOPPED;
KeQuerySystemTime(&end);
DbgLog(("writeAudioFirmware time cost:%d\n", end.QuadPart-start.QuadPart));
unlock();
return status;
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID SyncRegIo::verifyAudioFirmware(HANDLE file_handle)
{
DbgLog(("****Verifying every byte of audio firmware **** \n"));
lock();
DWORD dl_ctrl = 0xFF;
readDword(DL_CTL, &dl_ctrl);
dl_ctrl &= 0x00FFFFFF;
dl_ctrl |= 0x0F000000;
//Put the 8051 in reset and enable firmware upload
writeDword(DL_CTL, dl_ctrl);
//Read DL_CTL until the address gets to 0
while(dl_ctrl & 0x3FFF)
{
//we failed I2C transaction - no point in writing any further. Bail out
if (!NT_SUCCESS(readDword(DL_CTL, &dl_ctrl)))
{
DbgLogError(("Firmware verify failed - I2C transcation failed. Bailing out !!!\n"));
return;
}
}
//Now get the data bytes from the file one at a time
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK status_block;
DWORD address = 0;
while(status == STATUS_SUCCESS)
{
BYTE data;
status = ZwReadFile(
file_handle, //file handle
NULL, //event
NULL, //apc routine
NULL, //apc context
&status_block, // io status block
&data, //buffer
1, //Size of buffer
NULL, //Offset in the file to read
NULL); //key
if(NT_SUCCESS(status))
{
DWORD address2 = dl_ctrl & 0x3FFF;
if(address != address2)
{
DbgLog(("Address is incorrect. Address in DL_CTL = %x, Should be %x\n",
address2, address));
break;
}
DWORD data2 = ((dl_ctrl & 0x00FF0000) >> 16);
if(data != data2)
{
DbgLog(("Data is incorrect. Address = %x, data = %x, should be %x\n",
address, data2, data));
break;
}
readDword(DL_CTL, &dl_ctrl);
address++;
}
else
{
if (status != STATUS_END_OF_FILE)
DbgLogError(("Firmware verify ZwReadFile error status %lx\n",status));
}
}
//We were successful if we dropped out of the loop at the end of the file.
if(status == STATUS_END_OF_FILE)
{
DbgLog(("Firmware verify successful\n"));
status = STATUS_SUCCESS;
}
else
{
DbgLogError(("Firmware verify failed\n"));
status = STATUS_SUCCESS;
}
dl_ctrl &= 0x00FFFFFF;
dl_ctrl |= 0x3000000;
//do not enable 8051 but disable auto increment on read and disable download
writeDword(DL_CTL, dl_ctrl);
#if 0 // Only enable firmware based on crossbar switching to tuner
if(status == STATUS_SUCCESS)
{
if(!_firmware_stop_reasons)
{
//Take the 8051 out of reset and enable firmware execution
writeDword(DL_CTL, FLD_START_8051 | FLD_DL_MAP | address);
_firmware_state = FIRMWARE_STATE_ENABLED;
}
else
{
_firmware_state = FIRMWARE_STATE_STOPPED;
}
}
#endif
unlock();
}
NTSTATUS SyncRegIo::RegMaskWrite(BYTE size, WORD register_address,BYTE bit_start,BYTE bit_end, DWORD value)
{
if (bit_start>(size-1) || bit_end>(size-1))
{
return STATUS_UNSUCCESSFUL;
}
CHAR tmp[4] = {0,};
NTSTATUS status = STATUS_SUCCESS;
if (size==8)
{
status = readByte(register_address, (PBYTE)tmp);
}
else
{
status = readDword(register_address, (PDWORD)tmp);
}
if (!NT_SUCCESS(status))
{
return status;
}
DWORD mask = 1<<bit_end;
for (int i=bit_end; i>bit_start&&i>0; i--)
{
mask = mask + (1<<(i-1));
}
value <<= bit_start;
if (size==8)
{
(*(PBYTE)tmp) = (*(PBYTE)tmp) & ((BYTE)~mask);
(*(PBYTE)tmp) = (*(PBYTE)tmp) | ((BYTE)value);
status = writeByte(register_address, (*(PBYTE)tmp));
}
else
{
(*(PDWORD)tmp) = (*(PDWORD)tmp) & ((DWORD)~mask);
(*(PDWORD)tmp) = (*(PDWORD)tmp) | ((DWORD)value);
status = writeDword(register_address, (*(PDWORD)tmp));
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -