Home | History | Annotate | Download | only in Pp2Dxe
      1 /********************************************************************************
      2 Copyright (C) 2016 Marvell International Ltd.
      3 
      4 Marvell BSD License Option
      5 
      6 If you received this File from Marvell, you may opt to use, redistribute and/or
      7 modify this File under the following licensing terms.
      8 Redistribution and use in source and binary forms, with or without modification,
      9 are permitted provided that the following conditions are met:
     10 
     11   * Redistributions of source code must retain the above copyright notice,
     12     this list of conditions and the following disclaimer.
     13 
     14   * Redistributions in binary form must reproduce the above copyright
     15     notice, this list of conditions and the following disclaimer in the
     16     documentation and/or other materials provided with the distribution.
     17 
     18   * Neither the name of Marvell nor the names of its contributors may be
     19     used to endorse or promote products derived from this software without
     20     specific prior written permission.
     21 
     22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     24 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     25 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
     26 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     29 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32 
     33 *******************************************************************************/
     34 
     35 #include <Protocol/DevicePath.h>
     36 #include <Protocol/DriverBinding.h>
     37 #include <Protocol/SimpleNetwork.h>
     38 
     39 #include <Library/BaseLib.h>
     40 #include <Library/BaseMemoryLib.h>
     41 #include <Library/CacheMaintenanceLib.h>
     42 #include <Library/DebugLib.h>
     43 #include <Library/IoLib.h>
     44 #include <Library/MemoryAllocationLib.h>
     45 #include <Library/NetLib.h>
     46 #include <Library/PcdLib.h>
     47 #include <Library/UefiBootServicesTableLib.h>
     48 #include <Library/UefiLib.h>
     49 
     50 #include "Mvpp2LibHw.h"
     51 #include "Mvpp2Lib.h"
     52 #include "Pp2Dxe.h"
     53 
     54 #define ReturnUnlock(tpl, status) do { gBS->RestoreTPL (tpl); return (status); } while(0)
     55 
     56 STATIC MVPP2_SHARED *Mvpp2Shared;
     57 STATIC BUFFER_LOCATION BufferLocation;
     58 STATIC PP2_DEVICE_PATH Pp2DevicePathTemplate = {
     59   {
     60     {
     61       MESSAGING_DEVICE_PATH,
     62       MSG_MAC_ADDR_DP,
     63       {
     64         (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)),
     65         (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8)
     66       }
     67     },
     68     { { 0 } },
     69     0
     70   },
     71   {
     72     END_DEVICE_PATH_TYPE,
     73     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     74     { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
     75   }
     76 };
     77 
     78 EFI_SIMPLE_NETWORK_PROTOCOL Pp2SnpTemplate = {
     79   EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,                 // Revision
     80   Pp2SnpStart,                                          // Start
     81   Pp2SnpStop,                                           // Stop
     82   Pp2DxeSnpInitialize,                                  // Initialize
     83   Pp2SnpReset,                                          // Reset
     84   Pp2SnpShutdown,                                       // Shutdown
     85   Pp2SnpReceiveFilters,                                 // ReceiveFilters
     86   Pp2SnpStationAddress,                                 // StationAddress
     87   Pp2SnpNetStat,                                        // Statistics
     88   Pp2SnpIpToMac,                                        // MCastIpToMac
     89   NULL,                                                 // NvData
     90   Pp2SnpGetStatus,                                      // GetStatus
     91   Pp2SnpTransmit,                                       // Transmit
     92   Pp2SnpReceive,                                        // Receive
     93   NULL,                                                 // WaitForPacket
     94   NULL                                                  // Mode
     95 };
     96 
     97 EFI_SIMPLE_NETWORK_MODE Pp2SnpModeTemplate = {
     98   EfiSimpleNetworkStopped,                              // State
     99   NET_ETHER_ADDR_LEN,                                   // HwAddressSize
    100   sizeof (ETHER_HEAD),                                  // MediaHeaderSize
    101   EFI_PAGE_SIZE,                                        // MaxPacketSize
    102   0,                                                    // NvRamSize
    103   0,                                                    // MvRamAccessSize
    104   EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
    105   EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
    106   EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
    107   EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
    108   EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST,     // ReceiveFilterMask
    109   EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
    110   EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
    111   EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST,                 // ReceiveFilterSetting
    112   MAX_MCAST_FILTER_CNT,                                 // MacMCastFilterCount
    113   0,                                                    // MCastFilterCount
    114   {
    115     { { 0 } }
    116   },                                                    // MCastFilter
    117   {
    118     { 0 }
    119   },                                                    // CurrentAddress
    120   {
    121     { 0 }
    122   },                                                    // BroadcastAddress
    123   {
    124     { 0 }
    125   },                                                    // Permanent Address
    126   NET_IFTYPE_ETHERNET,                                  // IfType
    127   TRUE,                                                 // MacAddressChangeable
    128   FALSE,                                                // MultipleTxSupported
    129   TRUE,                                                 // MediaPresentSupported
    130   FALSE                                                 // MediaPresent
    131 };
    132 
    133 #define QueueNext(off)  ((((off) + 1) >= QUEUE_DEPTH) ? 0 : ((off) + 1))
    134 
    135 STATIC
    136 EFI_STATUS
    137 QueueInsert (
    138   IN PP2DXE_CONTEXT *Pp2Context,
    139   IN VOID *Buffer
    140   )
    141 {
    142 
    143   if (QueueNext (Pp2Context->CompletionQueueTail) == Pp2Context->CompletionQueueHead) {
    144     return EFI_OUT_OF_RESOURCES;
    145   }
    146 
    147   Pp2Context->CompletionQueue[Pp2Context->CompletionQueueTail] = Buffer;
    148   Pp2Context->CompletionQueueTail = QueueNext (Pp2Context->CompletionQueueTail);
    149 
    150   return EFI_SUCCESS;
    151 }
    152 
    153 STATIC
    154 VOID *
    155 QueueRemove (
    156   IN PP2DXE_CONTEXT *Pp2Context
    157   )
    158 {
    159   VOID *Buffer;
    160 
    161   if (Pp2Context->CompletionQueueTail == Pp2Context->CompletionQueueHead) {
    162     return NULL;
    163   }
    164 
    165   Buffer = Pp2Context->CompletionQueue[Pp2Context->CompletionQueueHead];
    166   Pp2Context->CompletionQueue[Pp2Context->CompletionQueueHead] = NULL;
    167   Pp2Context->CompletionQueueHead = QueueNext (Pp2Context->CompletionQueueHead);
    168 
    169   return Buffer;
    170 }
    171 
    172 STATIC
    173 EFI_STATUS
    174 Pp2DxeBmPoolInit (
    175   VOID
    176   )
    177 {
    178   INTN Index;
    179   UINT8 *PoolAddr;
    180   UINT32 PoolSize = (sizeof(VOID *) * MVPP2_BM_SIZE) * 2 + MVPP2_BM_POOL_PTR_ALIGN;
    181 
    182   ASSERT(MVPP2_BM_POOL_PTR_ALIGN >= sizeof(UINTN));
    183 
    184   PoolSize = (sizeof(VOID *) * MVPP2_BM_SIZE) * 2 + MVPP2_BM_POOL_PTR_ALIGN;
    185 
    186   for (Index = 0; Index < MVPP2_BM_POOLS_NUM; Index++) {
    187     /* BmIrqClear */
    188     Mvpp2BmIrqClear(Mvpp2Shared, Index);
    189   }
    190 
    191   Mvpp2Shared->BmPools = AllocateZeroPool (sizeof(MVPP2_BMS_POOL));
    192 
    193   if (Mvpp2Shared->BmPools == NULL) {
    194     return EFI_OUT_OF_RESOURCES;
    195   }
    196 
    197   PoolAddr = UncachedAllocateAlignedZeroPool (PoolSize, MVPP2_BM_POOL_PTR_ALIGN);
    198   if (PoolAddr == NULL) {
    199     return EFI_OUT_OF_RESOURCES;
    200   }
    201 
    202   Mvpp2Shared->BmPools->Id = MVPP2_BM_POOL;
    203   Mvpp2Shared->BmPools->VirtAddr = (UINT32 *)PoolAddr;
    204   Mvpp2Shared->BmPools->PhysAddr = (UINTN)PoolAddr;
    205 
    206   Mvpp2BmPoolHwCreate(Mvpp2Shared, Mvpp2Shared->BmPools, MVPP2_BM_SIZE);
    207 
    208   return EFI_SUCCESS;
    209 }
    210 
    211 /* Enable and fill BM pool */
    212 STATIC
    213 EFI_STATUS
    214 Pp2DxeBmStart (
    215   VOID
    216   )
    217 {
    218   UINT8 *Buff, *BuffPhys;
    219   INTN Index;
    220 
    221   ASSERT(BM_ALIGN >= sizeof(UINTN));
    222 
    223   Mvpp2BmPoolCtrl(Mvpp2Shared, MVPP2_BM_POOL, MVPP2_START);
    224   Mvpp2BmPoolBufsizeSet(Mvpp2Shared, Mvpp2Shared->BmPools, RX_BUFFER_SIZE);
    225 
    226   /* Fill BM pool with Buffers */
    227   for (Index = 0; Index < MVPP2_BM_SIZE; Index++) {
    228     Buff = (UINT8 *)(BufferLocation.RxBuffers + (Index * RX_BUFFER_SIZE));
    229     if (Buff == NULL) {
    230       return EFI_OUT_OF_RESOURCES;
    231     }
    232 
    233     BuffPhys = ALIGN_POINTER(Buff, BM_ALIGN);
    234     Mvpp2BmPoolPut(Mvpp2Shared, MVPP2_BM_POOL, (UINTN)BuffPhys, (UINTN)BuffPhys);
    235   }
    236 
    237   return EFI_SUCCESS;
    238 }
    239 
    240 STATIC
    241 VOID
    242 Pp2DxeStartDev (
    243   IN PP2DXE_CONTEXT *Pp2Context
    244   )
    245 {
    246   PP2DXE_PORT *Port = &Pp2Context->Port;
    247 
    248   /* Config classifier decoding table */
    249   Mvpp2ClsPortConfig(Port);
    250   Mvpp2ClsOversizeRxqSet(Port);
    251   MvGop110PortEventsMask(Port);
    252   MvGop110PortEnable(Port);
    253 
    254   /* Enable transmit and receive */
    255   Mvpp2EgressEnable(Port);
    256   Mvpp2IngressEnable(Port);
    257 }
    258 
    259 STATIC
    260 EFI_STATUS
    261 Pp2DxeSetupRxqs (
    262   IN PP2DXE_CONTEXT *Pp2Context
    263   )
    264 {
    265   INTN Queue;
    266   EFI_STATUS Status;
    267   MVPP2_RX_QUEUE *Rxq;
    268 
    269   for (Queue = 0; Queue < RxqNumber; Queue++) {
    270     Rxq = &Pp2Context->Port.Rxqs[Queue];
    271     Rxq->DescsPhys = (DmaAddrT)Rxq->Descs;
    272     if (Rxq->Descs == NULL) {
    273       Status = EFI_OUT_OF_RESOURCES;
    274       goto ErrCleanup;
    275     }
    276 
    277     Mvpp2RxqHwInit(&Pp2Context->Port, Rxq);
    278   }
    279 
    280   return EFI_SUCCESS;
    281 
    282 ErrCleanup:
    283   Mvpp2CleanupRxqs(&Pp2Context->Port);
    284   return Status;
    285 }
    286 
    287 STATIC
    288 EFI_STATUS
    289 Pp2DxeSetupTxqs (
    290   IN PP2DXE_CONTEXT *Pp2Context
    291   )
    292 {
    293   INTN Queue;
    294   MVPP2_TX_QUEUE *Txq;
    295   EFI_STATUS Status;
    296 
    297   for (Queue = 0; Queue < TxqNumber; Queue++) {
    298     Txq = &Pp2Context->Port.Txqs[Queue];
    299     Txq->DescsPhys = (DmaAddrT)Txq->Descs;
    300     if (Txq->Descs == NULL) {
    301       Status = EFI_OUT_OF_RESOURCES;
    302       goto ErrCleanup;
    303     }
    304 
    305     Mvpp2TxqHwInit(&Pp2Context->Port, Txq);
    306   }
    307 
    308   return EFI_SUCCESS;
    309 
    310 ErrCleanup:
    311   Mvpp2CleanupTxqs(&Pp2Context->Port);
    312   return Status;
    313 }
    314 
    315 STATIC
    316 EFI_STATUS
    317 Pp2DxeSetupAggrTxqs (
    318   IN PP2DXE_CONTEXT *Pp2Context
    319   )
    320 {
    321   MVPP2_TX_QUEUE *AggrTxq;
    322 
    323   AggrTxq = Mvpp2Shared->AggrTxqs;
    324   AggrTxq->DescsPhys = (DmaAddrT)AggrTxq->Descs;
    325   if (AggrTxq->Descs == NULL) {
    326     return EFI_OUT_OF_RESOURCES;
    327   }
    328 
    329   Mvpp2AggrTxqHwInit(AggrTxq, AggrTxq->Size, 0, Mvpp2Shared);
    330 
    331   return EFI_SUCCESS;
    332 }
    333 
    334 STATIC
    335 EFI_STATUS
    336 Pp2DxeOpen (
    337   IN PP2DXE_CONTEXT *Pp2Context
    338   )
    339 {
    340   PP2DXE_PORT *Port = &Pp2Context->Port;
    341   UINT8 MacBcast[NET_ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
    342   UINT8 DevAddr[NET_ETHER_ADDR_LEN];
    343   INTN Ret;
    344   EFI_STATUS Status;
    345 
    346   CopyMem (DevAddr, Pp2Context->Snp.Mode->CurrentAddress.Addr, NET_ETHER_ADDR_LEN);
    347 
    348   Ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, MacBcast, TRUE);
    349   if (Ret != 0) {
    350     return EFI_DEVICE_ERROR;
    351   }
    352   Ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, DevAddr, TRUE);
    353   if (Ret != 0) {
    354     return EFI_DEVICE_ERROR;
    355   }
    356   Ret = Mvpp2PrsTagModeSet(Mvpp2Shared, Port->Id, MVPP2_TAG_TYPE_MH);
    357   if (Ret != 0) {
    358     return EFI_DEVICE_ERROR;
    359   }
    360   Ret = Mvpp2PrsDefFlow(Port);
    361   if (Ret != 0) {
    362     return EFI_DEVICE_ERROR;
    363   }
    364 
    365   Status = Pp2DxeSetupRxqs(Pp2Context);
    366   if (EFI_ERROR(Status)) {
    367     return Status;
    368   }
    369 
    370   Status = Pp2DxeSetupTxqs(Pp2Context);
    371   if (EFI_ERROR(Status)) {
    372     return Status;
    373   }
    374 
    375   Status = Pp2DxeSetupAggrTxqs(Pp2Context);
    376   if (EFI_ERROR(Status)) {
    377     return Status;
    378   }
    379 
    380   Pp2DxeStartDev(Pp2Context);
    381 
    382   return EFI_SUCCESS;
    383 }
    384 
    385 STATIC
    386 EFI_STATUS
    387 Pp2DxeLatePortInitialize (
    388   IN PP2DXE_CONTEXT *Pp2Context
    389   )
    390 {
    391   PP2DXE_PORT *Port = &Pp2Context->Port;
    392   INTN Queue;
    393 
    394   Port->TxRingSize = MVPP2_MAX_TXD;
    395   Port->RxRingSize = MVPP2_MAX_RXD;
    396 
    397   Mvpp2EgressDisable(Port);
    398   MvGop110PortEventsMask(Port);
    399   MvGop110PortDisable(Port);
    400 
    401   Port->Txqs = AllocateZeroPool (sizeof(MVPP2_TX_QUEUE) * TxqNumber);
    402   if (Port->Txqs == NULL) {
    403     DEBUG((DEBUG_ERROR, "Failed to allocate Txqs\n"));
    404     return EFI_OUT_OF_RESOURCES;
    405   }
    406 
    407   /* Use preallocated area */
    408   Port->Txqs[0].Descs = BufferLocation.TxDescs;
    409 
    410   for (Queue = 0; Queue < TxqNumber; Queue++) {
    411     MVPP2_TX_QUEUE *Txq = &Port->Txqs[Queue];
    412 
    413     Txq->Id = Mvpp2TxqPhys(Port->Id, Queue);
    414     Txq->LogId = Queue;
    415     Txq->Size = Port->TxRingSize;
    416   }
    417 
    418   Port->Rxqs = AllocateZeroPool (sizeof(MVPP2_RX_QUEUE) * RxqNumber);
    419   if (Port->Rxqs == NULL) {
    420     DEBUG((DEBUG_ERROR, "Failed to allocate Rxqs\n"));
    421     return EFI_OUT_OF_RESOURCES;
    422   }
    423 
    424   Port->Rxqs[0].Descs = BufferLocation.RxDescs;
    425 
    426   for (Queue = 0; Queue < TxqNumber; Queue++) {
    427     MVPP2_RX_QUEUE *Rxq = &Port->Rxqs[Queue];
    428 
    429     Rxq->Id = Queue + Port->FirstRxq;
    430     Rxq->Size = Port->RxRingSize;
    431   }
    432 
    433   Mvpp2IngressDisable(Port);
    434 
    435   Mvpp2DefaultsSet(Port);
    436 
    437   return Pp2DxeOpen(Pp2Context);
    438 }
    439 
    440 STATIC
    441 EFI_STATUS
    442 Pp2DxeLateInitialize (
    443   IN PP2DXE_CONTEXT *Pp2Context
    444   )
    445 {
    446   PP2DXE_PORT *Port = &Pp2Context->Port;
    447   EFI_STATUS Status;
    448 
    449   if (!Pp2Context->LateInitialized) {
    450     /* Full init on first call */
    451     Status = Pp2DxeLatePortInitialize(Pp2Context);
    452     if (EFI_ERROR(Status)) {
    453       DEBUG((DEBUG_ERROR, "Pp2Dxe: late initialization failed\n"));
    454       return Status;
    455     }
    456 
    457     /* Attach pool to Rxq */
    458     Mvpp2RxqLongPoolSet(Port, 0, MVPP2_BM_POOL);
    459     Mvpp2RxqShortPoolSet(Port, 0, MVPP2_BM_POOL);
    460 
    461     /*
    462      * Mark this port being fully initialized,
    463      * otherwise it will be inited again
    464      * during next networking transaction,
    465      * including memory allocatation for
    466      * TX/RX queue, PHY connect/configuration
    467      * and address decode configuration.
    468      */
    469     Pp2Context->LateInitialized = TRUE;
    470   } else {
    471     /* Upon all following calls, this is enough */
    472     MvGop110PortEventsMask(Port);
    473     MvGop110PortEnable(Port);
    474   }
    475   return 0;
    476 }
    477 
    478 EFI_STATUS
    479 Pp2DxePhyInitialize (
    480   PP2DXE_CONTEXT *Pp2Context
    481   )
    482 {
    483   EFI_STATUS Status;
    484   UINT8 *PhyAddresses;
    485 
    486   PhyAddresses = PcdGetPtr (PcdPhySmiAddresses);
    487   Status = gBS->LocateProtocol (
    488                &gMarvellPhyProtocolGuid,
    489                NULL,
    490                (VOID **) &Pp2Context->Phy
    491              );
    492 
    493   if (EFI_ERROR(Status)) {
    494     return Status;
    495   }
    496 
    497   if (PhyAddresses[Pp2Context->Instance] == 0xff) {
    498     /* PHY iniitalization not required */
    499     return EFI_SUCCESS;
    500   }
    501 
    502   Status = Pp2Context->Phy->Init(
    503                Pp2Context->Phy,
    504                PhyAddresses[Pp2Context->Instance],
    505                Pp2Context->Port.PhyInterface,
    506                &Pp2Context->PhyDev
    507              );
    508 
    509   if (EFI_ERROR(Status) && Status != EFI_TIMEOUT) {
    510     return Status;
    511   }
    512 
    513   Pp2Context->Phy->Status(Pp2Context->Phy, Pp2Context->PhyDev);
    514   Mvpp2SmiPhyAddrCfg(&Pp2Context->Port, Pp2Context->Port.GopIndex, Pp2Context->PhyDev->Addr);
    515 
    516   return EFI_SUCCESS;
    517 }
    518 
    519 EFI_STATUS
    520 EFIAPI
    521 Pp2DxeSnpInitialize (
    522   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    523   IN UINTN                       ExtraRxBufferSize  OPTIONAL,
    524   IN UINTN                       ExtraTxBufferSize  OPTIONAL
    525   )
    526 {
    527   EFI_STATUS Status;
    528   PP2DXE_CONTEXT *Pp2Context;
    529   Pp2Context = INSTANCE_FROM_SNP(This);
    530   UINT32 State = This->Mode->State;
    531   EFI_TPL SavedTpl;
    532 
    533   if (ExtraRxBufferSize != 0 || ExtraTxBufferSize != 0) {
    534     DEBUG((DEBUG_ERROR, "Pp2Dxe%d: non-zero buffer requests\n", Pp2Context->Instance));
    535     return EFI_UNSUPPORTED;
    536   }
    537 
    538   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    539 
    540   if (State != EfiSimpleNetworkStarted) {
    541     switch (State) {
    542     case EfiSimpleNetworkInitialized:
    543       DEBUG((DEBUG_WARN, "Pp2Dxe%d: already initialized\n", Pp2Context->Instance));
    544       ReturnUnlock (SavedTpl, EFI_SUCCESS);
    545     case EfiSimpleNetworkStopped:
    546       DEBUG((DEBUG_WARN, "Pp2Dxe%d: network stopped\n", Pp2Context->Instance));
    547       ReturnUnlock (SavedTpl, EFI_NOT_STARTED);
    548     default:
    549       DEBUG((DEBUG_ERROR, "Pp2Dxe%d: wrong state\n", Pp2Context->Instance));
    550       ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR);
    551     }
    552   }
    553 
    554   /* Successfully started, change state to Initialized */
    555   This->Mode->State = EfiSimpleNetworkInitialized;
    556 
    557   if (Pp2Context->Initialized) {
    558     ReturnUnlock(SavedTpl, EFI_SUCCESS);
    559   }
    560 
    561   Pp2Context->Initialized = TRUE;
    562 
    563   Status = Pp2DxePhyInitialize(Pp2Context);
    564   if (EFI_ERROR(Status)) {
    565     ReturnUnlock (SavedTpl, Status);
    566   }
    567 
    568   Status = Pp2DxeLateInitialize(Pp2Context);
    569   ReturnUnlock (SavedTpl, Status);
    570 }
    571 
    572 EFI_STATUS
    573 EFIAPI
    574 Pp2SnpStart (
    575   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
    576   )
    577 {
    578   PP2DXE_CONTEXT *Pp2Context;
    579   UINT32 State = This->Mode->State;
    580   EFI_TPL SavedTpl;
    581 
    582   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    583   Pp2Context = INSTANCE_FROM_SNP(This);
    584 
    585   if (State != EfiSimpleNetworkStopped) {
    586     switch (State) {
    587     case EfiSimpleNetworkStarted:
    588     case EfiSimpleNetworkInitialized:
    589       DEBUG((DEBUG_WARN, "Pp2Dxe%d: already initialized\n", Pp2Context->Instance));
    590       ReturnUnlock (SavedTpl, EFI_ALREADY_STARTED);
    591     default:
    592       DEBUG((DEBUG_ERROR, "Pp2Dxe%d: wrong state\n", Pp2Context->Instance));
    593       ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR);
    594     }
    595   }
    596 
    597   This->Mode->State = EfiSimpleNetworkStarted;
    598   ReturnUnlock (SavedTpl, EFI_SUCCESS);
    599 }
    600 
    601 EFI_STATUS
    602 EFIAPI
    603 Pp2SnpStop (
    604   IN EFI_SIMPLE_NETWORK_PROTOCOL  *This
    605   )
    606 {
    607   EFI_TPL SavedTpl;
    608   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    609   PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(This);
    610   UINT32 State = This->Mode->State;
    611 
    612   if (State != EfiSimpleNetworkStarted && State != EfiSimpleNetworkInitialized) {
    613     switch (State) {
    614     case EfiSimpleNetworkStopped:
    615       DEBUG((DEBUG_WARN, "Pp2Dxe%d: not started\n", Pp2Context->Instance));
    616       ReturnUnlock (SavedTpl, EFI_NOT_STARTED);
    617     default:
    618       DEBUG((DEBUG_ERROR, "Pp2Dxe%d: wrong state\n", Pp2Context->Instance));
    619       ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR);
    620     }
    621   }
    622 
    623   This->Mode->State = EfiSimpleNetworkStopped;
    624   ReturnUnlock (SavedTpl, EFI_SUCCESS);
    625 }
    626 
    627 EFI_STATUS
    628 EFIAPI
    629 Pp2SnpReset (
    630   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    631   IN BOOLEAN                     ExtendedVerification
    632   )
    633 {
    634   return EFI_SUCCESS;
    635 }
    636 
    637 VOID
    638 EFIAPI
    639 Pp2DxeHalt (
    640   IN EFI_EVENT Event,
    641   IN VOID *Context
    642   )
    643 {
    644   PP2DXE_CONTEXT *Pp2Context = Context;
    645   PP2DXE_PORT *Port = &Pp2Context->Port;
    646   STATIC BOOLEAN CommonPartHalted = FALSE;
    647 
    648   if (!CommonPartHalted) {
    649     Mvpp2BmStop(Mvpp2Shared, MVPP2_BM_POOL);
    650     CommonPartHalted = TRUE;
    651   }
    652 
    653   Mvpp2TxqDrainSet(Port, 0, TRUE);
    654   Mvpp2IngressDisable(Port);
    655   Mvpp2EgressDisable(Port);
    656 
    657   MvGop110PortEventsMask(Port);
    658   MvGop110PortDisable(Port);
    659 }
    660 
    661 EFI_STATUS
    662 EFIAPI
    663 Pp2SnpShutdown (
    664   IN EFI_SIMPLE_NETWORK_PROTOCOL *This
    665   )
    666 {
    667   EFI_TPL SavedTpl;
    668   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    669   PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(This);
    670   UINT32 State = This->Mode->State;
    671 
    672   if (State != EfiSimpleNetworkInitialized) {
    673     switch (State) {
    674     case EfiSimpleNetworkStopped:
    675       DEBUG((DEBUG_WARN, "Pp2Dxe%d: not started\n", Pp2Context->Instance));
    676       ReturnUnlock (SavedTpl, EFI_NOT_STARTED);
    677     case EfiSimpleNetworkStarted:
    678     /* Fall through */
    679     default:
    680       DEBUG((DEBUG_ERROR, "Pp2Dxe%d: wrong state\n", Pp2Context->Instance));
    681       ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR);
    682     }
    683   }
    684 
    685   ReturnUnlock (SavedTpl, EFI_SUCCESS);
    686 }
    687 
    688 EFI_STATUS
    689 EFIAPI
    690 Pp2SnpReceiveFilters (
    691   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    692   IN UINT32                      Enable,
    693   IN UINT32                      Disable,
    694   IN BOOLEAN                     ResetMCastFilter,
    695   IN UINTN                       MCastFilterCnt     OPTIONAL,
    696   IN EFI_MAC_ADDRESS             *MCastFilter OPTIONAL
    697   )
    698 {
    699   return EFI_SUCCESS;
    700 }
    701 
    702 EFI_STATUS
    703 EFIAPI
    704 Pp2SnpStationAddress (
    705   IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
    706   IN BOOLEAN Reset,
    707   IN EFI_MAC_ADDRESS *NewMac
    708 )
    709 {
    710   PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(Snp);
    711   PP2_DEVICE_PATH *Pp2DevicePath = Pp2Context->DevicePath;
    712   PP2DXE_PORT *Port = &Pp2Context->Port;
    713   UINT32 State = Snp->Mode->State;
    714   EFI_TPL SavedTpl;
    715   INTN Ret;
    716 
    717   /* Check Snp instance */
    718   ASSERT(Snp != NULL);
    719 
    720   /* Serialize access to data and registers */
    721   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    722 
    723   /* Check that driver was started and initialised */
    724   if (State != EfiSimpleNetworkInitialized) {
    725     switch (State) {
    726     case EfiSimpleNetworkStopped:
    727       DEBUG((DEBUG_WARN, "Pp2Dxe%d: not started\n", Pp2Context->Instance));
    728       ReturnUnlock (SavedTpl, EFI_NOT_STARTED);
    729     case EfiSimpleNetworkStarted:
    730     /* Fall through */
    731     default:
    732       DEBUG((DEBUG_ERROR, "Pp2Dxe%d: wrong state\n", Pp2Context->Instance));
    733       ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR);
    734     }
    735   }
    736 
    737   /* Invalidate old unicast address in parser */
    738   Ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, Snp->Mode->CurrentAddress.Addr, FALSE);
    739   if (Ret != 0) {
    740     DEBUG((DEBUG_ERROR, "Pp2SnpStationAddress - Fail\n"));
    741     return EFI_DEVICE_ERROR;
    742   }
    743 
    744   if (Reset) {
    745     CopyMem (Snp->Mode->CurrentAddress.Addr, Snp->Mode->PermanentAddress.Addr, NET_ETHER_ADDR_LEN);
    746     CopyMem (NewMac->Addr, Snp->Mode->PermanentAddress.Addr, NET_ETHER_ADDR_LEN);
    747     CopyMem (Pp2DevicePath->Pp2Mac.MacAddress.Addr, Snp->Mode->PermanentAddress.Addr, NET_ETHER_ADDR_LEN);
    748   } else {
    749     if (NewMac == NULL) {
    750       ReturnUnlock (SavedTpl, EFI_INVALID_PARAMETER);
    751     }
    752     CopyMem (Snp->Mode->CurrentAddress.Addr, NewMac->Addr, NET_ETHER_ADDR_LEN);
    753     CopyMem (Pp2DevicePath->Pp2Mac.MacAddress.Addr, NewMac->Addr, NET_ETHER_ADDR_LEN);
    754   }
    755 
    756   /* Update parser with new unicast address */
    757   Ret = Mvpp2PrsMacDaAccept(Mvpp2Shared, Port->Id, Snp->Mode->CurrentAddress.Addr, TRUE);
    758   if (Ret != 0) {
    759     DEBUG((DEBUG_ERROR, "Pp2SnpStationAddress - Fail\n"));
    760     return EFI_DEVICE_ERROR;
    761   }
    762 
    763   /* Restore TPL and return */
    764   gBS->RestoreTPL (SavedTpl);
    765 
    766   return EFI_SUCCESS;
    767 }
    768 
    769 EFI_STATUS
    770 EFIAPI
    771 Pp2SnpNetStat (
    772   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    773   IN BOOLEAN                     Reset,
    774   IN OUT UINTN                   *StatisticsSize   OPTIONAL,
    775   OUT EFI_NETWORK_STATISTICS     *StatisticsTable  OPTIONAL
    776   )
    777 {
    778   return EFI_UNSUPPORTED;
    779 }
    780 
    781 EFI_STATUS
    782 EFIAPI
    783 Pp2SnpIpToMac (
    784   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    785   IN BOOLEAN                     IPv6,
    786   IN EFI_IP_ADDRESS              *IP,
    787   OUT EFI_MAC_ADDRESS            *MAC
    788   )
    789 {
    790   return EFI_UNSUPPORTED;
    791 }
    792 
    793 EFI_STATUS
    794 EFIAPI
    795 Pp2SnpNvData (
    796   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    797   IN BOOLEAN                     ReadWrite,
    798   IN UINTN                       Offset,
    799   IN UINTN                       BufferSize,
    800   IN OUT VOID                    *Buffer
    801   )
    802 {
    803   return EFI_UNSUPPORTED;
    804 }
    805 
    806 EFI_STATUS
    807 EFIAPI
    808 Pp2SnpGetStatus (
    809   IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
    810   OUT UINT32                     *InterruptStatus OPTIONAL,
    811   OUT VOID                       **TxBuf OPTIONAL
    812   )
    813 {
    814   PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(Snp);
    815   PP2DXE_PORT *Port = &Pp2Context->Port;
    816   BOOLEAN LinkUp;
    817   EFI_TPL SavedTpl;
    818 
    819   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    820 
    821   if (!Pp2Context->Initialized)
    822     ReturnUnlock(SavedTpl, EFI_NOT_READY);
    823 
    824   LinkUp = Port->AlwaysUp ? TRUE : MvGop110PortIsLinkUp(Port);
    825 
    826   if (LinkUp != Snp->Mode->MediaPresent) {
    827     DEBUG((DEBUG_INFO, "Pp2Dxe%d: Link ", Pp2Context->Instance));
    828     DEBUG((DEBUG_INFO, LinkUp ? "up\n" : "down\n"));
    829   }
    830   Snp->Mode->MediaPresent = LinkUp;
    831 
    832   if (TxBuf != NULL) {
    833     *TxBuf = QueueRemove (Pp2Context);
    834   }
    835 
    836   ReturnUnlock(SavedTpl, EFI_SUCCESS);
    837 }
    838 
    839 EFI_STATUS
    840 EFIAPI
    841 Pp2SnpTransmit (
    842   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    843   IN UINTN                       HeaderSize,
    844   IN UINTN                       BufferSize,
    845   IN VOID                        *Buffer,
    846   IN EFI_MAC_ADDRESS             *SrcAddr  OPTIONAL,
    847   IN EFI_MAC_ADDRESS             *DestAddr OPTIONAL,
    848   IN UINT16                      *EtherTypePtr OPTIONAL
    849   )
    850 {
    851   PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(This);
    852   PP2DXE_PORT *Port = &Pp2Context->Port;
    853   MVPP2_TX_QUEUE *AggrTxq = Mvpp2Shared->AggrTxqs;
    854   MVPP2_TX_DESC *TxDesc;
    855   EFI_STATUS Status;
    856   INTN PollingCount;
    857   INTN TxSent;
    858   UINT8 *DataPtr = Buffer;
    859   UINT16 EtherType;
    860   UINT32 State = This->Mode->State;
    861   EFI_TPL SavedTpl;
    862 
    863   if (This == NULL || Buffer == NULL) {
    864     DEBUG((DEBUG_ERROR, "Pp2Dxe: NULL Snp or Buffer\n"));
    865     return EFI_INVALID_PARAMETER;
    866   }
    867 
    868   if (HeaderSize != 0) {
    869     ASSERT (HeaderSize == This->Mode->MediaHeaderSize);
    870     ASSERT (EtherTypePtr != NULL);
    871     ASSERT (DestAddr != NULL);
    872   }
    873 
    874   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    875 
    876   /* Check that driver was started and initialised */
    877   if (State != EfiSimpleNetworkInitialized) {
    878     switch (State) {
    879     case EfiSimpleNetworkStopped:
    880       DEBUG((DEBUG_WARN, "Pp2Dxe%d: not started\n", Pp2Context->Instance));
    881       ReturnUnlock (SavedTpl, EFI_NOT_STARTED);
    882     case EfiSimpleNetworkStarted:
    883     /* Fall through */
    884     default:
    885       DEBUG((DEBUG_ERROR, "Pp2Dxe%d: wrong state\n", Pp2Context->Instance));
    886       ReturnUnlock (SavedTpl, EFI_DEVICE_ERROR);
    887     }
    888   }
    889 
    890   if (!This->Mode->MediaPresent) {
    891     DEBUG((DEBUG_ERROR, "Pp2Dxe: link not ready\n"));
    892     ReturnUnlock(SavedTpl, EFI_NOT_READY);
    893   }
    894 
    895   EtherType = HTONS (*EtherTypePtr);
    896 
    897   /* Fetch next descriptor */
    898   TxDesc = Mvpp2TxqNextDescGet(AggrTxq);
    899 
    900   if (!TxDesc) {
    901     DEBUG((DEBUG_ERROR, "No tx descriptor to use\n"));
    902     ReturnUnlock(SavedTpl, EFI_OUT_OF_RESOURCES);
    903   }
    904 
    905   if (HeaderSize != 0) {
    906     CopyMem(DataPtr, DestAddr, NET_ETHER_ADDR_LEN);
    907 
    908     if (SrcAddr != NULL)
    909       CopyMem(DataPtr + NET_ETHER_ADDR_LEN, SrcAddr, NET_ETHER_ADDR_LEN);
    910     else
    911       CopyMem(DataPtr + NET_ETHER_ADDR_LEN, &This->Mode->CurrentAddress, NET_ETHER_ADDR_LEN);
    912 
    913     CopyMem(DataPtr + NET_ETHER_ADDR_LEN * 2, &EtherType, 2);
    914   }
    915 
    916   /* Set descriptor fields */
    917   TxDesc->command =  MVPP2_TXD_IP_CSUM_DISABLE | MVPP2_TXD_L4_CSUM_NOT |
    918                      MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC;
    919   TxDesc->DataSize = BufferSize;
    920   TxDesc->PacketOffset = (PhysAddrT)DataPtr & MVPP2_TX_DESC_ALIGN;
    921   Mvpp2x2TxdescPhysAddrSet((PhysAddrT)DataPtr & ~MVPP2_TX_DESC_ALIGN, TxDesc);
    922   TxDesc->PhysTxq = Mvpp2TxqPhys(Port->Id, 0);
    923 
    924   InvalidateDataCacheRange (DataPtr, BufferSize);
    925 
    926   /* Issue send */
    927   Mvpp2AggrTxqPendDescAdd(Port, 1);
    928 
    929   /*
    930    * Egress processing:
    931    * Wait until packet is passed from per-cpu aggregated queue
    932    * to physical per-port TXQ.
    933    */
    934   PollingCount = 0;
    935   TxSent = Mvpp2AggrTxqPendDescNumGet(Mvpp2Shared, 0);
    936   do {
    937     if (PollingCount++ > MVPP2_TX_SEND_MAX_POLLING_COUNT) {
    938       DEBUG((DEBUG_ERROR, "Pp2Dxe: transmit polling failed\n"));
    939       ReturnUnlock(SavedTpl, EFI_TIMEOUT);
    940     }
    941     TxSent = Mvpp2AggrTxqPendDescNumGet(Mvpp2Shared, 0);
    942   } while (TxSent);
    943 
    944   /* Wait for packet to be transmitted by hardware. */
    945   PollingCount = 0;
    946   TxSent = Mvpp2TxqSentDescProc(Port, &Port->Txqs[0]);
    947   while (!TxSent) {
    948     if (PollingCount++ > MVPP2_TX_SEND_MAX_POLLING_COUNT) {
    949       DEBUG((DEBUG_ERROR, "Pp2Dxe: transmit polling failed\n"));
    950       ReturnUnlock(SavedTpl, EFI_TIMEOUT);
    951     }
    952     TxSent = Mvpp2TxqSentDescProc(Port, &Port->Txqs[0]);
    953   }
    954 
    955   /*
    956    * At this point TxSent has increased - HW sent the packet
    957    * Add buffer to completion queue and return.
    958    */
    959   Status = QueueInsert (Pp2Context, Buffer);
    960   ReturnUnlock (SavedTpl, Status);
    961 }
    962 
    963 EFI_STATUS
    964 EFIAPI
    965 Pp2SnpReceive (
    966   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
    967   OUT UINTN                      *HeaderSize OPTIONAL,
    968   IN OUT UINTN                   *BufferSize,
    969   OUT VOID                       *Buffer,
    970   OUT EFI_MAC_ADDRESS            *SrcAddr OPTIONAL,
    971   OUT EFI_MAC_ADDRESS            *DstAddr OPTIONAL,
    972   OUT UINT16                     *EtherType OPTIONAL
    973   )
    974 {
    975   INTN ReceivedPackets;
    976   PP2DXE_CONTEXT *Pp2Context = INSTANCE_FROM_SNP(This);
    977   PP2DXE_PORT *Port = &Pp2Context->Port;
    978   UINTN PhysAddr, VirtAddr;
    979   EFI_STATUS Status = EFI_SUCCESS;
    980   EFI_TPL SavedTpl;
    981   UINT32 StatusReg;
    982   INTN PoolId;
    983   UINTN PktLength;
    984   UINT8 *DataPtr;
    985   MVPP2_RX_DESC *RxDesc;
    986   MVPP2_RX_QUEUE *Rxq = &Port->Rxqs[0];
    987 
    988   ASSERT (Port != NULL);
    989   ASSERT (Rxq != NULL);
    990 
    991   SavedTpl = gBS->RaiseTPL (TPL_CALLBACK);
    992   ReceivedPackets = Mvpp2RxqReceived(Port, Rxq->Id);
    993 
    994   if (ReceivedPackets == 0) {
    995     ReturnUnlock(SavedTpl, EFI_NOT_READY);
    996   }
    997 
    998   /* Process one packet per call */
    999   RxDesc = Mvpp2RxqNextDescGet(Rxq);
   1000   StatusReg = RxDesc->status;
   1001 
   1002   /* extract addresses from descriptor */
   1003   PhysAddr = RxDesc->BufPhysAddrKeyHash & MVPP22_ADDR_MASK;
   1004   VirtAddr = RxDesc->BufCookieBmQsetClsInfo & MVPP22_ADDR_MASK;
   1005 
   1006   /* Drop packets with error or with buffer header (MC, SG) */
   1007   if ((StatusReg & MVPP2_RXD_BUF_HDR) || (StatusReg & MVPP2_RXD_ERR_SUMMARY)) {
   1008     DEBUG((DEBUG_WARN, "Pp2Dxe: dropping packet\n"));
   1009     Status = EFI_DEVICE_ERROR;
   1010     goto drop;
   1011   }
   1012 
   1013   PktLength = (UINTN) RxDesc->DataSize - 2;
   1014   if (PktLength > *BufferSize) {
   1015     *BufferSize = PktLength;
   1016     DEBUG((DEBUG_ERROR, "Pp2Dxe: buffer too small\n"));
   1017     ReturnUnlock(SavedTpl, EFI_BUFFER_TOO_SMALL);
   1018   }
   1019 
   1020   CopyMem (Buffer, (VOID*) (PhysAddr + 2), PktLength);
   1021   *BufferSize = PktLength;
   1022 
   1023   if (HeaderSize != NULL) {
   1024     *HeaderSize = Pp2Context->Snp.Mode->MediaHeaderSize;
   1025   }
   1026 
   1027   DataPtr = Buffer;
   1028 
   1029   /* Extract the destination address */
   1030   if (DstAddr != NULL) {
   1031     ZeroMem (DstAddr, sizeof(EFI_MAC_ADDRESS));
   1032     CopyMem (DstAddr, &DataPtr[0], NET_ETHER_ADDR_LEN);
   1033   }
   1034 
   1035   /* Get the source address */
   1036   if (SrcAddr != NULL) {
   1037     ZeroMem (SrcAddr, sizeof(EFI_MAC_ADDRESS));
   1038     CopyMem (SrcAddr, &DataPtr[6], NET_ETHER_ADDR_LEN);
   1039   }
   1040 
   1041   /* Obtain Ether Type */
   1042   if (EtherType != NULL) {
   1043     *EtherType = NTOHS (*(UINT16 *)(&DataPtr[12]));
   1044   }
   1045 
   1046 drop:
   1047   /* Refill: pass packet back to BM */
   1048   PoolId = (StatusReg & MVPP2_RXD_BM_POOL_ID_MASK) >> MVPP2_RXD_BM_POOL_ID_OFFS;
   1049   Mvpp2BmPoolPut(Mvpp2Shared, PoolId, PhysAddr, VirtAddr);
   1050 
   1051   /* Update counters with 1 packet received and 1 packet refilled */
   1052   Mvpp2RxqStatusUpdate(Port, Rxq->Id, 1, 1);
   1053 
   1054   ReturnUnlock(SavedTpl, Status);
   1055 }
   1056 
   1057 EFI_STATUS
   1058 Pp2DxeSnpInstall (
   1059   IN PP2DXE_CONTEXT *Pp2Context
   1060   )
   1061 {
   1062   EFI_HANDLE Handle = NULL;
   1063   EFI_STATUS Status;
   1064   PP2_DEVICE_PATH *Pp2DevicePath;
   1065   EFI_SIMPLE_NETWORK_MODE *SnpMode;
   1066 
   1067   Pp2DevicePath = AllocateCopyPool (sizeof (PP2_DEVICE_PATH), &Pp2DevicePathTemplate);
   1068   if (Pp2DevicePath == NULL) {
   1069     return EFI_OUT_OF_RESOURCES;
   1070   }
   1071 
   1072   SnpMode = AllocateZeroPool (sizeof (EFI_SIMPLE_NETWORK_MODE));
   1073   if (SnpMode == NULL) {
   1074     return EFI_OUT_OF_RESOURCES;
   1075   }
   1076 
   1077   /* Copy SNP data from templates */
   1078   CopyMem (&Pp2Context->Snp, &Pp2SnpTemplate, sizeof (EFI_SIMPLE_NETWORK_PROTOCOL));
   1079   CopyMem (SnpMode, &Pp2SnpModeTemplate, sizeof (EFI_SIMPLE_NETWORK_MODE));
   1080 
   1081   /* Handle device path of the controller */
   1082   Pp2DevicePath->Pp2Mac.MacAddress.Addr[5] = Pp2Context->Instance + 1;
   1083   Pp2Context->Signature = PP2DXE_SIGNATURE;
   1084   Pp2Context->DevicePath = Pp2DevicePath;
   1085   Pp2DevicePath->Pp2Mac.IfType = SnpMode->IfType;
   1086 
   1087   /* Update SNP Mode */
   1088   CopyMem (SnpMode->CurrentAddress.Addr, Pp2DevicePath->Pp2Mac.MacAddress.Addr, NET_ETHER_ADDR_LEN);
   1089   CopyMem (SnpMode->PermanentAddress.Addr, Pp2DevicePath->Pp2Mac.MacAddress.Addr, NET_ETHER_ADDR_LEN);
   1090   ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS));
   1091   SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);
   1092 
   1093   Pp2Context->Snp.Mode = SnpMode;
   1094 
   1095   /* Install protocol */
   1096   Status = gBS->InstallMultipleProtocolInterfaces (
   1097       &Handle,
   1098       &gEfiSimpleNetworkProtocolGuid, &Pp2Context->Snp,
   1099       &gEfiDevicePathProtocolGuid, Pp2DevicePath,
   1100       NULL
   1101       );
   1102 
   1103   if (EFI_ERROR(Status)) {
   1104     DEBUG((DEBUG_ERROR, "Failed to install protocols.\n"));
   1105   }
   1106 
   1107   return Status;
   1108 }
   1109 
   1110 STATIC
   1111 VOID
   1112 Pp2DxeParsePortPcd (
   1113   IN PP2DXE_CONTEXT *Pp2Context
   1114   )
   1115 {
   1116   UINT8 *PortIds, *GopIndexes, *PhyConnectionTypes, *AlwaysUp, *Speed;
   1117 
   1118   PortIds = PcdGetPtr (PcdPp2PortIds);
   1119   GopIndexes = PcdGetPtr (PcdPp2GopIndexes);
   1120   PhyConnectionTypes = PcdGetPtr (PcdPhyConnectionTypes);
   1121   AlwaysUp = PcdGetPtr (PcdPp2InterfaceAlwaysUp);
   1122   Speed = PcdGetPtr (PcdPp2InterfaceSpeed);
   1123 
   1124   ASSERT (PcdGetSize (PcdPp2GopIndexes) == PcdGetSize (PcdPp2PortIds));
   1125   ASSERT (PcdGetSize (PcdPhyConnectionTypes) == PcdGetSize (PcdPp2PortIds));
   1126   ASSERT (PcdGetSize (PcdPp2InterfaceAlwaysUp) == PcdGetSize (PcdPp2PortIds));
   1127   ASSERT (PcdGetSize (PcdPp2InterfaceSpeed) == PcdGetSize (PcdPp2PortIds));
   1128 
   1129   Pp2Context->Port.Id = PortIds[Pp2Context->Instance];
   1130   Pp2Context->Port.GopIndex = GopIndexes[Pp2Context->Instance];
   1131   Pp2Context->Port.PhyInterface = PhyConnectionTypes[Pp2Context->Instance];
   1132   Pp2Context->Port.AlwaysUp = AlwaysUp[Pp2Context->Instance];
   1133   Pp2Context->Port.Speed = Speed[Pp2Context->Instance];
   1134   Pp2Context->Port.GmacBase = PcdGet64 (PcdPp2GmacBaseAddress) +
   1135                               PcdGet32 (PcdPp2GmacDevSize) * Pp2Context->Port.GopIndex;
   1136   Pp2Context->Port.XlgBase = PcdGet64 (PcdPp2XlgBaseAddress) +
   1137                              PcdGet32 (PcdPp2XlgDevSize) * Pp2Context->Port.GopIndex;
   1138 }
   1139 
   1140 EFI_STATUS
   1141 EFIAPI
   1142 Pp2DxeInitialise (
   1143   IN EFI_HANDLE ImageHandle,
   1144   IN EFI_SYSTEM_TABLE *SystemTable
   1145   )
   1146 {
   1147   PP2DXE_CONTEXT *Pp2Context = NULL;
   1148   EFI_STATUS Status;
   1149   INTN Index;
   1150   VOID *BufferSpace;
   1151   UINT32 NetCompConfig = 0;
   1152   UINT8 NumPorts = PcdGet32 (PcdPp2NumPorts);
   1153 
   1154   if (NumPorts == 0) {
   1155     DEBUG((DEBUG_ERROR, "Pp2Dxe: port number set to 0\n"));
   1156     return EFI_INVALID_PARAMETER;
   1157   }
   1158 
   1159   /* Initialize private data */
   1160   Mvpp2Shared = AllocateZeroPool (sizeof (MVPP2_SHARED));
   1161   if (Mvpp2Shared == NULL) {
   1162     DEBUG((DEBUG_ERROR, "Allocation fail.\n"));
   1163     return EFI_OUT_OF_RESOURCES;
   1164   }
   1165 
   1166   Mvpp2Shared->Base = PcdGet64 (PcdPp2SharedAddress);
   1167   Mvpp2Shared->Rfu1Base = PcdGet64 (PcdPp2Rfu1BaseAddress);
   1168   Mvpp2Shared->SmiBase = PcdGet64 (PcdPp2SmiBaseAddress);
   1169   Mvpp2Shared->Tclk = PcdGet32 (PcdPp2ClockFrequency);
   1170 
   1171   /* Prepare buffers */
   1172   BufferSpace = UncachedAllocateAlignedZeroPool (BD_SPACE, MVPP2_BUFFER_ALIGN_SIZE);
   1173   if (BufferSpace == NULL) {
   1174     DEBUG((DEBUG_ERROR, "Failed to allocate buffer space\n"));
   1175     return EFI_OUT_OF_RESOURCES;
   1176   }
   1177 
   1178   BufferLocation.TxDescs = BufferSpace;
   1179   BufferLocation.AggrTxDescs = (MVPP2_TX_DESC *)((UINTN)BufferSpace + MVPP2_MAX_TXD * sizeof(MVPP2_TX_DESC));
   1180   BufferLocation.RxDescs = (MVPP2_RX_DESC *)((UINTN)BufferSpace +
   1181                                              (MVPP2_MAX_TXD + MVPP2_AGGR_TXQ_SIZE) * sizeof(MVPP2_TX_DESC));
   1182   BufferLocation.RxBuffers = (DmaAddrT)(BufferSpace +
   1183                                         (MVPP2_MAX_TXD + MVPP2_AGGR_TXQ_SIZE) * sizeof(MVPP2_TX_DESC) +
   1184                                         MVPP2_MAX_RXD * sizeof(MVPP2_RX_DESC));
   1185 
   1186   /* Initialize HW */
   1187   Mvpp2AxiConfig(Mvpp2Shared);
   1188   Pp2DxeBmPoolInit();
   1189   Mvpp2RxFifoInit(Mvpp2Shared);
   1190 
   1191   Mvpp2Shared->PrsShadow = AllocateZeroPool (sizeof(MVPP2_PRS_SHADOW) * MVPP2_PRS_TCAM_SRAM_SIZE);
   1192   if (Mvpp2Shared->PrsShadow == NULL) {
   1193     DEBUG((DEBUG_ERROR, "Failed to allocate PrsShadow\n"));
   1194     return EFI_OUT_OF_RESOURCES;
   1195   }
   1196 
   1197   Status = Mvpp2PrsDefaultInit(Mvpp2Shared);
   1198   if (EFI_ERROR(Status)) {
   1199     DEBUG((DEBUG_ERROR, "Failed to intialize prs\n"));
   1200     return EFI_DEVICE_ERROR;
   1201   }
   1202 
   1203   Mvpp2ClsInit(Mvpp2Shared);
   1204 
   1205   Status = Pp2DxeBmStart();
   1206   if (EFI_ERROR(Status)) {
   1207     DEBUG((DEBUG_ERROR, "Pp2Dxe: BM start error\n"));
   1208     return Status;
   1209   }
   1210 
   1211   /* Initialize aggregated transmit queues */
   1212   Mvpp2Shared->AggrTxqs = AllocateZeroPool (sizeof(MVPP2_TX_QUEUE));
   1213   if (Mvpp2Shared->AggrTxqs == NULL) {
   1214     DEBUG((DEBUG_ERROR, "Failed to allocate aggregated Txqs\n"));
   1215     return EFI_OUT_OF_RESOURCES;
   1216   }
   1217 
   1218   Mvpp2Shared->AggrTxqs->Descs = BufferLocation.AggrTxDescs;
   1219   Mvpp2Shared->AggrTxqs->Id = 0;
   1220   Mvpp2Shared->AggrTxqs->LogId = 0;
   1221   Mvpp2Shared->AggrTxqs->Size = MVPP2_AGGR_TXQ_SIZE;
   1222 
   1223   for (Index = 0; Index < NumPorts; Index++) {
   1224     Pp2Context = AllocateZeroPool (sizeof (PP2DXE_CONTEXT));
   1225     if (Pp2Context == NULL) {
   1226       /*
   1227        * If allocation fails, all resources allocated before will get freed
   1228        * at ExitBootServices, as only EfiBootServicesData is used.
   1229        */
   1230       DEBUG((DEBUG_ERROR, "Allocation fail.\n"));
   1231       return EFI_OUT_OF_RESOURCES;
   1232     }
   1233 
   1234     /* Instances are enumerated from 0 */
   1235     Pp2Context->Instance = Index;
   1236 
   1237     /* Install SNP protocol */
   1238     Status = Pp2DxeSnpInstall(Pp2Context);
   1239     if (EFI_ERROR(Status)) {
   1240       return Status;
   1241     }
   1242 
   1243     Pp2DxeParsePortPcd(Pp2Context);
   1244     Pp2Context->Port.TxpNum = 1;
   1245     Pp2Context->Port.Priv = Mvpp2Shared;
   1246     Pp2Context->Port.FirstRxq = 4 * Pp2Context->Instance;
   1247 
   1248     /* Gather accumulated configuration data of all ports' MAC's */
   1249     NetCompConfig |= MvpPp2xGop110NetcCfgCreate(&Pp2Context->Port);
   1250 
   1251     MvGop110PortInit(&Pp2Context->Port);
   1252     MvGop110FlCfg(&Pp2Context->Port);
   1253 
   1254     Status = gBS->CreateEvent (
   1255                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
   1256                  TPL_NOTIFY,
   1257                  Pp2DxeHalt,
   1258                  Pp2Context,
   1259                  &Pp2Context->EfiExitBootServicesEvent
   1260                );
   1261 
   1262     if (EFI_ERROR(Status)) {
   1263       return Status;
   1264     }
   1265   }
   1266 
   1267   MvGop110NetcInit(&Pp2Context->Port, NetCompConfig, MV_NETC_FIRST_PHASE);
   1268   MvGop110NetcInit(&Pp2Context->Port, NetCompConfig, MV_NETC_SECOND_PHASE);
   1269 
   1270   return EFI_SUCCESS;
   1271 }
   1272