274 lines
7.6 KiB
C
274 lines
7.6 KiB
C
//**********************************************************************
|
|
//**********************************************************************
|
|
//** **
|
|
//** (C)Copyright 1985-2016, American Megatrends, Inc. **
|
|
//** **
|
|
//** All Rights Reserved. **
|
|
//** **
|
|
//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
|
|
//** **
|
|
//** Phone: (770)-246-8600 **
|
|
//** **
|
|
//**********************************************************************
|
|
//**********************************************************************
|
|
|
|
/** @file KbcUhciDxe.c
|
|
Functions for UHCI in Non-Smm mode.
|
|
|
|
**/
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "KbcEmulDxe.h"
|
|
#include "KbcUhci.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
extern BOOLEAN KbcPresent;
|
|
static UINT16 SavedLegcyStatus = 0;
|
|
|
|
static UINT16 UhciTrapByMask = UHCI_TRAPBY_MASK_WITHOUTKBC;
|
|
static UINT16 UhciTrapEnMask = UHCI_TRAPEN_MASK_WITHOUTKBC;
|
|
|
|
UHCI_EMUL_DEVICE Uhci_Hc_Array[] = {
|
|
#if defined(UHCI_EMUL_PCI_DEVICES)
|
|
UHCI_EMUL_PCI_DEVICES,
|
|
#endif
|
|
#if defined(INTEL_LEGACY_USB_KBC_EMUL_CONTROL_REG_PCI_DEVICES)
|
|
INTEL_LEGACY_USB_KBC_EMUL_CONTROL_REG_PCI_DEVICES,
|
|
#endif
|
|
{ 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
|
};
|
|
|
|
UINTN Uhci_Hc_Array_Size = sizeof(Uhci_Hc_Array) / sizeof(Uhci_Hc_Array[0]);
|
|
|
|
/**
|
|
Validate the UHCI controller.
|
|
|
|
@param Uhc
|
|
|
|
@retval Boolean
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
NonSmmValidateUhc (
|
|
UHCI_EMUL_DEVICE *Uhc
|
|
)
|
|
{
|
|
UINT32 Data32 = 0;
|
|
|
|
// End of the Device List.
|
|
if(Uhc->BusDevFunc == 0xFFFF) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (NonSmmReadPCIConfig (Uhc->BusDevFunc, 0) == 0xFFFFFFFF) {
|
|
return FALSE;
|
|
}
|
|
|
|
Data32 = NonSmmReadPCIConfig (Uhc->BusDevFunc, 8) >> 8;
|
|
if (Data32 != (*((UINT32*)&Uhc->InterfaceType) & 0x00FFFFFF)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Write the Value in to all the UHCI controller Legacy Regsiters.
|
|
|
|
@param Value
|
|
|
|
@retval VOID
|
|
|
|
**/
|
|
|
|
VOID
|
|
NonSmmWriteLegKeyReg (
|
|
UINT16 Value
|
|
)
|
|
{
|
|
UINTN UhciCount;
|
|
|
|
for( UhciCount = 0; UhciCount < Uhci_Hc_Array_Size; ++UhciCount ){
|
|
if (!NonSmmValidateUhc(&Uhci_Hc_Array[UhciCount])) {
|
|
continue;
|
|
}
|
|
NonSmmWordWritePCIConfig( Uhci_Hc_Array[UhciCount].BusDevFunc,
|
|
Uhci_Hc_Array[UhciCount].LegacyRegOffset, Value);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Clear the Port6064 SMI Status
|
|
|
|
@param Value
|
|
|
|
@retval VOID
|
|
|
|
**/
|
|
|
|
VOID
|
|
NonSmmClearLegKeyStatusReg (
|
|
UINT16 Value
|
|
)
|
|
{
|
|
|
|
UINTN UhciCount;
|
|
|
|
#if ICH10_WORKAROUND
|
|
//
|
|
// Enable all the UCHI controller
|
|
// In ICH10 chipset, we need to clear the Port 6064 SMI status in disabled controller
|
|
// also. Otherwise it's keep on generating SMI
|
|
//
|
|
EnableAllUhciController();
|
|
#endif
|
|
|
|
for( UhciCount = 0; UhciCount < Uhci_Hc_Array_Size; ++UhciCount ){
|
|
if (!NonSmmValidateUhc(&Uhci_Hc_Array[UhciCount])) {
|
|
continue;
|
|
}
|
|
NonSmmWordWritePCIConfig( Uhci_Hc_Array[UhciCount].BusDevFunc,
|
|
Uhci_Hc_Array[UhciCount].LegacyRegOffset, Value);
|
|
}
|
|
|
|
#if ICH10_WORKAROUND
|
|
//
|
|
// Restore the UCHI controller's in RCBA Reg
|
|
//
|
|
RestoreUhciControllerStatus();
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Check if trap status is set in UHCI HC.
|
|
|
|
@param None
|
|
|
|
@retval BOOLEAN
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
NonSmmUhci_HasTrapStatus ()
|
|
{
|
|
UINT16 LegcyKeyStatus = 0;
|
|
UINTN UhciCount;
|
|
|
|
for( UhciCount = 0; UhciCount < Uhci_Hc_Array_Size; ++UhciCount ){
|
|
if (!NonSmmValidateUhc(&Uhci_Hc_Array[UhciCount])) {
|
|
continue;
|
|
}
|
|
|
|
LegcyKeyStatus =(UINT16) NonSmmReadPCIConfig( Uhci_Hc_Array[UhciCount].BusDevFunc ,
|
|
Uhci_Hc_Array[UhciCount].LegacyRegOffset );
|
|
break;
|
|
}
|
|
return ((LegcyKeyStatus & UhciTrapEnMask) != 0 );
|
|
}
|
|
|
|
/**
|
|
Enable/Disable trapping in UHCI HC.
|
|
|
|
@param TrapEnable
|
|
|
|
@retval BOOLEAN
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
NonSmmUhci_TrapEnable (
|
|
BOOLEAN TrapEnable
|
|
)
|
|
{
|
|
|
|
UINT16 LegcyKeyStatus;
|
|
EFI_TPL OldTpl;
|
|
UINT16 UhciCount;
|
|
|
|
for( UhciCount = 0; UhciCount < Uhci_Hc_Array_Size; ++UhciCount ){
|
|
if (!NonSmmValidateUhc(&Uhci_Hc_Array[UhciCount])) {
|
|
continue;
|
|
}
|
|
|
|
LegcyKeyStatus =(UINT16) NonSmmReadPCIConfig( Uhci_Hc_Array[UhciCount].BusDevFunc ,
|
|
Uhci_Hc_Array[UhciCount].LegacyRegOffset );
|
|
//
|
|
//Record first time that trapping is disabled. Record only trap status bits handled by Trap handler
|
|
//
|
|
if( (LegcyKeyStatus & UhciTrapEnMask)== UhciTrapEnMask &&
|
|
( LegcyKeyStatus & UhciTrapByMask) != 0 ){
|
|
//If legacy I/O caused SMI# and this is first time we are in uhci_trapEnable
|
|
//then trapping in LEGKEY reg must have been enabled and one trap status is set.
|
|
//Any port 60/64 operation within SMI# must be wrapped into
|
|
//enable/ disable&clear status. So subsequent trapEnable will not produce any
|
|
//trap statuses
|
|
SavedLegcyStatus |= LegcyKeyStatus;
|
|
}
|
|
|
|
OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
|
|
|
|
if(TrapEnable){
|
|
//
|
|
// Clear the status
|
|
//
|
|
NonSmmClearLegKeyStatusReg(LegcyKeyStatus | UhciTrapByMask);
|
|
//
|
|
// Enable Traps
|
|
//
|
|
NonSmmWriteLegKeyReg( LegcyKeyStatus | UhciTrapEnMask);
|
|
} else {
|
|
//
|
|
// Clear the status
|
|
//
|
|
NonSmmClearLegKeyStatusReg(LegcyKeyStatus | UhciTrapByMask);
|
|
|
|
//
|
|
// Disable the Trap
|
|
//
|
|
NonSmmWriteLegKeyReg( (LegcyKeyStatus & ~UhciTrapEnMask) );
|
|
}
|
|
pBS->RestoreTPL(OldTpl);
|
|
}
|
|
return TRUE;
|
|
}
|
|
/**
|
|
* Sets the UHCI Trap Enable Mask value by checking the presence of
|
|
* KBC on the platform by reading port 64h.If KBC controller is present
|
|
* loads the global variables UhciTrapEnMask and UhciTrapByMask.
|
|
* If the platform has KBC then for Port 64h Read SMI will not be generated
|
|
* and handled by the KBC Emulation driver.
|
|
*
|
|
* @param none
|
|
* @param none
|
|
*
|
|
*/
|
|
void
|
|
NonSmmUhci_SetTrapEnMask()
|
|
{
|
|
if(KbcPresent){
|
|
UhciTrapByMask = UHCI_TRAPBY_MASK_WITHKBC;
|
|
UhciTrapEnMask = UHCI_TRAPEN_MASK_WITHKBC;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//**********************************************************************
|
|
//**********************************************************************
|
|
//** **
|
|
//** (C)Copyright 1985-2016, American Megatrends, Inc. **
|
|
//** **
|
|
//** All Rights Reserved. **
|
|
//** **
|
|
//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
|
|
//** **
|
|
//** Phone: (770)-246-8600 **
|
|
//** **
|
|
//**********************************************************************
|
|
//**********************************************************************
|
|
|