• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
QueueInsert(IN PP2DXE_CONTEXT * Pp2Context,IN VOID * Buffer)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 *
QueueRemove(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeBmPoolInit(VOID)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
Pp2DxeBmStart(VOID)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
Pp2DxeStartDev(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeSetupRxqs(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeSetupTxqs(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeSetupAggrTxqs(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeOpen(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeLatePortInitialize(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeLateInitialize(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxePhyInitialize(PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeSnpInitialize(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN ExtraRxBufferSize OPTIONAL,IN UINTN ExtraTxBufferSize OPTIONAL)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
Pp2SnpStart(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)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
Pp2SnpStop(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)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
Pp2SnpReset(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN ExtendedVerification)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
Pp2DxeHalt(IN EFI_EVENT Event,IN VOID * Context)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
Pp2SnpShutdown(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)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
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)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
Pp2SnpStationAddress(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN BOOLEAN Reset,IN EFI_MAC_ADDRESS * NewMac)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
Pp2SnpNetStat(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN Reset,IN OUT UINTN * StatisticsSize OPTIONAL,OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL)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
Pp2SnpIpToMac(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN IPv6,IN EFI_IP_ADDRESS * IP,OUT EFI_MAC_ADDRESS * MAC)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
Pp2SnpNvData(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN ReadWrite,IN UINTN Offset,IN UINTN BufferSize,IN OUT VOID * Buffer)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
Pp2SnpGetStatus(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,OUT UINT32 * InterruptStatus OPTIONAL,OUT VOID ** TxBuf OPTIONAL)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
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 * EtherTypePtr OPTIONAL)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
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 * EtherType OPTIONAL)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
Pp2DxeSnpInstall(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeParsePortPcd(IN PP2DXE_CONTEXT * Pp2Context)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
Pp2DxeInitialise(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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