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