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
), 0 }
40 ** Entry point for the LAN9118 driver
46 IN EFI_SYSTEM_TABLE
*SystemTable
50 LAN9118_DRIVER
*LanDriver
;
51 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
52 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
53 LAN9118_DEVICE_PATH
*Lan9118Path
;
54 EFI_HANDLE ControllerHandle
;
56 // The PcdLan9118DxeBaseAddress PCD must be defined
57 ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress
) != 0);
60 LanDriver
= AllocateZeroPool (sizeof (LAN9118_DRIVER
));
61 if (LanDriver
== NULL
) {
62 return EFI_OUT_OF_RESOURCES
;
64 Lan9118Path
= (LAN9118_DEVICE_PATH
*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH
), &Lan9118PathTemplate
);
65 if (Lan9118Path
== NULL
) {
66 return EFI_OUT_OF_RESOURCES
;
69 // Initialize pointers
70 Snp
= &(LanDriver
->Snp
);
71 SnpMode
= &(LanDriver
->SnpMode
);
74 // Set the signature of the LAN Driver structure
75 LanDriver
->Signature
= LAN9118_SIGNATURE
;
77 // Assign fields and func pointers
78 Snp
->Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
79 Snp
->WaitForPacket
= NULL
;
80 Snp
->Initialize
= SnpInitialize
;
81 Snp
->Start
= SnpStart
;
83 Snp
->Reset
= SnpReset
;
84 Snp
->Shutdown
= SnpShutdown
;
85 Snp
->ReceiveFilters
= SnpReceiveFilters
;
86 Snp
->StationAddress
= SnpStationAddress
;
87 Snp
->Statistics
= SnpStatistics
;
88 Snp
->MCastIpToMac
= SnpMcastIptoMac
;
89 Snp
->NvData
= SnpNvData
;
90 Snp
->GetStatus
= SnpGetStatus
;
91 Snp
->Transmit
= SnpTransmit
;
92 Snp
->Receive
= SnpReceive
;
94 // Start completing simple network mode structure
95 SnpMode
->State
= EfiSimpleNetworkStopped
;
96 SnpMode
->HwAddressSize
= NET_ETHER_ADDR_LEN
; // HW address is 6 bytes
97 SnpMode
->MediaHeaderSize
= sizeof(ETHER_HEAD
); // Not sure of this
98 SnpMode
->MaxPacketSize
= EFI_PAGE_SIZE
; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
99 SnpMode
->NvRamSize
= 0; // No NVRAM with this device
100 SnpMode
->NvRamAccessSize
= 0; // No NVRAM with this device
102 // Update network mode information
103 SnpMode
->ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
104 EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
105 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
106 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;/* |
107 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;*/
108 // Current allowed settings
109 SnpMode
->ReceiveFilterSetting
= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
110 EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
111 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
113 // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses
114 SnpMode
->MaxMCastFilterCount
= MAX_MCAST_FILTER_CNT
;
115 SnpMode
->MCastFilterCount
= 0;
116 ZeroMem (&SnpMode
->MCastFilter
, MAX_MCAST_FILTER_CNT
* sizeof(EFI_MAC_ADDRESS
));
118 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
119 SnpMode
->IfType
= NET_IFTYPE_ETHERNET
;
121 // Mac address is changeable as it is loaded from erasable memory
122 SnpMode
->MacAddressChangeable
= TRUE
;
124 // Can only transmit one packet at a time
125 SnpMode
->MultipleTxSupported
= FALSE
;
127 // MediaPresent checks for cable connection and partner link
128 SnpMode
->MediaPresentSupported
= TRUE
;
129 SnpMode
->MediaPresent
= FALSE
;
131 // Set broadcast address
132 SetMem (&SnpMode
->BroadcastAddress
, sizeof (EFI_MAC_ADDRESS
), 0xFF);
134 // Power up the device so we can find the MAC address
135 Status
= Lan9118Initialize (Snp
);
136 if (EFI_ERROR (Status
)) {
137 DEBUG ((EFI_D_ERROR
, "Lan9118: Error initialising hardware\n"));
138 return EFI_DEVICE_ERROR
;
141 // Assign fields for device path
142 CopyMem (&Lan9118Path
->Lan9118
.MacAddress
, &Snp
->Mode
->CurrentAddress
, NET_ETHER_ADDR_LEN
);
143 Lan9118Path
->Lan9118
.IfType
= Snp
->Mode
->IfType
;
145 // Initialise the protocol
146 ControllerHandle
= NULL
;
147 Status
= gBS
->InstallMultipleProtocolInterfaces (
149 &gEfiSimpleNetworkProtocolGuid
, Snp
,
150 &gEfiDevicePathProtocolGuid
, Lan9118Path
,
153 // Say what the status of loading the protocol structure is
154 if (EFI_ERROR(Status
)) {
155 FreePool (LanDriver
);
157 LanDriver
->ControllerHandle
= ControllerHandle
;
164 * UEFI Start() function
168 * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
172 * This function starts a network interface. If the network interface successfully starts, then
173 * EFI_SUCCESS will be returned.
178 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
181 // Check Snp instance
183 return EFI_INVALID_PARAMETER
;
187 if ((Snp
->Mode
->State
== EfiSimpleNetworkStarted
) || (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
)) {
188 return EFI_ALREADY_STARTED
;
189 } else if (Snp
->Mode
->State
== EfiSimpleNetworkMaxState
) {
190 return EFI_DEVICE_ERROR
;
194 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
199 * UEFI Stop() function
205 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
208 // Check Snp Instance
210 return EFI_INVALID_PARAMETER
;
213 // Check state of the driver
214 if ((Snp
->Mode
->State
== EfiSimpleNetworkStopped
) || (Snp
->Mode
->State
== EfiSimpleNetworkMaxState
)) {
215 return EFI_NOT_STARTED
;
218 // Stop the Tx and Rx
219 StopTx (STOP_TX_CFG
| STOP_TX_MAC
, Snp
);
223 switch (Snp
->Mode
->State
) {
224 case EfiSimpleNetworkStarted
:
225 case EfiSimpleNetworkInitialized
:
226 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
229 return EFI_DEVICE_ERROR
;
232 // Put the device into a power saving mode ?
237 // Allocated receive and transmit buffers
238 STATIC UINT32 gTxBuffer
= 0;
241 * UEFI Initialize() function
247 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
248 IN UINTN RxBufferSize OPTIONAL
,
249 IN UINTN TxBufferSize OPTIONAL
258 // Initialize variables
259 // Global variables to hold tx and rx FIFO allocation
262 // Check Snp Instance
264 return EFI_INVALID_PARAMETER
;
267 // First check that driver has not already been initialized
268 if (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) {
269 DEBUG ((EFI_D_WARN
, "LAN9118 Driver already initialized\n"));
272 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
273 DEBUG ((EFI_D_WARN
, "LAN9118 Driver not started\n"));
274 return EFI_NOT_STARTED
;
277 // Initiate a PHY reset
278 if (PhySoftReset (PHY_RESET_PMT
| PHY_RESET_CHECK_LINK
, Snp
) < 0) {
279 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
280 DEBUG ((EFI_D_WARN
, "Warning: Link not ready after TimeOut. Check ethernet cable\n"));
281 return EFI_NOT_STARTED
;
284 // Initiate a software reset
285 Status
= SoftReset (0, Snp
);
286 if (EFI_ERROR(Status
)) {
287 DEBUG ((EFI_D_WARN
, "Soft Reset Failed: Hardware Error\n"));
288 return EFI_DEVICE_ERROR
;
291 // Read the PM register
292 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
294 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
295 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
296 // MPTCTRL_PME_EN: Allow Power Management Events
298 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
300 // Write the current configuration to the register
301 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
302 gBS
->Stall (LAN9118_STALL
);
303 gBS
->Stall (LAN9118_STALL
);
305 // Configure GPIO and HW
306 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
307 if (EFI_ERROR(Status
)) {
311 // Assign the transmitter buffer size (default values)
312 TxStatusSize
= LAN9118_TX_STATUS_SIZE
;
313 RxStatusSize
= LAN9118_RX_STATUS_SIZE
;
315 // Check that a buff size was specified
316 if (TxBufferSize
> 0) {
317 if (RxBufferSize
== 0) {
318 RxBufferSize
= LAN9118_RX_DATA_SIZE
;
321 AllocResult
= ChangeFifoAllocation (
330 if (AllocResult
< 0) {
331 return EFI_OUT_OF_RESOURCES
;
335 // Do auto-negotiation if supported
336 Status
= AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL
, Snp
);
337 if (EFI_ERROR(Status
)) {
338 DEBUG ((EFI_D_WARN
, "Lan9118: Auto Negociation not supported.\n"));
341 // Configure flow control depending on speed capabilities
342 Status
= ConfigureFlow (0, 0, 0, 0, Snp
);
343 if (EFI_ERROR(Status
)) {
347 // Enable the receiver and transmitter
348 Status
= StartRx (0, Snp
);
349 if (EFI_ERROR(Status
)) {
353 Status
= StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
354 if (EFI_ERROR(Status
)) {
358 // Now acknowledge all interrupts
359 MmioWrite32 (LAN9118_INT_STS
, ~0);
361 // Declare the driver as initialized
362 Snp
->Mode
->State
= EfiSimpleNetworkInitialized
;
368 * UEFI Reset () function
374 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
375 IN BOOLEAN Verification
386 // Check Snp Instance
388 return EFI_INVALID_PARAMETER
;
391 // First check that driver has not already been initialized
392 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
393 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
394 return EFI_DEVICE_ERROR
;
395 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
396 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
397 return EFI_NOT_STARTED
;
400 // Initiate a PHY reset
401 if (PhySoftReset (PHY_RESET_PMT
| PHY_RESET_CHECK_LINK
, Snp
) < 0) {
402 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
403 return EFI_NOT_STARTED
;
406 // Initiate a software reset
407 ResetFlags
|= SOFT_RESET_CHECK_MAC_ADDR_LOAD
| SOFT_RESET_CLEAR_INT
;
410 ResetFlags
|= SOFT_RESET_SELF_TEST
;
413 if (SoftReset (ResetFlags
, Snp
) < 0) {
414 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
415 return EFI_DEVICE_ERROR
;
418 // Read the PM register
419 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
421 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
422 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
423 // MPTCTRL_PME_EN: Allow Power Management Events
424 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
426 // Write the current configuration to the register
427 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
428 gBS
->Stall (LAN9118_STALL
);
430 // Check that a buffer size was specified in SnpInitialize
431 if (gTxBuffer
!= 0) {
432 HwConf
= MmioRead32 (LAN9118_HW_CFG
); // Read the HW register
433 HwConf
&= ~HW_CFG_TX_FIFO_SIZE_MASK
; // Clear buffer bits first
434 HwConf
|= HW_CFG_TX_FIFO_SIZE(gTxBuffer
); // assign size chosen in SnpInitialize
436 MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
437 gBS
->Stall (LAN9118_STALL
);
440 // Enable the receiver and transmitter and clear their contents
441 StartRx (START_RX_CLEAR
, Snp
);
442 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
444 // Now acknowledge all interrupts
445 MmioWrite32 (LAN9118_INT_STS
, ~0);
451 * UEFI Shutdown () function
457 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
460 // Check Snp Instance
462 return EFI_INVALID_PARAMETER
;
465 // First check that driver has not already been initialized
466 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
467 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
468 return EFI_DEVICE_ERROR
;
469 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
470 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
471 return EFI_NOT_STARTED
;
474 // Initiate a PHY reset
475 PhySoftReset (PHY_RESET_PMT
, Snp
);
477 // Initiate a software reset
478 if (SoftReset (0, Snp
) < 0) {
479 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
480 return EFI_DEVICE_ERROR
;
488 * UEFI ReceiveFilters() function
494 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
498 IN UINTN NumMfilter OPTIONAL
,
499 IN EFI_MAC_ADDRESS
*Mfilter OPTIONAL
503 UINT32 MultHashTableHigh
;
504 UINT32 MultHashTableLow
;
510 MultHashTableHigh
= 0;
511 MultHashTableLow
= 0;
516 // Check that driver was started and initialised
517 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
518 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
519 return EFI_DEVICE_ERROR
;
520 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
521 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
522 return EFI_NOT_STARTED
;
525 // If reset then clear the filter registers
527 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
528 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, 0x00000000);
529 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, 0x00000000);
532 // Set the hash tables
533 if ((NumMfilter
> 0) && (!Reset
)) {
535 // Read the Multicast High Hash Table
536 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
538 // Read the Multicast Low Hash Table
539 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
541 // Go through each filter address and set appropriate bits on hash table
542 for (Count
= 0; Count
< NumMfilter
; Count
++) {
544 // Generate a 32-bit CRC for Ethernet
545 Crc
= GenEtherCrc32 (&Mfilter
[Count
],6);
546 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
548 // Get the most significant 6 bits to index hash registers
549 BitToSelect
= (Crc
>> 26) & 0x3F;
551 // Select hashlow register if MSB is not set
552 if ((BitToSelect
& 0x20) == 0) {
553 MultHashTableLow
|= (1 << BitToSelect
);
555 MultHashTableHigh
|= (1 << (BitToSelect
& 0x1F));
559 // Write the desired hash
560 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
561 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
564 // Read MAC controller
565 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
567 // Set the options for the MAC_CSR
568 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
570 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
573 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
575 DEBUG ((DEBUG_NET
, "Disabling Unicast Frame Reception\n"));
578 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
579 MacCSRValue
|= MACCR_HPFILT
;
580 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
583 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
584 MacCSRValue
&= ~MACCR_HPFILT
;
585 DEBUG ((DEBUG_NET
, "Disabling Multicast Frame Reception\n"));
588 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) {
589 MacCSRValue
&= ~(MACCR_BCAST
);
590 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
593 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) {
594 MacCSRValue
|= MACCR_BCAST
;
595 DEBUG ((DEBUG_NET
, "Disabling Broadcast Frame Reception\n"));
598 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
599 MacCSRValue
|= MACCR_PRMS
;
600 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
603 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
604 MacCSRValue
&= ~MACCR_PRMS
;
605 DEBUG ((DEBUG_NET
, "Disabling Promiscuous Mode\n"));
608 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
609 MacCSRValue
|= (MACCR_HPFILT
| MACCR_PRMS
);
610 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
613 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
614 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_PRMS
);
615 DEBUG ((DEBUG_NET
, "Disabling Promiscuous Multicast Mode\n"));
618 // Write the options to the MAC_CSR
619 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
620 gBS
->Stall (LAN9118_STALL
);
626 * UEFI StationAddress() function
632 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
634 IN EFI_MAC_ADDRESS
*NewMac
637 DEBUG ((DEBUG_NET
, "SnpStationAddress()\n"));
641 UINT64 DefaultMacAddress
;
645 // Check Snp instance
647 return EFI_INVALID_PARAMETER
;
650 // Check that driver was started and initialised
651 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
652 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
653 return EFI_DEVICE_ERROR
;
654 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
655 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
656 return EFI_NOT_STARTED
;
659 // Get the Permanent MAC address if need reset
661 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
662 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM
) {
663 for (Count
= 1; Count
< 7; Count
++) {
664 PermAddr
[Count
- 1] = IndirectEEPROMRead32 (Count
);
668 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) PermAddr
, Snp
);
670 DEBUG ((EFI_D_ERROR
, "Lan9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
671 DefaultMacAddress
= FixedPcdGet64 (PcdLan9118DefaultMacAddress
);
672 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) &DefaultMacAddress
, Snp
);
675 // Otherwise use the specified new MAC address
676 if (NewMac
== NULL
) {
677 return EFI_INVALID_PARAMETER
;
681 Lan9118SetMacAddress (NewMac
, Snp
);
688 * UEFI Statistics() function
694 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
696 IN OUT UINTN
*StatSize
,
697 OUT EFI_NETWORK_STATISTICS
*Statistics
700 LAN9118_DRIVER
*LanDriver
;
702 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
704 DEBUG ((DEBUG_NET
, "SnpStatistics()\n"));
706 // Check Snp instance
708 return EFI_INVALID_PARAMETER
;
711 // Check that driver was started and initialised
712 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
713 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
714 return EFI_DEVICE_ERROR
;
715 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
716 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
717 return EFI_NOT_STARTED
;
720 // Check pointless condition
721 if ((!Reset
) && (StatSize
== NULL
) && (Statistics
== NULL
)) {
725 // Check the parameters
726 if ((StatSize
== NULL
) && (Statistics
!= NULL
)) {
727 return EFI_INVALID_PARAMETER
;
730 // Do a reset if required
732 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
736 if (*StatSize
< sizeof(EFI_NETWORK_STATISTICS
)) {
737 *StatSize
= sizeof(EFI_NETWORK_STATISTICS
);
738 return EFI_BUFFER_TOO_SMALL
;
741 // Fill in the statistics
742 CopyMem(&Statistics
, &LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
748 * UEFI MCastIPtoMAC() function
754 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
756 IN EFI_IP_ADDRESS
*Ip
,
757 OUT EFI_MAC_ADDRESS
*McastMac
760 DEBUG ((DEBUG_NET
, "SnpMcastIptoMac()\n"));
762 // Check Snp instance
764 return EFI_INVALID_PARAMETER
;
767 // Check that driver was started and initialised
768 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
769 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
770 return EFI_DEVICE_ERROR
;
771 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
772 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
773 return EFI_NOT_STARTED
;
777 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
778 return EFI_INVALID_PARAMETER
;
781 // Make sure MAC address is empty
782 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
784 // If we need ipv4 address
786 // Most significant 25 bits of a multicast HW address are set.
787 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
788 McastMac
->Addr
[0] = 0x01;
789 McastMac
->Addr
[1] = 0x00;
790 McastMac
->Addr
[2] = 0x5E;
792 // Lower 23 bits from ipv4 address
793 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
794 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
795 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
797 // Most significant 16 bits of multicast v6 HW address are set
798 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
799 McastMac
->Addr
[0] = 0x33;
800 McastMac
->Addr
[1] = 0x33;
802 // lower four octets are taken from ipv6 address
803 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
804 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
805 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
806 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
813 * UEFI NvData() function
819 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
820 IN BOOLEAN read_write
,
826 DEBUG ((DEBUG_NET
, "SnpNvData()\n"));
828 return EFI_UNSUPPORTED
;
833 * UEFI GetStatus () function
839 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
840 OUT UINT32
*IrqStat OPTIONAL
,
841 OUT VOID
**TxBuff OPTIONAL
846 UINTN NumTxStatusEntries
;
850 LAN9118_DRIVER
*LanDriver
;
852 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
854 // Check preliminaries
856 return EFI_INVALID_PARAMETER
;
859 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
860 return EFI_NOT_STARTED
;
863 // Check and acknowledge TX Status interrupt (this will happen if the
864 // consumer of SNP does not call GetStatus.)
865 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
866 // should check for it and dump the TX Status FIFO.
867 FifoInt
= MmioRead32 (LAN9118_FIFO_INT
);
869 // Clear the TX Status FIFO Overflow
870 if ((FifoInt
& INSTS_TXSO
) == 0) {
871 FifoInt
|= INSTS_TXSO
;
872 MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
875 // Read interrupt status if IrqStat is not NULL
876 if (IrqStat
!= NULL
) {
878 // Check for receive interrupt
879 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
880 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
881 MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
883 *IrqStat
&= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
886 // Check for transmit interrupt
887 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
888 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
889 MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
891 *IrqStat
&= ~EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
894 // Check for software interrupt
895 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
896 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
897 MmioWrite32 (LAN9118_INT_STS
,INSTS_SW_INT
);
899 *IrqStat
&= ~EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
903 // Check Status of transmitted packets
904 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
906 NumTxStatusEntries
= MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
907 if (NumTxStatusEntries
> 0) {
908 TxStatus
= MmioRead32 (LAN9118_TX_STATUS
);
909 PacketTag
= TxStatus
>> 16;
910 TxStatus
= TxStatus
& 0xFFFF;
911 if ((TxStatus
& TXSTATUS_ES
) && TxStatus
!= (TXSTATUS_ES
| TXSTATUS_NO_CA
)) {
912 DEBUG ((EFI_D_ERROR
, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus
));
913 if (TxStatus
& TXSTATUS_NO_CA
) {
914 DEBUG ((EFI_D_ERROR
, "- No carrier\n"));
916 if (TxStatus
& TXSTATUS_DEF
) {
917 DEBUG ((EFI_D_ERROR
, "- Packet tx was deferred\n"));
919 if (TxStatus
& TXSTATUS_EDEF
) {
920 DEBUG ((EFI_D_ERROR
, "- Tx ended because of excessive deferral\n"));
922 if (TxStatus
& TXSTATUS_ECOLL
) {
923 DEBUG ((EFI_D_ERROR
, "- Tx ended because of Excessive Collisions\n"));
925 if (TxStatus
& TXSTATUS_LCOLL
) {
926 DEBUG ((EFI_D_ERROR
, "- Packet Tx aborted after coll window of 64 bytes\n"));
928 if (TxStatus
& TXSTATUS_LOST_CA
) {
929 DEBUG ((EFI_D_ERROR
, "- Lost carrier during Tx\n"));
931 return EFI_DEVICE_ERROR
;
933 LanDriver
->Stats
.TxTotalFrames
+= 1;
934 *TxBuff
= LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
];
938 // Check for a TX Error interrupt
939 Interrupts
= MmioRead32 (LAN9118_INT_STS
);
940 if (Interrupts
& INSTS_TXE
) {
941 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
943 // Initiate a software reset
944 if (SoftReset (0, Snp
) < 0) {
945 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
946 return EFI_DEVICE_ERROR
;
949 // Acknowledge the TXE
950 MmioWrite32 (LAN9118_INT_STS
, INSTS_TXE
);
951 gBS
->Stall (LAN9118_STALL
);
953 // Restart the transmitter
954 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
957 // Update the media status
958 Status
= CheckLinkStatus (0, Snp
);
959 if (EFI_ERROR(Status
)) {
960 Snp
->Mode
->MediaPresent
= FALSE
;
962 Snp
->Mode
->MediaPresent
= TRUE
;
970 * UEFI Transmit() function
976 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
980 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
981 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
982 IN UINT16
*Protocol OPTIONAL
985 LAN9118_DRIVER
*LanDriver
;
987 UINT32 TxStatusSpace
;
991 UINT16 LocalProtocol
;
995 #if defined(EVAL_PERFORMANCE)
1000 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1001 StartClock
= GetPerformanceCounter ();
1004 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1006 // Check preliminaries
1007 if ((Snp
== NULL
) || (Data
== NULL
)) {
1008 return EFI_INVALID_PARAMETER
;
1010 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
1011 return EFI_NOT_STARTED
;
1014 // Ensure header is correct size if non-zero
1016 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1017 return EFI_INVALID_PARAMETER
;
1020 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1021 return EFI_INVALID_PARAMETER
;
1025 // Before transmitting check the link status
1026 /*if (CheckLinkStatus (0, Snp) < 0) {
1027 return EFI_NOT_READY;
1030 // Get DATA FIFO free space in bytes
1031 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1032 if (TxFreeSpace
< BuffSize
) {
1033 return EFI_NOT_READY
;
1036 // Get STATUS FIFO used space in bytes
1037 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1038 if (TxStatusSpace
> 500) {
1039 return EFI_NOT_READY
;
1042 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1043 // has provided a well-formed frame).
1044 if (DstAddr
== NULL
) {
1045 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1048 // Check for the nature of the frame
1049 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1050 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1052 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1055 // Check if broadcast
1056 if (DstAddr
->Addr
[0] == 0xFF) {
1057 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1060 PacketTag
= LanDriver
->NextPacketTag
;
1061 LanDriver
->NextPacketTag
++;
1066 LocalData
= (UINT32
*) Data
;
1067 LocalProtocol
= *Protocol
;
1069 // Create first buffer to pass to controller (for the header)
1070 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1071 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1073 // Write the commands first
1074 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1075 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1077 // Write the destination address
1078 MmioWrite32 (LAN9118_TX_DATA
,
1079 (DstAddr
->Addr
[0]) |
1080 (DstAddr
->Addr
[1] << 8) |
1081 (DstAddr
->Addr
[2] << 16) |
1082 (DstAddr
->Addr
[3] << 24)
1085 MmioWrite32 (LAN9118_TX_DATA
,
1086 (DstAddr
->Addr
[4]) |
1087 (DstAddr
->Addr
[5] << 8) |
1088 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1089 (SrcAddr
->Addr
[1] << 24)
1092 MmioWrite32 (LAN9118_TX_DATA
,
1093 (SrcAddr
->Addr
[2]) |
1094 (SrcAddr
->Addr
[3] << 8) |
1095 (SrcAddr
->Addr
[4] << 16) |
1096 (SrcAddr
->Addr
[5] << 24)
1099 // Write the Protocol
1100 MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1102 // Next buffer is the payload
1103 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
1105 // Write the commands
1106 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1107 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1109 // Write the payload
1110 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1111 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1115 LocalData
= (UINT32
*) Data
;
1117 // Create a buffer to pass to controller
1118 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1119 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1121 // Write the commands first
1122 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1123 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1125 // Write all the data
1126 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1127 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1131 // Save the address of the submitted packet so we can notify the consumer that
1132 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1133 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1134 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1136 #if defined(EVAL_PERFORMANCE)
1137 EndClock
= GetPerformanceCounter ();
1138 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1141 LanDriver
->Stats
.TxGoodFrames
+= 1;
1148 * UEFI Receive() function
1154 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1155 OUT UINTN
*HdrSize OPTIONAL
,
1156 IN OUT UINTN
*BuffSize
,
1158 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1159 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1160 OUT UINT16
*Protocol OPTIONAL
1163 LAN9118_DRIVER
*LanDriver
;
1164 UINT32 RxFifoStatus
;
1167 UINT32 PLength
; // Packet length
1172 EFI_MAC_ADDRESS Dst
;
1173 EFI_MAC_ADDRESS Src
;
1174 UINTN DroppedFrames
;
1176 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1178 #if defined(EVAL_PERFORMANCE)
1179 UINT64 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1180 UINT64 StartClock
= GetPerformanceCounter ();
1183 // Check preliminaries
1184 if ((Snp
== NULL
) || (Data
== NULL
)) {
1185 return EFI_INVALID_PARAMETER
;
1188 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
1189 return EFI_NOT_STARTED
;
1192 // Count dropped frames
1193 DroppedFrames
= MmioRead32 (LAN9118_RX_DROP
);
1194 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1196 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1198 return EFI_NOT_READY
;
1201 // Read Rx Status (only if not empty)
1202 RxFifoStatus
= MmioRead32 (LAN9118_RX_STATUS
);
1203 LanDriver
->Stats
.RxTotalFrames
+= 1;
1205 // First check for errors
1206 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1207 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1208 (RxFifoStatus
& RXSTATUS_FTL
) ||
1209 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1210 (RxFifoStatus
& RXSTATUS_LE
) ||
1211 (RxFifoStatus
& RXSTATUS_DB
))
1213 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1214 return EFI_DEVICE_ERROR
;
1217 // Check if we got a CRC error
1218 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1219 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1220 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1221 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1222 return EFI_DEVICE_ERROR
;
1225 // Check if we got a runt frame
1226 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1227 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1228 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1229 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1230 return EFI_DEVICE_ERROR
;
1233 // Check filtering status for this packet
1234 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1235 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1239 // Check if we got a broadcast frame
1240 if (RxFifoStatus
& RXSTATUS_BCF
) {
1241 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1244 // Check if we got a multicast frame
1245 if (RxFifoStatus
& RXSTATUS_MCF
) {
1246 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1249 // Check if we got a unicast frame
1250 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1251 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1254 // Get the received packet length
1255 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1256 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1258 // Check buffer size
1259 if (*BuffSize
< PLength
) {
1260 *BuffSize
= PLength
;
1261 return EFI_BUFFER_TOO_SMALL
;
1264 // If padding is applied, read more DWORDs
1266 Padding
= 4 - (PLength
% 4);
1267 ReadLimit
= (PLength
+ Padding
)/4;
1269 ReadLimit
= PLength
/4;
1273 // Set the amount of data to be transfered out of FIFO for THIS packet
1274 // This can be used to trigger an interrupt, and status can be checked
1275 RxCfgValue
= MmioRead32 (LAN9118_RX_CFG
);
1276 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1277 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1279 // Set end alignment to 4-bytes
1280 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1281 MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1283 // Update buffer size
1284 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1285 // 4 bytes longer than packet actually is, unless
1286 // packet is < 64 bytes
1288 if (HdrSize
!= NULL
)
1289 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1291 // Format the pointer
1292 RawData
= (UINT32
*)Data
;
1295 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1296 RawData
[Count
] = MmioRead32 (LAN9118_RX_DATA
);
1299 // Check for Rx errors (worst possible error)
1300 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1301 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1303 // Initiate a software reset
1304 if (SoftReset (0, Snp
) < 0) {
1305 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1306 return EFI_DEVICE_ERROR
;
1309 // Acknowledge the RXE
1310 MmioWrite32 (LAN9118_INT_STS
, INSTS_RXE
);
1311 gBS
->Stall (LAN9118_STALL
);
1313 // Restart the rx (and do not clear FIFO)
1316 // Say that command could not be sent
1317 return EFI_DEVICE_ERROR
;
1320 // Get the destination address
1321 if (DstAddr
!= NULL
) {
1322 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1323 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1324 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1325 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1326 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1327 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1328 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1331 // Get the source address
1332 if (SrcAddr
!= NULL
) {
1333 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1334 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1335 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1336 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1337 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1338 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1339 CopyMem (SrcAddr
,&Src
, NET_ETHER_ADDR_LEN
);
1343 if (Protocol
!= NULL
) {
1344 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1347 #if defined(EVAL_PERFORMANCE)
1348 UINT64 EndClock
= GetPerformanceCounter ();
1349 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1352 LanDriver
->Stats
.RxGoodFrames
+= 1;