⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syncregio.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*+++ *******************************************************************\
*
*  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 + -