From: Bartosz Szczepanek bsz@semihalf.com
Pp2Dxe supports Marvell PP2 NIC. It comprise up to 3 ports in a single unit (1x 10G and 2x 2.5G). Also parser and hardware buffer manager offload engines support are enabled, as their usage is obligatory.
EFI_SIMPLE_NETWORK_PROTOCOL is implemented for configurable number of interfaces via PCD.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Bartosz Szczepanek bsz@semihalf.com Signed-off-by: Marcin Wojtas mw@semihalf.com --- Documentation/Marvell/PortingGuide/Pp2.txt | 70 ++ Drivers/Net/Pp2Dxe/Pp2Dxe.c | 1280 ++++++++++++++++++++++++++++ Drivers/Net/Pp2Dxe/Pp2Dxe.h | 455 ++++++++++ Drivers/Net/Pp2Dxe/Pp2Dxe.inf | 94 ++ Platforms/Marvell/Marvell.dec | 19 + 5 files changed, 1918 insertions(+) create mode 100644 Documentation/Marvell/PortingGuide/Pp2.txt create mode 100644 Drivers/Net/Pp2Dxe/Pp2Dxe.c create mode 100644 Drivers/Net/Pp2Dxe/Pp2Dxe.h create mode 100644 Drivers/Net/Pp2Dxe/Pp2Dxe.inf
diff --git a/Documentation/Marvell/PortingGuide/Pp2.txt b/Documentation/Marvell/PortingGuide/Pp2.txt new file mode 100644 index 0000000..4eb10c0 --- /dev/null +++ b/Documentation/Marvell/PortingGuide/Pp2.txt @@ -0,0 +1,70 @@ +Pp2Dxe porting guide +-------------------- +Pp2Dxe is driver supporting PP2 NIC on Marvell platforms. Following PCDs +are required to operate: + +Number of ports/network interfaces: + gMarvellTokenSpaceGuid.PcdPp2PortNumber + +Addresses of PHY devices: + gMarvellTokenSpaceGuid.PcdPhySmiAddresses + +Identificators of PP2 ports: + gMarvellTokenSpaceGuid.PcdPp2PortIds + +Indexes used in GOP operation: + gMarvellTokenSpaceGuid.PcdPp2GopIndexes + +Set to 0x1 for always-up interface, 0x0 otherwise: + gMarvellTokenSpaceGuid.PcdPp2InterfaceAlwaysUp + +Values corresponding to PHY_SPEED enum: + gMarvellTokenSpaceGuid.PcdPp2InterfaceSpeed + +PHY_SPEED is defined as follows: + typedef enum { + 0 NO_SPEED, + 1 SPEED_10, + 2 SPEED_100, + 3 SPEED_1000, + 4 SPEED_2500, + 5 SPEED_10000 + } PHY_SPEED; + +Base address of shared register space of PP2: + gMarvellTokenSpaceGuid.PcdPp2SharedAddress + +Spacing between consecutive GMAC register spaces: + gMarvellTokenSpaceGuid.PcdPp2GmacObjSize + +Base address of GMAC: + gMarvellTokenSpaceGuid.PcdPp2GmacBaseAddress + +Spacing between consecutive XLG register spaces: + gMarvellTokenSpaceGuid.PcdPp2XlgObjSize + +Base address of XLG: + gMarvellTokenSpaceGuid.PcdPp2XlgBaseAddress + +Base address of RFU1: + gMarvellTokenSpaceGuid.PcdPp2Rfu1BaseAddress + +Base address of SMI: + gMarvellTokenSpaceGuid.PcdPp2SmiBaseAddress + +TCLK frequency: + gMarvellTokenSpaceGuid.PcdPp2ClockFrequency + +GMAC and XLG addresses are computed as follows: + address = base_address + obj_size * gop_index + +MAC adresses for up to 3 ports per controller +are defined in following tables: + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort<N>, + +where N is port number (0-2). Example: Set Port1 +address to value 0a:70:40:00:00:02: + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort1|{ 0x0a, 0x70, 0x40, 0x00, 0x00, 0x2 } + +Default value, for MAC address not defined in board's +.dsc file is 00:00:00:00:00:0<N>, where N is port index + 1 diff --git a/Drivers/Net/Pp2Dxe/Pp2Dxe.c b/Drivers/Net/Pp2Dxe/Pp2Dxe.c new file mode 100644 index 0000000..8e6dbc0 --- /dev/null +++ b/Drivers/Net/Pp2Dxe/Pp2Dxe.c @@ -0,0 +1,1280 @@ +/******************************************************************************** +Copyright (C) 2016 Marvell International Ltd. + +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include <Protocol/DriverBinding.h> +#include <Protocol/SimpleNetwork.h> +#include <Protocol/DevicePath.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/IoLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/NetLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/CacheMaintenanceLib.h> + +#include "Mvpp2LibHw.h" +#include "Pp2Dxe.h" +#include "Mvpp2Lib.h" + +#define ReturnUnlock(tpl, status) do { gBS->RestoreTPL (tpl); return (status); } while(0) +MVPP2_SHARED *Mvpp2Shared; +BUFFER_LOCATION BufferLocation; + +PP2_DEVICE_PATH Pp2DevicePathTemplate = { + { + { + MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, + { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) } + }, + { { 0 } }, + 0 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 } + } +}; + +#define QueueNext(off) ((((off) + 1) >= QUEUE_DEPTH) ? 0 : ((off) + 1)) + +STATIC +EFI_STATUS +QueueInsert ( + IN PP2DXE_CONTEXT *Pp2Context, + IN VOID *Buffer + ) +{ + + if (QueueNext (Pp2Context->CompletionQueueTail) == + Pp2Context->CompletionQueueHead) { + return EFI_OUT_OF_RESOURCES; + } + + Pp2Context->CompletionQueue[Pp2Context->CompletionQueueTail] = Buffer; + Pp2Context->CompletionQueueTail = QueueNext (Pp2Context->CompletionQueueTail); + + return EFI_SUCCESS; +} + +STATIC +VOID * +QueueRemove ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + VOID *Buffer; + + if (Pp2Context->CompletionQueueTail == Pp2Context->CompletionQueueHead) { + return NULL; + } + + Buffer = Pp2Context->CompletionQueue[Pp2Context->CompletionQueueHead]; + Pp2Context->CompletionQueue[Pp2Context->CompletionQueueHead] = NULL; + Pp2Context->CompletionQueueHead = QueueNext (Pp2Context->CompletionQueueHead); + + return Buffer; +} + +STATIC +EFI_STATUS +Pp2DxeBmPoolInit ( + VOID + ) +{ + INTN Index; + UINT8 *PoolAddr; + + for (Index = 0; Index < MVPP2_BM_POOLS_NUM; Index++) { + /* BmIrqClear */ + Mvpp2BmIrqClear(Mvpp2Shared, Index); + } + + Mvpp2Shared->BmPools = AllocateZeroPool (sizeof(MVPP2_BMS_POOL)); + + if (!Mvpp2Shared->BmPools) + return EFI_OUT_OF_RESOURCES; + + PoolAddr = AllocateZeroPool ((sizeof(VOID*) * MVPP2_BM_SIZE)*2 + + MVPP2_BM_POOL_PTR_ALIGN); + + if (!PoolAddr) { + return EFI_OUT_OF_RESOURCES; + } + if (IS_NOT_ALIGN((UINT64)PoolAddr, + MVPP2_BM_POOL_PTR_ALIGN)) + PoolAddr = + (UINT8 *)ALIGN_UP((UINT64)PoolAddr, + MVPP2_BM_POOL_PTR_ALIGN); + + Mvpp2Shared->BmPools->Id = MVPP2_BM_POOL; + Mvpp2Shared->BmPools->VirtAddr = (UINT32*)PoolAddr; + Mvpp2Shared->BmPools->PhysAddr = (UINT64)PoolAddr; + + Mvpp2BmPoolHwCreate(Mvpp2Shared, Mvpp2Shared->BmPools, MVPP2_BM_SIZE); + + return EFI_SUCCESS; +} + +/* Enable and fill BM pool */ +STATIC +EFI_STATUS +Pp2DxeBmStart ( + VOID + ) +{ + UINT8 *buff, *BuffPhys; + INTN Index; + + Mvpp2BmPoolCtrl(Mvpp2Shared, MVPP2_BM_POOL, MVPP2_START); + + Mvpp2BmPoolBufsizeSet(Mvpp2Shared, Mvpp2Shared->BmPools, RX_BUFFER_SIZE); + + /* Fill BM pool with buffers */ + for (Index = 0; Index < MVPP2_BM_SIZE; Index++) { + buff = (UINT8 *)(BufferLocation.RxBuffers + + (Index * RX_BUFFER_SIZE)); + if (!buff) + return EFI_OUT_OF_RESOURCES; + + BuffPhys = (UINT8 *)ALIGN_UP((UINT64)buff, + BM_ALIGN); + Mvpp2BmPoolPut(Mvpp2Shared, MVPP2_BM_POOL, + (UINT64)BuffPhys, (UINT64)BuffPhys); + } + + return EFI_SUCCESS; +} + +STATIC +VOID +Pp2DxeStartDev ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + PP2DXE_PORT *Port = &Pp2Context->Port; + + Mvpp2IngressEnable(Port); + + /* Config classifier decoding table */ + Mvpp2ClsPortConfig(Port); + Mvpp2ClsOversizeRxqSet(Port); + MvGop110PortEventsMask(Port); + MvGop110PortEnable(Port); + + gBS->Stall(2000); + Mvpp2EgressEnable(Port); +} + +STATIC +EFI_STATUS +Pp2DxeSetupRxqs ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + INTN Queue; + EFI_STATUS Status; + MVPP2_RX_QUEUE *Rxq; + + for (Queue = 0; Queue < RxqNumber; Queue++) { + Rxq = &Pp2Context->Port.Rxqs[Queue]; + Rxq->DescsPhys = (DmaAddrT)Rxq->Descs; + if (!Rxq->Descs) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrCleanup; + } + + Mvpp2RxqHwInit(&Pp2Context->Port, Rxq); + } + + return EFI_SUCCESS; + +ErrCleanup: + Mvpp2CleanupRxqs(&Pp2Context->Port); + return Status; +} + +STATIC +EFI_STATUS +Pp2DxeSetupTxqs ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + INTN Queue; + MVPP2_TX_QUEUE *Txq; + EFI_STATUS Status; + + for (Queue = 0; Queue < TxqNumber; Queue++) { + Txq = &Pp2Context->Port.Txqs[Queue]; + Txq->DescsPhys = (DmaAddrT) Txq->Descs; + if (!Txq->DescsPhys) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrCleanup; + } + Mvpp2TxqHwInit(&Pp2Context->Port, Txq); + } + + return EFI_SUCCESS; + +ErrCleanup: + Mvpp2CleanupTxqs(&Pp2Context->Port); + return Status; +} + +STATIC +EFI_STATUS +Pp2DxeSetupAggrTxqs ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + MVPP2_TX_QUEUE *AggrTxq; + + AggrTxq = Mvpp2Shared->AggrTxqs; + AggrTxq->DescsPhys = (DmaAddrT)AggrTxq->Descs; + if (!AggrTxq->Descs) + return EFI_OUT_OF_RESOURCES; + Mvpp2AggrTxqHwInit(AggrTxq, AggrTxq->Size, 0, Mvpp2Shared); + return EFI_SUCCESS; + +} + +STATIC +EFI_STATUS +Pp2DxeOpen ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + PP2DXE_PORT *Port = &Pp2Context->Port; + UINT8 MacBcast[NET_ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff }; + UINT8 DevAddr[NET_ETHER_ADDR_LEN]; + INTN ret; + EFI_STATUS Status; + + DEBUG((DEBUG_INFO, "Pp2Dxe: Open\n")); + + CopyMem (DevAddr, Pp2Context->Snp.Mode->CurrentAddress.Addr, NET_ETHER_ADDR_LEN); + + ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, MacBcast, TRUE); + if (ret) { + return EFI_DEVICE_ERROR; + } + ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, DevAddr, TRUE); + if (ret) { + return EFI_DEVICE_ERROR; + } + ret = Mvpp2PrsTagModeSet(Mvpp2Shared, Port->Id, MVPP2_TAG_TYPE_MH); + if (ret) { + return EFI_DEVICE_ERROR; + } + ret = Mvpp2PrsDefFlow(Port); + if (ret) { + return EFI_DEVICE_ERROR; + } + + Status = Pp2DxeSetupRxqs(Pp2Context); + if (EFI_ERROR(Status)) + return Status; + + Status = Pp2DxeSetupTxqs(Pp2Context); + if (EFI_ERROR(Status)) + return Status; + + Status = Pp2DxeSetupAggrTxqs(Pp2Context); + if (EFI_ERROR(Status)) + return Status; + + Pp2DxeStartDev(Pp2Context); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +Pp2DxeLatePortInitialize ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + PP2DXE_PORT *Port = &Pp2Context->Port; + INTN Queue; + + DEBUG((DEBUG_INFO, "Pp2Dxe: LatePortInitialize\n")); + Port->TxRingSize = MVPP2_MAX_TXD; + Port->RxRingSize = MVPP2_MAX_RXD; + + Mvpp2EgressDisable(Port); + MvGop110PortEventsMask(Port); + MvGop110PortDisable(Port); + + Port->Txqs = AllocateZeroPool (sizeof(MVPP2_TX_QUEUE) * TxqNumber); + if (Port->Txqs == NULL) { + DEBUG((DEBUG_ERROR, "Failed to allocate Txqs\n")); + return EFI_OUT_OF_RESOURCES; + } + + /* Use preallocated area */ + Port->Txqs[0].Descs = BufferLocation.TxDescs; + + for (Queue = 0; Queue < TxqNumber; Queue++) { + MVPP2_TX_QUEUE *Txq = &Port->Txqs[Queue]; + + Txq->Id = Mvpp2TxqPhys(Port->Id, Queue); + Txq->LogId = Queue; + Txq->Size = Port->TxRingSize; + } + + Port->Rxqs = AllocateZeroPool (sizeof(MVPP2_RX_QUEUE) * RxqNumber); + if (Port->Rxqs == NULL) { + DEBUG((DEBUG_ERROR, "Failed to allocate Rxqs\n")); + return EFI_OUT_OF_RESOURCES; + } + + Port->Rxqs[0].Descs = BufferLocation.RxDescs; + + for (Queue = 0; Queue < TxqNumber; Queue++) { + MVPP2_RX_QUEUE *Rxq = &Port->Rxqs[Queue]; + + Rxq->Id = Queue + Port->FirstRxq; + Rxq->Size = Port->RxRingSize; + } + + Mvpp2IngressDisable(Port); + + Mvpp2DefaultsSet(Port); + + return Pp2DxeOpen(Pp2Context); +} + +STATIC +EFI_STATUS +Pp2DxeLateInitialize ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + PP2DXE_PORT *Port = &Pp2Context->Port; + EFI_STATUS Status; + + DEBUG((DEBUG_INFO, "Pp2Dxe: Pp2DxeLateInitialize\n")); + + if (!Pp2Context->LateInitialized) { + /* Full init on first call */ + Status = Pp2DxeLatePortInitialize(Pp2Context); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Pp2Dxe: late initialization failed\n")); + return Status; + } + /* Attach pool to Rxq */ + Mvpp2RxqLongPoolSet(Port, 0, MVPP2_BM_POOL); + Mvpp2RxqShortPoolSet(Port, 0, MVPP2_BM_POOL); + + /* + * Mark this port being fully initialized, + * otherwise it will be inited again + * during next networking transaction, + * including memory allocatation for + * TX/RX queue, PHY connect/configuration + * and address decode configuration. + */ + Pp2Context->LateInitialized = TRUE; + } else { + /* Upon all following calls, this is enough */ + MvGop110PortEventsMask(Port); + MvGop110PortEnable(Port); + } + return 0; +} + +EFI_STATUS +Pp2DxePhyInitialize ( + PP2DXE_CONTEXT *Pp2Context + ) +{ + EFI_STATUS Status; + UINT8 *PhyAddresses; + + PhyAddresses = PcdGetPtr (PcdPhySmiAddresses); + Status = gBS->LocateProtocol ( + &gMarvellPhyProtocolGuid, + NULL, + (VOID **) &Pp2Context->Phy + ); + if (EFI_ERROR(Status)) + return Status; + + if (PhyAddresses[Pp2Context->Instance] == 0xff) + /* PHY iniitalization not required */ + return EFI_SUCCESS; + + Status = Pp2Context->Phy->Init( + Pp2Context->Phy, + PhyAddresses[Pp2Context->Instance], + Pp2Context->Port.PhyInterface, + &Pp2Context->PhyDev + ); + if (EFI_ERROR(Status) && Status != EFI_TIMEOUT) + return Status; + Pp2Context->Phy->Status(Pp2Context->Phy, Pp2Context->PhyDev); + DEBUG((DEBUG_INFO, + "PHY%d: ", + Pp2Context->PhyDev->Addr)); + DEBUG((DEBUG_INFO, + Pp2Context->PhyDev->LinkUp ? "link up, " : "link down, ")); + DEBUG((DEBUG_INFO, + Pp2Context->PhyDev->FullDuplex ? "full duplex, " : "half duplex, ")); + DEBUG((DEBUG_INFO, + Pp2Context->PhyDev->Speed == SPEED_10 ? "speed 10\n" : + (Pp2Context->PhyDev->Speed == SPEED_100 ? "speed 100\n" : "speed 1000\n"))); + + Mvpp2SmiPhyAddrCfg(&Pp2Context->Port, Pp2Context->Port.GopIndex, + Pp2Context->PhyDev->Addr); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +Pp2DxeSnpInitialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ) +{ + EFI_STATUS Status; + PP2DXE_CONTEXT *Pp2Context; + Pp2Context = INSTANCE_FROM_SNP(This); + EFI_TPL SavedTpl; + + DEBUG((DEBUG_INFO, "Pp2Dxe%d: initialize\n", Pp2Context->Instance)); + if (ExtraRxBufferSize != 0 || ExtraTxBufferSize != 0) { + DEBUG((DEBUG_ERROR, "Pp2Dxe%d: non-zero buffer requests\n", Pp2Context->Instance)); + return EFI_UNSUPPORTED; + } + + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + + switch (This->Mode->State) { + case EfiSimpleNetworkStarted: + DEBUG((DEBUG_INFO, "Pp2Dxe%d: started state\n", Pp2Context->Instance)); + break; + case EfiSimpleNetworkInitialized: + DEBUG((DEBUG_INFO, "Pp2Dxe%d: already initialized\n", Pp2Context->Instance)); + ReturnUnlock (SavedTpl, EFI_SUCCESS); + case EfiSimpleNetworkStopped: + DEBUG((DEBUG_INFO, "Pp2Dxe%d: network stopped\n", Pp2Context->Instance)); + ReturnUnlock (SavedTpl, EFI_NOT_STARTED); + default: + DEBUG((DEBUG_INFO, "Pp2Dxe%d: wrong state\n", Pp2Context->Instance)); + ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR); + } + + This->Mode->State = EfiSimpleNetworkInitialized; + + if (Pp2Context->Initialized) + ReturnUnlock(SavedTpl, EFI_SUCCESS); + + Pp2Context->Initialized = TRUE; + + Status = Pp2DxePhyInitialize(Pp2Context); + if (EFI_ERROR(Status)) + ReturnUnlock (SavedTpl, Status); + + ReturnUnlock (SavedTpl, Pp2DxeLateInitialize(Pp2Context)); +} + +EFI_STATUS +EFIAPI +Pp2SnpStart ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + PP2DXE_CONTEXT *Pp2Context; + EFI_TPL SavedTpl; + + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + Pp2Context = INSTANCE_FROM_SNP(This); + + DEBUG((DEBUG_INFO, "Pp2Dxe%d: started\n", Pp2Context->Instance)); + switch (This->Mode->State) { + case EfiSimpleNetworkStopped: + DEBUG((DEBUG_INFO, "Pp2Dxe%d: stopped state\n", Pp2Context->Instance)); + break; + case EfiSimpleNetworkStarted: + case EfiSimpleNetworkInitialized: + DEBUG((DEBUG_INFO, "Pp2Dxe: Driver already started\n")); + ReturnUnlock (SavedTpl, EFI_ALREADY_STARTED); + default: + DEBUG((DEBUG_ERROR, "Pp2Dxe: Driver in an invalid state: %u\n", + (UINTN)This->Mode->State)); + ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR); + } + This->Mode->State = EfiSimpleNetworkStarted; + ReturnUnlock (SavedTpl, EFI_SUCCESS); +} + +EFI_STATUS +EFIAPI +Pp2SnpStop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_TPL SavedTpl; + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + + DEBUG((DEBUG_INFO, "Pp2SnpStop \n")); + switch (This->Mode->State) { + case EfiSimpleNetworkStarted: + case EfiSimpleNetworkInitialized: + break; + case EfiSimpleNetworkStopped: + ReturnUnlock (SavedTpl, EFI_NOT_STARTED); + default: + ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR); + } + This->Mode->State = EfiSimpleNetworkStopped; + ReturnUnlock (SavedTpl, EFI_SUCCESS); +} + +EFI_STATUS +EFIAPI +Pp2SnpReset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + DEBUG((DEBUG_INFO, "Pp2SnpReset \n")); + return EFI_SUCCESS; +} + +VOID +EFIAPI +Pp2DxeHalt ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + PP2DXE_CONTEXT *Pp2Context = Context; + PP2DXE_PORT *Port = &Pp2Context->Port; + STATIC BOOLEAN CommonPartHalted = FALSE; + + if (!CommonPartHalted) { + Mvpp2BmStop(Mvpp2Shared, MVPP2_BM_POOL); + CommonPartHalted = TRUE; + } + Mvpp2TxqDrainSet(Port, 0, TRUE); + Mvpp2IngressDisable(Port); + Mvpp2EgressDisable(Port); + + MvGop110PortEventsMask(Port); + MvGop110PortDisable(Port); +} + +EFI_STATUS +EFIAPI +Pp2SnpShutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +{ + EFI_TPL SavedTpl; + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + + switch (This->Mode->State) { + case EfiSimpleNetworkInitialized: + break; + case EfiSimpleNetworkStarted: + ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR); + case EfiSimpleNetworkStopped: + ReturnUnlock (SavedTpl, EFI_NOT_STARTED); + default: + ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR); + } + + ReturnUnlock (SavedTpl, EFI_SUCCESS); +} + +EFI_STATUS +EFIAPI +Pp2SnpReceiveFilters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL + ) +{ + DEBUG((DEBUG_INFO, "Pp2SnpReceiveFilt \n")); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +Pp2SnpStationAddress ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *NewMac +) +{ + PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(Snp); + PP2_DEVICE_PATH *Pp2DevicePath = Pp2Context->DevicePath; + PP2DXE_PORT *Port = &Pp2Context->Port; + EFI_TPL SavedTpl; + INTN Ret; + + /* Check Snp instance */ + if (Snp == NULL) { + return EFI_INVALID_PARAMETER; + } + + /* Serialize access to data and registers */ + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + + /* Check that driver was started and initialised */ + switch (Snp->Mode->State) { + case EfiSimpleNetworkInitialized: + break; + case EfiSimpleNetworkStarted: + DEBUG((DEBUG_WARN, "Pp2Dxe%d: Driver not yet initialized\n", + Pp2Context->Instance)); + ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR); + case EfiSimpleNetworkStopped: + DEBUG((DEBUG_WARN, "Pp2Dxe%d: Driver not started\n", + Pp2Context->Instance)); + ReturnUnlock (SavedTpl, EFI_NOT_STARTED); + default: + DEBUG((DEBUG_ERROR, "Pp2Dxe%d: Driver in an invalid state\n", + Pp2Context->Instance)); + ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR); + } + + /* Invalidate old unicast address in parser */ + Ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, + Snp->Mode->CurrentAddress.Addr, FALSE); + if (Ret) { + DEBUG((DEBUG_ERROR, "Pp2SnpStationAddress - Fail\n")); + return EFI_DEVICE_ERROR; + } + + if (Reset) { + CopyMem (Snp->Mode->CurrentAddress.Addr, Snp->Mode->PermanentAddress.Addr, + NET_ETHER_ADDR_LEN); + CopyMem (NewMac->Addr, Snp->Mode->PermanentAddress.Addr, + NET_ETHER_ADDR_LEN); + CopyMem (Pp2DevicePath->Pp2Mac.MacAddress.Addr, Snp->Mode->PermanentAddress.Addr, + NET_ETHER_ADDR_LEN); + } else { + if (NewMac == NULL) { + ReturnUnlock (SavedTpl, EFI_INVALID_PARAMETER); + } + CopyMem (Snp->Mode->CurrentAddress.Addr, NewMac->Addr, + NET_ETHER_ADDR_LEN); + CopyMem (Pp2DevicePath->Pp2Mac.MacAddress.Addr, NewMac->Addr, + NET_ETHER_ADDR_LEN); + } + + /* Update parser with new unicast address */ + Ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, + Snp->Mode->CurrentAddress.Addr, TRUE); + if (Ret) { + DEBUG((DEBUG_ERROR, "Pp2SnpStationAddress - Fail\n")); + return EFI_DEVICE_ERROR; + } + + /* Restore TPL and return */ + gBS->RestoreTPL (SavedTpl); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +Pp2SnpNetStat ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL + ) +{ + DEBUG((DEBUG_INFO, "Pp2SnpNetStat \n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Pp2SnpIpToMac ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +{ + DEBUG((DEBUG_INFO, "Pp2SnpIpToMac \n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Pp2SnpNvData ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ) +{ + DEBUG((DEBUG_INFO, "Pp2SnpNvData \n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Pp2SnpGetStatus ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ) +{ + PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(Snp); + PP2DXE_PORT *Port = &Pp2Context->Port; + BOOLEAN LinkUp; + EFI_TPL SavedTpl; + + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + + if (!Pp2Context->Initialized) + ReturnUnlock(SavedTpl, EFI_NOT_READY); + + LinkUp = Port->AlwaysUp ? TRUE : MvGop110PortIsLinkUp(Port); + + if (LinkUp != Snp->Mode->MediaPresent) { + DEBUG((DEBUG_INFO, "Pp2Dxe%d: Link ", Pp2Context->Instance)); + DEBUG((DEBUG_INFO, LinkUp ? "up\n" : "down\n")); + } + Snp->Mode->MediaPresent = LinkUp; + + if (TxBuf != NULL) { + *TxBuf = QueueRemove (Pp2Context); + } + + ReturnUnlock(SavedTpl, EFI_SUCCESS); +} + +EFI_STATUS +EFIAPI +Pp2SnpTransmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *ProtocolPtr OPTIONAL + ) +{ + PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(This); + PP2DXE_PORT *Port = &Pp2Context->Port; + MVPP2_TX_QUEUE *AggrTxq = Mvpp2Shared->AggrTxqs; + MVPP2_TX_DESC *TxDesc; + INTN timeout = 0; + INTN TxDone; + UINT8 *DataPtr = Buffer; + UINT16 Protocol; + EFI_TPL SavedTpl; + + if (This == NULL || Buffer == NULL) { + DEBUG((DEBUG_ERROR, "Pp2Dxe: null Snp or Buffer\n")); + return EFI_INVALID_PARAMETER; + } + + if (HeaderSize != 0) { + ASSERT (HeaderSize == This->Mode->MediaHeaderSize); + ASSERT (ProtocolPtr != NULL); + ASSERT (DestAddr != NULL); + } + + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + + switch (This->Mode->State) { + case EfiSimpleNetworkInitialized: + break; + case EfiSimpleNetworkStarted: + DEBUG((DEBUG_WARN, "Pp2Dxe: Driver not yet initialized\n")); + ReturnUnlock(SavedTpl, EFI_DEVICE_ERROR); + case EfiSimpleNetworkStopped: + DEBUG((DEBUG_WARN, "Pp2Dxe: Driver not started\n")); + ReturnUnlock(SavedTpl, EFI_NOT_STARTED); + default: + DEBUG((DEBUG_ERROR, "Pp2Dxe: Driver in an invalid state\n")); + ReturnUnlock(SavedTpl, EFI_DEVICE_ERROR); + } + + if (!This->Mode->MediaPresent) { + DEBUG((DEBUG_ERROR, "Pp2Dxe: link not ready\n")); + ReturnUnlock(SavedTpl, EFI_NOT_READY); + } + + Protocol = HTONS(*ProtocolPtr); + + TxDesc = Mvpp2TxqNextDescGet(AggrTxq); + + if (!TxDesc) { + DEBUG((DEBUG_ERROR, "No tx descriptor to use\n")); + ReturnUnlock(SavedTpl, EFI_OUT_OF_RESOURCES); + } + + if (HeaderSize != 0) { + CopyMem(DataPtr, DestAddr, NET_ETHER_ADDR_LEN); + + if (SrcAddr != NULL) + CopyMem(DataPtr + NET_ETHER_ADDR_LEN, SrcAddr, NET_ETHER_ADDR_LEN); + else + CopyMem(DataPtr + NET_ETHER_ADDR_LEN, &This->Mode->CurrentAddress, NET_ETHER_ADDR_LEN); + + CopyMem(DataPtr + NET_ETHER_ADDR_LEN * 2, &Protocol, 2); + } + + /* set descriptor fields */ + TxDesc->command = MVPP2_TXD_IP_CSUM_DISABLE | + MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC; + TxDesc->DataSize = BufferSize; + + TxDesc->PacketOffset = (PhysAddrT)DataPtr & MVPP2_TX_DESC_ALIGN; + + Mvpp2x2TxdescPhysAddrSet( + (PhysAddrT)DataPtr & ~MVPP2_TX_DESC_ALIGN, TxDesc); + TxDesc->PhysTxq = Mvpp2TxqPhys(Port->Id, 0); + + InvalidateDataCacheRange (DataPtr, BufferSize); + + /* iowmb */ + __asm__ __volatile__ ("" : : : "memory"); + /* send */ + Mvpp2AggrTxqPendDescAdd(Port, 1); + + /* Tx done processing */ + /* wait for agrregated to physical TXQ transfer */ + TxDone = Mvpp2AggrTxqPendDescNumGet(Mvpp2Shared, 0); + do { + if (timeout++ > MVPP2_TX_SEND_TIMEOUT) { + DEBUG((DEBUG_ERROR, "Pp2Dxe: transmit timeout\n")); + ReturnUnlock(SavedTpl, EFI_TIMEOUT); + } + TxDone = Mvpp2AggrTxqPendDescNumGet(Mvpp2Shared, 0); + } while (TxDone); + + timeout = 0; + TxDone = Mvpp2TxqSentDescProc(Port, &Port->Txqs[0]); + /* wait for packet to be transmitted */ + while (!TxDone) { + if (timeout++ > MVPP2_TX_SEND_TIMEOUT) { + DEBUG((DEBUG_ERROR, "Pp2Dxe: transmit timeout\n")); + ReturnUnlock(SavedTpl, EFI_TIMEOUT); + } + TxDone = Mvpp2TxqSentDescProc(Port, &Port->Txqs[0]); + } + /* TxDone has increased - hw sent packet */ + + /* add buffer to completion queue and return */ + ReturnUnlock (SavedTpl, QueueInsert (Pp2Context, Buffer)); +} + +EFI_STATUS +EFIAPI +Pp2SnpReceive ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DstAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ) +{ + INTN ReceivedPackets; + PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(This); + PP2DXE_PORT *Port = &Pp2Context->Port; + UINT64 PhysAddr, VirtAddr; + EFI_STATUS Status = EFI_SUCCESS; + EFI_TPL SavedTpl; + UINT32 StatusReg; + INTN PoolId; + UINTN PktLength; + UINT8 *DataPtr; + MVPP2_RX_DESC *RxDesc; + MVPP2_RX_QUEUE *Rxq = &Port->Rxqs[0]; + + SavedTpl = gBS->RaiseTPL (TPL_CALLBACK); + ReceivedPackets = Mvpp2RxqReceived(Port, Rxq->Id); + + if (ReceivedPackets == 0) { + ReturnUnlock(SavedTpl, EFI_NOT_READY); + } + + /* process one packet per call */ + RxDesc = Mvpp2RxqNextDescGet(Rxq); + + StatusReg = RxDesc->status; + + /* extract addresses from descriptor */ + PhysAddr = RxDesc->BufPhysAddrKeyHash & + MVPP22_ADDR_MASK; + VirtAddr = RxDesc->BufCookieBmQsetClsInfo & + MVPP22_ADDR_MASK; + + /* drop packets with error or with buffer header (MC, SG) */ + if ((StatusReg & MVPP2_RXD_BUF_HDR) || + (StatusReg & MVPP2_RXD_ERR_SUMMARY)) { + DEBUG((DEBUG_WARN, "Pp2Dxe: dropping packet\n")); + Status = EFI_DEVICE_ERROR; + goto drop; + } + + PktLength = (UINTN) RxDesc->DataSize - 2; + if (PktLength > *BufferSize) { + *BufferSize = PktLength; + DEBUG((DEBUG_ERROR, "Pp2Dxe: buffer too small\n")); + ReturnUnlock(SavedTpl, EFI_BUFFER_TOO_SMALL); + } + + CopyMem (Buffer, (VOID*) (PhysAddr + 2), PktLength); + *BufferSize = PktLength; + + if (HeaderSize != NULL) { + *HeaderSize = Pp2Context->Snp.Mode->MediaHeaderSize; + } + + DataPtr = (UINT8 *)Buffer; + + + /* extract the destination address */ + if (DstAddr != NULL) { + ZeroMem (DstAddr, sizeof(EFI_MAC_ADDRESS)); + CopyMem (DstAddr, &DataPtr[0], NET_ETHER_ADDR_LEN); + } + + /* get the source address */ + if (SrcAddr != NULL) { + ZeroMem (SrcAddr, sizeof(EFI_MAC_ADDRESS)); + CopyMem (SrcAddr, &DataPtr[6], NET_ETHER_ADDR_LEN); + } + + /* get the protocol */ + if (Protocol != NULL) { + *Protocol = NTOHS (*(UINT16*)(&DataPtr[12])); + } + +drop: + /* refill: pass packet back to BM */ + PoolId = (StatusReg & MVPP2_RXD_BM_POOL_ID_MASK) >> + MVPP2_RXD_BM_POOL_ID_OFFS; + Mvpp2BmPoolPut(Mvpp2Shared, PoolId, PhysAddr, VirtAddr); + + /* iowmb */ + __asm__ __volatile__ ("" : : : "memory"); + + ASSERT (Port != NULL); + ASSERT (Rxq != NULL); + Mvpp2RxqStatusUpdate(Port, Rxq->Id, 1, 1); + ReturnUnlock(SavedTpl, Status); +} + +STATIC +VOID +Pp2DxeConfigureMacAddress ( + IN PP2DXE_CONTEXT *Pp2Context, + IN PP2_DEVICE_PATH *Pp2DevicePath + ) +{ + UINT8 *MacAddressPtr; + INTN Index; + + switch (Pp2Context->Instance) { + case 0: + MacAddressPtr = PcdGetPtr (PcdPp2MacAddressPort0); + break; + case 1: + MacAddressPtr = PcdGetPtr (PcdPp2MacAddressPort1); + break; + case 2: + MacAddressPtr = PcdGetPtr (PcdPp2MacAddressPort2); + break; + default: + Pp2DevicePath->Pp2Mac.MacAddress.Addr[5] = Pp2Context->Instance + 1; + return; + } + + for (Index = 0; Index < NET_ETHER_ADDR_LEN; Index++) + Pp2DevicePath->Pp2Mac.MacAddress.Addr[Index] = MacAddressPtr[Index]; +} + +EFI_STATUS +Pp2DxeSnpInstall ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + PP2_DEVICE_PATH *Pp2DevicePath; + + DEBUG((DEBUG_INFO, "Pp2Dxe%d: Installing protocols\n", Pp2Context->Instance)); + Pp2Context->Snp.Mode = AllocateZeroPool (sizeof (EFI_SIMPLE_NETWORK_MODE)); + Pp2DevicePath = AllocateCopyPool (sizeof (PP2_DEVICE_PATH), &Pp2DevicePathTemplate); + Pp2DxeConfigureMacAddress(Pp2Context, Pp2DevicePath); + Pp2Context->Signature = PP2DXE_SIGNATURE; + Pp2Context->Snp.Initialize = Pp2DxeSnpInitialize; + Pp2Context->Snp.Start = Pp2SnpStart; + Pp2Context->Snp.Stop = Pp2SnpStop; + Pp2Context->Snp.Reset = Pp2SnpReset; + Pp2Context->Snp.Shutdown = Pp2SnpShutdown; + Pp2Context->Snp.ReceiveFilters = Pp2SnpReceiveFilters; + Pp2Context->Snp.StationAddress = Pp2SnpStationAddress; + Pp2Context->Snp.Statistics = Pp2SnpNetStat; + Pp2Context->Snp.MCastIpToMac = Pp2SnpIpToMac; + Pp2Context->Snp.NvData = Pp2SnpNvData; + Pp2Context->Snp.GetStatus = Pp2SnpGetStatus; + Pp2Context->Snp.Transmit = Pp2SnpTransmit; + Pp2Context->Snp.Receive = Pp2SnpReceive; + Pp2Context->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + + Pp2Context->Snp.Mode->MacAddressChangeable = TRUE; + Pp2Context->Snp.Mode->CurrentAddress = Pp2DevicePath->Pp2Mac.MacAddress; + Pp2Context->Snp.Mode->PermanentAddress = Pp2DevicePath->Pp2Mac.MacAddress; + Pp2Context->Snp.Mode->State = EfiSimpleNetworkStopped; + Pp2Context->Snp.Mode->IfType = NET_IFTYPE_ETHERNET; + Pp2Context->Snp.Mode->HwAddressSize = NET_ETHER_ADDR_LEN; + Pp2Context->Snp.Mode->MediaHeaderSize = sizeof (ETHER_HEAD); + Pp2Context->Snp.Mode->MaxPacketSize = EFI_PAGE_SIZE; + Pp2Context->Snp.Mode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + Pp2Context->Snp.Mode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + Pp2Context->Snp.Mode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT; + Pp2Context->Snp.Mode->MCastFilterCount = 0; + Pp2Context->Snp.Mode->MediaPresentSupported = TRUE; + Pp2Context->Snp.Mode->MediaPresent = FALSE; + ZeroMem (&Pp2Context->Snp.Mode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS)); + SetMem (&Pp2Context->Snp.Mode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF); + + Pp2DevicePath->Pp2Mac.IfType = Pp2Context->Snp.Mode->IfType; + Pp2Context->DevicePath = Pp2DevicePath; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiSimpleNetworkProtocolGuid, &Pp2Context->Snp, + &gEfiDevicePathProtocolGuid, Pp2DevicePath, + NULL + ); + + if (EFI_ERROR(Status)) + DEBUG((DEBUG_ERROR, "Failed to install protocols.\n")); + + return Status; +} + +STATIC +VOID +Pp2DxeParsePortPcd ( + IN PP2DXE_CONTEXT *Pp2Context + ) +{ + UINT8 *PortIds, *GopIndexes, *PhyConnectionTypes, *AlwaysUp, *Speed; + + PortIds = PcdGetPtr (PcdPp2PortIds); + GopIndexes = PcdGetPtr (PcdPp2GopIndexes); + PhyConnectionTypes = PcdGetPtr (PcdPhyConnectionTypes); + AlwaysUp = PcdGetPtr (PcdPp2InterfaceAlwaysUp); + Speed = PcdGetPtr (PcdPp2InterfaceSpeed); + + ASSERT (PcdGetSize (PcdPp2GopIndexes) == PcdGetSize (PcdPp2PortIds)); + ASSERT (PcdGetSize (PcdPhyConnectionTypes) == PcdGetSize (PcdPp2PortIds)); + ASSERT (PcdGetSize (PcdPp2InterfaceAlwaysUp) == PcdGetSize (PcdPp2PortIds)); + ASSERT (PcdGetSize (PcdPp2InterfaceSpeed) == PcdGetSize (PcdPp2PortIds)); + + Pp2Context->Port.Id = PortIds[Pp2Context->Instance]; + Pp2Context->Port.GopIndex = GopIndexes[Pp2Context->Instance]; + Pp2Context->Port.PhyInterface = PhyConnectionTypes[Pp2Context->Instance]; + Pp2Context->Port.AlwaysUp = AlwaysUp[Pp2Context->Instance]; + Pp2Context->Port.Speed = Speed[Pp2Context->Instance]; + Pp2Context->Port.GmacBase = PcdGet64 (PcdPp2GmacBaseAddress) + + PcdGet32 (PcdPp2GmacObjSize) * Pp2Context->Port.GopIndex; + Pp2Context->Port.XlgBase = PcdGet64 (PcdPp2XlgBaseAddress) + + PcdGet32 (PcdPp2XlgObjSize) * Pp2Context->Port.GopIndex; +} + +EFI_STATUS +EFIAPI +Pp2DxeInitialise ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + PP2DXE_CONTEXT *Pp2Context = NULL; + EFI_STATUS Status; + INTN Index; + VOID *BufferSpace; + UINT32 NetCompConfig = 0; + + Mvpp2Shared = AllocateZeroPool (sizeof (MVPP2_SHARED)); + if (Mvpp2Shared == NULL) { + DEBUG((DEBUG_ERROR, "Allocation fail.\n")); + return EFI_OUT_OF_RESOURCES; + } + + Mvpp2Shared->base = PcdGet64 (PcdPp2SharedAddress); + Mvpp2Shared->Rfu1Base = PcdGet64 (PcdPp2Rfu1BaseAddress); + Mvpp2Shared->SmiBase = PcdGet64 (PcdPp2SmiBaseAddress); + Mvpp2Shared->Tclk = PcdGet32 (PcdPp2ClockFrequency); + DEBUG((DEBUG_INFO, "Pp2Dxe: shared base is 0x%lx\n", Mvpp2Shared->base)); + DEBUG((DEBUG_INFO, "Pp2Dxe: RFU1 base is 0x%lx\n", Mvpp2Shared->Rfu1Base)); + DEBUG((DEBUG_INFO, "Pp2Dxe: SMI base is 0x%lx\n", Mvpp2Shared->SmiBase)); + + BufferSpace = UncachedAllocateAlignedPool (BD_SPACE, MVPP2_BUFFER_ALIGN_SIZE); + if (BufferSpace == NULL) { + DEBUG((DEBUG_ERROR, "Failed to allocate buffer space\n")); + return EFI_OUT_OF_RESOURCES; + } + SetMem (BufferSpace, BD_SPACE, 0x0); + + BufferLocation.TxDescs = (MVPP2_TX_DESC *)BufferSpace; + + BufferLocation.AggrTxDescs = (MVPP2_TX_DESC *) + ((UINT64)BufferSpace + MVPP2_MAX_TXD + * sizeof(MVPP2_TX_DESC)); + + BufferLocation.RxDescs = (MVPP2_RX_DESC *) + ((UINT64)BufferSpace + + (MVPP2_MAX_TXD + MVPP2_AGGR_TXQ_SIZE) + * sizeof(MVPP2_TX_DESC)); + + BufferLocation.RxBuffers = (UINT64) + (BufferSpace + (MVPP2_MAX_TXD + MVPP2_AGGR_TXQ_SIZE) + * sizeof(MVPP2_TX_DESC) + + MVPP2_MAX_RXD * sizeof(MVPP2_RX_DESC)); + + Mvpp2AxiConfig(Mvpp2Shared); + Pp2DxeBmPoolInit(); + Mvpp2RxFifoInit(Mvpp2Shared); + + Mvpp2Shared->PrsShadow = AllocateZeroPool (sizeof(MVPP2_PRS_SHADOW) + * MVPP2_PRS_TCAM_SRAM_SIZE); + if (Mvpp2Shared->PrsShadow == NULL) { + DEBUG((DEBUG_ERROR, "Failed to allocate PrsShadow\n")); + return EFI_OUT_OF_RESOURCES; + } + + if (Mvpp2PrsDefaultInit(Mvpp2Shared)) { + DEBUG((DEBUG_ERROR, "Failed to intialize prs\n")); + return EFI_DEVICE_ERROR; + } + + Mvpp2ClsInit(Mvpp2Shared); + + Status = Pp2DxeBmStart(); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Pp2Dxe: bm start error\n")); + return Status; + } + + Mvpp2Shared->AggrTxqs = AllocateZeroPool (sizeof(MVPP2_TX_QUEUE)); + if (Mvpp2Shared->AggrTxqs == NULL) { + DEBUG((DEBUG_ERROR, "Failed to allocate aggregated Txqs\n")); + return EFI_OUT_OF_RESOURCES; + } + + Mvpp2Shared->AggrTxqs->Descs = BufferLocation.AggrTxDescs; + Mvpp2Shared->AggrTxqs->Id = 0; + Mvpp2Shared->AggrTxqs->LogId = 0; + Mvpp2Shared->AggrTxqs->Size = MVPP2_AGGR_TXQ_SIZE; + + if (PcdGet32 (PcdPp2PortNumber) == 0) { + DEBUG((DEBUG_ERROR, "Pp2Dxe: port number set to 0\n")); + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; Index < PcdGet32 (PcdPp2PortNumber); Index++) { + + Pp2Context = AllocateZeroPool (sizeof (PP2DXE_CONTEXT)); + if (Pp2Context == NULL) { + /* + * If allocation fails, all resources allocated before will get freed + * at ExitBootServices, as only EfiBootServicesData is used. + */ + DEBUG((DEBUG_ERROR, "Allocation fail.\n")); + return EFI_OUT_OF_RESOURCES; + } + + /* Instances are enumerated from 0 */ + Pp2Context->Instance = Index; + + /* Install SNP protocol */ + Status = Pp2DxeSnpInstall(Pp2Context); + + if (EFI_ERROR(Status)) + return Status; + + Pp2DxeParsePortPcd(Pp2Context); + Pp2Context->Port.TxpNum = 1; + Pp2Context->Port.Priv = Mvpp2Shared; + Pp2Context->Port.FirstRxq = 4 * Pp2Context->Instance; + DEBUG((DEBUG_INFO, "Pp2Dxe%d: port%d - gmac at 0x%lx, xlg at 0x%lx\n", Pp2Context->Instance, Pp2Context->Port.Id, + Pp2Context->Port.GmacBase, Pp2Context->Port.XlgBase)); + + NetCompConfig |= MvpPp2xGop110NetcCfgCreate(&Pp2Context->Port); + + MvGop110PortInit(&Pp2Context->Port); + MvGop110FlCfg(&Pp2Context->Port); + + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_NOTIFY, + Pp2DxeHalt, + Pp2Context, + &Pp2Context->EfiExitBootServicesEvent); + + if (EFI_ERROR(Status)) + return Status; + } + + MvGop110NetcInit(&Pp2Context->Port, NetCompConfig, + MV_NETC_FIRST_PHASE); + MvGop110NetcInit(&Pp2Context->Port, NetCompConfig, + MV_NETC_SECOND_PHASE); + + return EFI_SUCCESS; +} diff --git a/Drivers/Net/Pp2Dxe/Pp2Dxe.h b/Drivers/Net/Pp2Dxe/Pp2Dxe.h new file mode 100644 index 0000000..c73421e --- /dev/null +++ b/Drivers/Net/Pp2Dxe/Pp2Dxe.h @@ -0,0 +1,455 @@ +/******************************************************************************** +Copyright (C) 2016 Marvell International Ltd. + +Marvell BSD License Option + +If you received this File from Marvell, you may opt to use, redistribute and/or +modify this File under the following licensing terms. +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Marvell nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef __PP2_DXE_H__ +#define __PP2_DXE_H__ + +#include <Protocol/Cpu.h> +#include <Protocol/DriverBinding.h> +#include <Protocol/SimpleNetwork.h> +#include <Protocol/DevicePath.h> +#include <Protocol/MvPhy.h> +#include <Protocol/Ip4.h> +#include <Protocol/Ip6.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UncachedMemoryAllocationLib.h> +#include <Library/IoLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/NetLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include "Mvpp2LibHw.h" + +#define PP2DXE_SIGNATURE SIGNATURE_32('P', 'P', '2', 'D') +#define INSTANCE_FROM_SNP(a) CR((a), PP2DXE_CONTEXT, Snp, PP2DXE_SIGNATURE) + +/* RX buffer constants */ +#define MVPP2_RX_PKT_SIZE(mtu) \ + ALIGN((mtu) + MVPP2_MH_SIZE + MVPP2_VLAN_TAG_LEN + \ + ETH_HLEN + ETH_FCS_LEN, MVPP2_CPU_D_CACHE_LINE_SIZE) + +#define MVPP2_RX_BUF_SIZE(PktSize) ((PktSize)) +#define MVPP2_RX_TOTAL_SIZE(BufSize) ((BufSize)) +#define MVPP2_RX_MAX_PKT_SIZE(TotalSize) ((TotalSize)) +#define MVPP2_RXQ_OFFSET 0 + +#define IS_NOT_ALIGN(number, align) ((number) & ((align) - 1)) +/* Macro for alignment up. For example, ALIGN_UP(0x0330, 0x20) = 0x0340 */ +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) +#define ALIGN_UP(number, align) (((number) & ((align) - 1)) ? \ + (((number) + (align)) & ~((align)-1)) : (number)) + +/* OS API */ +#define Mvpp2Alloc(v) AllocateZeroPool(v) +#define Mvpp2Free(p) FreePool(p) +#define Mvpp2Memset(a, v, s) SetMem((a), (s), (v)) +#define Mvpp2Mdelay(t) gBS->Stall((t) * 1000) +#define Mvpp2Prefetch(v) do {} while(0); +#define Mvpp2Fls(v) 1 +#define Mvpp2IsBroadcastEtherAddr(da) 1 +#define Mvpp2IsMulticastEtherAddr(da) 1 +#define Mvpp2Printf(...) do {} while(0); +#define Mvpp2Swap(a,b) \ + do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) +#define Mvpp2Swab16(x) \ + ((UINT16)((((UINT16)(x) & (UINT16)0x00ffU) << 8) | \ + (((UINT16)(x) & (UINT16)0xff00U) >> 8) )) +#define Mvpp2Iphdr EFI_IP4_HEADER +#define Mvpp2Ipv6hdr EFI_IP6_HEADER +#define MVPP2_ALIGN(x, m) ALIGN((x), (m)) +#define MVPP2_ALIGN_UP(number, align) ALIGN_UP((number), (align)) +#define MVPP2_NULL NULL +#define MVPP2_ENOMEM -1 +#define MVPP2_EINVAL -2 +#define MVPP2_ERANGE -3 +#define MVPP2_USEC_PER_SEC 1000000L + +#define DmaAddrT UINT64 +#define PhysAddrT UINT64 + +#define Upper32Bits(n) ((UINT32)(((n) >> 16) >> 16)) +#define Lower32Bits(n) ((UINT32)(n)) + +#define __iomem + +#define ARCH_DMA_MINALIGN 64 + +/* Port speeds */ +#define MV_PORT_SPEED_10 SPEED_10 +#define MV_PORT_SPEED_100 SPEED_100 +#define MV_PORT_SPEED_1000 SPEED_1000 +#define MV_PORT_SPEED_2500 SPEED_2500 +#define MV_PORT_SPEED_10000 SPEED_10000 + +/* L2 and L3 protocol macros */ +#define MV_IPPR_TCP 0 +#define MV_IPPR_UDP 1 +#define MV_IPPR_IPIP 2 +#define MV_IPPR_ICMPV6 3 +#define MV_IPPR_IGMP 4 +#define MV_ETH_P_IP 5 +#define MV_ETH_P_IPV6 6 +#define MV_ETH_P_PPP_SES 7 +#define MV_ETH_P_ARP 8 +#define MV_ETH_P_8021Q 9 +#define MV_ETH_P_8021AD 10 +#define MV_ETH_P_EDSA 11 +#define MV_PPP_IP 12 +#define MV_PPP_IPV6 13 +#define MV_ETH_ALEN NET_ETHER_ADDR_LEN + +/* PHY modes */ +#define MV_MODE_SGMII PHY_CONNECTION_SGMII +#define MV_MODE_RGMII PHY_CONNECTION_RGMII +#define MV_MODE_XAUI PHY_CONNECTION_XAUI +#define MV_MODE_RXAUI PHY_CONNECTION_RXAUI +#define MV_MODE_QSGMII 100 +#define PP2DXE_MAX_PHY 2 + +/* Gop */ +/* Sets the field located at the specified in data. */ +#define U32_SET_FIELD(data, mask, val) \ + ((data) = (((data) & ~(mask)) | (val))) +#define MV_RGMII_TX_FIFO_MIN_TH (0x41) +#define MV_SGMII_TX_FIFO_MIN_TH (0x5) +#define MV_SGMII2_5_TX_FIFO_MIN_TH (0xB) + +/* BM constants */ +#define MVPP2_BM_POOLS_NUM 8 +#define MVPP2_BM_LONG_BUF_NUM 1024 +#define MVPP2_BM_SHORT_BUF_NUM 2048 +#define MVPP2_BM_POOL_SIZE_MAX (16*1024 - MVPP2_BM_POOL_PTR_ALIGN/4) +#define MVPP2_BM_POOL_PTR_ALIGN 128 +#define MVPP2_BM_SWF_LONG_POOL(Port) ((Port > 2) ? 2 : Port) +#define MVPP2_BM_SWF_SHORT_POOL 3 +#define MVPP2_BM_POOL 0 +#define MVPP2_BM_SIZE 32 +/* BM short pool packet Size + * These value assure that for SWF the total number + * of bytes allocated for each buffer will be 512 + */ +#define MVPP2_BM_SHORT_PKT_SIZE MVPP2_RX_MAX_PKT_SIZE(512) + +/* Page table entries are set to 1MB, or multiples of 1MB + * (not < 1MB). driver uses less bd's so use 1MB bdspace. + */ +#define BD_SPACE (1 << 20) + +/* buffer has to be aligned to 1M */ +#define MVPP2_BUFFER_ALIGN_SIZE (1 << 20) + +/* RX constants */ +#define BUFF_HDR_OFFS 32 +#define BM_ALIGN 32 +#define ETH_HLEN 14 +#define ETH_ALEN NET_ETHER_ADDR_LEN + +/* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */ +#define WRAP (2 + ETH_HLEN + 4 + 32) +#define MTU 1500 +#define RX_BUFFER_SIZE (ALIGN(MTU + WRAP, ARCH_DMA_MINALIGN)) + +#define MVPP2_TX_SEND_TIMEOUT 10000 + +/* Structures */ +typedef struct { + /* Physical number of this Tx queue */ + UINT8 Id; + + /* Logical number of this Tx queue */ + UINT8 LogId; + + /* Number of Tx DMA descriptors in the descriptor ring */ + INT32 Size; + + /* Number of currently used Tx DMA descriptor in the descriptor ring */ + INT32 count; + + UINT32 DonePktsCoal; + + /* Virtual address of thex Tx DMA descriptors array */ + MVPP2_TX_DESC *Descs; + + /* DMA address of the Tx DMA descriptors array */ + DmaAddrT DescsPhys; + + /* Index of the last Tx DMA descriptor */ + INT32 LastDesc; + + /* Index of the next Tx DMA descriptor to process */ + INT32 NextDescToProc; +} MVPP2_TX_QUEUE; + +typedef struct { + /* RX queue number, in the range 0-31 for physical RXQs */ + UINT8 Id; + + /* Num of rx descriptors in the rx descriptor ring */ + INT32 Size; + + UINT32 PktsCoal; + UINT32 TimeCoal; + + /* Virtual address of the RX DMA descriptors array */ + MVPP2_RX_DESC *Descs; + + /* DMA address of the RX DMA descriptors array */ + DmaAddrT DescsPhys; + + /* Index of the last RX DMA descriptor */ + INT32 LastDesc; + + /* Index of the next RX DMA descriptor to process */ + INT32 NextDescToProc; + + /* ID of Port to which physical RXQ is mapped */ + INT32 Port; + + /* Port's logic RXQ number to which physical RXQ is mapped */ + INT32 LogicRxq; +} MVPP2_RX_QUEUE; + +enum Mvpp2BmType { + MVPP2_BM_FREE, + MVPP2_BM_SWF_LONG, + MVPP2_BM_SWF_SHORT +}; + +typedef struct { + /* Pool number in the range 0-7 */ + INT32 Id; + enum Mvpp2BmType type; + + /* Buffer Pointers Pool External (BPPE) Size */ + INT32 Size; + /* Number of buffers for this pool */ + INT32 BufNum; + /* Pool buffer Size */ + INT32 BufSize; + /* Packet Size */ + INT32 PktSize; + + /* BPPE virtual base address */ + UINT32 *VirtAddr; + /* BPPE physical base address */ + DmaAddrT PhysAddr; + + /* Ports using BM pool */ + UINT32 PortMap; +} MVPP2_BMS_POOL; + +typedef struct Pp2DxePort PP2DXE_PORT; + +/* Shared Packet Processor resources */ +typedef struct { + /* Shared registers' base addresses */ + UINT64 __iomem base; + UINT64 __iomem Rfu1Base; + UINT64 __iomem SmiBase; + VOID __iomem *LmsBase; + + /* List of pointers to Port structures */ + PP2DXE_PORT **PortList; + + /* Aggregated TXQs */ + MVPP2_TX_QUEUE *AggrTxqs; + + /* BM pools */ + MVPP2_BMS_POOL *BmPools; + + /* PRS shadow table */ + MVPP2_PRS_SHADOW *PrsShadow; + /* PRS auxiliary table for double vlan entries control */ + BOOLEAN *PrsDoubleVlans; + + /* Tclk value */ + UINT32 Tclk; +} MVPP2_SHARED; + +/* Individual Port structure */ +struct Pp2DxePort { + UINT8 Id; + UINT8 GopIndex; + + INT32 Irq; + + MVPP2_SHARED *Priv; + + /* Per-Port registers' base address */ + UINT64 GmacBase; + UINT64 XlgBase; + + MVPP2_RX_QUEUE *Rxqs; + MVPP2_TX_QUEUE *Txqs; + + INT32 PktSize; + + UINT32 PendingCauseRx; + + /* Flags */ + UINTN Flags; + + UINT16 TxRingSize; + UINT16 RxRingSize; + + INT32 PhyInterface; + BOOLEAN Link; + BOOLEAN Duplex; + BOOLEAN AlwaysUp; + PHY_SPEED Speed; + + MVPP2_BMS_POOL *PoolLong; + MVPP2_BMS_POOL *PoolShort; + + UINT8 TxpNum; + + /* Index of first Port's physical RXQ */ + UINT8 FirstRxq; +}; + +/* Structure for preallocation for buffer */ +typedef struct { + MVPP2_TX_DESC *TxDescs; + MVPP2_TX_DESC *AggrTxDescs; + MVPP2_RX_DESC *RxDescs; + DmaAddrT RxBuffers; +} BUFFER_LOCATION; + +typedef struct { + MAC_ADDR_DEVICE_PATH Pp2Mac; + EFI_DEVICE_PATH_PROTOCOL End; +} PP2_DEVICE_PATH; + +#define QUEUE_DEPTH 64 +typedef struct { + UINT32 Signature; + INTN Instance; + EFI_HANDLE Controller; + EFI_LOCK Lock; + EFI_SIMPLE_NETWORK_PROTOCOL Snp; + MARVELL_PHY_PROTOCOL *Phy; + PHY_DEVICE *PhyDev; + PP2DXE_PORT Port; + BOOLEAN Initialized; + BOOLEAN LateInitialized; + VOID *CompletionQueue[QUEUE_DEPTH]; + UINTN CompletionQueueHead; + UINTN CompletionQueueTail; + EFI_EVENT EfiExitBootServicesEvent; + PP2_DEVICE_PATH *DevicePath; +} PP2DXE_CONTEXT; + +STATIC inline VOID Mvpp2Write(MVPP2_SHARED *Priv, UINT32 Offset, + UINT32 data) +{ + ASSERT (Priv->base != 0); + MmioWrite32 (Priv->base + Offset, data); +} + +STATIC inline UINT32 Mvpp2Read(MVPP2_SHARED *Priv, UINT32 Offset) +{ + ASSERT (Priv->base != 0); + return MmioRead32 (Priv->base + Offset); +} + +STATIC inline UINT32 Mvpp2Rfu1Read(MVPP2_SHARED *Priv, UINT32 Offset) +{ + ASSERT (Priv->Rfu1Base != 0); + return MmioRead32 (Priv->Rfu1Base + Offset); +} + +STATIC inline UINT32 Mvpp2Rfu1Write(MVPP2_SHARED *Priv, UINT32 Offset, + UINT32 data) +{ + ASSERT (Priv->Rfu1Base != 0); + return MmioWrite32 (Priv->Rfu1Base + Offset, data); +} + +STATIC inline UINT32 Mvpp2SmiRead(MVPP2_SHARED *Priv, UINT32 Offset) +{ + ASSERT (Priv->SmiBase != 0); + return MmioRead32 (Priv->SmiBase + Offset); +} + +STATIC inline UINT32 Mvpp2SmiWrite(MVPP2_SHARED *Priv, UINT32 Offset, + UINT32 data) +{ + ASSERT (Priv->SmiBase != 0); + return MmioWrite32 (Priv->SmiBase + Offset, data); +} + +STATIC inline VOID Mvpp2GmacWrite(PP2DXE_PORT *Port, UINT32 Offset, + UINT32 data) +{ + ASSERT (Port->Priv->base != 0); + MmioWrite32 (Port->Priv->base + Offset, data); +} + +STATIC inline UINT32 Mvpp2GmacRead(PP2DXE_PORT *Port, UINT32 Offset) +{ + ASSERT (Port->Priv->base != 0); + return MmioRead32 (Port->Priv->base + Offset); +} + +STATIC inline VOID MvGop110GmacWrite(PP2DXE_PORT *Port, UINT32 Offset, + UINT32 data) +{ + ASSERT (Port->GmacBase != 0); + MmioWrite32 (Port->GmacBase + Offset, data); +} + +STATIC inline UINT32 MvGop110GmacRead(PP2DXE_PORT *Port, UINT32 Offset) +{ + ASSERT (Port->GmacBase != 0); + return MmioRead32 (Port->GmacBase + Offset); +} + +STATIC inline VOID Mvpp2XlgWrite(PP2DXE_PORT *Port, UINT32 Offset, + UINT32 data) +{ + ASSERT (Port->XlgBase != 0); + MmioWrite32 (Port->XlgBase + Offset, data); +} + +STATIC inline UINT32 Mvpp2XlgRead(PP2DXE_PORT *Port, UINT32 Offset) +{ + ASSERT (Port->XlgBase != 0); + return MmioRead32 (Port->XlgBase + Offset); +} +#endif diff --git a/Drivers/Net/Pp2Dxe/Pp2Dxe.inf b/Drivers/Net/Pp2Dxe/Pp2Dxe.inf new file mode 100644 index 0000000..0714b95 --- /dev/null +++ b/Drivers/Net/Pp2Dxe/Pp2Dxe.inf @@ -0,0 +1,94 @@ +# Copyright (C) 2016 Marvell International Ltd. +# +# Marvell BSD License Option +# +# If you received this File from Marvell, you may opt to use, redistribute and/or +# modify this File under the following licensing terms. +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Marvell nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MdioDxe + FILE_GUID = 5ffc3843-d8d4-40ba-ae07-38967138509c + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = Pp2DxeInitialise + +[Sources.common] + Pp2Dxe.c + Mvpp2Lib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPkg/ArmPkg.dec + OpenPlatformPkg/Platforms/Marvell/Marvell.dec + +[LibraryClasses] + IoLib + PcdLib + BaseLib + BaseMemoryLib + DebugLib + UefiLib + NetLib + UefiDriverEntryPoint + UefiBootServicesTableLib + MemoryAllocationLib + UncachedMemoryAllocationLib + CacheMaintenanceLib + +[Protocols] + gEfiSimpleNetworkProtocolGuid + gEfiDevicePathProtocolGuid + gEfiCpuArchProtocolGuid + gMarvellMdioProtocolGuid + gMarvellPhyProtocolGuid + +[Pcd] + gMarvellTokenSpaceGuid.PcdPhyConnectionTypes + gMarvellTokenSpaceGuid.PcdPp2PortNumber + gMarvellTokenSpaceGuid.PcdPhySmiAddresses + gMarvellTokenSpaceGuid.PcdPp2PortIds + gMarvellTokenSpaceGuid.PcdPp2GopIndexes + gMarvellTokenSpaceGuid.PcdPp2InterfaceAlwaysUp + gMarvellTokenSpaceGuid.PcdPp2InterfaceSpeed + gMarvellTokenSpaceGuid.PcdPp2SharedAddress + gMarvellTokenSpaceGuid.PcdPp2GmacObjSize + gMarvellTokenSpaceGuid.PcdPp2GmacBaseAddress + gMarvellTokenSpaceGuid.PcdPp2XlgObjSize + gMarvellTokenSpaceGuid.PcdPp2XlgBaseAddress + gMarvellTokenSpaceGuid.PcdPp2Rfu1BaseAddress + gMarvellTokenSpaceGuid.PcdPp2SmiBaseAddress + gMarvellTokenSpaceGuid.PcdPp2ClockFrequency + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort0 + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort1 + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort2 + +[Depex] + TRUE diff --git a/Platforms/Marvell/Marvell.dec b/Platforms/Marvell/Marvell.dec index 44bbdc1..6c53f50 100644 --- a/Platforms/Marvell/Marvell.dec +++ b/Platforms/Marvell/Marvell.dec @@ -193,6 +193,25 @@ gMarvellTokenSpaceGuid.PcdPhyDeviceIds|{ 0 }|VOID*|0x3000095 gMarvellTokenSpaceGuid.PcdPhyStartupAutoneg|FALSE|BOOLEAN|0x3000070
+#NET + gMarvellTokenSpaceGuid.PcdPhySmiAddresses|{ 0 }|VOID*|0x3000024 + gMarvellTokenSpaceGuid.PcdPp2SharedAddress|0|UINT64|0x40000026 + gMarvellTokenSpaceGuid.PcdPp2PortNumber|0|UINT32|0x40000013 + gMarvellTokenSpaceGuid.PcdPp2PortIds|{ 0 }|VOID*|0x3000025 + gMarvellTokenSpaceGuid.PcdPp2GopIndexes|{ 0 }|VOID*|0x3000041 + gMarvellTokenSpaceGuid.PcdPp2InterfaceAlwaysUp|{ 0 }|VOID*|0x3000075 + gMarvellTokenSpaceGuid.PcdPp2InterfaceSpeed|{ 0 }|VOID*|0x3000076 + gMarvellTokenSpaceGuid.PcdPp2GmacBaseAddress|0|UINT64|0x40000028 + gMarvellTokenSpaceGuid.PcdPp2GmacObjSize|0|UINT32|0x3000026 + gMarvellTokenSpaceGuid.PcdPp2XlgBaseAddress|0|UINT64|0x40000031 + gMarvellTokenSpaceGuid.PcdPp2XlgObjSize|0|UINT32|0x3000030 + gMarvellTokenSpaceGuid.PcdPp2Rfu1BaseAddress|0|UINT64|0x40000029 + gMarvellTokenSpaceGuid.PcdPp2SmiBaseAddress|0|UINT64|0x40000030 + gMarvellTokenSpaceGuid.PcdPp2ClockFrequency|0|UINT32|0x3000042 + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort0|{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 }|VOID*|0x40000033 + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort1|{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 }|VOID*|0x40000034 + gMarvellTokenSpaceGuid.PcdPp2MacAddressPort2|{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3 }|VOID*|0x40000035 + #ResetLib gMarvellTokenSpaceGuid.PcdResetRegAddress|0|UINT64|0x40000050 gMarvellTokenSpaceGuid.PcdResetRegMask|0|UINT32|0x4000051