diff options
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Smbus/Dxe')
8 files changed, 1507 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbus.dxs b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbus.dxs new file mode 100644 index 0000000..a64aee1 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbus.dxs @@ -0,0 +1,40 @@ +/** @file + Dispatch dependency expression file for the DXE PchSmbus driver. + +@copyright + Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement + +**/ + +// +// Common for R8 and R9 codebase +// +#include "AutoGen.h" +#include "DxeDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" + +#include EFI_PROTOCOL_DEFINITION (PchPlatformPolicy) +#endif + +DEPENDENCY_START + DXE_PCH_PLATFORM_POLICY_PROTOCOL_GUID +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbus.h b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbus.h new file mode 100644 index 0000000..6c6b93b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbus.h @@ -0,0 +1,360 @@ +/** @file + PCH Smbus Protocol + +@copyright + Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#ifndef _DXE_PCH_SMBUS_H +#define _DXE_PCH_SMBUS_H + +// +// External include files do NOT need to be explicitly specified in real EDKII +// environment +// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) + +#include "EdkIIGlueDxe.h" +// +// Driver Produced Protocol Prototypes +// +#include EFI_PROTOCOL_PRODUCER (Smbus) +#include EFI_GUID_DEFINITION (SmbusArpMap) +// +// Driver Consumed Protcol Prototypes +// +#include EFI_PROTOCOL_CONSUMER (PchPlatformPolicy) +#include "PchSmbusCommon.h" +#endif +// +// Definitions +// +/// +/// Max number of SMBus devices (7 bit address yields 128 combinations but 21 of those are reserved) +/// +#define MAX_SMBUS_DEVICES 107 +#define MICROSECOND 10 +#define MILLISECOND (1000 * MICROSECOND) +#define ONESECOND (1000 * MILLISECOND) + +/// +/// Private Data Structures +/// +typedef struct _SMBUS_NOTIFY_FUNCTION_LIST_NODE { + UINT32 Signature; + LIST_ENTRY Link; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINTN Data; + EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction; +} SMBUS_NOTIFY_FUNCTION_LIST_NODE; + +#define SMBUS_NOTIFY_FUNCTION_LIST_NODE_FROM_LINK(_node) \ + CR ( \ + _node, \ + SMBUS_NOTIFY_FUNCTION_LIST_NODE, \ + Link, \ + PCH_SMBUS_PRIVATE_DATA_SIGNATURE \ + ) + +/// +/// Declare a local instance structure for this driver +/// +typedef struct _SMBUS_INSTANCE { + UINTN Signature; + EFI_HANDLE Handle; + + UINT32 SmbusIoBase; + SMBUS_IO_READ SmbusIoRead; + SMBUS_IO_WRITE SmbusIoWrite; + SMBUS_IO_DONE IoDone; + + /// + /// Published interface + /// + EFI_SMBUS_HC_PROTOCOL SmbusController; + + UINT8 DeviceMapEntries; + EFI_SMBUS_DEVICE_MAP DeviceMap[MAX_SMBUS_DEVICES]; + + UINT8 PlatformNumRsvd; + UINT8 *PlatformRsvdAddr; + + LIST_ENTRY NotifyFunctionList; + EFI_EVENT NotificationEvent; + +} SMBUS_INSTANCE; + +// +// Driver global data +// +SMBUS_INSTANCE *mSmbusContext; + +// +// Prototypes +// + +/** + Execute an SMBUS operation + + @param[in] This The protocol instance + @param[in] SlaveAddress The address of the SMBUS slave device + @param[in] Command The SMBUS command + @param[in] Operation Which SMBus protocol will be issued + @param[in] PecCheck If Packet Error Code Checking is to be used + @param[out] Length Length of data + @param[out] Buffer Data buffer + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +EFIAPI +SmbusExecute ( + 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 driver entry point + + @param[in] ImageHandle ImageHandle of this module + @param[in] SystemTable EFI System Table + + @retval EFI_SUCCESS Driver initializes successfully + @retval Other values Some error occurred +**/ +EFI_STATUS +EFIAPI +InitializePchSmbus ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Set Slave address for an Smbus device with a known UDID or perform a general + ARP of all devices. + + @param[in] This Pointer to the instance of the EFI_SMBUS_HC_PROTOCOL. + @param[in] ArpAll If TRUE, do a full ARP. Otherwise, just ARP the specified UDID. + @param[in] SmbusUdid When doing a directed ARP, ARP the device with this UDID. + @@param[in, out] SlaveAddress Buffer to store new Slave Address during directed ARP. On output,If + ArpAlll == TRUE, this will contain the newly assigned Slave address. + + @retval EFI_INVALID_PARAMETER ArpAll == FALSE but SmbusUdid or SlaveAddress are NULL. + Return value from SmbusFullArp() or SmbusDirectedArp(). +**/ +EFI_STATUS +EFIAPI +SmbusArpDevice ( + IN EFI_SMBUS_HC_PROTOCOL * This, + IN BOOLEAN ArpAll, + IN EFI_SMBUS_UDID * SmbusUdid, OPTIONAL + IN OUT EFI_SMBUS_DEVICE_ADDRESS * SlaveAddress OPTIONAL + ); + +/** + Get a pointer to the assigned mappings of UDID's to Slave Addresses. + + @param[in] This Pointer to the instance of the EFI_SMBUS_HC_PROTOCOL. + @param[in, out] Length Buffer to contain the lenght of the Device Map, it will be updated to + contain the number of pairs of UDID's mapped to Slave Addresses. + @param[in, out] SmbusDeviceMap Buffer to contian a pointer to the Device Map, it will be updated to + point to the first pair in the Device Map + + @retval EFI_SUCCESS Function completed successfully. +**/ +EFI_STATUS +EFIAPI +SmbusGetArpMap ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ); + +/** + Register a callback in the event of a Host Notify command being sent by a + specified Slave Device. + + @param[in] This Pointer to the instance of the EFI_SMBUS_HC_PROTOCOL. + @param[in] SlaveAddress Address of the device whose Host Notify command we want to + trap. + @param[in] Data Data of the Host Notify command we want to trap. + @param[in] NotifyFunction Function to be called in the event the desired Host Notify + command occurs. + + @exception EFI_UNSUPPORTED Unable to create the event needed for notifications. + @retval EFI_INVALID_PARAMETER NotifyFunction was NULL. + @retval EFI_OUT_OF_RESOURCES Unable to allocate space to register the notification. + @retval EFI_SUCCESS Function completed successfully +**/ +EFI_STATUS +EFIAPI +SmbusNotify ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data, + IN EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction + ); + +/** + Set up a periodic event so that we can check if any Slave Device has sent a + Notify ARP Master command. + + @param[in] None. + + @retval EFI_SUCCESS Periodic event successfully set up. + @retval Other Errors Failed to set up Periodic event. + Error value from CreateEvent(). + Error value from SetTimer(). +**/ +EFI_STATUS +InitializePeriodicEvent ( + VOID + ); + +/** + Function to be called every time periodic event happens. This will check if + the SMBus Host Controller has received a Host Notify command. If so, it will + see if a notification has been reqested on that event and make any callbacks + that may be necessary. + + @param[in] Event The periodic event that occured and got us into this callback. + @param[in] Context Event context. Will be NULL in this case, since we already have our + private data in a module global variable. + + @retval None +**/ +VOID +EFIAPI +PollSmbusNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Issue a prepare ARP command to informs all devices that the ARP Master is starting the ARP process + + @param[in] Private Pointer to the SMBUS_INSTANCE + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +SmbusPrepareToArp ( + IN SMBUS_INSTANCE *Private + ); + +/** + Issue a Get UDID (general) command to requests ARP-capable and/or Discoverable devices to + return their slave address along with their UDID. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in, out] DeviceMap Pointer to SMBUS device map table that slave device return + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +SmbusGetUdidGeneral ( + IN SMBUS_INSTANCE *Private, + IN OUT EFI_SMBUS_DEVICE_MAP *DeviceMap + ); + +/** + Issue a Assign address command to assigns an address to a specific slave device. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in, out] DeviceMap Pointer to SMBUS device map table that send to slave device + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +SmbusAssignAddress ( + IN SMBUS_INSTANCE *Private, + IN OUT EFI_SMBUS_DEVICE_MAP *DeviceMap + ); + +/** + Do a fully (general) Arp procress to assign the slave address of all ARP-capable device. + This function will issue issue the "Prepare to ARP", "Get UDID" and "Assign Address" commands. + + @param[in] Private Pointer to the SMBUS_INSTANCE + + @retval EFI_OUT_OF_RESOURCES No available address to assign + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SmbusFullArp ( + IN SMBUS_INSTANCE *Private + ); + +/** + Do a directed Arp procress to assign the slave address of a single ARP-capable device. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in] SmbusUdid When doing a directed ARP, ARP the device with this UDID. + @param[in, out] SlaveAddress Buffer to store new Slave Address during directed ARP. + + @retval EFI_OUT_OF_RESOURCES DeviceMapEntries is more than Max number of SMBus devices + Or there is no available address to assign + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SmbusDirectedArp ( + IN SMBUS_INSTANCE *Private, + IN EFI_SMBUS_UDID *SmbusUdid, + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress + ); + +/** + Find an available address to assign + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in] SlaveAddress Buffer to store new Slave Address during directed ARP. + + @retval EFI_OUT_OF_RESOURCES There is no available address to assign + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +GetNextAvailableAddress ( + IN SMBUS_INSTANCE *Private, + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress + ); + +/** + Check whether the address is assignable. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in] SlaveAddress The Slave Address for checking + + @retval TRUE The address is assignable + @retval FALSE The address is not assignable +**/ +BOOLEAN +IsAddressAvailable ( + IN SMBUS_INSTANCE *Private, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusArp.c b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusArp.c new file mode 100644 index 0000000..88124d4 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusArp.c @@ -0,0 +1,681 @@ +/** @file + PCH Smbus Driver, ARP functions common to PEI and DXE + +@copyright + Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchSmbus.h" + +/// +/// These addresses are reserved by the SMBus 2.0 specification +/// +static UINT8 mReservedAddress[SMBUS_NUM_RESERVED] = { + 0x00, + 0x02, + 0x04, + 0x06, + 0x08, + 0x0A, + 0x0C, + 0x0E, + 0x10, + 0x18, + 0x50, + 0x6E, + 0xC2, + 0xF0, + 0xF2, + 0xF4, + 0xF6, + 0xF8, + 0xFA, + 0xFC, + 0xFE, + 0x12, + 0x14, + 0x16, + 0x58, + 0x5A, + 0x80, + 0x82, + 0x84, + 0x86, + 0x88, + 0x90, + 0x92, + 0x94, + 0x96, + 0x1A, + 0x1C, + 0x1E +}; + +/** + Set Slave address for an Smbus device with a known UDID or perform a general + ARP of all devices. + + @param[in] This Pointer to the instance of the EFI_SMBUS_HC_PROTOCOL. + @param[in] ArpAll If TRUE, do a full ARP. Otherwise, just ARP the specified UDID. + @param[in] SmbusUdid When doing a directed ARP, ARP the device with this UDID. + @@param[in, out] SlaveAddress Buffer to store new Slave Address during directed ARP. On output,If + ArpAlll == TRUE, this will contain the newly assigned Slave address. + + @retval EFI_INVALID_PARAMETER ArpAll == FALSE but SmbusUdid or SlaveAddress are NULL. + Return value from SmbusFullArp() or SmbusDirectedArp(). +**/ +EFI_STATUS +EFIAPI +SmbusArpDevice ( + IN EFI_SMBUS_HC_PROTOCOL * This, + IN BOOLEAN ArpAll, + IN EFI_SMBUS_UDID * SmbusUdid, OPTIONAL + IN OUT EFI_SMBUS_DEVICE_ADDRESS * SlaveAddress OPTIONAL + ) +{ + DEBUG ((EFI_D_INFO, "SmbusArpDevice() Start\n")); + + InitializeSmbusRegisters (); + + DEBUG ((EFI_D_INFO, "SmbusArpDevice() End\n")); + + if (ArpAll) { + return SmbusFullArp (mSmbusContext); + } else { + if ((SmbusUdid == NULL) || (SlaveAddress == NULL)) { + return EFI_INVALID_PARAMETER; + } + + return SmbusDirectedArp (mSmbusContext, SmbusUdid, SlaveAddress); + } +} + +/** + Get a pointer to the assigned mappings of UDID's to Slave Addresses. + + @param[in] This Pointer to the instance of the EFI_SMBUS_HC_PROTOCOL. + @param[in, out] Length Buffer to contain the lenght of the Device Map, it will be updated to + contain the number of pairs of UDID's mapped to Slave Addresses. + @param[in, out] SmbusDeviceMap Buffer to contian a pointer to the Device Map, it will be updated to + point to the first pair in the Device Map + + @retval EFI_SUCCESS Function completed successfully. +**/ +EFI_STATUS +EFIAPI +SmbusGetArpMap ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ) +{ + *Length = mSmbusContext->DeviceMapEntries * sizeof (EFI_SMBUS_DEVICE_MAP); + *SmbusDeviceMap = mSmbusContext->DeviceMap; + return EFI_SUCCESS; +} + +/** + Register a callback in the event of a Host Notify command being sent by a + specified Slave Device. + + @param[in] This Pointer to the instance of the EFI_SMBUS_HC_PROTOCOL. + @param[in] SlaveAddress Address of the device whose Host Notify command we want to + trap. + @param[in] Data Data of the Host Notify command we want to trap. + @param[in] NotifyFunction Function to be called in the event the desired Host Notify + command occurs. + + @exception EFI_UNSUPPORTED Unable to create the event needed for notifications. + @retval EFI_INVALID_PARAMETER NotifyFunction was NULL. + @retval EFI_OUT_OF_RESOURCES Unable to allocate space to register the notification. + @retval EFI_SUCCESS Function completed successfully +**/ +EFI_STATUS +EFIAPI +SmbusNotify ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data, + IN EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction + ) +{ + EFI_STATUS Status; + SMBUS_NOTIFY_FUNCTION_LIST_NODE *NewNode; + + DEBUG ((EFI_D_INFO, "SmbusNotify() Start\n")); + + if (NotifyFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + NewNode = (SMBUS_NOTIFY_FUNCTION_LIST_NODE *) AllocatePool (sizeof (SMBUS_NOTIFY_FUNCTION_LIST_NODE)); + if (NewNode == NULL) { + DEBUG ((EFI_D_ERROR, "Failed to allocate memory for NewNode! \n")); + return EFI_OUT_OF_RESOURCES; + } + /// + /// If this is the first notification request, start an event to periodically + /// check for a Notify master command. + /// + if (!mSmbusContext->NotificationEvent) { + Status = InitializePeriodicEvent (); + if (EFI_ERROR (Status)) { + FreePool (NewNode); + return EFI_UNSUPPORTED; + } + } + + NewNode->Signature = PCH_SMBUS_PRIVATE_DATA_SIGNATURE; + NewNode->SlaveAddress.SmbusDeviceAddress = SlaveAddress.SmbusDeviceAddress; + NewNode->Data = Data; + NewNode->NotifyFunction = NotifyFunction; + + InsertTailList (&mSmbusContext->NotifyFunctionList, &NewNode->Link); + + DEBUG ((EFI_D_INFO, "SmbusNotify() End\n")); + return EFI_SUCCESS; +} + +/** + Set up a periodic event so that we can check if any Slave Device has sent a + Notify ARP Master command. + + @param[in] None. + + @retval EFI_SUCCESS Periodic event successfully set up. + @retval Other Errors Failed to set up Periodic event. + Error value from CreateEvent(). +**/ +EFI_STATUS +InitializePeriodicEvent ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->CreateEvent ( + (EVENT_TIMER | EVENT_NOTIFY_SIGNAL), + TPL_CALLBACK, + PollSmbusNotify, + NULL, + &mSmbusContext->NotificationEvent + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SetTimer ( + mSmbusContext->NotificationEvent, + TimerPeriodic, + 1000 * MILLISECOND + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Function to be called every time periodic event happens. This will check if + the SMBus Host Controller has received a Host Notify command. If so, it will + see if a notification has been reqested on that event and make any callbacks + that may be necessary. + + @param[in] Event The periodic event that occured and got us into this callback. + @param[in] Context Event context. Will be NULL in this case, since we already have our + private data in a module global variable. + + @retval None +**/ +VOID +EFIAPI +PollSmbusNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + LIST_ENTRY *Link; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + SMBUS_NOTIFY_FUNCTION_LIST_NODE *Node; + UINT8 SstsReg; + UINTN Data; + + DEBUG ((EFI_D_INFO, "PollSmbusNotify() Start\n")); + + InitializeSmbusRegisters (); + + SstsReg = SmbusIoRead (R_PCH_SMBUS_SSTS); + if (!(SstsReg & B_PCH_SMBUS_HOST_NOTIFY_STS)) { + /// + /// Host Notify has not been received + /// + return; + } + /// + /// There was a Host Notify, see if any one wants to know about it + /// + SlaveAddress.SmbusDeviceAddress = (SmbusIoRead (R_PCH_SMBUS_NDA)) >> 1; + + Link = GetFirstNode (&mSmbusContext->NotifyFunctionList); + + while (!IsNull (&mSmbusContext->NotifyFunctionList, Link)) { + Node = SMBUS_NOTIFY_FUNCTION_LIST_NODE_FROM_LINK (Link); + + if (Node->SlaveAddress.SmbusDeviceAddress == SlaveAddress.SmbusDeviceAddress) { + Data = (SmbusIoRead (R_PCH_SMBUS_NDHB) << 8) + (SmbusIoRead (R_PCH_SMBUS_NDLB)); + if ((UINT16) Node->Data == (UINT16) Data) { + /// + /// We have a match, notify the requested function + /// + Node->NotifyFunction (SlaveAddress, Data); + } + } + + Link = GetNextNode (&mSmbusContext->NotifyFunctionList, &Node->Link); + } + /// + /// Clear the Notify Status bit and exit. + /// + SmbusIoWrite (R_PCH_SMBUS_SSTS, B_PCH_SMBUS_HOST_NOTIFY_STS); + + DEBUG ((EFI_D_INFO, "PollSmbusNotify() End\n")); + + return; +} + +/** + Issue a prepare ARP command to informs all devices that the ARP Master is starting the ARP process + + @param[in] Private Pointer to the SMBUS_INSTANCE + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +SmbusPrepareToArp ( + IN SMBUS_INSTANCE *Private + ) +{ + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + EFI_STATUS Status; + UINTN Length; + UINT8 Buffer; + + DEBUG ((EFI_D_INFO, "SmbusPrepareToArp() Start\n")); + + SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP; + Length = 1; + Buffer = SMBUS_DATA_PREPARE_TO_ARP; + + Status = SmbusExec ( + SlaveAddress, + 0, + EfiSmbusSendByte, + TRUE, + &Length, + &Buffer + ); + + DEBUG ((EFI_D_INFO, "SmbusPrepareToArp() End\n")); + + return Status; +} + +/** + Issue a Get UDID (general) command to requests ARP-capable and/or Discoverable devices to + return their slave address along with their UDID. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in, out] DeviceMap Pointer to SMBUS device map table that slave device return + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +SmbusGetUdidGeneral ( + IN SMBUS_INSTANCE *Private, + IN OUT EFI_SMBUS_DEVICE_MAP *DeviceMap + ) +{ + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + EFI_STATUS Status; + UINTN Length; + UINT8 Buffer[SMBUS_GET_UDID_LENGTH]; + + DEBUG ((EFI_D_INFO, "SmbusGetUdidGeneral() Start\n")); + + SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP; + Length = SMBUS_GET_UDID_LENGTH; + + Status = SmbusExec ( + SlaveAddress, + SMBUS_DATA_GET_UDID_GENERAL, + EfiSmbusReadBlock, + TRUE, + &Length, + Buffer + ); + + if (!EFI_ERROR (Status)) { + if (Length == SMBUS_GET_UDID_LENGTH) { + DeviceMap->SmbusDeviceUdid.DeviceCapabilities = Buffer[0]; + DeviceMap->SmbusDeviceUdid.VendorRevision = Buffer[1]; + DeviceMap->SmbusDeviceUdid.VendorId = (UINT16) ((Buffer[2] << 8) + Buffer[3]); + DeviceMap->SmbusDeviceUdid.DeviceId = (UINT16) ((Buffer[4] << 8) + Buffer[5]); + DeviceMap->SmbusDeviceUdid.Interface = (UINT16) ((Buffer[6] << 8) + Buffer[7]); + DeviceMap->SmbusDeviceUdid.SubsystemVendorId = (UINT16) ((Buffer[8] << 8) + Buffer[9]); + DeviceMap->SmbusDeviceUdid.SubsystemDeviceId = (UINT16) ((Buffer[10] << 8) + Buffer[11]); + DeviceMap->SmbusDeviceUdid.VendorSpecificId = (UINT32) ((Buffer[12] << 24) + (Buffer[13] << 16) + (Buffer[14] << 8) + Buffer[15]); + DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress = (UINT8) (Buffer[16] >> 1); + } else { + Status = EFI_DEVICE_ERROR; + } + } + + DEBUG ((EFI_D_INFO, "SmbusGetUdidGeneral() End\n")); + + return Status; +} + +/** + Issue a Assign address command to assigns an address to a specific slave device. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in, out] DeviceMap Pointer to SMBUS device map table that send to slave device + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +SmbusAssignAddress ( + IN SMBUS_INSTANCE *Private, + IN OUT EFI_SMBUS_DEVICE_MAP *DeviceMap + ) +{ + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + EFI_STATUS Status; + UINTN Length; + UINT8 Buffer[SMBUS_GET_UDID_LENGTH]; + + DEBUG ((EFI_D_INFO, "SmbusAssignAddress() Start\n")); + + Buffer[0] = DeviceMap->SmbusDeviceUdid.DeviceCapabilities; + Buffer[1] = DeviceMap->SmbusDeviceUdid.VendorRevision; + Buffer[2] = (UINT8) (DeviceMap->SmbusDeviceUdid.VendorId >> 8); + Buffer[3] = (UINT8) (DeviceMap->SmbusDeviceUdid.VendorId); + Buffer[4] = (UINT8) (DeviceMap->SmbusDeviceUdid.DeviceId >> 8); + Buffer[5] = (UINT8) (DeviceMap->SmbusDeviceUdid.DeviceId); + Buffer[6] = (UINT8) (DeviceMap->SmbusDeviceUdid.Interface >> 8); + Buffer[7] = (UINT8) (DeviceMap->SmbusDeviceUdid.Interface); + Buffer[8] = (UINT8) (DeviceMap->SmbusDeviceUdid.SubsystemVendorId >> 8); + Buffer[9] = (UINT8) (DeviceMap->SmbusDeviceUdid.SubsystemVendorId); + Buffer[10] = (UINT8) (DeviceMap->SmbusDeviceUdid.SubsystemDeviceId >> 8); + Buffer[11] = (UINT8) (DeviceMap->SmbusDeviceUdid.SubsystemDeviceId); + Buffer[12] = (UINT8) (DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 24); + Buffer[13] = (UINT8) (DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 16); + Buffer[14] = (UINT8) (DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 8); + Buffer[15] = (UINT8) (DeviceMap->SmbusDeviceUdid.VendorSpecificId); + Buffer[16] = (UINT8) (DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress << 1); + + SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP; + Length = SMBUS_GET_UDID_LENGTH; + + Status = SmbusExec ( + SlaveAddress, + SMBUS_DATA_ASSIGN_ADDRESS, + EfiSmbusWriteBlock, + TRUE, + &Length, + Buffer + ); + + DEBUG ((EFI_D_INFO, "SmbusAssignAddress() End\n")); + + return Status; +} + +/** + Do a fully (general) Arp procress to assign the slave address of all ARP-capable device. + This function will issue issue the "Prepare to ARP", "Get UDID" and "Assign Address" commands. + + @param[in] Private Pointer to the SMBUS_INSTANCE + + @retval EFI_OUT_OF_RESOURCES No available address to assign + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SmbusFullArp ( + IN SMBUS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_MAP *CurrentDeviceMap; + + DEBUG ((EFI_D_INFO, "SmbusFullArp() Start\n")); + + Status = SmbusPrepareToArp (Private); + if (EFI_ERROR (Status)) { + if (Status == EFI_DEVICE_ERROR) { + /// + /// ARP is complete + /// + return EFI_SUCCESS; + } else { + return Status; + } + } + /// + /// Main loop to ARP all ARP-capable devices + /// + do { + CurrentDeviceMap = &Private->DeviceMap[Private->DeviceMapEntries]; + Status = SmbusGetUdidGeneral (Private, CurrentDeviceMap); + if (EFI_ERROR (Status)) { + break; + } + + if (CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress == (0xFF >> 1)) { + /// + /// If address is unassigned, assign it + /// + Status = GetNextAvailableAddress ( + Private, + &CurrentDeviceMap->SmbusDeviceAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } else if (((CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities) & 0xC0) != 0) { + /// + /// if address is not fixed, check if the current address is available + /// + if (!IsAddressAvailable ( + Private, + CurrentDeviceMap->SmbusDeviceAddress + )) { + /// + /// if currently assigned address is already used, get a new one + /// + Status = GetNextAvailableAddress ( + Private, + &CurrentDeviceMap->SmbusDeviceAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + } + + Status = SmbusAssignAddress (Private, CurrentDeviceMap); + if (EFI_ERROR (Status)) { + /// + /// If there was a device error, just continue on and try again. + /// Other errors should be reported. + /// + if (Status != EFI_DEVICE_ERROR) { + return Status; + } + } else { + /// + /// If there was no error, the address was assigned and we must update our + /// records. + /// + Private->DeviceMapEntries++; + } + + } while (Private->DeviceMapEntries < MAX_SMBUS_DEVICES); + + DEBUG ((EFI_D_INFO, "SmbusFullArp() End\n")); + + return EFI_SUCCESS; +} + +/** + Do a directed Arp procress to assign the slave address of a single ARP-capable device. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in] SmbusUdid When doing a directed ARP, ARP the device with this UDID. + @param[in, out] SlaveAddress Buffer to store new Slave Address during directed ARP. + + @retval EFI_OUT_OF_RESOURCES DeviceMapEntries is more than Max number of SMBus devices + Or there is no available address to assign + + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +SmbusDirectedArp ( + IN SMBUS_INSTANCE *Private, + IN EFI_SMBUS_UDID *SmbusUdid, + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress + ) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_MAP *CurrentDeviceMap; + + DEBUG ((EFI_D_INFO, "SmbusDirectedArp() Start\n")); + + if (Private->DeviceMapEntries >= MAX_SMBUS_DEVICES) { + return EFI_OUT_OF_RESOURCES; + } + + CurrentDeviceMap = &Private->DeviceMap[Private->DeviceMapEntries]; + + /// + /// Find an available address to assign + /// + Status = GetNextAvailableAddress ( + Private, + &CurrentDeviceMap->SmbusDeviceAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities = SmbusUdid->DeviceCapabilities; + CurrentDeviceMap->SmbusDeviceUdid.DeviceId = SmbusUdid->DeviceId; + CurrentDeviceMap->SmbusDeviceUdid.Interface = SmbusUdid->Interface; + CurrentDeviceMap->SmbusDeviceUdid.SubsystemDeviceId = SmbusUdid->SubsystemDeviceId; + CurrentDeviceMap->SmbusDeviceUdid.SubsystemVendorId = SmbusUdid->SubsystemVendorId; + CurrentDeviceMap->SmbusDeviceUdid.VendorId = SmbusUdid->VendorId; + CurrentDeviceMap->SmbusDeviceUdid.VendorRevision = SmbusUdid->VendorRevision; + CurrentDeviceMap->SmbusDeviceUdid.VendorSpecificId = SmbusUdid->VendorSpecificId; + + Status = SmbusAssignAddress (Private, CurrentDeviceMap); + if (EFI_ERROR (Status)) { + return Status; + } + + Private->DeviceMapEntries++; + SlaveAddress->SmbusDeviceAddress = CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress; + + DEBUG ((EFI_D_INFO, "SmbusDirectedArp() End\n")); + + return EFI_SUCCESS; +} + +/** + Find an available address to assign + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in] SlaveAddress Buffer to store new Slave Address during directed ARP. + + @retval EFI_OUT_OF_RESOURCES There is no available address to assign + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +GetNextAvailableAddress ( + IN SMBUS_INSTANCE *Private, + IN EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress + ) +{ + for (SlaveAddress->SmbusDeviceAddress = 0x03; + SlaveAddress->SmbusDeviceAddress < 0x7F; + SlaveAddress->SmbusDeviceAddress++ + ) { + if (IsAddressAvailable (Private, *SlaveAddress)) { + return EFI_SUCCESS; + } + } + + return EFI_OUT_OF_RESOURCES; +} + +/** + Check whether the address is assignable. + + @param[in] Private Pointer to the SMBUS_INSTANCE + @param[in] SlaveAddress The Slave Address for checking + + @retval TRUE The address is assignable + @retval FALSE The address is not assignable +**/ +BOOLEAN +IsAddressAvailable ( + IN SMBUS_INSTANCE *Private, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress + ) +{ + UINT8 Index; + + /// + /// See if we have already assigned this address to a device + /// + for (Index = 0; Index < Private->DeviceMapEntries; Index++) { + if (SlaveAddress.SmbusDeviceAddress == Private->DeviceMap[Index].SmbusDeviceAddress.SmbusDeviceAddress) { + return FALSE; + } + } + /// + /// See if this address is claimed by a platform non-ARP-capable device + /// + for (Index = 0; Index < Private->PlatformNumRsvd; Index++) { + if ((SlaveAddress.SmbusDeviceAddress << 1) == Private->PlatformRsvdAddr[Index]) { + return FALSE; + } + } + /// + /// See if this is a reserved address + /// + for (Index = 0; Index < SMBUS_NUM_RESERVED; Index++) { + if ((SlaveAddress.SmbusDeviceAddress << 1) == (UINTN) mReservedAddress[Index]) { + return FALSE; + } + } + + return TRUE; +} diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.cif b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.cif new file mode 100644 index 0000000..5a97eaa --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.cif @@ -0,0 +1,14 @@ +<component> + name = "PchSmbusDxe" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Smbus\Dxe" + RefName = "PchSmbusDxe" +[files] +"PchSmbusDxe.sdl" +"PchSmbusDxe.mak" +"PchSmbus.h" +"PchSmbusArp.c" +"PchSmbusEntry.c" +"PchSmbus.dxs" +"PchSmbusDxe.inf" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.inf b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.inf new file mode 100644 index 0000000..ae41336 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.inf @@ -0,0 +1,93 @@ +## @file +# Component description file for PchSmbus driver +# +#@copyright +# Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchSmbusDxe +FILE_GUID = E052D8A6-224A-4c32-8D37-2E0AE162364D +COMPONENT_TYPE = BS_DRIVER + +[sources.common] + PchSmbusEntry.c + PchSmbus.h + PchSmbusArp.c + ../Common/PchSmbusExec.c +# +# Edk II Glue Driver Entry Point +# + EdkIIGlueDxeDriverEntryPoint.c + +[includes.common] + $(EDK_SOURCE)/Foundation/Efi + . + ../Common + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include +# +# Typically the sample code referenced will be available in the code base already +# So keep this include at the end to defer to the source base definition +# and only use the sample code definition if source base does not include these files. +# + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/SampleCode + +[libraries.common] + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseLib + EdkIIGlueDxeReportStatusCodeLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueUefiRuntimeServicesTableLib + EdkIIGlueDxeMemoryAllocationLib + EdkIIGlueDxeHobLib + EdkIIGlueBasePciLibPciExpress + EdkFrameworkProtocolLib + EdkProtocolLib + $(PROJECT_PCH_FAMILY)ProtocolLib + PchPlatformLib + +[nmake.common] + IMAGE_ENTRY_POINT=_ModuleEntryPoint + DPX_SOURCE=PchSmbus.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InitializePchSmbus + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_LIB__ \ + -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_DXE_HOB_LIB__ \ + -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
\ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.mak b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.mak new file mode 100644 index 0000000..3e74002 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.mak @@ -0,0 +1,103 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (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 Refcode/PchSmbusDxe/PchSmbusDxe.mak 2 2/24/12 2:22a Victortu $ +# +# $Revision: 2 $ +# +# $Date: 2/24/12 2:22a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSmbusDxe/PchSmbusDxe.mak $ +# +# 2 2/24/12 2:22a Victortu +# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00. +# +# 1 2/08/12 9:19a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +#--------------------------------------------------------------------------- +# Create PchSmbusDxe Driver +#--------------------------------------------------------------------------- +EDK : PchSmbusDxe +PchSmbusDxe : $(BUILD_DIR)\PchSmbusDxe.mak PchSmbusDxeBin + + +$(BUILD_DIR)\PchSmbusDxe.mak : $(PchSmbusDxe_DIR)\$(@B).cif $(PchSmbusDxe_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchSmbusDxe_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchSmbusDxe_INCLUDES=\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + +PchSmbusDxe_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializePchSmbus"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_BASE_LIB__ \ + /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_DXE_HOB_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ + +PchSmbusDxe_LIB_LINKS =\ +!IF "$(x64_BUILD)"=="1" + $(EdkIIGlueBaseLibX64_LIB)\ +!ELSE + $(EdkIIGlueBaseLibIA32_LIB)\ +!ENDIF + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueBaseLib_LIB)\ + $(EdkIIGlueDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EdkIIGlueDxeHobLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + $(EDKPROTOCOLLIB)\ + $(INTEL_PCH_PROTOCOL_LIB)\ + $(PchPlatformDxeLib_LIB)\ + $(PchSmbusCommonDxeLib_LIB) + +PchSmbusDxeBin: $(PchSmbusDxe_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchSmbusDxe.mak all \ + "MY_INCLUDES=$(PchSmbusDxe_INCLUDES)"\ + "MY_DEFINES=$(PchSmbusDxe_DEFINES)"\ + GUID=E052D8A6-224A-4c32-8D37-2E0AE162364D\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=BS_DRIVER\ + EDKIIModule=DXEDRIVER\ + DEPEX1=$(PchSmbusDxe_DIR)\PchSmbus.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\ + COMPRESS=1 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.sdl b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.sdl new file mode 100644 index 0000000..8d5afd7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusDxe.sdl @@ -0,0 +1,67 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (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 Refcode/PchSmbusDxe/PchSmbusDxe.sdl 1 2/08/12 9:19a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 9:19a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSmbusDxe/PchSmbusDxe.sdl $ +# +# 1 2/08/12 9:19a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchSmbusDxe_SUPPORT" + Value = "1" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes + Help = "Main switch to enable PchSmbusDxe support in Project" +End + +PATH + Name = "PchSmbusDxe_DIR" + Help = "PchSmbusDxe file source directory" +End + +MODULE + Help = "Includes PchSmbusDxe.mak to Project" + File = "PchSmbusDxe.mak" +End + +ELINK + Name = "$(BUILD_DIR)\PchSmbusDxe.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusEntry.c b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusEntry.c new file mode 100644 index 0000000..35cab3f --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Smbus/Dxe/PchSmbusEntry.c @@ -0,0 +1,149 @@ +/** @file + PCH Smbus Driver + +@copyright + Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#include "PchSmbus.h" + +EFI_GUID mEfiSmbusArpMapGuid = EFI_SMBUS_ARP_MAP_GUID; + +/** + Execute an SMBUS operation + + @param[in] This The protocol instance + @param[in] SlaveAddress The address of the SMBUS slave device + @param[in] Command The SMBUS command + @param[in] Operation Which SMBus protocol will be issued + @param[in] PecCheck If Packet Error Code Checking is to be used + @param[in, out] Length Length of data + @param[in, out] Buffer Data buffer + + @retval EFI_SUCCESS The SMBUS operation is successful + @retval Other Values Something error occurred +**/ +EFI_STATUS +EFIAPI +SmbusExecute ( + 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 + ) +{ + DEBUG ((EFI_D_INFO, "SmbusExecute() Start, SmbusDeviceAddress=%x, Command=%x, Operation=%x\n", (SlaveAddress.SmbusDeviceAddress << 1), Command, Operation)); + InitializeSmbusRegisters (); + + return SmbusExec ( + SlaveAddress, + Command, + Operation, + PecCheck, + Length, + Buffer + ); +} + +/** + Smbus driver entry point + + @param[in] ImageHandle ImageHandle of this module + @param[in] SystemTable EFI System Table + + @retval EFI_SUCCESS Driver initializes successfully + @retval Other values Some error occurred +**/ +EFI_STATUS +EFIAPI +InitializePchSmbus ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy; + EFI_STATUS Status; + UINTN DataSize; + VOID *Data; + EFI_PEI_HOB_POINTERS HobList; + + DEBUG ((EFI_D_INFO, "InitializePchSmbus() Start\n")); + + Status = gBS->LocateProtocol ( + &gDxePchPlatformPolicyProtocolGuid, + NULL, + (VOID **) &PchPlatformPolicy + ); + ASSERT_EFI_ERROR (Status); + + mSmbusContext = AllocateZeroPool (sizeof (SMBUS_INSTANCE)); + if (mSmbusContext == NULL) { + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + mSmbusContext->Signature = PCH_SMBUS_PRIVATE_DATA_SIGNATURE; + mSmbusContext->IoDone = IoDone; + mSmbusContext->SmbusIoRead = SmbusIoRead; + mSmbusContext->SmbusIoWrite = SmbusIoWrite; + mSmbusContext->SmbusController.Execute = SmbusExecute; + mSmbusContext->SmbusController.ArpDevice = SmbusArpDevice; + mSmbusContext->SmbusController.GetArpMap = SmbusGetArpMap; + mSmbusContext->SmbusController.Notify = SmbusNotify; + mSmbusContext->PlatformNumRsvd = PchPlatformPolicy->SmbusConfig->NumRsvdSmbusAddresses; + mSmbusContext->PlatformRsvdAddr = PchPlatformPolicy->SmbusConfig->RsvdSmbusAddressTable; + + /// + /// See if PEI already ARPed any devices, and if so, update our device map. + /// + /// Get Hob list + /// + Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, (VOID **) &HobList.Raw); + ASSERT_EFI_ERROR (Status); + + HobList.Raw = GetNextGuidHob (&mEfiSmbusArpMapGuid, HobList.Raw); + /// + /// If we found the right hob, store the information. Otherwise, continue. + /// + if (HobList.Raw != NULL) { + Data = (VOID *) ((UINT8 *) (&HobList.Guid->Name) + sizeof (EFI_GUID)); + DataSize = HobList.Header->HobLength - sizeof (EFI_HOB_GUID_TYPE); + CopyMem (mSmbusContext->DeviceMap, Data, DataSize); + mSmbusContext->DeviceMapEntries = (UINT8) (DataSize / sizeof (EFI_SMBUS_DEVICE_MAP)); + } + /// + /// Initialize the NotifyFunctionList + /// + InitializeListHead (&mSmbusContext->NotifyFunctionList); + + /// + /// Install the SMBUS interface + /// + Status = gBS->InstallMultipleProtocolInterfaces ( + &mSmbusContext->Handle, + &gEfiSmbusProtocolGuid, + &mSmbusContext->SmbusController, + NULL + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "InitializePchSmbus() End\n")); + + return EFI_SUCCESS; +} |