📄 syncregio.cpp
字号:
/*+++ *******************************************************************\
*
* Copyright and Disclaimer:
*
* ---------------------------------------------------------------
* This software is provided "AS IS" without warranty of any kind,
* either expressed or implied, including but not limited to the
* implied warranties of noninfringement, merchantability and/or
* fitness for a particular purpose.
* ---------------------------------------------------------------
*
* Copyright (c) 2008 Conexant Systems, Inc.
* All rights reserved.
*
\******************************************************************* ---*/
#include "SyncRegIo.h"
#include "debug.h"
#include "hammerhead_registers.h"
//I2C Address of the HammerHead core
#define HAMMERHEAD_I2C_ADDRESS 0x88
SyncRegIo::SyncRegIo(DriverI2C *p_i2c) :
_p_i2c(p_i2c),
_firmware_state(FIRMWARE_STATE_NOT_STARTED),
_firmware_stop_reasons(0)
{
BYTE value;
_p_i2c->addRef();
KeInitializeMutex(&_mutex, 0);
//Make sure the firmware is disabled
writeDwordNoLock(DL_CTL, FLD_DL_MAP);
// TODO, need check
readByteNoLock(CHIP_CTRL, &value);
_chip_rev = value & 0xF;
}
SyncRegIo::~SyncRegIo()
{
if( _p_i2c )
{
_p_i2c->release();
}
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID SyncRegIo::lock()
{
KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );
}
/////////////////////////////////////////////////////////////////////////////////////////
VOID SyncRegIo::unlock()
{
KeReleaseMutex(&_mutex, FALSE);
}
NTSTATUS SyncRegIo::setCommandFormat(BOOLEAN first,BOOLEAN last)
{
if(!_p_i2c)
return STATUS_UNSUCCESSFUL;
else
return _p_i2c->setCommandFormat(first,last);
}
VOID SyncRegIo::stopAudioFirmware(DWORD firmware_stop_reason)
{
DbgLog(("SyncRegIo::stopAudioFirmware\n"));
KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );
_firmware_stop_reasons |= firmware_stop_reason;
if(_firmware_state == FIRMWARE_STATE_ENABLED)
{
DbgLog(("SyncRegIo::stopAudioFirmware firmware was running, stopping\n"));
//Disable the firmware
writeDwordNoLock(DL_CTL, FLD_DL_MAP);
_firmware_state = FIRMWARE_STATE_STOPPED;
}
else
DbgLog(("SyncRegIo::stopAudioFirmware firmware already stopped\n"));
//Mute Mako if we are doing a channel change. Note that we check against all the
// mute reasons since we do not want to force a mute if we were running
// in line-in audio and someone changed the tuner channel
if((_firmware_stop_reasons == FIRMWARE_STOP_REASON_CHANNEL_CHANGE) ||
(_firmware_stop_reasons == FIRMWARE_STOP_REASON_HW_INIT))
{
DbgLog(("SyncRegIo::stopAudioFirmware channel change or hw_init, muting\n"));
DWORD path1_ctrl;
readDword(PATH1_CTL1, &path1_ctrl);
path1_ctrl |= 0x1F000000;
writeDword(PATH1_CTL1, path1_ctrl);
}
KeReleaseMutex(&_mutex, FALSE);
}
VOID SyncRegIo::restartAudioFirmware(DWORD start_reason)
{
DbgLog(("SyncRegIo::restartAudioFirmware\n"));
KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );
_firmware_stop_reasons &= ~start_reason;
if(_firmware_stop_reasons)
{
DbgLog(("SyncRegIo::restartAudioFirmware firmware stop reasons override start_reason\n"));
KeReleaseMutex(&_mutex, FALSE);
return;
}
if(_firmware_state == FIRMWARE_STATE_STOPPED)
{
DbgLog(("SyncRegIo::restartAudioFirmware firmware stopped, restarting\n"));
//Enable the firmware
writeDwordNoLock(DL_CTL, FLD_START_8051 | FLD_DL_MAP);
_firmware_state = FIRMWARE_STATE_ENABLED;
}
else
DbgLog(("SyncRegIo::restartAudioFirmware firmware already running\n"));
KeReleaseMutex(&_mutex, FALSE);
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::readByte(WORD register_address, PBYTE p_value)
{
lock();
NTSTATUS ret_val = readByteNoLock(register_address, p_value);
unlock();
return ret_val;
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::writeByte(WORD register_address, BYTE value)
{
lock();
NTSTATUS ret_val = writeByteNoLock(register_address, value);
unlock();
return ret_val;
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::readByteNoLock(WORD register_address, PBYTE p_value)
{
BYTE addr[2] = {0,0};
addr[0] = (BYTE) register_address;
addr[1] = (register_address >> 8) & 0xff;
BOOLEAN status = _p_i2c->read(
HAMMERHEAD_I2C_ADDRESS>>1, //device address
2, //subaddr size
&addr[0], //subaddr buffer
1, //read size
p_value); //read buffer
if (status==TRUE)
{
return STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::writeByteNoLock(WORD register_address, BYTE value)
{
BYTE buffer[2];
buffer[0] = (register_address) & 0xff;
buffer[1] = (register_address>>8) & 0xff;
BOOLEAN status = _p_i2c->write(
HAMMERHEAD_I2C_ADDRESS>>1, //device address
2, //subaddr size
buffer, //subaddr buffer
1, //write size
&value); //write buffer
if (status==TRUE)
{
return STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::writeDword(WORD register_address, DWORD value)
{
lock();
NTSTATUS status = writeDwordNoLock(register_address, value);
unlock();
return status;
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::readModifyWriteDword(WORD address, DWORD mask, DWORD value)
{
DWORD temp;
NTSTATUS ret_val = readDword(address, &temp);
if(!NT_SUCCESS(ret_val))
return ret_val;
temp &= ~mask;
temp |= value;
return writeDword(address, temp);
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::writeDwordNoLock(WORD register_address, DWORD value)
{
BYTE buffer[2];
BYTE v[4];
buffer[0] = (BYTE) (register_address );
buffer[1] = (BYTE) (register_address>>8);
v[0] = (BYTE) (value);
v[1] = (BYTE) (value >> 8);
v[2] = (BYTE) (value >> 16);
v[3] = (BYTE) (value >> 24);
BOOLEAN status = _p_i2c->write(
HAMMERHEAD_I2C_ADDRESS>>1, //device address
2, //subaddr size
buffer, //subaddr buffer
4, //write size
v); //write buffer
if (status==TRUE)
{
return STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS SyncRegIo::writeMultiByte(WORD register_address, BYTE* p_value, DWORD value_num)
{
lock();
NTSTATUS status = writeMultiByteNoLock(register_address, p_value, value_num);
unlock();
return status;
}
NTSTATUS SyncRegIo::writeMultiByteNoLock(WORD register_address, BYTE* p_value, DWORD value_num)
{
BYTE buffer[2];
buffer[0] = (BYTE) (register_address );
buffer[1] = (BYTE) (register_address>>8);
BOOLEAN status = _p_i2c->write(
HAMMERHEAD_I2C_ADDRESS>>1, //device address
2, //subaddr size
buffer, //subaddr buffer
value_num, //write size
p_value); //write buffer
if (status==TRUE)
{
return STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS SyncRegIo::readDword(WORD register_address, PDWORD p_value)
{
lock();
NTSTATUS status = readDwordNoLock(register_address, p_value);
unlock();
return status;
}
NTSTATUS SyncRegIo::readDwordNoLock(WORD register_address, PDWORD p_value)
{
BYTE addr[2] = {0,0};
addr[0] = (BYTE) register_address ;
addr[1] = (register_address>> 8 ) & 0xff;
BOOLEAN status = _p_i2c->read(
HAMMERHEAD_I2C_ADDRESS>>1, //device address
2, //subaddr size
&addr[0], //subaddr buffer
4, //read size
(PBYTE)p_value); //read buffer
if (status==TRUE)
{
return STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
// SyncRegIo::Set_Field()
//
// Purpose: This function will shift a normalized data value into the proper
// field position. It does not read or write any registers.
//
// Input parameters: DWORD mask
// DWORD data
//
// Return Value: none
/////////////////////////////////////////////////////////////////////////////////////////
DWORD SyncRegIo::Set_Field(DWORD field_mask, DWORD data)
{
DWORD temp;
for (temp = field_mask; (temp & 1) == 0; temp >>= 1)
{
data <<= 1;
}
return data;
}
/////////////////////////////////////////////////////////////////////////////////////////
//SyncRegIo::writeAudioFirmware
//
// Note: in order to improve the speed of the firmware download, this function uses the
// protected functions in the I2CIF interface.
//
// The function turns off Mako's auto address increment feature during the upload so
// that it can write data bytes to the same address without having to send the address
// each time. The actual firmware write is a single I2C multi-byte transaction so no
// other I2C transactions can take place during it.
//
/* // MAE Keeping this around in case we run into any issues similar to MiniMe
NTSTATUS SyncRegIo::writeAudioFirmware(HANDLE file_handle)
{
lock();
DWORD dl_control = 0;
readDword(DL_CTL, &dl_control);
dl_control &= 0x00FFFFFF;
dl_control |= 0x0F000000;
//Put the 8051 in reset and enable firmware upload
writeDword(DL_CTL, dl_control);
DWORD retries = 0;
//Read DL_CTL until the address gets to 0
while(dl_control & 0x3FFF)
{
readDword(DL_CTL, &dl_control);
//It's possible the previous write to put it in firmware upload mode
// could have failed. If it did, retry here. Note that the address
// won't change if we aren't in firmware upload mode.
if((dl_control & 0xFF000000) != 0x0F000000)
{
if(retries >= 5)
{
DbgLogError((
"Failed to put Merlin into firmware upload mode DL_CTL = %x\n",
dl_control));
return STATUS_UNSUCCESSFUL;
}
dl_control &= 0x00FFFFFF;
dl_control |= 0x0F000000;
writeDword(DL_CTL, dl_control);
retries++;
}
}
//Now get the data bytes from the file one at a time and send them accross
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 dl_control = 0x0F000000;
dl_control |= address;
address++;
dl_control |= (((DWORD) data) << 16);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -