3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "Lan9118Dxe.h"
19 MAC_ADDR_DEVICE_PATH Lan9118
;
20 EFI_DEVICE_PATH_PROTOCOL End
;
21 } LAN9118_DEVICE_PATH
;
23 LAN9118_DEVICE_PATH Lan9118PathTemplate
= {
26 MESSAGING_DEVICE_PATH
, MSG_MAC_ADDR_DP
,
27 { (UINT8
) (sizeof(MAC_ADDR_DEVICE_PATH
)), (UINT8
) ((sizeof(MAC_ADDR_DEVICE_PATH
)) >> 8) }
34 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
35 sizeof(EFI_DEVICE_PATH_PROTOCOL
),
41 ** Entry point for the LAN9118 driver
47 IN EFI_SYSTEM_TABLE
*SystemTable
51 LAN9118_DRIVER
*LanDriver
;
52 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
53 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
54 LAN9118_DEVICE_PATH
*Lan9118Path
;
55 EFI_HANDLE ControllerHandle
;
57 // The PcdLan9118DxeBaseAddress PCD must be defined
58 ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress
) != 0);
61 LanDriver
= AllocateZeroPool (sizeof (LAN9118_DRIVER
));
62 if (LanDriver
== NULL
) {
63 return EFI_OUT_OF_RESOURCES
;
65 Lan9118Path
= (LAN9118_DEVICE_PATH
*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH
), &Lan9118PathTemplate
);
66 if (Lan9118Path
== NULL
) {
67 return EFI_OUT_OF_RESOURCES
;
70 // Initialize pointers
71 Snp
= &(LanDriver
->Snp
);
72 SnpMode
= &(LanDriver
->SnpMode
);
75 // Set the signature of the LAN Driver structure
76 LanDriver
->Signature
= LAN9118_SIGNATURE
;
78 // Assign fields and func pointers
79 Snp
->Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
80 Snp
->WaitForPacket
= NULL
;
81 Snp
->Initialize
= SnpInitialize
;
82 Snp
->Start
= SnpStart
;
84 Snp
->Reset
= SnpReset
;
85 Snp
->Shutdown
= SnpShutdown
;
86 Snp
->ReceiveFilters
= SnpReceiveFilters
;
87 Snp
->StationAddress
= SnpStationAddress
;
88 Snp
->Statistics
= SnpStatistics
;
89 Snp
->MCastIpToMac
= SnpMcastIptoMac
;
90 Snp
->NvData
= SnpNvData
;
91 Snp
->GetStatus
= SnpGetStatus
;
92 Snp
->Transmit
= SnpTransmit
;
93 Snp
->Receive
= SnpReceive
;
95 // Start completing simple network mode structure
96 SnpMode
->State
= EfiSimpleNetworkStopped
;
97 SnpMode
->HwAddressSize
= NET_ETHER_ADDR_LEN
; // HW address is 6 bytes
98 SnpMode
->MediaHeaderSize
= sizeof(ETHER_HEAD
); // Not sure of this
99 SnpMode
->MaxPacketSize
= EFI_PAGE_SIZE
; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
100 SnpMode
->NvRamSize
= 0; // No NVRAM with this device
101 SnpMode
->NvRamAccessSize
= 0; // No NVRAM with this device
103 // Update network mode information
104 SnpMode
->ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
105 EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
106 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
107 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;/* |
108 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;*/
109 // Current allowed settings
110 SnpMode
->ReceiveFilterSetting
= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
111 EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
112 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
114 // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses
115 SnpMode
->MaxMCastFilterCount
= MAX_MCAST_FILTER_CNT
;
116 SnpMode
->MCastFilterCount
= 0;
117 ZeroMem (&SnpMode
->MCastFilter
, MAX_MCAST_FILTER_CNT
* sizeof(EFI_MAC_ADDRESS
));
119 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
120 SnpMode
->IfType
= NET_IFTYPE_ETHERNET
;
122 // Mac address is changeable as it is loaded from erasable memory
123 SnpMode
->MacAddressChangeable
= TRUE
;
125 // Can only transmit one packet at a time
126 SnpMode
->MultipleTxSupported
= FALSE
;
128 // MediaPresent checks for cable connection and partner link
129 SnpMode
->MediaPresentSupported
= TRUE
;
130 SnpMode
->MediaPresent
= FALSE
;
132 // Set broadcast address
133 SetMem (&SnpMode
->BroadcastAddress
, sizeof (EFI_MAC_ADDRESS
), 0xFF);
135 // Power up the device so we can find the MAC address
136 Status
= Lan9118Initialize (Snp
);
137 if (EFI_ERROR (Status
)) {
138 DEBUG ((EFI_D_ERROR
, "Lan9118: Error initialising hardware\n"));
139 return EFI_DEVICE_ERROR
;
142 // Assign fields for device path
143 CopyMem (&Lan9118Path
->Lan9118
.MacAddress
, &Snp
->Mode
->CurrentAddress
, NET_ETHER_ADDR_LEN
);
144 Lan9118Path
->Lan9118
.IfType
= Snp
->Mode
->IfType
;
146 // Initialise the protocol
147 ControllerHandle
= NULL
;
148 Status
= gBS
->InstallMultipleProtocolInterfaces (
150 &gEfiSimpleNetworkProtocolGuid
, Snp
,
151 &gEfiDevicePathProtocolGuid
, Lan9118Path
,
154 // Say what the status of loading the protocol structure is
155 if (EFI_ERROR(Status
)) {
156 FreePool (LanDriver
);
158 LanDriver
->ControllerHandle
= ControllerHandle
;
165 * UEFI Start() function
169 * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
173 * This function starts a network interface. If the network interface successfully starts, then
174 * EFI_SUCCESS will be returned.
179 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
182 // Check Snp instance
184 return EFI_INVALID_PARAMETER
;
188 if ((Snp
->Mode
->State
== EfiSimpleNetworkStarted
) || (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
)) {
189 return EFI_ALREADY_STARTED
;
190 } else if (Snp
->Mode
->State
== EfiSimpleNetworkMaxState
) {
191 return EFI_DEVICE_ERROR
;
195 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
200 * UEFI Stop() function
206 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
209 // Check Snp Instance
211 return EFI_INVALID_PARAMETER
;
214 // Check state of the driver
215 if ((Snp
->Mode
->State
== EfiSimpleNetworkStopped
) || (Snp
->Mode
->State
== EfiSimpleNetworkMaxState
)) {
216 return EFI_NOT_STARTED
;
219 // Stop the Tx and Rx
220 StopTx (STOP_TX_CFG
| STOP_TX_MAC
, Snp
);
224 switch (Snp
->Mode
->State
) {
225 case EfiSimpleNetworkStarted
:
226 case EfiSimpleNetworkInitialized
:
227 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
230 return EFI_DEVICE_ERROR
;
233 // Put the device into a power saving mode ?
238 // Allocated receive and transmit buffers
239 STATIC UINT32 gTxBuffer
= 0;
242 * UEFI Initialize() function
248 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
249 IN UINTN RxBufferSize OPTIONAL
,
250 IN UINTN TxBufferSize OPTIONAL
259 // Initialize variables
260 // Global variables to hold tx and rx FIFO allocation
263 // Check Snp Instance
265 return EFI_INVALID_PARAMETER
;
268 // First check that driver has not already been initialized
269 if (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) {
270 DEBUG ((EFI_D_WARN
, "LAN9118 Driver already initialized\n"));
273 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
274 DEBUG ((EFI_D_WARN
, "LAN9118 Driver not started\n"));
275 return EFI_NOT_STARTED
;
278 // Initiate a PHY reset
279 if (PhySoftReset (PHY_RESET_PMT
| PHY_RESET_CHECK_LINK
, Snp
) < 0) {
280 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
281 DEBUG ((EFI_D_WARN
, "Warning: Link not ready after TimeOut. Check ethernet cable\n"));
282 return EFI_NOT_STARTED
;
285 // Initiate a software reset
286 Status
= SoftReset (0, Snp
);
287 if (EFI_ERROR(Status
)) {
288 DEBUG ((EFI_D_WARN
, "Soft Reset Failed: Hardware Error\n"));
289 return EFI_DEVICE_ERROR
;
292 // Read the PM register
293 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
295 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
296 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
297 // MPTCTRL_PME_EN: Allow Power Management Events
299 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
301 // Write the current configuration to the register
302 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
303 gBS
->Stall (LAN9118_STALL
);
304 gBS
->Stall (LAN9118_STALL
);
306 // Configure GPIO and HW
307 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
308 if (EFI_ERROR(Status
)) {
312 // Assign the transmitter buffer size (default values)
313 TxStatusSize
= LAN9118_TX_STATUS_SIZE
;
314 RxStatusSize
= LAN9118_RX_STATUS_SIZE
;
316 // Check that a buff size was specified
317 if (TxBufferSize
> 0) {
318 if (RxBufferSize
== 0) {
319 RxBufferSize
= LAN9118_RX_DATA_SIZE
;
322 AllocResult
= ChangeFifoAllocation (
331 if (AllocResult
< 0) {
332 return EFI_OUT_OF_RESOURCES
;
336 // Do auto-negotiation if supported
337 Status
= AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL
, Snp
);
338 if (EFI_ERROR(Status
)) {
339 DEBUG ((EFI_D_WARN
, "Lan9118: Auto Negociation not supported.\n"));
342 // Configure flow control depending on speed capabilities
343 Status
= ConfigureFlow (0, 0, 0, 0, Snp
);
344 if (EFI_ERROR(Status
)) {
348 // Enable the receiver and transmitter
349 Status
= StartRx (0, Snp
);
350 if (EFI_ERROR(Status
)) {
354 Status
= StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
355 if (EFI_ERROR(Status
)) {
359 // Now acknowledge all interrupts
360 MmioWrite32 (LAN9118_INT_STS
, ~0);
362 // Declare the driver as initialized
363 Snp
->Mode
->State
= EfiSimpleNetworkInitialized
;
369 * UEFI Reset () function
375 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
376 IN BOOLEAN Verification
387 // Check Snp Instance
389 return EFI_INVALID_PARAMETER
;
392 // First check that driver has not already been initialized
393 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
394 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
395 return EFI_DEVICE_ERROR
;
396 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
397 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
398 return EFI_NOT_STARTED
;
401 // Initiate a PHY reset
402 if (PhySoftReset (PHY_RESET_PMT
| PHY_RESET_CHECK_LINK
, Snp
) < 0) {
403 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
404 return EFI_NOT_STARTED
;
407 // Initiate a software reset
408 ResetFlags
|= SOFT_RESET_CHECK_MAC_ADDR_LOAD
| SOFT_RESET_CLEAR_INT
;
411 ResetFlags
|= SOFT_RESET_SELF_TEST
;
414 if (SoftReset (ResetFlags
, Snp
) < 0) {
415 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
416 return EFI_DEVICE_ERROR
;
419 // Read the PM register
420 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
422 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
423 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
424 // MPTCTRL_PME_EN: Allow Power Management Events
425 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
427 // Write the current configuration to the register
428 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
429 gBS
->Stall (LAN9118_STALL
);
431 // Check that a buffer size was specified in SnpInitialize
432 if (gTxBuffer
!= 0) {
433 HwConf
= MmioRead32 (LAN9118_HW_CFG
); // Read the HW register
434 HwConf
&= ~HW_CFG_TX_FIFO_SIZE_MASK
; // Clear buffer bits first
435 HwConf
|= HW_CFG_TX_FIFO_SIZE(gTxBuffer
); // assign size chosen in SnpInitialize
437 MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
438 gBS
->Stall (LAN9118_STALL
);
441 // Enable the receiver and transmitter and clear their contents
442 StartRx (START_RX_CLEAR
, Snp
);
443 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
445 // Now acknowledge all interrupts
446 MmioWrite32 (LAN9118_INT_STS
, ~0);
452 * UEFI Shutdown () function
458 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
461 // Check Snp Instance
463 return EFI_INVALID_PARAMETER
;
466 // First check that driver has not already been initialized
467 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
468 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
469 return EFI_DEVICE_ERROR
;
470 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
471 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
472 return EFI_NOT_STARTED
;
475 // Initiate a PHY reset
476 PhySoftReset (PHY_RESET_PMT
, Snp
);
478 // Initiate a software reset
479 if (SoftReset (0, Snp
) < 0) {
480 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
481 return EFI_DEVICE_ERROR
;
489 * UEFI ReceiveFilters() function
495 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
499 IN UINTN NumMfilter OPTIONAL
,
500 IN EFI_MAC_ADDRESS
*Mfilter OPTIONAL
504 UINT32 MultHashTableHigh
;
505 UINT32 MultHashTableLow
;
511 MultHashTableHigh
= 0;
512 MultHashTableLow
= 0;
517 // Check that driver was started and initialised
518 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
519 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
520 return EFI_DEVICE_ERROR
;
521 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
522 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
523 return EFI_NOT_STARTED
;
526 // If reset then clear the filter registers
528 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
529 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, 0x00000000);
530 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, 0x00000000);
533 // Set the hash tables
534 if ((NumMfilter
> 0) && (!Reset
)) {
536 // Read the Multicast High Hash Table
537 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
539 // Read the Multicast Low Hash Table
540 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
542 // Go through each filter address and set appropriate bits on hash table
543 for (Count
= 0; Count
< NumMfilter
; Count
++) {
545 // Generate a 32-bit CRC for Ethernet
546 Crc
= GenEtherCrc32 (&Mfilter
[Count
],6);
547 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
549 // Get the most significant 6 bits to index hash registers
550 BitToSelect
= (Crc
>> 26) & 0x3F;
552 // Select hashlow register if MSB is not set
553 if ((BitToSelect
& 0x20) == 0) {
554 MultHashTableLow
|= (1 << BitToSelect
);
556 MultHashTableHigh
|= (1 << (BitToSelect
& 0x1F));
560 // Write the desired hash
561 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
562 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
565 // Read MAC controller
566 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
568 // Set the options for the MAC_CSR
569 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
571 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
574 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
576 DEBUG ((DEBUG_NET
, "Disabling Unicast Frame Reception\n"));
579 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
580 MacCSRValue
|= MACCR_HPFILT
;
581 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
584 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
585 MacCSRValue
&= ~MACCR_HPFILT
;
586 DEBUG ((DEBUG_NET
, "Disabling Multicast Frame Reception\n"));
589 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) {
590 MacCSRValue
&= ~(MACCR_BCAST
);
591 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
594 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) {
595 MacCSRValue
|= MACCR_BCAST
;
596 DEBUG ((DEBUG_NET
, "Disabling Broadcast Frame Reception\n"));
599 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
600 MacCSRValue
|= MACCR_PRMS
;
601 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
604 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
605 MacCSRValue
&= ~MACCR_PRMS
;
606 DEBUG ((DEBUG_NET
, "Disabling Promiscuous Mode\n"));
609 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
610 MacCSRValue
|= (MACCR_HPFILT
| MACCR_PRMS
);
611 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
614 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
615 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_PRMS
);
616 DEBUG ((DEBUG_NET
, "Disabling Promiscuous Multicast Mode\n"));
619 // Write the options to the MAC_CSR
620 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
621 gBS
->Stall (LAN9118_STALL
);
627 * UEFI StationAddress() function
633 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
635 IN EFI_MAC_ADDRESS
*NewMac
638 DEBUG ((DEBUG_NET
, "SnpStationAddress()\n"));
642 UINT64 DefaultMacAddress
;
646 // Check Snp instance
648 return EFI_INVALID_PARAMETER
;
651 // Check that driver was started and initialised
652 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
653 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
654 return EFI_DEVICE_ERROR
;
655 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
656 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
657 return EFI_NOT_STARTED
;
660 // Get the Permanent MAC address if need reset
662 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
663 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM
) {
664 for (Count
= 1; Count
< 7; Count
++) {
665 PermAddr
[Count
- 1] = IndirectEEPROMRead32 (Count
);
669 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) PermAddr
, Snp
);
671 DEBUG ((EFI_D_ERROR
, "Lan9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
672 DefaultMacAddress
= FixedPcdGet64 (PcdLan9118DefaultMacAddress
);
673 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) &DefaultMacAddress
, Snp
);
676 // Otherwise use the specified new MAC address
677 if (NewMac
== NULL
) {
678 return EFI_INVALID_PARAMETER
;
682 Lan9118SetMacAddress (NewMac
, Snp
);
689 * UEFI Statistics() function
695 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
697 IN OUT UINTN
*StatSize
,
698 OUT EFI_NETWORK_STATISTICS
*Statistics
701 LAN9118_DRIVER
*LanDriver
;
703 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
705 DEBUG ((DEBUG_NET
, "SnpStatistics()\n"));
707 // Check Snp instance
709 return EFI_INVALID_PARAMETER
;
712 // Check that driver was started and initialised
713 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
714 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
715 return EFI_DEVICE_ERROR
;
716 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
717 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
718 return EFI_NOT_STARTED
;
721 // Check pointless condition
722 if ((!Reset
) && (StatSize
== NULL
) && (Statistics
== NULL
)) {
726 // Check the parameters
727 if ((StatSize
== NULL
) && (Statistics
!= NULL
)) {
728 return EFI_INVALID_PARAMETER
;
731 // Do a reset if required
733 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
737 if (*StatSize
< sizeof(EFI_NETWORK_STATISTICS
)) {
738 *StatSize
= sizeof(EFI_NETWORK_STATISTICS
);
739 return EFI_BUFFER_TOO_SMALL
;
742 // Fill in the statistics
743 CopyMem(&Statistics
, &LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
749 * UEFI MCastIPtoMAC() function
755 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
757 IN EFI_IP_ADDRESS
*Ip
,
758 OUT EFI_MAC_ADDRESS
*McastMac
761 DEBUG ((DEBUG_NET
, "SnpMcastIptoMac()\n"));
763 // Check Snp instance
765 return EFI_INVALID_PARAMETER
;
768 // Check that driver was started and initialised
769 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
770 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
771 return EFI_DEVICE_ERROR
;
772 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
773 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
774 return EFI_NOT_STARTED
;
778 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
779 return EFI_INVALID_PARAMETER
;
782 // Make sure MAC address is empty
783 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
785 // If we need ipv4 address
787 // Most significant 25 bits of a multicast HW address are set.
788 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
789 McastMac
->Addr
[0] = 0x01;
790 McastMac
->Addr
[1] = 0x00;
791 McastMac
->Addr
[2] = 0x5E;
793 // Lower 23 bits from ipv4 address
794 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
795 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
796 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
798 // Most significant 16 bits of multicast v6 HW address are set
799 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
800 McastMac
->Addr
[0] = 0x33;
801 McastMac
->Addr
[1] = 0x33;
803 // lower four octets are taken from ipv6 address
804 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
805 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
806 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
807 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
814 * UEFI NvData() function
820 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
821 IN BOOLEAN read_write
,
827 DEBUG ((DEBUG_NET
, "SnpNvData()\n"));
829 return EFI_UNSUPPORTED
;
834 * UEFI GetStatus () function
840 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
841 OUT UINT32
*IrqStat OPTIONAL
,
842 OUT VOID
**TxBuff OPTIONAL
847 UINTN NumTxStatusEntries
;
851 LAN9118_DRIVER
*LanDriver
;
853 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
855 // Check preliminaries
857 return EFI_INVALID_PARAMETER
;
860 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
861 return EFI_NOT_STARTED
;
864 // Check and acknowledge TX Status interrupt (this will happen if the
865 // consumer of SNP does not call GetStatus.)
866 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
867 // should check for it and dump the TX Status FIFO.
868 FifoInt
= MmioRead32 (LAN9118_FIFO_INT
);
870 // Clear the TX Status FIFO Overflow
871 if ((FifoInt
& INSTS_TXSO
) == 0) {
872 FifoInt
|= INSTS_TXSO
;
873 MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
876 // Read interrupt status if IrqStat is not NULL
877 if (IrqStat
!= NULL
) {
879 // Check for receive interrupt
880 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
881 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
882 MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
884 *IrqStat
&= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
887 // Check for transmit interrupt
888 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
889 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
890 MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
892 *IrqStat
&= ~EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
895 // Check for software interrupt
896 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
897 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
898 MmioWrite32 (LAN9118_INT_STS
,INSTS_SW_INT
);
900 *IrqStat
&= ~EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
904 // Check Status of transmitted packets
905 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
907 NumTxStatusEntries
= MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
908 if (NumTxStatusEntries
> 0) {
909 TxStatus
= MmioRead32 (LAN9118_TX_STATUS
);
910 PacketTag
= TxStatus
>> 16;
911 TxStatus
= TxStatus
& 0xFFFF;
912 if ((TxStatus
& TXSTATUS_ES
) && TxStatus
!= (TXSTATUS_ES
| TXSTATUS_NO_CA
)) {
913 DEBUG ((EFI_D_ERROR
, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus
));
914 if (TxStatus
& TXSTATUS_NO_CA
) {
915 DEBUG ((EFI_D_ERROR
, "- No carrier\n"));
917 if (TxStatus
& TXSTATUS_DEF
) {
918 DEBUG ((EFI_D_ERROR
, "- Packet tx was deferred\n"));
920 if (TxStatus
& TXSTATUS_EDEF
) {
921 DEBUG ((EFI_D_ERROR
, "- Tx ended because of excessive deferral\n"));
923 if (TxStatus
& TXSTATUS_ECOLL
) {
924 DEBUG ((EFI_D_ERROR
, "- Tx ended because of Excessive Collisions\n"));
926 if (TxStatus
& TXSTATUS_LCOLL
) {
927 DEBUG ((EFI_D_ERROR
, "- Packet Tx aborted after coll window of 64 bytes\n"));
929 if (TxStatus
& TXSTATUS_LOST_CA
) {
930 DEBUG ((EFI_D_ERROR
, "- Lost carrier during Tx\n"));
932 return EFI_DEVICE_ERROR
;
934 LanDriver
->Stats
.TxTotalFrames
+= 1;
935 *TxBuff
= LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
];
939 // Check for a TX Error interrupt
940 Interrupts
= MmioRead32 (LAN9118_INT_STS
);
941 if (Interrupts
& INSTS_TXE
) {
942 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
944 // Initiate a software reset
945 if (SoftReset (0, Snp
) < 0) {
946 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
947 return EFI_DEVICE_ERROR
;
950 // Acknowledge the TXE
951 MmioWrite32 (LAN9118_INT_STS
, INSTS_TXE
);
952 gBS
->Stall (LAN9118_STALL
);
954 // Restart the transmitter
955 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
958 // Update the media status
959 Status
= CheckLinkStatus (0, Snp
);
960 if (EFI_ERROR(Status
)) {
961 Snp
->Mode
->MediaPresent
= FALSE
;
963 Snp
->Mode
->MediaPresent
= TRUE
;
971 * UEFI Transmit() function
977 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
981 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
982 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
983 IN UINT16
*Protocol OPTIONAL
986 LAN9118_DRIVER
*LanDriver
;
988 UINT32 TxStatusSpace
;
992 UINT16 LocalProtocol
;
996 #if defined(EVAL_PERFORMANCE)
1001 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1002 StartClock
= GetPerformanceCounter ();
1005 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1007 // Check preliminaries
1008 if ((Snp
== NULL
) || (Data
== NULL
)) {
1009 return EFI_INVALID_PARAMETER
;
1011 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
1012 return EFI_NOT_STARTED
;
1015 // Ensure header is correct size if non-zero
1017 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1018 return EFI_INVALID_PARAMETER
;
1021 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1022 return EFI_INVALID_PARAMETER
;
1026 // Before transmitting check the link status
1027 /*if (CheckLinkStatus (0, Snp) < 0) {
1028 return EFI_NOT_READY;
1031 // Get DATA FIFO free space in bytes
1032 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1033 if (TxFreeSpace
< BuffSize
) {
1034 return EFI_NOT_READY
;
1037 // Get STATUS FIFO used space in bytes
1038 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1039 if (TxStatusSpace
> 500) {
1040 return EFI_NOT_READY
;
1043 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1044 // has provided a well-formed frame).
1045 if (DstAddr
== NULL
) {
1046 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1049 // Check for the nature of the frame
1050 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1051 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1053 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1056 // Check if broadcast
1057 if (DstAddr
->Addr
[0] == 0xFF) {
1058 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1061 PacketTag
= LanDriver
->NextPacketTag
;
1062 LanDriver
->NextPacketTag
++;
1067 LocalData
= (UINT32
*) Data
;
1068 LocalProtocol
= *Protocol
;
1070 // Create first buffer to pass to controller (for the header)
1071 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1072 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1074 // Write the commands first
1075 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1076 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1078 // Write the destination address
1079 MmioWrite32 (LAN9118_TX_DATA
,
1080 (DstAddr
->Addr
[0]) |
1081 (DstAddr
->Addr
[1] << 8) |
1082 (DstAddr
->Addr
[2] << 16) |
1083 (DstAddr
->Addr
[3] << 24)
1086 MmioWrite32 (LAN9118_TX_DATA
,
1087 (DstAddr
->Addr
[4]) |
1088 (DstAddr
->Addr
[5] << 8) |
1089 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1090 (SrcAddr
->Addr
[1] << 24)
1093 MmioWrite32 (LAN9118_TX_DATA
,
1094 (SrcAddr
->Addr
[2]) |
1095 (SrcAddr
->Addr
[3] << 8) |
1096 (SrcAddr
->Addr
[4] << 16) |
1097 (SrcAddr
->Addr
[5] << 24)
1100 // Write the Protocol
1101 MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1103 // Next buffer is the payload
1104 CommandA
= TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
- HdrSize
) | TX_CMD_A_COMPLETION_INT
| TX_CMD_A_DATA_START_OFFSET (2); // 2 bytes beginning offset
1106 // Write the commands
1107 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1108 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1110 // Write the payload
1111 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1112 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1116 LocalData
= (UINT32
*) Data
;
1118 // Create a buffer to pass to controller
1119 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1120 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1122 // Write the commands first
1123 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1124 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1126 // Write all the data
1127 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1128 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1132 // Save the address of the submitted packet so we can notify the consumer that
1133 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1134 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1135 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1137 #if defined(EVAL_PERFORMANCE)
1138 EndClock
= GetPerformanceCounter ();
1139 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1142 LanDriver
->Stats
.TxGoodFrames
+= 1;
1149 * UEFI Receive() function
1155 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1156 OUT UINTN
*HdrSize OPTIONAL
,
1157 IN OUT UINTN
*BuffSize
,
1159 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1160 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1161 OUT UINT16
*Protocol OPTIONAL
1164 LAN9118_DRIVER
*LanDriver
;
1165 UINT32 RxFifoStatus
;
1168 UINT32 PLength
; // Packet length
1173 EFI_MAC_ADDRESS Dst
;
1174 EFI_MAC_ADDRESS Src
;
1175 UINTN DroppedFrames
;
1177 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1179 #if defined(EVAL_PERFORMANCE)
1180 UINT64 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1181 UINT64 StartClock
= GetPerformanceCounter ();
1184 // Check preliminaries
1185 if ((Snp
== NULL
) || (Data
== NULL
)) {
1186 return EFI_INVALID_PARAMETER
;
1189 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
1190 return EFI_NOT_STARTED
;
1193 // Count dropped frames
1194 DroppedFrames
= MmioRead32 (LAN9118_RX_DROP
);
1195 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1197 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1199 return EFI_NOT_READY
;
1202 // Read Rx Status (only if not empty)
1203 RxFifoStatus
= MmioRead32 (LAN9118_RX_STATUS
);
1204 LanDriver
->Stats
.RxTotalFrames
+= 1;
1206 // First check for errors
1207 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1208 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1209 (RxFifoStatus
& RXSTATUS_FTL
) ||
1210 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1211 (RxFifoStatus
& RXSTATUS_LE
) ||
1212 (RxFifoStatus
& RXSTATUS_DB
))
1214 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1215 return EFI_DEVICE_ERROR
;
1218 // Check if we got a CRC error
1219 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1220 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1221 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1222 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1223 return EFI_DEVICE_ERROR
;
1226 // Check if we got a runt frame
1227 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1228 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1229 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1230 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1231 return EFI_DEVICE_ERROR
;
1234 // Check filtering status for this packet
1235 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1236 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1240 // Check if we got a broadcast frame
1241 if (RxFifoStatus
& RXSTATUS_BCF
) {
1242 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1245 // Check if we got a multicast frame
1246 if (RxFifoStatus
& RXSTATUS_MCF
) {
1247 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1250 // Check if we got a unicast frame
1251 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1252 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1255 // Get the received packet length
1256 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1257 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1259 // Check buffer size
1260 if (*BuffSize
< PLength
) {
1261 *BuffSize
= PLength
;
1262 return EFI_BUFFER_TOO_SMALL
;
1265 // If padding is applied, read more DWORDs
1267 Padding
= 4 - (PLength
% 4);
1268 ReadLimit
= (PLength
+ Padding
)/4;
1270 ReadLimit
= PLength
/4;
1274 // Set the amount of data to be transfered out of FIFO for THIS packet
1275 // This can be used to trigger an interrupt, and status can be checked
1276 RxCfgValue
= MmioRead32 (LAN9118_RX_CFG
);
1277 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1278 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1280 // Set end alignment to 4-bytes
1281 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1282 MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1284 // Update buffer size
1285 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1286 // 4 bytes longer than packet actually is, unless
1287 // packet is < 64 bytes
1289 if (HdrSize
!= NULL
)
1290 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1292 // Format the pointer
1293 RawData
= (UINT32
*)Data
;
1296 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1297 RawData
[Count
] = MmioRead32 (LAN9118_RX_DATA
);
1300 // Check for Rx errors (worst possible error)
1301 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1302 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1304 // Initiate a software reset
1305 if (SoftReset (0, Snp
) < 0) {
1306 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1307 return EFI_DEVICE_ERROR
;
1310 // Acknowledge the RXE
1311 MmioWrite32 (LAN9118_INT_STS
, INSTS_RXE
);
1312 gBS
->Stall (LAN9118_STALL
);
1314 // Restart the rx (and do not clear FIFO)
1317 // Say that command could not be sent
1318 return EFI_DEVICE_ERROR
;
1321 // Get the destination address
1322 if (DstAddr
!= NULL
) {
1323 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1324 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1325 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1326 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1327 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1328 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1329 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1332 // Get the source address
1333 if (SrcAddr
!= NULL
) {
1334 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1335 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1336 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1337 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1338 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1339 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1340 CopyMem (SrcAddr
,&Src
, NET_ETHER_ADDR_LEN
);
1344 if (Protocol
!= NULL
) {
1345 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1348 #if defined(EVAL_PERFORMANCE)
1349 UINT64 EndClock
= GetPerformanceCounter ();
1350 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1353 LanDriver
->Stats
.RxGoodFrames
+= 1;