Message ID | 20180724070922.63362-23-ming.huang@linaro.org |
---|---|
State | New |
Headers | show |
Series | Upload for D06 platform | expand |
On Tue, Jul 24, 2018 at 03:09:06PM +0800, Ming Huang wrote: > OemNicLib provide nic related api like GetMac,SetMac. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ming Huang <ming.huang@linaro.org> > Signed-off-by: Heyi Guo <heyi.guo@linaro.org> > --- > Platform/Hisilicon/D06/D06.dsc | 1 + > Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c | 571 ++++++++++++++++++++ > Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf | 35 ++ > 3 files changed, 607 insertions(+) > > diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc > index 43af043cfd..744a4a0d6d 100644 > --- a/Platform/Hisilicon/D06/D06.dsc > +++ b/Platform/Hisilicon/D06/D06.dsc > @@ -91,6 +91,7 @@ > > LpcLib|Silicon/Hisilicon/Hi1620/Library/LpcLibHi1620/LpcLib.inf > SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf > + OemNicLib|Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf > !if $(SECURE_BOOT_ENABLE) == TRUE > FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf > !endif > diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c > new file mode 100644 > index 0000000000..55ed1625ce > --- /dev/null > +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c > @@ -0,0 +1,571 @@ > +/** @file > +* > +* Copyright (c) 2018, Hisilicon Limited. All rights reserved. > +* Copyright (c) 2017, Linaro Limited. All rights reserved. > +* > +* This program and the accompanying materials > +* are licensed and made available under the terms and conditions of the BSD License > +* which accompanies this distribution. The full text of the license may be found at > +* http://opensource.org/licenses/bsd-license.php > +* > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +* > +**/ > + > +#include <Uefi.h> > +#include <Library/CpldIoLib.h> > +#include <Library/DebugLib.h> > +#include <Library/I2CLib.h> > +#include <Library/IoLib.h> > +#include <Library/OemNicLib.h> > + > +#define CPU2_SFP2_100G_CARD_OFFSET 0x25 > +#define CPU1_SFP1_LOCATE_OFFSET 0x16 > +#define CPU1_SFP0_LOCATE_OFFSET 0x12 > +#define CPU2_SFP1_LOCATE_OFFSET 0x21 > +#define CPU2_SFP0_LOCATE_OFFSET 0x19 > +#define CPU2_SFP2_10G_GE_CARD_OFFSET 0x25 > + > +#define SFP_10G_SPEED 10 > +#define SFP_25G_SPEED 25 > +#define SFP_100G_SPEED 100 > +#define SFP_GE_SPEED 1 > + > +#define SFP_GE_SPEED_VAL_VENDOR_FINISAR 0x0C > +#define SFP_GE_SPEED_VAL 0x0D > +#define SFP_10G_SPEED_VAL 0x67 > +#define SFP_25G_SPEED_VAL 0xFF > + > +#define CPU1_9545_I2C_ADDR 0x70 > +#define CPU2_9545_I2C_ADDR 0x71 > + > +#define FIBER_PRESENT 0 > +#define CARD_PRESENT 1 > +#define I2C_PORT_SFP 4 > +#define CPU2_I2C_PORT_SFP 5 > + > +#define SOCKET_0 0 > +#define SOCKET_1 1 > +#define EEPROM_I2C_PORT 4 > +#define EEPROM_PAGE_SIZE 0x40 > +#define MAC_ADDR_LEN 6 > +#define I2C_OFFSET_EEPROM_ETH0 (0xc00) > +#define I2C_SLAVEADDR_EEPROM (0x52) > + > +#pragma pack(1) > +typedef struct { > + UINT16 Crc16; > + UINT16 MacLen; > + UINT8 Mac[MAC_ADDR_LEN]; > +} NIC_MAC_ADDRESS; > +#pragma pack() > + > +ETH_PRODUCT_DESC gEthPdtDesc[ETH_MAX_PORT] = > +{ > + {TRUE, ETH_SPEED_10KM, ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID}, > + {TRUE, ETH_SPEED_10KM, ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID}, > + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, > + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, > + {TRUE, ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 0}, > + {TRUE, ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 1}, > + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, > + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID} > +}; > + > +volatile unsigned char g_2pserveraddr[4][6] = { VOLATILE UINT8. No '_' in variable name. Also, can we please have #defines for that 4 and 6? > + {0x00, 0x18, 0x16, 0x29, 0x11, 0x00}, > + {0x00, 0x18, 0x16, 0x29, 0x11, 0x01}, > + {0x00, 0x18, 0x16, 0x29, 0x11, 0x02}, > + {0x00, 0x18, 0x16, 0x29, 0x11, 0x03} > +}; > + > +UINT16 crc_tab[256] = { CrcTable. Hmm. This might be useful to add to a core library/driver/protocol. We don't appear to have it yet. This is another note to the universe. > + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, > + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, > + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, > + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, > + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, > + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, > + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, > + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, > + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, > + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, > + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, > + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, > + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, > + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, > + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, > + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, > + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, > + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, > + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, > + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, > + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, > + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, > + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, > + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, > + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, > + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, > + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, > + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, > + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, > + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, > + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, > + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, > +}; > + > +EFI_STATUS > +GetSfpSpeed ( > + UINT16 Socket, > + UINT16 SfpNum, > + UINT8* FiberSpeed > + ) > +{ > + EFI_STATUS Status; > + I2C_DEVICE SpdDev; > + UINT8 SpdReg; > + UINT8 SfpSpeed; > + UINT32 RegAddr; > + UINT16 I2cAddr; > + UINT32 SfpPort; > + > + SfpSpeed = 0x0; > + if(Socket == 1) { Space before '('. Please add a descriptive #define for that 1. > + I2cAddr = CPU2_9545_I2C_ADDR; > + SfpPort = CPU2_I2C_PORT_SFP; > + } else { > + I2cAddr = CPU1_9545_I2C_ADDR; > + SfpPort = I2C_PORT_SFP; > + } > + > + Status = I2CInit (Socket, SfpPort, Normal); > + if (EFI_ERROR (Status)) > + { > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Socket%d Call I2CInit failed! p1=0x%x.\n", > + __FUNCTION__, __LINE__, Socket, Status)); > + return Status; > + } > + > + SpdDev.Socket = Socket; > + SpdDev.DeviceType = DEVICE_TYPE_SPD; > + SpdDev.Port = SfpPort; > + SpdDev.SlaveDeviceAddress = I2cAddr; > + RegAddr = 0x0; > + SpdReg = 1 << (SfpNum - 1); Please add descriptive #define. > + > + Status = I2CWrite (&SpdDev, RegAddr, 1, &SpdReg); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "I2CWrite Error =%r.\n", Status)); > + return Status; > + } > + > + SpdDev.Socket = Socket; > + SpdDev.DeviceType = DEVICE_TYPE_SPD; > + SpdDev.Port = SfpPort; > + SpdDev.SlaveDeviceAddress = 0x50; Please add descriptive #define. > + > + RegAddr = 12; Please add descriptive #define. > + Status = I2CRead (&SpdDev, RegAddr, 1, &SfpSpeed); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "I2CRead Error =%r.\n", Status)); > + return Status; > + } > + > + DEBUG ((DEBUG_INFO, "BR, Nominal, Nominal signalling rate, SfpSpeed: 0x%x\n", > + SfpSpeed)); > + > + if (SfpSpeed == SFP_10G_SPEED_VAL) { > + *FiberSpeed = SFP_10G_SPEED; > + } else if (SfpSpeed == SFP_25G_SPEED_VAL) { > + *FiberSpeed = SFP_25G_SPEED; > + } else if ((SfpSpeed == SFP_GE_SPEED_VAL) || (SfpSpeed == SFP_GE_SPEED_VAL_VENDOR_FINISAR)) { Long line, please break. > + *FiberSpeed = SFP_GE_SPEED; > + } > + > + return EFI_SUCCESS; > +} > + > +//Fiber1Type/Fiber2Type/Fiber3Type return: SFP_10G_SPEED, SFP_100G_SPEED, SFP_GE_SPEED > +UINT32 > +GetCpu2FiberType ( > + UINT8* Fiber1Type, > + UINT8* Fiber2Type, > + UINT8* Fiber100Ge > + ) > +{ > + EFI_STATUS Status; > + UINT16 SfpNum1; > + UINT8 SfpSpeed1; > + UINT16 SfpNum2; > + UINT8 SfpSpeed2; > + > + SfpNum1 = 0x1; > + SfpSpeed1 = SFP_10G_SPEED; > + SfpNum2 = 0x2; > + SfpSpeed2 = SFP_10G_SPEED; > + *Fiber100Ge = 0x0; > + *Fiber1Type = SFP_10G_SPEED; > + *Fiber2Type = SFP_10G_SPEED; > + > + if ((ReadCpldReg (CPU2_SFP2_100G_CARD_OFFSET) & BIT7) == (CARD_PRESENT << 7)) { Please add descriptively named helper macros or #defines (& BIT7, << 7). > + // 100 Ge card > + *Fiber1Type = SFP_10G_SPEED; > + *Fiber2Type = SFP_10G_SPEED; > + *Fiber100Ge = SFP_100G_SPEED; > + DEBUG ((DEBUG_ERROR,"Detect Fiber SFP_100G is Present, Set 100Ge\n")); > + } else if ((ReadCpldReg (CPU2_SFP2_10G_GE_CARD_OFFSET) & BIT0) == CARD_PRESENT) { Please add descriptively named helper macro or #define (& BIT0). > + *Fiber100Ge = 0x0; > + *Fiber1Type = SFP_10G_SPEED; > + *Fiber2Type = SFP_10G_SPEED; > + if (ReadCpldReg (CPU2_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) { > + // Fiber detected in CPU2 slot0, read speed via i2c > + Status = GetSfpSpeed (SOCKET_1, SfpNum1, &SfpSpeed1); > + if (EFI_ERROR (Status)) { > + DEBUG((DEBUG_ERROR, > + "Get Socket1 Sfp%d Speed Error: %r.\n", > + SfpNum1, > + Status)); > + return Status; > + } > + if (SfpSpeed1 == SFP_25G_SPEED) { > + // P1 don't support 25G, so set speed to 10G > + *Fiber1Type = SFP_10G_SPEED; > + } else { > + *Fiber1Type = SfpSpeed1; > + } > + } else { > + // No fiber, set speed to 10G > + *Fiber1Type = SFP_10G_SPEED; > + } > + > + if (ReadCpldReg (CPU2_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) { > + // Fiber detected in CPU2 slot1, read speed via i2c > + Status = GetSfpSpeed (SOCKET_1, SfpNum2, &SfpSpeed2); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status)); > + return Status; > + } > + if (SfpSpeed2 == SFP_25G_SPEED) { > + *Fiber2Type = SFP_10G_SPEED; > + } else { > + *Fiber2Type = SfpSpeed2; > + } > + } else { > + // No fiber, set speed to 10G > + *Fiber2Type = SFP_10G_SPEED; > + } > + } else { > + // 100Ge/10Ge/Ge Fiber is not found. > + *Fiber1Type = SFP_10G_SPEED; > + *Fiber2Type = SFP_10G_SPEED; > + *Fiber100Ge = 0x0; > + } > + > + return EFI_SUCCESS; > +} > + > +//Fiber1Type/Fiber2Type return: SFP_10G_SPEED, SFP_25G_SPEED, SFP_GE_SPEED > +UINT32 > +GetCpu1FiberType ( > + UINT8* Fiber1Type, > + UINT8* Fiber2Type > + ) > +{ > + EFI_STATUS Status; > + UINT16 SfpNum1; > + UINT8 SfpSpeed1; > + UINT16 SfpNum2; > + UINT8 SfpSpeed2; > + > + SfpNum1 = 0x1; > + SfpSpeed1 = SFP_10G_SPEED; > + SfpNum2 = 0x2; > + SfpSpeed2 = SFP_10G_SPEED; > + *Fiber1Type = SFP_10G_SPEED; > + *Fiber2Type = SFP_10G_SPEED; > + // Fiber detected in CPU1 slot0, read speed via i2c > + if (ReadCpldReg (CPU1_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) { > + Status = GetSfpSpeed (SOCKET_0, SfpNum1, &SfpSpeed1); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Get Socket0 Sfp%d Speed Error: %r.\n", > + SfpNum1, Status)); > + return Status; > + } > + *Fiber1Type = SfpSpeed1; > + } else { > + *Fiber1Type = SFP_10G_SPEED; > + } > + > + // Fiber detected in CPU1 slot1, read speed via i2c > + if (ReadCpldReg (CPU1_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) { > + Status = GetSfpSpeed (SOCKET_0, SfpNum2, &SfpSpeed2); > + if (EFI_ERROR (Status)) { > + *Fiber2Type = SFP_10G_SPEED; > + DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status)); > + return Status; > + } > + *Fiber2Type = SfpSpeed2; > + } else { > + *Fiber2Type = SFP_10G_SPEED; > + } > + > + return EFI_SUCCESS; > +} > + > +UINT16 make_crc_checksum ( MakeCrcChecksum > + UINT8 *buf, Buffer. > + UINT32 len Length. > + ) > +{ > + UINT16 StartCRC = 0; > + > + if (len > (512 * 1024)) { SIZE_512KB? > + return 0; > + } > + > + if (buf == NULL) { > + return 0; > + } > + > + while (len) { > + StartCRC = crc_tab [((UINT8) ((StartCRC >> 8) & 0xff)) ^ *(buf++)] ^ > + ((UINT16) (StartCRC << 8)); > + len--; > + } > + > + return StartCRC; > +} > + > + > +EFI_STATUS > +OemGetMacE2prom( > + IN UINT32 Port, > + OUT UINT8 *pucAddr Hungarian notation. Drop 'puc'. > + ) > +{ > + I2C_DEVICE stI2cDev = {0}; Hungarian notation. Drop 'st'. > + EFI_STATUS Status; > + UINT16 I2cOffset; > + UINT16 crc16; Crc16. > + NIC_MAC_ADDRESS stMacDesc = {0}; Hungarian notation. Drop 'st'. > + UINT16 RemainderMacOffset; > + UINT16 LessSizeOfPage; > + UINT32 i = 0; I. > + > + Status = I2CInit (0, EEPROM_I2C_PORT, Normal); > + if (EFI_ERROR (Status)) > + { > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n", > + __FUNCTION__, __LINE__, Status)); > + return Status; > + } > + > + I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS)); > + > + stI2cDev.DeviceType = DEVICE_TYPE_E2PROM; > + stI2cDev.Port = EEPROM_I2C_PORT; > + stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM; > + stI2cDev.Socket = 0; > + RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE; > + LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset; > + //The length of NIC_MAC_ADDRESS is 10 bytes long, > + //It surly less than EEPROM page size, so we could > + //code as bellow, check the address whether across the page boundary, bellow -> below > + //and split the data when across page boundary. > + if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) { > + Status = I2CRead (&stI2cDev, I2cOffset, sizeof (NIC_MAC_ADDRESS), (UINT8 *) &stMacDesc); > + } else { > + Status = I2CRead (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc); > + if (!(EFI_ERROR (Status))) { Parantheses around EFI_ERROR not needed. > + Status |= I2CRead ( > + &stI2cDev, > + I2cOffset + LessSizeOfPage, > + sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage, > + (UINT8 *) &stMacDesc + LessSizeOfPage > + ); > + } > + } > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cRead failed! p1=0x%x.\n", > + __FUNCTION__, __LINE__, Status)); > + return Status; > + } > + > + crc16 = make_crc_checksum ( > + (UINT8 *) & (stMacDesc.MacLen), > + sizeof (stMacDesc.MacLen) + sizeof (stMacDesc.Mac) > + ); > + if ((crc16 != stMacDesc.Crc16) || (0 == crc16)) { > + return EFI_NOT_FOUND; > + } > + > + for (i = 0; i < MAC_ADDR_LEN; i++) { > + pucAddr[i] = stMacDesc.Mac[i]; > + } > + > + return EFI_SUCCESS; > +} > + > + > +EFI_STATUS > +OemSetMacE2prom ( > + IN UINT32 Port, > + IN UINT8 *pucAddr Hungarian notation. Drop 'puc'. > + ) > +{ > + I2C_DEVICE stI2cDev = {0}; Hungarian notation. Drop 'st'. > + EFI_STATUS Status; > + UINT16 I2cOffset; > + NIC_MAC_ADDRESS stMacDesc = {0}; Hungarian notation. Drop 'st'. > + UINT32 i; I. > + UINT16 RemainderMacOffset; > + UINT16 LessSizeOfPage; > + > + i = 0; > + stMacDesc.MacLen = MAC_ADDR_LEN; > + > + for (i = 0; i < MAC_ADDR_LEN; i++) { > + stMacDesc.Mac[i] = pucAddr[i]; > + } > + > + stMacDesc.Crc16 = make_crc_checksum ( > + (UINT8 *) & (stMacDesc.MacLen), > + sizeof (stMacDesc.MacLen) + MAC_ADDR_LEN > + ); > + > + Status = I2CInit (0, EEPROM_I2C_PORT, Normal); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n", > + __FUNCTION__, __LINE__, Status)); > + return Status; > + } > + > + I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS)); > + > + stI2cDev.DeviceType = DEVICE_TYPE_E2PROM; > + stI2cDev.Port = EEPROM_I2C_PORT; > + stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM; > + stI2cDev.Socket = 0; > + RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE; > + LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset; > + //The length of NIC_MAC_ADDRESS is 10 bytes long, > + //It surly less than EEPROM page size, so we could > + //code as bellow, check the address whether across the page boundary, bellow -> below > + //and split the data when across page boundary. > + if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) { > + Status = I2CWrite ( > + &stI2cDev, > + I2cOffset, > + sizeof (NIC_MAC_ADDRESS), > + (UINT8 *) &stMacDesc > + ); > + } else { > + Status = I2CWrite (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc); > + if (!(EFI_ERROR (Status))) { Parantheses around EFI_ERROR are not needed. > + Status |= I2CWrite ( > + &stI2cDev, > + I2cOffset + LessSizeOfPage, > + sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage, > + (UINT8 *) &stMacDesc + LessSizeOfPage > + ); > + } > + } > + if (EFI_ERROR (Status)) > + { Move { to previous line. > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cWrite failed! p1=0x%x.\n", > + __FUNCTION__, __LINE__, Status)); > + return Status; > + } > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +OemGetMac ( > + IN OUT EFI_MAC_ADDRESS *Mac, > + IN UINTN Port > + ) > +{ > + EFI_STATUS Status; > + > + if (NULL == Mac) { No jeopardy tests. Turn the comparison around to the logical order. > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", > + __FUNCTION__, __LINE__)); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = OemGetMacE2prom (Port, Mac->Addr); > + if ((EFI_ERROR (Status))) { Parantheses around EFI_ERROR are not needed. > + DEBUG ((DEBUG_ERROR, > + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", > + __FUNCTION__, __LINE__, Status)); > + > + Mac->Addr[0] = 0x00; > + Mac->Addr[1] = 0x18; > + Mac->Addr[2] = 0x82; > + Mac->Addr[3] = 0x2F; > + Mac->Addr[4] = 0x02; > + Mac->Addr[5] = Port; I'm not super happy about this. This would wreak havoc on any real network. Arguably, a server platform should just fail hard at this point. I would certainly appreciate a Pcd making that an option. Otherwise, some sort of proper scheme would need to be implemented: using the 'locally administered range' of MAC addresses, and ensuring addresses are only allocated after checking for possible duplicates on the network. > + return EFI_SUCCESS; > + } > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +OemSetMac ( > + IN EFI_MAC_ADDRESS *Mac, > + IN UINTN Port > + ) > +{ > + EFI_STATUS Status; > + > + if (NULL == Mac) { No jeopardy tests. > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", > + __FUNCTION__, __LINE__)); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = OemSetMacE2prom (Port, Mac->Addr); > + if ((EFI_ERROR (Status))) { Unneeded parantheses. > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Set mac failed!\n", __FUNCTION__, __LINE__)); > + return Status; > + } > + > + return EFI_SUCCESS; > +} > + > +UINT32 > +OemEthFindFirstSP ( > + VOID > + ) > +{ > + UINT32 i; I. > + > + for (i = 0; i < ETH_MAX_PORT; i++) { > + if (gEthPdtDesc[i].Valid == TRUE) { > + return i; > + } > + } > + > + return ETH_INVALID; > +} > + > +ETH_PRODUCT_DESC * > +OemEthInit ( > + UINT32 port > + ) > +{ > + return (ETH_PRODUCT_DESC *)(&(gEthPdtDesc[port])); > +} > + > + > +BOOLEAN > +OemIsInitEth ( > + UINT32 Port > + ) > +{ > + return TRUE; > +} > diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf > new file mode 100644 > index 0000000000..ac849cb992 > --- /dev/null > +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf > @@ -0,0 +1,35 @@ > +#/** @file > +# > +# Copyright (c) 2018, Hisilicon Limited. All rights reserved. > +# Copyright (c) 2017, Linaro Limited. All rights reserved. > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD License > +# which accompanies this distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x00010005 0x0001001a > + BASE_NAME = OemNicLib > + FILE_GUID = 520F872C-FFCF-4EF3-AC01-85BDB0816DCE > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = OemNicLib > + > +[Sources.common] > + OemNicLib.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + ArmPkg/ArmPkg.dec > + Silicon/Hisilicon/HisiPkg.dec Please sort alphabetically. > + > +[LibraryClasses] > + I2CLib > + CpldIoLib Please sort alphabetically. / Leif > -- > 2.17.0 > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
在 8/3/2018 10:36 PM, Leif Lindholm 写道: > On Tue, Jul 24, 2018 at 03:09:06PM +0800, Ming Huang wrote: >> OemNicLib provide nic related api like GetMac,SetMac. >> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Ming Huang <ming.huang@linaro.org> >> Signed-off-by: Heyi Guo <heyi.guo@linaro.org> >> --- >> Platform/Hisilicon/D06/D06.dsc | 1 + >> Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c | 571 ++++++++++++++++++++ >> Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf | 35 ++ >> 3 files changed, 607 insertions(+) >> >> diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc >> index 43af043cfd..744a4a0d6d 100644 >> --- a/Platform/Hisilicon/D06/D06.dsc >> +++ b/Platform/Hisilicon/D06/D06.dsc >> @@ -91,6 +91,7 @@ >> >> LpcLib|Silicon/Hisilicon/Hi1620/Library/LpcLibHi1620/LpcLib.inf >> SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf >> + OemNicLib|Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf >> !if $(SECURE_BOOT_ENABLE) == TRUE >> FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf >> !endif >> diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c >> new file mode 100644 >> index 0000000000..55ed1625ce >> --- /dev/null >> +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c >> @@ -0,0 +1,571 @@ >> +/** @file >> +* >> +* Copyright (c) 2018, Hisilicon Limited. All rights reserved. >> +* Copyright (c) 2017, Linaro Limited. All rights reserved. >> +* >> +* This program and the accompanying materials >> +* are licensed and made available under the terms and conditions of the BSD License >> +* which accompanies this distribution. The full text of the license may be found at >> +* http://opensource.org/licenses/bsd-license.php >> +* >> +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> +* >> +**/ >> + >> +#include <Uefi.h> >> +#include <Library/CpldIoLib.h> >> +#include <Library/DebugLib.h> >> +#include <Library/I2CLib.h> >> +#include <Library/IoLib.h> >> +#include <Library/OemNicLib.h> >> + >> +#define CPU2_SFP2_100G_CARD_OFFSET 0x25 >> +#define CPU1_SFP1_LOCATE_OFFSET 0x16 >> +#define CPU1_SFP0_LOCATE_OFFSET 0x12 >> +#define CPU2_SFP1_LOCATE_OFFSET 0x21 >> +#define CPU2_SFP0_LOCATE_OFFSET 0x19 >> +#define CPU2_SFP2_10G_GE_CARD_OFFSET 0x25 >> + >> +#define SFP_10G_SPEED 10 >> +#define SFP_25G_SPEED 25 >> +#define SFP_100G_SPEED 100 >> +#define SFP_GE_SPEED 1 >> + >> +#define SFP_GE_SPEED_VAL_VENDOR_FINISAR 0x0C >> +#define SFP_GE_SPEED_VAL 0x0D >> +#define SFP_10G_SPEED_VAL 0x67 >> +#define SFP_25G_SPEED_VAL 0xFF >> + >> +#define CPU1_9545_I2C_ADDR 0x70 >> +#define CPU2_9545_I2C_ADDR 0x71 >> + >> +#define FIBER_PRESENT 0 >> +#define CARD_PRESENT 1 >> +#define I2C_PORT_SFP 4 >> +#define CPU2_I2C_PORT_SFP 5 >> + >> +#define SOCKET_0 0 >> +#define SOCKET_1 1 >> +#define EEPROM_I2C_PORT 4 >> +#define EEPROM_PAGE_SIZE 0x40 >> +#define MAC_ADDR_LEN 6 >> +#define I2C_OFFSET_EEPROM_ETH0 (0xc00) >> +#define I2C_SLAVEADDR_EEPROM (0x52) >> + >> +#pragma pack(1) >> +typedef struct { >> + UINT16 Crc16; >> + UINT16 MacLen; >> + UINT8 Mac[MAC_ADDR_LEN]; >> +} NIC_MAC_ADDRESS; >> +#pragma pack() >> + >> +ETH_PRODUCT_DESC gEthPdtDesc[ETH_MAX_PORT] = >> +{ >> + {TRUE, ETH_SPEED_10KM, ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID}, >> + {TRUE, ETH_SPEED_10KM, ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID}, >> + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, >> + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, >> + {TRUE, ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 0}, >> + {TRUE, ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 1}, >> + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, >> + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID} >> +}; >> + >> +volatile unsigned char g_2pserveraddr[4][6] = { > > VOLATILE UINT8. > No '_' in variable name. > Also, can we please have #defines for that 4 and 6? OK, modify it in v2. > >> + {0x00, 0x18, 0x16, 0x29, 0x11, 0x00}, >> + {0x00, 0x18, 0x16, 0x29, 0x11, 0x01}, >> + {0x00, 0x18, 0x16, 0x29, 0x11, 0x02}, >> + {0x00, 0x18, 0x16, 0x29, 0x11, 0x03} >> +}; >> + >> +UINT16 crc_tab[256] = { > > CrcTable. Modify it in v2. > Hmm. > This might be useful to add to a core library/driver/protocol. We > don't appear to have it yet. This is another note to the universe. Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ? I think it's not enouth time to do this before Linaro 18.08 maybe. > >> + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, >> + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, >> + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, >> + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, >> + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, >> + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, >> + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, >> + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, >> + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, >> + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, >> + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, >> + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, >> + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, >> + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, >> + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, >> + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, >> + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, >> + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, >> + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, >> + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, >> + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, >> + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, >> + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, >> + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, >> + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, >> + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, >> + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, >> + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, >> + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, >> + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, >> + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, >> + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, >> +}; >> + >> +EFI_STATUS >> +GetSfpSpeed ( >> + UINT16 Socket, >> + UINT16 SfpNum, >> + UINT8* FiberSpeed >> + ) >> +{ >> + EFI_STATUS Status; >> + I2C_DEVICE SpdDev; >> + UINT8 SpdReg; >> + UINT8 SfpSpeed; >> + UINT32 RegAddr; >> + UINT16 I2cAddr; >> + UINT32 SfpPort; >> + >> + SfpSpeed = 0x0; >> + if(Socket == 1) { > > Space before '('. > Please add a descriptive #define for that 1. > >> + I2cAddr = CPU2_9545_I2C_ADDR; >> + SfpPort = CPU2_I2C_PORT_SFP; >> + } else { >> + I2cAddr = CPU1_9545_I2C_ADDR; >> + SfpPort = I2C_PORT_SFP; >> + } >> + >> + Status = I2CInit (Socket, SfpPort, Normal); >> + if (EFI_ERROR (Status)) >> + { >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Socket%d Call I2CInit failed! p1=0x%x.\n", >> + __FUNCTION__, __LINE__, Socket, Status)); >> + return Status; >> + } >> + >> + SpdDev.Socket = Socket; >> + SpdDev.DeviceType = DEVICE_TYPE_SPD; >> + SpdDev.Port = SfpPort; >> + SpdDev.SlaveDeviceAddress = I2cAddr; >> + RegAddr = 0x0; >> + SpdReg = 1 << (SfpNum - 1); > > Please add descriptive #define. > >> + >> + Status = I2CWrite (&SpdDev, RegAddr, 1, &SpdReg); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "I2CWrite Error =%r.\n", Status)); >> + return Status; >> + } >> + >> + SpdDev.Socket = Socket; >> + SpdDev.DeviceType = DEVICE_TYPE_SPD; >> + SpdDev.Port = SfpPort; >> + SpdDev.SlaveDeviceAddress = 0x50; > > Please add descriptive #define. > >> + >> + RegAddr = 12; > > Please add descriptive #define. > >> + Status = I2CRead (&SpdDev, RegAddr, 1, &SfpSpeed); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "I2CRead Error =%r.\n", Status)); >> + return Status; >> + } >> + >> + DEBUG ((DEBUG_INFO, "BR, Nominal, Nominal signalling rate, SfpSpeed: 0x%x\n", >> + SfpSpeed)); >> + >> + if (SfpSpeed == SFP_10G_SPEED_VAL) { >> + *FiberSpeed = SFP_10G_SPEED; >> + } else if (SfpSpeed == SFP_25G_SPEED_VAL) { >> + *FiberSpeed = SFP_25G_SPEED; >> + } else if ((SfpSpeed == SFP_GE_SPEED_VAL) || (SfpSpeed == SFP_GE_SPEED_VAL_VENDOR_FINISAR)) { > > Long line, please break. > >> + *FiberSpeed = SFP_GE_SPEED; >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +//Fiber1Type/Fiber2Type/Fiber3Type return: SFP_10G_SPEED, SFP_100G_SPEED, SFP_GE_SPEED >> +UINT32 >> +GetCpu2FiberType ( >> + UINT8* Fiber1Type, >> + UINT8* Fiber2Type, >> + UINT8* Fiber100Ge >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT16 SfpNum1; >> + UINT8 SfpSpeed1; >> + UINT16 SfpNum2; >> + UINT8 SfpSpeed2; >> + >> + SfpNum1 = 0x1; >> + SfpSpeed1 = SFP_10G_SPEED; >> + SfpNum2 = 0x2; >> + SfpSpeed2 = SFP_10G_SPEED; >> + *Fiber100Ge = 0x0; >> + *Fiber1Type = SFP_10G_SPEED; >> + *Fiber2Type = SFP_10G_SPEED; >> + >> + if ((ReadCpldReg (CPU2_SFP2_100G_CARD_OFFSET) & BIT7) == (CARD_PRESENT << 7)) { > > Please add descriptively named helper macros or #defines (& BIT7, << 7). > >> + // 100 Ge card >> + *Fiber1Type = SFP_10G_SPEED; >> + *Fiber2Type = SFP_10G_SPEED; >> + *Fiber100Ge = SFP_100G_SPEED; >> + DEBUG ((DEBUG_ERROR,"Detect Fiber SFP_100G is Present, Set 100Ge\n")); >> + } else if ((ReadCpldReg (CPU2_SFP2_10G_GE_CARD_OFFSET) & BIT0) == CARD_PRESENT) { > > Please add descriptively named helper macro or #define (& BIT0). > >> + *Fiber100Ge = 0x0; >> + *Fiber1Type = SFP_10G_SPEED; >> + *Fiber2Type = SFP_10G_SPEED; >> + if (ReadCpldReg (CPU2_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) { >> + // Fiber detected in CPU2 slot0, read speed via i2c >> + Status = GetSfpSpeed (SOCKET_1, SfpNum1, &SfpSpeed1); >> + if (EFI_ERROR (Status)) { >> + DEBUG((DEBUG_ERROR, >> + "Get Socket1 Sfp%d Speed Error: %r.\n", >> + SfpNum1, >> + Status)); >> + return Status; >> + } >> + if (SfpSpeed1 == SFP_25G_SPEED) { >> + // P1 don't support 25G, so set speed to 10G >> + *Fiber1Type = SFP_10G_SPEED; >> + } else { >> + *Fiber1Type = SfpSpeed1; >> + } >> + } else { >> + // No fiber, set speed to 10G >> + *Fiber1Type = SFP_10G_SPEED; >> + } >> + >> + if (ReadCpldReg (CPU2_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) { >> + // Fiber detected in CPU2 slot1, read speed via i2c >> + Status = GetSfpSpeed (SOCKET_1, SfpNum2, &SfpSpeed2); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status)); >> + return Status; >> + } >> + if (SfpSpeed2 == SFP_25G_SPEED) { >> + *Fiber2Type = SFP_10G_SPEED; >> + } else { >> + *Fiber2Type = SfpSpeed2; >> + } >> + } else { >> + // No fiber, set speed to 10G >> + *Fiber2Type = SFP_10G_SPEED; >> + } >> + } else { >> + // 100Ge/10Ge/Ge Fiber is not found. >> + *Fiber1Type = SFP_10G_SPEED; >> + *Fiber2Type = SFP_10G_SPEED; >> + *Fiber100Ge = 0x0; >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +//Fiber1Type/Fiber2Type return: SFP_10G_SPEED, SFP_25G_SPEED, SFP_GE_SPEED >> +UINT32 >> +GetCpu1FiberType ( >> + UINT8* Fiber1Type, >> + UINT8* Fiber2Type >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT16 SfpNum1; >> + UINT8 SfpSpeed1; >> + UINT16 SfpNum2; >> + UINT8 SfpSpeed2; >> + >> + SfpNum1 = 0x1; >> + SfpSpeed1 = SFP_10G_SPEED; >> + SfpNum2 = 0x2; >> + SfpSpeed2 = SFP_10G_SPEED; >> + *Fiber1Type = SFP_10G_SPEED; >> + *Fiber2Type = SFP_10G_SPEED; >> + // Fiber detected in CPU1 slot0, read speed via i2c >> + if (ReadCpldReg (CPU1_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) { >> + Status = GetSfpSpeed (SOCKET_0, SfpNum1, &SfpSpeed1); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Get Socket0 Sfp%d Speed Error: %r.\n", >> + SfpNum1, Status)); >> + return Status; >> + } >> + *Fiber1Type = SfpSpeed1; >> + } else { >> + *Fiber1Type = SFP_10G_SPEED; >> + } >> + >> + // Fiber detected in CPU1 slot1, read speed via i2c >> + if (ReadCpldReg (CPU1_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) { >> + Status = GetSfpSpeed (SOCKET_0, SfpNum2, &SfpSpeed2); >> + if (EFI_ERROR (Status)) { >> + *Fiber2Type = SFP_10G_SPEED; >> + DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status)); >> + return Status; >> + } >> + *Fiber2Type = SfpSpeed2; >> + } else { >> + *Fiber2Type = SFP_10G_SPEED; >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +UINT16 make_crc_checksum ( > > MakeCrcChecksum > >> + UINT8 *buf, > > Buffer. > >> + UINT32 len > > Length. > >> + ) >> +{ >> + UINT16 StartCRC = 0; >> + >> + if (len > (512 * 1024)) { > > SIZE_512KB? Yes, SIZE_512KB is better. > >> + return 0; >> + } >> + >> + if (buf == NULL) { >> + return 0; >> + } >> + >> + while (len) { >> + StartCRC = crc_tab [((UINT8) ((StartCRC >> 8) & 0xff)) ^ *(buf++)] ^ >> + ((UINT16) (StartCRC << 8)); >> + len--; >> + } >> + >> + return StartCRC; >> +} >> + >> + >> +EFI_STATUS >> +OemGetMacE2prom( >> + IN UINT32 Port, >> + OUT UINT8 *pucAddr > > Hungarian notation. Drop 'puc'. > >> + ) >> +{ >> + I2C_DEVICE stI2cDev = {0}; > > Hungarian notation. Drop 'st'. > >> + EFI_STATUS Status; >> + UINT16 I2cOffset; >> + UINT16 crc16; > > Crc16. > >> + NIC_MAC_ADDRESS stMacDesc = {0}; > > Hungarian notation. Drop 'st'. > >> + UINT16 RemainderMacOffset; >> + UINT16 LessSizeOfPage; >> + UINT32 i = 0; > > I. > >> + >> + Status = I2CInit (0, EEPROM_I2C_PORT, Normal); >> + if (EFI_ERROR (Status)) >> + { >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n", >> + __FUNCTION__, __LINE__, Status)); >> + return Status; >> + } >> + >> + I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS)); >> + >> + stI2cDev.DeviceType = DEVICE_TYPE_E2PROM; >> + stI2cDev.Port = EEPROM_I2C_PORT; >> + stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM; >> + stI2cDev.Socket = 0; >> + RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE; >> + LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset; >> + //The length of NIC_MAC_ADDRESS is 10 bytes long, >> + //It surly less than EEPROM page size, so we could >> + //code as bellow, check the address whether across the page boundary, > > bellow -> below > >> + //and split the data when across page boundary. >> + if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) { >> + Status = I2CRead (&stI2cDev, I2cOffset, sizeof (NIC_MAC_ADDRESS), (UINT8 *) &stMacDesc); >> + } else { >> + Status = I2CRead (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc); >> + if (!(EFI_ERROR (Status))) { > > Parantheses around EFI_ERROR not needed. > >> + Status |= I2CRead ( >> + &stI2cDev, >> + I2cOffset + LessSizeOfPage, >> + sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage, >> + (UINT8 *) &stMacDesc + LessSizeOfPage >> + ); >> + } >> + } >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cRead failed! p1=0x%x.\n", >> + __FUNCTION__, __LINE__, Status)); >> + return Status; >> + } >> + >> + crc16 = make_crc_checksum ( >> + (UINT8 *) & (stMacDesc.MacLen), >> + sizeof (stMacDesc.MacLen) + sizeof (stMacDesc.Mac) >> + ); >> + if ((crc16 != stMacDesc.Crc16) || (0 == crc16)) { >> + return EFI_NOT_FOUND; >> + } >> + >> + for (i = 0; i < MAC_ADDR_LEN; i++) { >> + pucAddr[i] = stMacDesc.Mac[i]; >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> + >> +EFI_STATUS >> +OemSetMacE2prom ( >> + IN UINT32 Port, >> + IN UINT8 *pucAddr > > Hungarian notation. Drop 'puc'. > >> + ) >> +{ >> + I2C_DEVICE stI2cDev = {0}; > > Hungarian notation. Drop 'st'. > >> + EFI_STATUS Status; >> + UINT16 I2cOffset; >> + NIC_MAC_ADDRESS stMacDesc = {0}; > > Hungarian notation. Drop 'st'. > >> + UINT32 i; > > I. > >> + UINT16 RemainderMacOffset; >> + UINT16 LessSizeOfPage; >> + >> + i = 0; >> + stMacDesc.MacLen = MAC_ADDR_LEN; >> + >> + for (i = 0; i < MAC_ADDR_LEN; i++) { >> + stMacDesc.Mac[i] = pucAddr[i]; >> + } >> + >> + stMacDesc.Crc16 = make_crc_checksum ( >> + (UINT8 *) & (stMacDesc.MacLen), >> + sizeof (stMacDesc.MacLen) + MAC_ADDR_LEN >> + ); >> + >> + Status = I2CInit (0, EEPROM_I2C_PORT, Normal); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n", >> + __FUNCTION__, __LINE__, Status)); >> + return Status; >> + } >> + >> + I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS)); >> + >> + stI2cDev.DeviceType = DEVICE_TYPE_E2PROM; >> + stI2cDev.Port = EEPROM_I2C_PORT; >> + stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM; >> + stI2cDev.Socket = 0; >> + RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE; >> + LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset; >> + //The length of NIC_MAC_ADDRESS is 10 bytes long, >> + //It surly less than EEPROM page size, so we could >> + //code as bellow, check the address whether across the page boundary, > > bellow -> below > >> + //and split the data when across page boundary. >> + if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) { >> + Status = I2CWrite ( >> + &stI2cDev, >> + I2cOffset, >> + sizeof (NIC_MAC_ADDRESS), >> + (UINT8 *) &stMacDesc >> + ); >> + } else { >> + Status = I2CWrite (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc); >> + if (!(EFI_ERROR (Status))) { > > Parantheses around EFI_ERROR are not needed. > >> + Status |= I2CWrite ( >> + &stI2cDev, >> + I2cOffset + LessSizeOfPage, >> + sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage, >> + (UINT8 *) &stMacDesc + LessSizeOfPage >> + ); >> + } >> + } >> + if (EFI_ERROR (Status)) >> + { > > Move { to previous line. > >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cWrite failed! p1=0x%x.\n", >> + __FUNCTION__, __LINE__, Status)); >> + return Status; >> + } >> + return EFI_SUCCESS; >> +} >> + >> +EFI_STATUS >> +EFIAPI >> +OemGetMac ( >> + IN OUT EFI_MAC_ADDRESS *Mac, >> + IN UINTN Port >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if (NULL == Mac) { > > No jeopardy tests. Turn the comparison around to the logical order. > >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", >> + __FUNCTION__, __LINE__)); >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status = OemGetMacE2prom (Port, Mac->Addr); >> + if ((EFI_ERROR (Status))) { > > Parantheses around EFI_ERROR are not needed. > >> + DEBUG ((DEBUG_ERROR, >> + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", >> + __FUNCTION__, __LINE__, Status)); >> + >> + Mac->Addr[0] = 0x00; >> + Mac->Addr[1] = 0x18; >> + Mac->Addr[2] = 0x82; >> + Mac->Addr[3] = 0x2F; >> + Mac->Addr[4] = 0x02; >> + Mac->Addr[5] = Port; > > I'm not super happy about this. This would wreak havoc on any real > network. > Arguably, a server platform should just fail hard at this point. > I would certainly appreciate a Pcd making that an option. > > Otherwise, some sort of proper scheme would need to be implemented: > using the 'locally administered range' of MAC addresses, and ensuring > addresses are only allocated after checking for possible duplicates on > the network. Do you suggest we should return EFI_NOT_FOUND here? > >> + return EFI_SUCCESS; >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +EFI_STATUS >> +EFIAPI >> +OemSetMac ( >> + IN EFI_MAC_ADDRESS *Mac, >> + IN UINTN Port >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if (NULL == Mac) { > > No jeopardy tests. > >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", >> + __FUNCTION__, __LINE__)); >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status = OemSetMacE2prom (Port, Mac->Addr); >> + if ((EFI_ERROR (Status))) { > > Unneeded parantheses. > >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Set mac failed!\n", __FUNCTION__, __LINE__)); >> + return Status; >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +UINT32 >> +OemEthFindFirstSP ( >> + VOID >> + ) >> +{ >> + UINT32 i; > > I. > >> + >> + for (i = 0; i < ETH_MAX_PORT; i++) { >> + if (gEthPdtDesc[i].Valid == TRUE) { >> + return i; >> + } >> + } >> + >> + return ETH_INVALID; >> +} >> + >> +ETH_PRODUCT_DESC * >> +OemEthInit ( >> + UINT32 port >> + ) >> +{ >> + return (ETH_PRODUCT_DESC *)(&(gEthPdtDesc[port])); >> +} >> + >> + >> +BOOLEAN >> +OemIsInitEth ( >> + UINT32 Port >> + ) >> +{ >> + return TRUE; >> +} >> diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf >> new file mode 100644 >> index 0000000000..ac849cb992 >> --- /dev/null >> +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf >> @@ -0,0 +1,35 @@ >> +#/** @file >> +# >> +# Copyright (c) 2018, Hisilicon Limited. All rights reserved. >> +# Copyright (c) 2017, Linaro Limited. All rights reserved. >> +# >> +# This program and the accompanying materials >> +# are licensed and made available under the terms and conditions of the BSD License >> +# which accompanies this distribution. The full text of the license may be found at >> +# http://opensource.org/licenses/bsd-license.php >> +# >> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> +# >> +#**/ >> + >> +[Defines] >> + INF_VERSION = 0x00010005 > > 0x0001001a > >> + BASE_NAME = OemNicLib >> + FILE_GUID = 520F872C-FFCF-4EF3-AC01-85BDB0816DCE >> + MODULE_TYPE = BASE >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = OemNicLib >> + >> +[Sources.common] >> + OemNicLib.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + MdeModulePkg/MdeModulePkg.dec >> + ArmPkg/ArmPkg.dec >> + Silicon/Hisilicon/HisiPkg.dec > > Please sort alphabetically. > >> + >> +[LibraryClasses] >> + I2CLib >> + CpldIoLib > > Please sort alphabetically. OK, and all other comments will apply in v2. Thanks. > > / > Leif > >> -- >> 2.17.0 >>
On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote: > >> +UINT16 crc_tab[256] = { > > > > CrcTable. > > Modify it in v2. > > > Hmm. > > This might be useful to add to a core library/driver/protocol. We > > don't appear to have it yet. This is another note to the universe. > > Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ? > I think it's not enouth time to do this before Linaro 18.08 maybe. Not needed for 18.08, but I would like to see the improvement made afterwards. > >> +EFI_STATUS > >> +EFIAPI > >> +OemGetMac ( > >> + IN OUT EFI_MAC_ADDRESS *Mac, > >> + IN UINTN Port > >> + ) > >> +{ > >> + EFI_STATUS Status; > >> + > >> + if (NULL == Mac) { > > > > No jeopardy tests. Turn the comparison around to the logical order. > > > >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", > >> + __FUNCTION__, __LINE__)); > >> + return EFI_INVALID_PARAMETER; > >> + } > >> + > >> + Status = OemGetMacE2prom (Port, Mac->Addr); > >> + if ((EFI_ERROR (Status))) { > > > > Parantheses around EFI_ERROR are not needed. > > > >> + DEBUG ((DEBUG_ERROR, > >> + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", > >> + __FUNCTION__, __LINE__, Status)); > >> + > >> + Mac->Addr[0] = 0x00; > >> + Mac->Addr[1] = 0x18; > >> + Mac->Addr[2] = 0x82; > >> + Mac->Addr[3] = 0x2F; > >> + Mac->Addr[4] = 0x02; > >> + Mac->Addr[5] = Port; > > > > I'm not super happy about this. This would wreak havoc on any real > > network. > > Arguably, a server platform should just fail hard at this point. > > I would certainly appreciate a Pcd making that an option. > > > > Otherwise, some sort of proper scheme would need to be implemented: > > using the 'locally administered range' of MAC addresses, and ensuring > > addresses are only allocated after checking for possible duplicates on > > the network. > > Do you suggest we should return EFI_NOT_FOUND here? Yes please. It would be good if we could have some (common) code to handle the fluke situation where you end up without your own MAC address. (So that the node can boot up and report that it is broken.) But it needs to be done in a reliable way, and that's too big a task for 18.08. / Leif _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
在 8/9/2018 6:19 PM, Leif Lindholm 写道: > On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote: >>>> +UINT16 crc_tab[256] = { >>> >>> CrcTable. >> >> Modify it in v2. >> >>> Hmm. >>> This might be useful to add to a core library/driver/protocol. We >>> don't appear to have it yet. This is another note to the universe. >> >> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ? >> I think it's not enouth time to do this before Linaro 18.08 maybe. > > Not needed for 18.08, but I would like to see the improvement made > afterwards. OK, I will do this after 18.08. > >>>> +EFI_STATUS >>>> +EFIAPI >>>> +OemGetMac ( >>>> + IN OUT EFI_MAC_ADDRESS *Mac, >>>> + IN UINTN Port >>>> + ) >>>> +{ >>>> + EFI_STATUS Status; >>>> + >>>> + if (NULL == Mac) { >>> >>> No jeopardy tests. Turn the comparison around to the logical order. >>> >>>> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", >>>> + __FUNCTION__, __LINE__)); >>>> + return EFI_INVALID_PARAMETER; >>>> + } >>>> + >>>> + Status = OemGetMacE2prom (Port, Mac->Addr); >>>> + if ((EFI_ERROR (Status))) { >>> >>> Parantheses around EFI_ERROR are not needed. >>> >>>> + DEBUG ((DEBUG_ERROR, >>>> + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", >>>> + __FUNCTION__, __LINE__, Status)); >>>> + >>>> + Mac->Addr[0] = 0x00; >>>> + Mac->Addr[1] = 0x18; >>>> + Mac->Addr[2] = 0x82; >>>> + Mac->Addr[3] = 0x2F; >>>> + Mac->Addr[4] = 0x02; >>>> + Mac->Addr[5] = Port; >>> >>> I'm not super happy about this. This would wreak havoc on any real >>> network. >>> Arguably, a server platform should just fail hard at this point. >>> I would certainly appreciate a Pcd making that an option. >>> >>> Otherwise, some sort of proper scheme would need to be implemented: >>> using the 'locally administered range' of MAC addresses, and ensuring >>> addresses are only allocated after checking for possible duplicates on >>> the network. >> >> Do you suggest we should return EFI_NOT_FOUND here? > > Yes please. > It would be good if we could have some (common) code to handle the > fluke situation where you end up without your own MAC address. > (So that the node can boot up and report that it is broken.) > But it needs to be done in a reliable way, and that's too big a task > for 18.08. I will think about this after 18.08. Thanks. > > / > Leif >
在 8/9/2018 6:19 PM, Leif Lindholm 写道: > On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote: >>>> +UINT16 crc_tab[256] = { >>> >>> CrcTable. >> >> Modify it in v2. >> >>> Hmm. >>> This might be useful to add to a core library/driver/protocol. We >>> don't appear to have it yet. This is another note to the universe. >> >> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ? >> I think it's not enouth time to do this before Linaro 18.08 maybe. > > Not needed for 18.08, but I would like to see the improvement made > afterwards. > >>>> +EFI_STATUS >>>> +EFIAPI >>>> +OemGetMac ( >>>> + IN OUT EFI_MAC_ADDRESS *Mac, >>>> + IN UINTN Port >>>> + ) >>>> +{ >>>> + EFI_STATUS Status; >>>> + >>>> + if (NULL == Mac) { >>> >>> No jeopardy tests. Turn the comparison around to the logical order. >>> >>>> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", >>>> + __FUNCTION__, __LINE__)); >>>> + return EFI_INVALID_PARAMETER; >>>> + } >>>> + >>>> + Status = OemGetMacE2prom (Port, Mac->Addr); >>>> + if ((EFI_ERROR (Status))) { >>> >>> Parantheses around EFI_ERROR are not needed. >>> >>>> + DEBUG ((DEBUG_ERROR, >>>> + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", >>>> + __FUNCTION__, __LINE__, Status)); >>>> + >>>> + Mac->Addr[0] = 0x00; >>>> + Mac->Addr[1] = 0x18; >>>> + Mac->Addr[2] = 0x82; >>>> + Mac->Addr[3] = 0x2F; >>>> + Mac->Addr[4] = 0x02; >>>> + Mac->Addr[5] = Port; >>> >>> I'm not super happy about this. This would wreak havoc on any real >>> network. >>> Arguably, a server platform should just fail hard at this point. >>> I would certainly appreciate a Pcd making that an option. >>> >>> Otherwise, some sort of proper scheme would need to be implemented: >>> using the 'locally administered range' of MAC addresses, and ensuring >>> addresses are only allocated after checking for possible duplicates on >>> the network. >> >> Do you suggest we should return EFI_NOT_FOUND here? > > Yes please. > It would be good if we could have some (common) code to handle the > fluke situation where you end up without your own MAC address. > (So that the node can boot up and report that it is broken.) > But it needs to be done in a reliable way, and that's too big a task > for 18.08. I found some modules which invoke OemGetMac() don't judge the Status of OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND. How about change it while we handle the fluke situation after 18.08 ? > > / > Leif >
On Tue, Aug 14, 2018 at 10:38:14AM +0800, Ming wrote: > > > 在 8/9/2018 6:19 PM, Leif Lindholm 写道: > > On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote: > >>>> +UINT16 crc_tab[256] = { > >>> > >>> CrcTable. > >> > >> Modify it in v2. > >> > >>> Hmm. > >>> This might be useful to add to a core library/driver/protocol. We > >>> don't appear to have it yet. This is another note to the universe. > >> > >> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ? > >> I think it's not enouth time to do this before Linaro 18.08 maybe. > > > > Not needed for 18.08, but I would like to see the improvement made > > afterwards. > > > >>>> +EFI_STATUS > >>>> +EFIAPI > >>>> +OemGetMac ( > >>>> + IN OUT EFI_MAC_ADDRESS *Mac, > >>>> + IN UINTN Port > >>>> + ) > >>>> +{ > >>>> + EFI_STATUS Status; > >>>> + > >>>> + if (NULL == Mac) { > >>> > >>> No jeopardy tests. Turn the comparison around to the logical order. > >>> > >>>> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", > >>>> + __FUNCTION__, __LINE__)); > >>>> + return EFI_INVALID_PARAMETER; > >>>> + } > >>>> + > >>>> + Status = OemGetMacE2prom (Port, Mac->Addr); > >>>> + if ((EFI_ERROR (Status))) { > >>> > >>> Parantheses around EFI_ERROR are not needed. > >>> > >>>> + DEBUG ((DEBUG_ERROR, > >>>> + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", > >>>> + __FUNCTION__, __LINE__, Status)); > >>>> + > >>>> + Mac->Addr[0] = 0x00; > >>>> + Mac->Addr[1] = 0x18; > >>>> + Mac->Addr[2] = 0x82; > >>>> + Mac->Addr[3] = 0x2F; > >>>> + Mac->Addr[4] = 0x02; > >>>> + Mac->Addr[5] = Port; > >>> > >>> I'm not super happy about this. This would wreak havoc on any real > >>> network. > >>> Arguably, a server platform should just fail hard at this point. > >>> I would certainly appreciate a Pcd making that an option. > >>> > >>> Otherwise, some sort of proper scheme would need to be implemented: > >>> using the 'locally administered range' of MAC addresses, and ensuring > >>> addresses are only allocated after checking for possible duplicates on > >>> the network. > >> > >> Do you suggest we should return EFI_NOT_FOUND here? > > > > Yes please. > > It would be good if we could have some (common) code to handle the > > fluke situation where you end up without your own MAC address. > > (So that the node can boot up and report that it is broken.) > > But it needs to be done in a reliable way, and that's too big a task > > for 18.08. > > I found some modules which invoke OemGetMac() don't judge the Status of > OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND. > How about change it while we handle the fluke situation after 18.08 ? We cannot release 18.08 with known bugs. And not checking return value is a bug. I presume you mean that these calling functions are inside HwPkg? The alternative would be to ensure the function does not return. But I would not recommend that. / Leif
在 8/14/2018 11:48 PM, Leif Lindholm 写道: > On Tue, Aug 14, 2018 at 10:38:14AM +0800, Ming wrote: >> >> >> 在 8/9/2018 6:19 PM, Leif Lindholm 写道: >>> On Thu, Aug 09, 2018 at 02:16:49PM +0800, Ming wrote: >>>>>> +UINT16 crc_tab[256] = { >>>>> >>>>> CrcTable. >>>> >>>> Modify it in v2. >>>> >>>>> Hmm. >>>>> This might be useful to add to a core library/driver/protocol. We >>>>> don't appear to have it yet. This is another note to the universe. >>>> >>>> Do you suggest to move the CRC16 function to MdePkg/Library/BaseLib/CheckSum.c ? >>>> I think it's not enouth time to do this before Linaro 18.08 maybe. >>> >>> Not needed for 18.08, but I would like to see the improvement made >>> afterwards. >>> >>>>>> +EFI_STATUS >>>>>> +EFIAPI >>>>>> +OemGetMac ( >>>>>> + IN OUT EFI_MAC_ADDRESS *Mac, >>>>>> + IN UINTN Port >>>>>> + ) >>>>>> +{ >>>>>> + EFI_STATUS Status; >>>>>> + >>>>>> + if (NULL == Mac) { >>>>> >>>>> No jeopardy tests. Turn the comparison around to the logical order. >>>>> >>>>>> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", >>>>>> + __FUNCTION__, __LINE__)); >>>>>> + return EFI_INVALID_PARAMETER; >>>>>> + } >>>>>> + >>>>>> + Status = OemGetMacE2prom (Port, Mac->Addr); >>>>>> + if ((EFI_ERROR (Status))) { >>>>> >>>>> Parantheses around EFI_ERROR are not needed. >>>>> >>>>>> + DEBUG ((DEBUG_ERROR, >>>>>> + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", >>>>>> + __FUNCTION__, __LINE__, Status)); >>>>>> + >>>>>> + Mac->Addr[0] = 0x00; >>>>>> + Mac->Addr[1] = 0x18; >>>>>> + Mac->Addr[2] = 0x82; >>>>>> + Mac->Addr[3] = 0x2F; >>>>>> + Mac->Addr[4] = 0x02; >>>>>> + Mac->Addr[5] = Port; >>>>> >>>>> I'm not super happy about this. This would wreak havoc on any real >>>>> network. >>>>> Arguably, a server platform should just fail hard at this point. >>>>> I would certainly appreciate a Pcd making that an option. >>>>> >>>>> Otherwise, some sort of proper scheme would need to be implemented: >>>>> using the 'locally administered range' of MAC addresses, and ensuring >>>>> addresses are only allocated after checking for possible duplicates on >>>>> the network. >>>> >>>> Do you suggest we should return EFI_NOT_FOUND here? >>> >>> Yes please. >>> It would be good if we could have some (common) code to handle the >>> fluke situation where you end up without your own MAC address. >>> (So that the node can boot up and report that it is broken.) >>> But it needs to be done in a reliable way, and that's too big a task >>> for 18.08. >> >> I found some modules which invoke OemGetMac() don't judge the Status of >> OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND. >> How about change it while we handle the fluke situation after 18.08 ? > > We cannot release 18.08 with known bugs. > And not checking return value is a bug. > > I presume you mean that these calling functions are inside HwPkg? Yes. All D06 board will burn a Mac to eeprom before delivery and there is a command (SetMac) to write a Mac. For handling the fluke situation, we think there are several ways: 1 Initialize Mac to 0xFF; Kernel seems will create a random Mac while the Mac is 0xFF. 2 Make a Mac from ArmReadCntPct() and gTR->GetTime(); 3 Make a locally administered Mac from ArmReadCntPct() and gTR->GetTime(); The 2nd is the way our product project use to handle the fluke situation. What is your suggestion? > > The alternative would be to ensure the function does not return. > But I would not recommend that. > > / > Leif >
On Wed, Aug 15, 2018 at 07:08:33PM +0800, Ming wrote: > >>> Yes please. > >>> It would be good if we could have some (common) code to handle the > >>> fluke situation where you end up without your own MAC address. > >>> (So that the node can boot up and report that it is broken.) > >>> But it needs to be done in a reliable way, and that's too big a task > >>> for 18.08. > >> > >> I found some modules which invoke OemGetMac() don't judge the Status of > >> OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND. > >> How about change it while we handle the fluke situation after 18.08 ? > > > > We cannot release 18.08 with known bugs. > > And not checking return value is a bug. > > > > I presume you mean that these calling functions are inside HwPkg? > > Yes. > > All D06 board will burn a Mac to eeprom before delivery and there is a > command (SetMac) to write a Mac. > > For handling the fluke situation, we think there are several ways: > 1 Initialize Mac to 0xFF; > Kernel seems will create a random Mac while the Mac is 0xFF. I have no objections to that, but it would prevent from netbooting. But being unable to read the eeprom is a serious hw failure. So my gut feeling is that this should prevent the system from booting completely. If you want to make it possible to boot at all, and don't mind giving up netbooting for systems with known hardware failure, I think that's acceptable. > 2 Make a Mac from ArmReadCntPct() and gTR->GetTime(); > 3 Make a locally administered Mac from ArmReadCntPct() and gTR->GetTime(); > > The 2nd is the way our product project use to handle the fluke situation. > What is your suggestion? 2 is not OK. 3 would be totally valid, but is basically just "do 2 properly". And doing 2 properly means doing ARP lookups to ensure we don't have any duplicate MACs on the current network segment. Which is more effort (and probably functionality we want to get into edk2 core). My recommendation for 18.08 would be doing 1. Then we have time to discuss nicer fallback options afterwards. / Leif _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
在 8/15/2018 9:22 PM, Leif Lindholm 写道: > On Wed, Aug 15, 2018 at 07:08:33PM +0800, Ming wrote: >>>>> Yes please. >>>>> It would be good if we could have some (common) code to handle the >>>>> fluke situation where you end up without your own MAC address. >>>>> (So that the node can boot up and report that it is broken.) >>>>> But it needs to be done in a reliable way, and that's too big a task >>>>> for 18.08. >>>> >>>> I found some modules which invoke OemGetMac() don't judge the Status of >>>> OemGetMac, so it may cause some issue now if changing to EFI_NOT_FOUND. >>>> How about change it while we handle the fluke situation after 18.08 ? >>> >>> We cannot release 18.08 with known bugs. >>> And not checking return value is a bug. >>> >>> I presume you mean that these calling functions are inside HwPkg? >> >> Yes. >> >> All D06 board will burn a Mac to eeprom before delivery and there is a >> command (SetMac) to write a Mac. >> >> For handling the fluke situation, we think there are several ways: >> 1 Initialize Mac to 0xFF; >> Kernel seems will create a random Mac while the Mac is 0xFF. > > I have no objections to that, but it would prevent from netbooting. > > But being unable to read the eeprom is a serious hw failure. So my gut > feeling is that this should prevent the system from booting > completely. If you want to make it possible to boot at all, and don't > mind giving up netbooting for systems with known hardware failure, I > think that's acceptable. > >> 2 Make a Mac from ArmReadCntPct() and gTR->GetTime(); >> 3 Make a locally administered Mac from ArmReadCntPct() and gTR->GetTime(); >> >> The 2nd is the way our product project use to handle the fluke situation. >> What is your suggestion? > > 2 is not OK. > > 3 would be totally valid, but is basically just "do 2 properly". > > And doing 2 properly means doing ARP lookups to ensure we don't have > any duplicate MACs on the current network segment. Which is more > effort (and probably functionality we want to get into edk2 core). > > My recommendation for 18.08 would be doing 1. Then we have time to > discuss nicer fallback options afterwards. OK, doing 1 for 18.08. I will send v3 patch set ASAP. Thanks. > > / > Leif >
diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc index 43af043cfd..744a4a0d6d 100644 --- a/Platform/Hisilicon/D06/D06.dsc +++ b/Platform/Hisilicon/D06/D06.dsc @@ -91,6 +91,7 @@ LpcLib|Silicon/Hisilicon/Hi1620/Library/LpcLibHi1620/LpcLib.inf SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf + OemNicLib|Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf !if $(SECURE_BOOT_ENABLE) == TRUE FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf !endif diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c new file mode 100644 index 0000000000..55ed1625ce --- /dev/null +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.c @@ -0,0 +1,571 @@ +/** @file +* +* Copyright (c) 2018, Hisilicon Limited. All rights reserved. +* Copyright (c) 2017, Linaro Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <Uefi.h> +#include <Library/CpldIoLib.h> +#include <Library/DebugLib.h> +#include <Library/I2CLib.h> +#include <Library/IoLib.h> +#include <Library/OemNicLib.h> + +#define CPU2_SFP2_100G_CARD_OFFSET 0x25 +#define CPU1_SFP1_LOCATE_OFFSET 0x16 +#define CPU1_SFP0_LOCATE_OFFSET 0x12 +#define CPU2_SFP1_LOCATE_OFFSET 0x21 +#define CPU2_SFP0_LOCATE_OFFSET 0x19 +#define CPU2_SFP2_10G_GE_CARD_OFFSET 0x25 + +#define SFP_10G_SPEED 10 +#define SFP_25G_SPEED 25 +#define SFP_100G_SPEED 100 +#define SFP_GE_SPEED 1 + +#define SFP_GE_SPEED_VAL_VENDOR_FINISAR 0x0C +#define SFP_GE_SPEED_VAL 0x0D +#define SFP_10G_SPEED_VAL 0x67 +#define SFP_25G_SPEED_VAL 0xFF + +#define CPU1_9545_I2C_ADDR 0x70 +#define CPU2_9545_I2C_ADDR 0x71 + +#define FIBER_PRESENT 0 +#define CARD_PRESENT 1 +#define I2C_PORT_SFP 4 +#define CPU2_I2C_PORT_SFP 5 + +#define SOCKET_0 0 +#define SOCKET_1 1 +#define EEPROM_I2C_PORT 4 +#define EEPROM_PAGE_SIZE 0x40 +#define MAC_ADDR_LEN 6 +#define I2C_OFFSET_EEPROM_ETH0 (0xc00) +#define I2C_SLAVEADDR_EEPROM (0x52) + +#pragma pack(1) +typedef struct { + UINT16 Crc16; + UINT16 MacLen; + UINT8 Mac[MAC_ADDR_LEN]; +} NIC_MAC_ADDRESS; +#pragma pack() + +ETH_PRODUCT_DESC gEthPdtDesc[ETH_MAX_PORT] = +{ + {TRUE, ETH_SPEED_10KM, ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID}, + {TRUE, ETH_SPEED_10KM, ETH_FULL_DUPLEX, ETH_INVALID, ETH_INVALID}, + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, + {TRUE, ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 0}, + {TRUE, ETH_SPEED_1000M, ETH_FULL_DUPLEX, ETH_PHY_MVL88E1512_ID, 1}, + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID}, + {FALSE, ETH_INVALID, ETH_INVALID, ETH_INVALID, ETH_INVALID} +}; + +volatile unsigned char g_2pserveraddr[4][6] = { + {0x00, 0x18, 0x16, 0x29, 0x11, 0x00}, + {0x00, 0x18, 0x16, 0x29, 0x11, 0x01}, + {0x00, 0x18, 0x16, 0x29, 0x11, 0x02}, + {0x00, 0x18, 0x16, 0x29, 0x11, 0x03} +}; + +UINT16 crc_tab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, +}; + +EFI_STATUS +GetSfpSpeed ( + UINT16 Socket, + UINT16 SfpNum, + UINT8* FiberSpeed + ) +{ + EFI_STATUS Status; + I2C_DEVICE SpdDev; + UINT8 SpdReg; + UINT8 SfpSpeed; + UINT32 RegAddr; + UINT16 I2cAddr; + UINT32 SfpPort; + + SfpSpeed = 0x0; + if(Socket == 1) { + I2cAddr = CPU2_9545_I2C_ADDR; + SfpPort = CPU2_I2C_PORT_SFP; + } else { + I2cAddr = CPU1_9545_I2C_ADDR; + SfpPort = I2C_PORT_SFP; + } + + Status = I2CInit (Socket, SfpPort, Normal); + if (EFI_ERROR (Status)) + { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Socket%d Call I2CInit failed! p1=0x%x.\n", + __FUNCTION__, __LINE__, Socket, Status)); + return Status; + } + + SpdDev.Socket = Socket; + SpdDev.DeviceType = DEVICE_TYPE_SPD; + SpdDev.Port = SfpPort; + SpdDev.SlaveDeviceAddress = I2cAddr; + RegAddr = 0x0; + SpdReg = 1 << (SfpNum - 1); + + Status = I2CWrite (&SpdDev, RegAddr, 1, &SpdReg); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "I2CWrite Error =%r.\n", Status)); + return Status; + } + + SpdDev.Socket = Socket; + SpdDev.DeviceType = DEVICE_TYPE_SPD; + SpdDev.Port = SfpPort; + SpdDev.SlaveDeviceAddress = 0x50; + + RegAddr = 12; + Status = I2CRead (&SpdDev, RegAddr, 1, &SfpSpeed); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "I2CRead Error =%r.\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "BR, Nominal, Nominal signalling rate, SfpSpeed: 0x%x\n", + SfpSpeed)); + + if (SfpSpeed == SFP_10G_SPEED_VAL) { + *FiberSpeed = SFP_10G_SPEED; + } else if (SfpSpeed == SFP_25G_SPEED_VAL) { + *FiberSpeed = SFP_25G_SPEED; + } else if ((SfpSpeed == SFP_GE_SPEED_VAL) || (SfpSpeed == SFP_GE_SPEED_VAL_VENDOR_FINISAR)) { + *FiberSpeed = SFP_GE_SPEED; + } + + return EFI_SUCCESS; +} + +//Fiber1Type/Fiber2Type/Fiber3Type return: SFP_10G_SPEED, SFP_100G_SPEED, SFP_GE_SPEED +UINT32 +GetCpu2FiberType ( + UINT8* Fiber1Type, + UINT8* Fiber2Type, + UINT8* Fiber100Ge + ) +{ + EFI_STATUS Status; + UINT16 SfpNum1; + UINT8 SfpSpeed1; + UINT16 SfpNum2; + UINT8 SfpSpeed2; + + SfpNum1 = 0x1; + SfpSpeed1 = SFP_10G_SPEED; + SfpNum2 = 0x2; + SfpSpeed2 = SFP_10G_SPEED; + *Fiber100Ge = 0x0; + *Fiber1Type = SFP_10G_SPEED; + *Fiber2Type = SFP_10G_SPEED; + + if ((ReadCpldReg (CPU2_SFP2_100G_CARD_OFFSET) & BIT7) == (CARD_PRESENT << 7)) { + // 100 Ge card + *Fiber1Type = SFP_10G_SPEED; + *Fiber2Type = SFP_10G_SPEED; + *Fiber100Ge = SFP_100G_SPEED; + DEBUG ((DEBUG_ERROR,"Detect Fiber SFP_100G is Present, Set 100Ge\n")); + } else if ((ReadCpldReg (CPU2_SFP2_10G_GE_CARD_OFFSET) & BIT0) == CARD_PRESENT) { + *Fiber100Ge = 0x0; + *Fiber1Type = SFP_10G_SPEED; + *Fiber2Type = SFP_10G_SPEED; + if (ReadCpldReg (CPU2_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) { + // Fiber detected in CPU2 slot0, read speed via i2c + Status = GetSfpSpeed (SOCKET_1, SfpNum1, &SfpSpeed1); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, + "Get Socket1 Sfp%d Speed Error: %r.\n", + SfpNum1, + Status)); + return Status; + } + if (SfpSpeed1 == SFP_25G_SPEED) { + // P1 don't support 25G, so set speed to 10G + *Fiber1Type = SFP_10G_SPEED; + } else { + *Fiber1Type = SfpSpeed1; + } + } else { + // No fiber, set speed to 10G + *Fiber1Type = SFP_10G_SPEED; + } + + if (ReadCpldReg (CPU2_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) { + // Fiber detected in CPU2 slot1, read speed via i2c + Status = GetSfpSpeed (SOCKET_1, SfpNum2, &SfpSpeed2); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status)); + return Status; + } + if (SfpSpeed2 == SFP_25G_SPEED) { + *Fiber2Type = SFP_10G_SPEED; + } else { + *Fiber2Type = SfpSpeed2; + } + } else { + // No fiber, set speed to 10G + *Fiber2Type = SFP_10G_SPEED; + } + } else { + // 100Ge/10Ge/Ge Fiber is not found. + *Fiber1Type = SFP_10G_SPEED; + *Fiber2Type = SFP_10G_SPEED; + *Fiber100Ge = 0x0; + } + + return EFI_SUCCESS; +} + +//Fiber1Type/Fiber2Type return: SFP_10G_SPEED, SFP_25G_SPEED, SFP_GE_SPEED +UINT32 +GetCpu1FiberType ( + UINT8* Fiber1Type, + UINT8* Fiber2Type + ) +{ + EFI_STATUS Status; + UINT16 SfpNum1; + UINT8 SfpSpeed1; + UINT16 SfpNum2; + UINT8 SfpSpeed2; + + SfpNum1 = 0x1; + SfpSpeed1 = SFP_10G_SPEED; + SfpNum2 = 0x2; + SfpSpeed2 = SFP_10G_SPEED; + *Fiber1Type = SFP_10G_SPEED; + *Fiber2Type = SFP_10G_SPEED; + // Fiber detected in CPU1 slot0, read speed via i2c + if (ReadCpldReg (CPU1_SFP0_LOCATE_OFFSET) == FIBER_PRESENT) { + Status = GetSfpSpeed (SOCKET_0, SfpNum1, &SfpSpeed1); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Get Socket0 Sfp%d Speed Error: %r.\n", + SfpNum1, Status)); + return Status; + } + *Fiber1Type = SfpSpeed1; + } else { + *Fiber1Type = SFP_10G_SPEED; + } + + // Fiber detected in CPU1 slot1, read speed via i2c + if (ReadCpldReg (CPU1_SFP1_LOCATE_OFFSET) == FIBER_PRESENT) { + Status = GetSfpSpeed (SOCKET_0, SfpNum2, &SfpSpeed2); + if (EFI_ERROR (Status)) { + *Fiber2Type = SFP_10G_SPEED; + DEBUG ((DEBUG_ERROR, "Get Sfp%d Speed Error: %r.\n", SfpNum2, Status)); + return Status; + } + *Fiber2Type = SfpSpeed2; + } else { + *Fiber2Type = SFP_10G_SPEED; + } + + return EFI_SUCCESS; +} + +UINT16 make_crc_checksum ( + UINT8 *buf, + UINT32 len + ) +{ + UINT16 StartCRC = 0; + + if (len > (512 * 1024)) { + return 0; + } + + if (buf == NULL) { + return 0; + } + + while (len) { + StartCRC = crc_tab [((UINT8) ((StartCRC >> 8) & 0xff)) ^ *(buf++)] ^ + ((UINT16) (StartCRC << 8)); + len--; + } + + return StartCRC; +} + + +EFI_STATUS +OemGetMacE2prom( + IN UINT32 Port, + OUT UINT8 *pucAddr + ) +{ + I2C_DEVICE stI2cDev = {0}; + EFI_STATUS Status; + UINT16 I2cOffset; + UINT16 crc16; + NIC_MAC_ADDRESS stMacDesc = {0}; + UINT16 RemainderMacOffset; + UINT16 LessSizeOfPage; + UINT32 i = 0; + + Status = I2CInit (0, EEPROM_I2C_PORT, Normal); + if (EFI_ERROR (Status)) + { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS)); + + stI2cDev.DeviceType = DEVICE_TYPE_E2PROM; + stI2cDev.Port = EEPROM_I2C_PORT; + stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM; + stI2cDev.Socket = 0; + RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE; + LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset; + //The length of NIC_MAC_ADDRESS is 10 bytes long, + //It surly less than EEPROM page size, so we could + //code as bellow, check the address whether across the page boundary, + //and split the data when across page boundary. + if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) { + Status = I2CRead (&stI2cDev, I2cOffset, sizeof (NIC_MAC_ADDRESS), (UINT8 *) &stMacDesc); + } else { + Status = I2CRead (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc); + if (!(EFI_ERROR (Status))) { + Status |= I2CRead ( + &stI2cDev, + I2cOffset + LessSizeOfPage, + sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage, + (UINT8 *) &stMacDesc + LessSizeOfPage + ); + } + } + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cRead failed! p1=0x%x.\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + crc16 = make_crc_checksum ( + (UINT8 *) & (stMacDesc.MacLen), + sizeof (stMacDesc.MacLen) + sizeof (stMacDesc.Mac) + ); + if ((crc16 != stMacDesc.Crc16) || (0 == crc16)) { + return EFI_NOT_FOUND; + } + + for (i = 0; i < MAC_ADDR_LEN; i++) { + pucAddr[i] = stMacDesc.Mac[i]; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +OemSetMacE2prom ( + IN UINT32 Port, + IN UINT8 *pucAddr + ) +{ + I2C_DEVICE stI2cDev = {0}; + EFI_STATUS Status; + UINT16 I2cOffset; + NIC_MAC_ADDRESS stMacDesc = {0}; + UINT32 i; + UINT16 RemainderMacOffset; + UINT16 LessSizeOfPage; + + i = 0; + stMacDesc.MacLen = MAC_ADDR_LEN; + + for (i = 0; i < MAC_ADDR_LEN; i++) { + stMacDesc.Mac[i] = pucAddr[i]; + } + + stMacDesc.Crc16 = make_crc_checksum ( + (UINT8 *) & (stMacDesc.MacLen), + sizeof (stMacDesc.MacLen) + MAC_ADDR_LEN + ); + + Status = I2CInit (0, EEPROM_I2C_PORT, Normal); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2CInit failed! p1=0x%x.\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + I2cOffset = I2C_OFFSET_EEPROM_ETH0 + (Port * sizeof (NIC_MAC_ADDRESS)); + + stI2cDev.DeviceType = DEVICE_TYPE_E2PROM; + stI2cDev.Port = EEPROM_I2C_PORT; + stI2cDev.SlaveDeviceAddress = I2C_SLAVEADDR_EEPROM; + stI2cDev.Socket = 0; + RemainderMacOffset = I2cOffset % EEPROM_PAGE_SIZE; + LessSizeOfPage = EEPROM_PAGE_SIZE - RemainderMacOffset; + //The length of NIC_MAC_ADDRESS is 10 bytes long, + //It surly less than EEPROM page size, so we could + //code as bellow, check the address whether across the page boundary, + //and split the data when across page boundary. + if (sizeof (NIC_MAC_ADDRESS) <= LessSizeOfPage) { + Status = I2CWrite ( + &stI2cDev, + I2cOffset, + sizeof (NIC_MAC_ADDRESS), + (UINT8 *) &stMacDesc + ); + } else { + Status = I2CWrite (&stI2cDev, I2cOffset, LessSizeOfPage, (UINT8 *) &stMacDesc); + if (!(EFI_ERROR (Status))) { + Status |= I2CWrite ( + &stI2cDev, + I2cOffset + LessSizeOfPage, + sizeof (NIC_MAC_ADDRESS) - LessSizeOfPage, + (UINT8 *) &stMacDesc + LessSizeOfPage + ); + } + } + if (EFI_ERROR (Status)) + { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Call I2cWrite failed! p1=0x%x.\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +OemGetMac ( + IN OUT EFI_MAC_ADDRESS *Mac, + IN UINTN Port + ) +{ + EFI_STATUS Status; + + if (NULL == Mac) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", + __FUNCTION__, __LINE__)); + return EFI_INVALID_PARAMETER; + } + + Status = OemGetMacE2prom (Port, Mac->Addr); + if ((EFI_ERROR (Status))) { + DEBUG ((DEBUG_ERROR, + "[%a]:[%dL] Cannot get MAC from EEPROM, Status: %r; using default MAC.\n", + __FUNCTION__, __LINE__, Status)); + + Mac->Addr[0] = 0x00; + Mac->Addr[1] = 0x18; + Mac->Addr[2] = 0x82; + Mac->Addr[3] = 0x2F; + Mac->Addr[4] = 0x02; + Mac->Addr[5] = Port; + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +OemSetMac ( + IN EFI_MAC_ADDRESS *Mac, + IN UINTN Port + ) +{ + EFI_STATUS Status; + + if (NULL == Mac) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Mac buffer is null!\n", + __FUNCTION__, __LINE__)); + return EFI_INVALID_PARAMETER; + } + + Status = OemSetMacE2prom (Port, Mac->Addr); + if ((EFI_ERROR (Status))) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Set mac failed!\n", __FUNCTION__, __LINE__)); + return Status; + } + + return EFI_SUCCESS; +} + +UINT32 +OemEthFindFirstSP ( + VOID + ) +{ + UINT32 i; + + for (i = 0; i < ETH_MAX_PORT; i++) { + if (gEthPdtDesc[i].Valid == TRUE) { + return i; + } + } + + return ETH_INVALID; +} + +ETH_PRODUCT_DESC * +OemEthInit ( + UINT32 port + ) +{ + return (ETH_PRODUCT_DESC *)(&(gEthPdtDesc[port])); +} + + +BOOLEAN +OemIsInitEth ( + UINT32 Port + ) +{ + return TRUE; +} diff --git a/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf new file mode 100644 index 0000000000..ac849cb992 --- /dev/null +++ b/Platform/Hisilicon/D06/Library/OemNicLib/OemNicLib.inf @@ -0,0 +1,35 @@ +#/** @file +# +# Copyright (c) 2018, Hisilicon Limited. All rights reserved. +# Copyright (c) 2017, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OemNicLib + FILE_GUID = 520F872C-FFCF-4EF3-AC01-85BDB0816DCE + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = OemNicLib + +[Sources.common] + OemNicLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + I2CLib + CpldIoLib