diff options
Diffstat (limited to 'Chipset/SB/SmBus/SmBusDxe.c')
-rw-r--r-- | Chipset/SB/SmBus/SmBusDxe.c | 940 |
1 files changed, 940 insertions, 0 deletions
diff --git a/Chipset/SB/SmBus/SmBusDxe.c b/Chipset/SB/SmBus/SmBusDxe.c new file mode 100644 index 0000000..2aee2ff --- /dev/null +++ b/Chipset/SB/SmBus/SmBusDxe.c @@ -0,0 +1,940 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SmBus/SmBusDxe.c 1 6/06/12 8:00a Victortu $ +// +// $Revision: 1 $ +// +// $Date: 6/06/12 8:00a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Chipset/SmBus/SmBusDxe.c $ +// +// 1 6/06/12 8:00a Victortu +// Implement EFI_PEI_SMBUS2_PPI Support. +// +// 11 7/21/11 7:32a Abelwu +// [TAG] None +// [Category] New Feature +// [Description] Added SMBus SMM protocol support. +// [Files] SmBusDxe.c +// +// 10 7/19/11 8:28a Abelwu +// [TAG] EIP63768 +// [Category] Improvement +// [Description] 1. Supported Core 4.6.5.x PI 1.2 / uEFI 2.3.1 +// compliance +// 2. Added SMBus SMM protocol support. +// +// 9 6/17/11 5:54p Artems +// EIP 53378: Replaced tabs with spaces, formatted to follow coding +// standard +// +// 8 5/18/11 11:51a Artems +// +// 7 1/27/11 9:48p Abelwu +// Supports SMBUS Protocol in early DXE phase. (EIP#40778) +// +// 6 10/13/10 4:16p Artems +// EIP 45184 - fixed pointer size to be same in IA32 and X64 mode +// +// 5 10/16/09 7:32p Artems +// Updated copyright header +// +// 4 3/03/09 4:36p Artems +// EIP 19949 Added support for multiple SM Bus controllers that +// represented by different PCI devices +// +// 3 1/29/09 4:20p Artems +// Change "Note" to "Notes" for HelpBuilder +// +// 2 1/28/09 6:51p Artems +// Modified in accordance with coding standard +// +// 1 1/09/09 6:53p Artems +// New implementation of SMBus EIP 16730 +// +// 1 3/18/07 5:23p Felixp +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: SmBusDxe.c +// +// Description: SMBUS DXE functions implementation +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <AmiHobs.h> +#include "SmBusDxe.h" +#include <Protocol\PciRootBridgeIo.h> + +#define MICROSECOND 10 +#define MILLISECOND (1000 * MICROSECOND) +#define ONESECOND (1000 * MILLISECOND) + +extern EFI_GUID SmBusIdentifierGuid; + +EFI_DRIVER_BINDING_PROTOCOL SmBusDriverBindingProtocol = { + DriverBindingSupported, + DriverBindingStart, + DriverBindingStop, + 0x10, + NULL, + NULL + }; + +SMBUS_DXE_PRIVATE *gPrivate; +EFI_HANDLE gControllerHandle = NULL; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SmBusEarlyDxeDriver +// +// Description: This function configures and installs SMBUS protocol before +// SMBus EFI 1.1 drvier is installed. +// +// Input: None +// +// Output: EFI_STATUS +// EFI_SUCCESS - SMBUS protocol has been installed. +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmBusEarlyDxeDriver ( VOID ) +{ + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo = NULL; + EFI_GUID EfiPciRootBridgeIoProtocolGuid = \ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; +/* Porting Required + UINT32 IoBase32; + UINT16 Cmd16; +Porting End */ + + Status = pBS->AllocatePool( EfiBootServicesData, \ + sizeof(SMBUS_DXE_PRIVATE), \ + &gPrivate ); + if (EFI_ERROR(Status)) return Status; + + Status = pBS->AllocatePool( \ + EfiBootServicesData, \ + sizeof(EFI_SMBUS_DEVICE_MAP) * MAX_DXE_ARP_DEVICES, \ + &(gPrivate->SmBusContext.ArpDeviceList) ); + if (EFI_ERROR(Status)) { + pBS->FreePool( gPrivate ); + return Status; + } + + gPrivate->SmBusProtocol.Execute = SmBusDxeExecute; + gPrivate->SmBusProtocol.ArpDevice = SmBusDxeArpDevice; + gPrivate->SmBusProtocol.GetArpMap = SmBusDxeGetArpMap; + gPrivate->SmBusProtocol.Notify = SmBusDxeNotify; + + gPrivate->NotifyEvent = NULL; + gPrivate->Identifier = SmBusIdentifierGuid; + + gPrivate->SmBusContext.SmBusWait = SmBusDxeWait; + gPrivate->SmBusContext.MaxDevices = MAX_DXE_ARP_DEVICES; + RetrieveHobData( gPrivate ); + +/* Porting Required + Status = pBS->LocateProtocol( &EfiPciRootBridgeIoProtocolGuid, \ + NULL, \ + &PciRootBridgeIo ); + // Update SMBus I/O Base Address + PciRootBridgeIo->Pci.Read( PciRootBridgeIo, \ + EfiPciWidthUint32, \ + SMBUS_REG(SMBUS_REG_BASE_ADDR), \ + 1, \ + &IoBase32 ); + IoBase32 &= 0xfffffffe; + gPrivate->SmBusContext.SmBusBase = (UINT16)IoBase32; + + // Enable SMBus controller I/O decode. + PciRootBridgeIo->Pci.Read( PciRootBridgeIo, \ + EfiPciWidthUint16, \ + SMBUS_REG(SMBUS_REG_PCICMD), \ + 1, \ + &Cmd16 ); + Cmd16 |= 1; + PciRootBridgeIo->Pci.Write( PciRootBridgeIo, \ + EfiPciWidthUint16, \ + SMBUS_REG(SMBUS_REG_PCICMD), \ + 1, \ + &Cmd16 ); +Porting End */ + + Status = pBS->InstallProtocolInterface( &gControllerHandle, \ + &gEfiSmbusProtocolGuid, \ + EFI_NATIVE_INTERFACE, + &gPrivate->SmBusProtocol ); + + if (EFI_ERROR(Status)) { + TRACE((-1, "SBSmbusDxe: Install Protocol Interface Failed.\n")); + } + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SmBusSmmExecute +// +// Description: This Protocol Function can be used to execute SMBus command +// on a particular SMBus controller in SMM. +// +// Input: *This - Pointer to the SMBus Protocol structure +// SlaveAddress - Address of the SMBus device +// Command - Command to be sent to the device +// Operation - SMBus operation to be performed +// PecCheck - Flag indicating the usage of PEC +// *Length - Length of the data in the Buffer (IN or OUT) +// *Buffer - Pointer to the buffer with the data (IN or OUT) +// +// Output: EFI_STATUS +// +// Notes: PORTING REQUIRED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmBusSmmExecute ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer ) +{ + EFI_STATUS Status = EFI_UNSUPPORTED; +/* + // Porting Required + UINT16 SmBusBase = READ_PCI16_SMBUS(SMBUS_REG_BASE_ADDR) & 0xfff0; + UINT16 SmBusCmd = READ_PCI16_SMBUS(SMBUS_REG_PCICMD); + + if (SmBusBase == 0) { // Assign a new I/O if the original address is 0 + WRITE_PCI16_SMBUS(SMBUS_REG_BASE_ADDR, SMBUS_BASE_ADDRESS); + SmBusBase = SMBUS_BASE_ADDRESS; + } + + gPrivate->SmBusContext.SmBusBase = SmBusBase; + + if ((SmBusCmd & 1) == 0) { // Enable I/O command if needed. + WRITE_PCI16_SMBUS(SMBUS_REG_PCICMD, 1); + } + // Porting End + + Status = Execute( &(((SMBUS_DXE_PRIVATE *)This)->SmBusContext), \ + SlaveAddress, \ + Command, \ + Operation, \ + PecCheck, \ + Length, \ + Buffer ); + + // Porting Required + // Restore the SMBus PCI Command Register + WRITE_PCI16_SMBUS(SMBUS_REG_PCICMD, SmBusCmd); + // Porting End +*/ + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SMBusInSmmInit +// +// Description: This function installs SMBus SMM protocol for the SMBus +// controller present in the SB. +// +// Input: ImageHandle - Image handle for the SB component +// *SystemTable - Pointer to the system table +// +// Output: EFI_STATUS +// +// Notes: GENERALLY NO PORTING REQUIRED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SMBusInSmmInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_HANDLE Handle = NULL; + EFI_GUID SmmSmbusProtocolGuid = \ + AMI_SMBUS_SMM_PROTOCOL_GUID; + static SMBUS_DXE_PRIVATE SmbusSmmPrivate; + + gPrivate = &SmbusSmmPrivate; + gPrivate->SmBusProtocol.Execute = SmBusSmmExecute; + gPrivate->SmBusProtocol.ArpDevice = SmBusDxeArpDevice; + gPrivate->SmBusProtocol.GetArpMap = SmBusDxeGetArpMap; + gPrivate->SmBusProtocol.Notify = SmBusDxeNotify; + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A) + Status = InitAmiSmmLib( ImageHandle, SystemTable ); + if (EFI_ERROR(Status)) return Status; + + return pSmst->SmmInstallProtocolInterface( &Handle, \ + &SmmSmbusProtocolGuid, \ + EFI_NATIVE_INTERFACE, \ + &gPrivate->SmBusProtocol ); +#else + return pBS->InstallProtocolInterface( &Handle, + &SmmSmbusProtocolGuid, + EFI_NATIVE_INTERFACE, + &gPrivate->SmBusProtocol ); +#endif +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SMBusNotInSmmInit +// +// Description: This function installs SMBus DXE protocol for the SMBus +// controller present in the SB. +// +// Input: ImageHandle - Image handle for the SB component +// *SystemTable - Pointer to the system table +// +// Output: EFI_STATUS +// +// Notes: GENERALLY NO PORTING REQUIRED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SMBusNotInSmmInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable ) +{ + EFI_STATUS Status; + + Status = SmBusEarlyDxeDriver(); + +#if SMBUS_BLINDING_PROTOCOL_SUPPORT + SmBusDriverBindingProtocol.ImageHandle = ImageHandle; + SmBusDriverBindingProtocol.DriverBindingHandle = ImageHandle; + Status = pBS->InstallMultipleProtocolInterfaces( \ + &ImageHandle, \ + &gEfiDriverBindingProtocolGuid, \ + &SmBusDriverBindingProtocol, \ + NULL ); +#endif + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SmBusDxeEntryPoint +// +// Description: This function installs SMBus DXE/SMM protocols for the SMBus +// controller present in the SB. +// +// Input: ImageHandle - Image handle for the SB component +// *SystemTable - Pointer to the system table +// +// Output: EFI_STATUS +// +// Notes: GENERALLY NO PORTING REQUIRED +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmBusDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable ) +{ + InitAmiLib(ImageHandle, SystemTable); + + return InitSmmHandlerEx( ImageHandle, \ + SystemTable, \ + SMBusInSmmInit, \ + SMBusNotInSmmInit ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DriverBindingSupported +// +// Description: SMBUS DXE Driver binding protocol Supported function +// +// Input: IN EFI_DRIVER_BINDING_PROTOCOL* This - pointer to EFI_DRIVER_BINDING_PROTOCOL structure +// IN EFI_HANDLE ControllerHandle - handle of controller to serve +// IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath - pointer to EFI_DEVICE_PATH_PROTOCOL structure +// +// Output: EFI_SUCCESS - driver supports given controller +// EFI_UNSUPPORTED - given controller not supported +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 PciData[4]; + + Status = pBS->OpenProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + if (EFI_ERROR (Status)) + return EFI_UNSUPPORTED; + + // + // See if this is a PCI Smbus Controller by looking at the Class Code Register + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0x8, + 1, + (VOID *)PciData ); + if (EFI_ERROR (Status)) + return EFI_UNSUPPORTED; + + pBS->CloseProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle ); + + return (PciData[3] == 0x0c && PciData[2] == 0x05) ? EFI_SUCCESS : EFI_UNSUPPORTED; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DriverBindingStart +// +// Description: SMBUS DXE Driver binding protocol Start function +// +// Input: IN EFI_DRIVER_BINDING_PROTOCOL* This - pointer to EFI_DRIVER_BINDING_PROTOCOL structure +// IN EFI_HANDLE ControllerHandle - handle of controller to serve +// IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath - pointer to EFI_DEVICE_PATH_PROTOCOL structure +// +// Output: EFI_SUCCESS - driver supports given controller +// EFI_UNSUPPORTED - given controller not supported +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath +) +{ + EFI_STATUS Status; + SMBUS_DXE_PRIVATE *Private; + static BOOLEAN EarlyDxeProtocol = TRUE; + + if (EarlyDxeProtocol) { + Status = pBS->UninstallProtocolInterface( gControllerHandle, \ + &gEfiSmbusProtocolGuid, \ + &gPrivate->SmBusProtocol ); + if (Status == EFI_SUCCESS) { + pBS->FreePool( gPrivate->SmBusContext.ArpDeviceList ); + pBS->FreePool( gPrivate ); + } + EarlyDxeProtocol = FALSE; + } + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(SMBUS_DXE_PRIVATE), + &Private); + if(EFI_ERROR(Status)) + return Status; + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(EFI_SMBUS_DEVICE_MAP) * MAX_DXE_ARP_DEVICES, + &(Private->SmBusContext.ArpDeviceList)); + if(EFI_ERROR(Status)) + return Status; + + Status = pBS->OpenProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &(Private->PciIo), + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + if (EFI_ERROR (Status)) + { + pBS->FreePool(Private->SmBusContext.ArpDeviceList); + pBS->FreePool(Private); + return Status; + } + + Private->SmBusProtocol.Execute = SmBusDxeExecute; + Private->SmBusProtocol.ArpDevice = SmBusDxeArpDevice; + Private->SmBusProtocol.GetArpMap = SmBusDxeGetArpMap; + Private->SmBusProtocol.Notify = SmBusDxeNotify; + + Private->NotifyEvent = NULL; + Private->Identifier = SmBusIdentifierGuid; + + Private->SmBusContext.SmBusWait = SmBusDxeWait; + Private->SmBusContext.MaxDevices = MAX_DXE_ARP_DEVICES; + RetrieveHobData(Private); + +//TODO Fill Private->SmBusContext.SmBusBase with value read from PCI device + + DListInit(&(Private->NotifyList)); + + Status = pBS->InstallMultipleProtocolInterfaces( + &ControllerHandle, + &gEfiSmbusProtocolGuid, &Private->SmBusProtocol, + NULL); + if (EFI_ERROR (Status)) + { + pBS->CloseProtocol( + ControllerHandle, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle ); + pBS->FreePool(Private->SmBusContext.ArpDeviceList); + pBS->FreePool(Private); + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DriverBindingStop +// +// Description: SMBUS DXE Driver binding protocol Stop function +// +// Input: IN EFI_DRIVER_BINDING_PROTOCOL* This - pointer to EFI_DRIVER_BINDING_PROTOCOL structure +// IN EFI_HANDLE ControllerHandle - handle of controller to serve +// IN UINTN NumberOfChildren - number of child devices of controller +// IN EFI_HANDLE* ChildHandleBuffer - pointer to child devices handles array +// +// Output: EFI_SUCCESS - driver was successfully uninstalled from controller +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer +) +{ + EFI_STATUS Status; + SMBUS_DXE_PRIVATE *Private; + EFI_SMBUS_HC_PROTOCOL *SmBusProtocol; + + Status = pBS->OpenProtocol ( + ControllerHandle, + &gEfiSmbusProtocolGuid, + &SmBusProtocol, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ); + if (EFI_ERROR (Status)) + return EFI_NOT_STARTED; + + pBS->CloseProtocol ( + ControllerHandle, + &gEfiSmbusProtocolGuid, + This->DriverBindingHandle, + ControllerHandle ); + + Private = (SMBUS_DXE_PRIVATE *) SmBusProtocol; + + // uninstall the protocol + Status = pBS->UninstallMultipleProtocolInterfaces ( + ControllerHandle, + &gEfiSmbusProtocolGuid, &Private->SmBusProtocol, + NULL ); + if (EFI_ERROR (Status)) + return Status; + + if(Private->NotifyEvent != 0) + { + SMBUS_NOTIFY_LINK *NotifyLink = (SMBUS_NOTIFY_LINK *)(Private->NotifyList.pHead); + SMBUS_NOTIFY_LINK *DeleteLink; + + pBS->CloseEvent(Private->NotifyEvent); + while(NotifyLink != 0) + { + DeleteLink = NotifyLink; + NotifyLink = (SMBUS_NOTIFY_LINK *)NotifyLink->Link.pNext; + pBS->FreePool(DeleteLink); + } + } + + pBS->CloseProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle ); + pBS->FreePool(Private->SmBusContext.ArpDeviceList); + pBS->FreePool(Private); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmBusPeiExecute +// +// Description: EFI_SMBUS_HC_PROTOCOL Execute function +// +// Input: IN EFI_SMBUS_HC_PROTOCOL *This - pointer to EFI_SMBUS_HC_PROTOCOL structure +// IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress - slave address +// IN EFI_SMBUS_DEVICE_COMMAND Command - command +// IN EFI_SMBUS_OPERATION Operation - operation +// IN BOOLEAN PecCheck - parity check flag +// IN OUT UINTN *Length - pointer to size of data buffer +// IN OUT VOID *Buffer - pointer to data buffer +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmBusDxeExecute ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer +) +{ + SMBUS_DXE_PRIVATE *Private = (SMBUS_DXE_PRIVATE *)This; + + return Execute( + &(Private->SmBusContext), + SlaveAddress, + Command, + Operation, + PecCheck, + Length, + Buffer); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmBusDxeArpDevice +// +// Description: EFI_SMBUS_HC_PROTOCOL ArpDevice function +// +// Input: IN EFI_SMBUS_HC_PROTOCOL *This - pointer to EFI_SMBUS_HC_PROTOCOL structure +// IN EFI_PEI_SMBUS_PPI *This - pointer to PPI +// IN BOOLEAN ArpAll - Enumerate all devices flag +// IN EFI_SMBUS_UDID *SmbusUdid - pointer to device ID to assign new address +// IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress - pointer to return assigned address +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmBusDxeArpDevice ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN BOOLEAN ArpAll, + IN EFI_SMBUS_UDID *SmbusUdid, OPTIONAL + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL +) +{ + SMBUS_DXE_PRIVATE *Private = (SMBUS_DXE_PRIVATE *)This; + + return ArpDevice( + &(Private->SmBusContext), + ArpAll, + SmbusUdid, + SlaveAddress); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmBusDxeGetArpMap +// +// Description: EFI_SMBUS_HC_PROTOCOL GetArpMap function +// +// Input: IN EFI_SMBUS_HC_PROTOCOL *This - pointer to EFI_SMBUS_HC_PROTOCOL structure +// IN OUT UINTN *Length - pointer to store size of address map +// IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap - pointer to store pointer to address map +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmBusDxeGetArpMap ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap +) +{ + SMBUS_DXE_PRIVATE *Private = (SMBUS_DXE_PRIVATE *)This; + + return GetArpMap( + &(Private->SmBusContext), + Length, + SmbusDeviceMap); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmBusDxeNotify +// +// Description: EFI_SMBUS_HC_PROTOCOL Notify function +// +// Input: IN EFI_SMBUS_HC_PROTOCOL *This - pointer to EFI_SMBUS_HC_PROTOCOL structure +// IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress - address of notification device +// IN UINTN Data - notification data +// IN EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction - pointer to callback function +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SmBusDxeNotify ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data, + IN EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction +) +{ + SMBUS_DXE_PRIVATE *Private = (SMBUS_DXE_PRIVATE *)This; + SMBUS_NOTIFY_LINK *NewLink; + EFI_STATUS Status; + + if(NotifyFunction == NULL) + return EFI_INVALID_PARAMETER; + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(SMBUS_NOTIFY_LINK), &NewLink); + if(EFI_ERROR(Status)) + return Status; + + NewLink->SlaveAddress = SlaveAddress; + NewLink->Data = Data; + NewLink->NotifyFunction = NotifyFunction; + + DListAdd(&(Private->NotifyList), (DLINK *)NewLink); + if(Private->NotifyList.Size == 1) + Status = InitializeNotifyPolling(Private); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InitializeNotifyPolling +// +// Description: Function initializes host notify polling periodic event +// +// Input: IN SMBUS_DXE_PRIVATE *Context - pointer to SMBUS device private data +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS InitializeNotifyPolling ( + IN SMBUS_DXE_PRIVATE *Context +) +{ + EFI_STATUS Status; + + Status = pBS->CreateEvent ( + (EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL), + TPL_CALLBACK, + PollSmbusNotify, + Context, + &Context->NotifyEvent ); + if (EFI_ERROR(Status)) + return Status; + + Status = pBS->SetTimer ( + Context->NotifyEvent, + TimerPeriodic, + ONESECOND ); + if (EFI_ERROR(Status)) + return Status; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PollSmbusNotify +// +// Description: Function performs periodic check of host notifications +// +// Input: IN EFI_EVENT Event - periodic check event +// IN VOID *Context - event calling context +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID PollSmbusNotify ( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_ADDRESS Address; + UINTN Data; + SMBUS_DXE_PRIVATE *Private = (SMBUS_DXE_PRIVATE *)Context; + SMBUS_NOTIFY_LINK *NotifyLink = (SMBUS_NOTIFY_LINK *)(Private->NotifyList.pHead); + + Status = CheckNotify(&(Private->SmBusContext), &Address, &Data); + if (EFI_ERROR(Status)) + return; + + while(NotifyLink != NULL) + { + if(Address.SmbusDeviceAddress == NotifyLink->SlaveAddress.SmbusDeviceAddress && + Data == NotifyLink->Data) + NotifyLink->NotifyFunction(Address, Data); + + NotifyLink = (SMBUS_NOTIFY_LINK *)NotifyLink->Link.pNext; + } +} + +//------------------------------------------------------------------- +// Struct EFI_SMBUS_DEVICE_MAP has one member, that declared as UINTN +// Due to this declaration this struct may have different size if +// compiled in x64 mode - 4 bytes in PEI and 8 bytes in DXE +// So we need mediator structure, to convert from PEI to DXE map, that +// was saved in Hob in PEI phase +//------------------------------------------------------------------- + +#pragma pack(1) +typedef struct { + UINT32 Address; + EFI_SMBUS_UDID Udid; +} PEI_EFI_SMBUS_DEVICE_MAP; +#pragma pack() + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RetrieveHobData +// +// Description: Function reads device map created in PEI phase +// +// Input: IN OUT SMBUS_DXE_PRIVATE *Context - pointer to device private data +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID RetrieveHobData ( + IN OUT SMBUS_DXE_PRIVATE *Private +) +{ + AMI_SMBUS_HOB *Hob; + EFI_GUID HobListGuid = HOB_LIST_GUID; + EFI_STATUS Status; + SMBUS_PRIVATE *Context = &(Private->SmBusContext); + + PEI_EFI_SMBUS_DEVICE_MAP *PeiMap; + UINT32 i; + + Context->BoardReservedAddressCount = 0; + Context->BoardReservedAddressList = 0; + Context->ArpDeviceCount = 0; + + Hob = (AMI_SMBUS_HOB *)GetEfiConfigurationTable(pST, &HobListGuid); + + if(Hob == NULL) + return; + + Status = FindNextHobByGuid(&(Private->Identifier), &Hob); + if(EFI_ERROR(Status)) + return; + + Context->BoardReservedAddressCount = Hob->BoardReservedAddressCount; + Context->BoardReservedAddressList = (UINT8 *)(UINTN)Hob->BoardReservedAddressList; + Context->ArpDeviceCount = Hob->ArpDeviceCount; + + PeiMap = (PEI_EFI_SMBUS_DEVICE_MAP *)Hob->ArpDeviceList; + for(i = 0; i < Hob->ArpDeviceCount; i++) + { + Context->ArpDeviceList[i].SmbusDeviceAddress.SmbusDeviceAddress = PeiMap[i].Address; + Context->ArpDeviceList[i].SmbusDeviceUdid = PeiMap[i].Udid; + } +/* + MemCpy(Context->ArpDeviceList, + Hob->ArpDeviceList, + Context->ArpDeviceCount * sizeof(EFI_SMBUS_DEVICE_MAP)); +*/ +} + +//********************************************************************** +// Porting functions +//********************************************************************** + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SmBusDxeWait +// +// Description: This function waits given number of microseconds +// +// Input: IN UINTN Microseconds - number of microseconds to wait +// +// Output: None +// +// Notes: Porting required +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SmBusDxeWait( + IN UINTN Microseconds +) +{ +//Porting required - implement wait function for pei phase +} + +/* +VOID SmBusDxeInitialize( + IN SMBUS_PRIVATE *Context + ) +{ +//Porting required - initialize PCI device and fill SmBusBase + +} +*/ + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |