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 Status
= PhySoftReset (PHY_RESET_PMT
| PHY_RESET_CHECK_LINK
, Snp
);
279 if (EFI_ERROR (Status
)) {
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
388 // Check Snp Instance
390 return EFI_INVALID_PARAMETER
;
393 // First check that driver has not already been initialized
394 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
395 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
396 return EFI_DEVICE_ERROR
;
397 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
398 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
399 return EFI_NOT_STARTED
;
402 // Initiate a PHY reset
403 Status
= PhySoftReset (PHY_RESET_PMT
| PHY_RESET_CHECK_LINK
, Snp
);
404 if (EFI_ERROR (Status
)) {
405 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
406 return EFI_NOT_STARTED
;
409 // Initiate a software reset
410 ResetFlags
|= SOFT_RESET_CHECK_MAC_ADDR_LOAD
| SOFT_RESET_CLEAR_INT
;
413 ResetFlags
|= SOFT_RESET_SELF_TEST
;
416 Status
= SoftReset (ResetFlags
, Snp
);
417 if (EFI_ERROR (Status
)) {
418 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
419 return EFI_DEVICE_ERROR
;
422 // Read the PM register
423 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
425 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
426 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
427 // MPTCTRL_PME_EN: Allow Power Management Events
428 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
430 // Write the current configuration to the register
431 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
432 gBS
->Stall (LAN9118_STALL
);
434 // Check that a buffer size was specified in SnpInitialize
435 if (gTxBuffer
!= 0) {
436 HwConf
= MmioRead32 (LAN9118_HW_CFG
); // Read the HW register
437 HwConf
&= ~HW_CFG_TX_FIFO_SIZE_MASK
; // Clear buffer bits first
438 HwConf
|= HW_CFG_TX_FIFO_SIZE(gTxBuffer
); // assign size chosen in SnpInitialize
440 MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
441 gBS
->Stall (LAN9118_STALL
);
444 // Enable the receiver and transmitter and clear their contents
445 StartRx (START_RX_CLEAR
, Snp
);
446 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
448 // Now acknowledge all interrupts
449 MmioWrite32 (LAN9118_INT_STS
, ~0);
455 * UEFI Shutdown () function
461 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
466 // Check Snp Instance
468 return EFI_INVALID_PARAMETER
;
471 // First check that driver has not already been initialized
472 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
473 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
474 return EFI_DEVICE_ERROR
;
475 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
476 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
477 return EFI_NOT_STARTED
;
480 // Initiate a PHY reset
481 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
482 if (EFI_ERROR (Status
)) {
486 // Initiate a software reset
487 Status
= SoftReset (0, Snp
);
488 if (EFI_ERROR (Status
)) {
489 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
498 * UEFI ReceiveFilters() function
504 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
508 IN UINTN NumMfilter OPTIONAL
,
509 IN EFI_MAC_ADDRESS
*Mfilter OPTIONAL
513 UINT32 MultHashTableHigh
;
514 UINT32 MultHashTableLow
;
520 MultHashTableHigh
= 0;
521 MultHashTableLow
= 0;
526 // Check that driver was started and initialised
527 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
528 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
529 return EFI_DEVICE_ERROR
;
530 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
531 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
532 return EFI_NOT_STARTED
;
535 // If reset then clear the filter registers
537 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
538 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, 0x00000000);
539 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, 0x00000000);
542 // Set the hash tables
543 if ((NumMfilter
> 0) && (!Reset
)) {
545 // Read the Multicast High Hash Table
546 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
548 // Read the Multicast Low Hash Table
549 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
551 // Go through each filter address and set appropriate bits on hash table
552 for (Count
= 0; Count
< NumMfilter
; Count
++) {
554 // Generate a 32-bit CRC for Ethernet
555 Crc
= GenEtherCrc32 (&Mfilter
[Count
],6);
556 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
558 // Get the most significant 6 bits to index hash registers
559 BitToSelect
= (Crc
>> 26) & 0x3F;
561 // Select hashlow register if MSB is not set
562 if ((BitToSelect
& 0x20) == 0) {
563 MultHashTableLow
|= (1 << BitToSelect
);
565 MultHashTableHigh
|= (1 << (BitToSelect
& 0x1F));
569 // Write the desired hash
570 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
571 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
574 // Read MAC controller
575 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
577 // Set the options for the MAC_CSR
578 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
580 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
583 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
585 DEBUG ((DEBUG_NET
, "Disabling Unicast Frame Reception\n"));
588 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
589 MacCSRValue
|= MACCR_HPFILT
;
590 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
593 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
594 MacCSRValue
&= ~MACCR_HPFILT
;
595 DEBUG ((DEBUG_NET
, "Disabling Multicast Frame Reception\n"));
598 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) {
599 MacCSRValue
&= ~(MACCR_BCAST
);
600 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
603 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) {
604 MacCSRValue
|= MACCR_BCAST
;
605 DEBUG ((DEBUG_NET
, "Disabling Broadcast Frame Reception\n"));
608 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
609 MacCSRValue
|= MACCR_PRMS
;
610 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
613 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
614 MacCSRValue
&= ~MACCR_PRMS
;
615 DEBUG ((DEBUG_NET
, "Disabling Promiscuous Mode\n"));
618 if (Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
619 MacCSRValue
|= (MACCR_HPFILT
| MACCR_PRMS
);
620 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
623 if (Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
624 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_PRMS
);
625 DEBUG ((DEBUG_NET
, "Disabling Promiscuous Multicast Mode\n"));
628 // Write the options to the MAC_CSR
629 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
630 gBS
->Stall (LAN9118_STALL
);
636 * UEFI StationAddress() function
642 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
644 IN EFI_MAC_ADDRESS
*NewMac
647 DEBUG ((DEBUG_NET
, "SnpStationAddress()\n"));
651 UINT64 DefaultMacAddress
;
655 // Check Snp instance
657 return EFI_INVALID_PARAMETER
;
660 // Check that driver was started and initialised
661 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
662 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
663 return EFI_DEVICE_ERROR
;
664 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
665 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
666 return EFI_NOT_STARTED
;
669 // Get the Permanent MAC address if need reset
671 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
672 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM
) {
673 for (Count
= 1; Count
< 7; Count
++) {
674 PermAddr
[Count
- 1] = IndirectEEPROMRead32 (Count
);
678 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) PermAddr
, Snp
);
680 DEBUG ((EFI_D_ERROR
, "Lan9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
681 DefaultMacAddress
= FixedPcdGet64 (PcdLan9118DefaultMacAddress
);
682 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) &DefaultMacAddress
, Snp
);
685 // Otherwise use the specified new MAC address
686 if (NewMac
== NULL
) {
687 return EFI_INVALID_PARAMETER
;
691 Lan9118SetMacAddress (NewMac
, Snp
);
698 * UEFI Statistics() function
704 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
706 IN OUT UINTN
*StatSize
,
707 OUT EFI_NETWORK_STATISTICS
*Statistics
710 LAN9118_DRIVER
*LanDriver
;
712 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
714 DEBUG ((DEBUG_NET
, "SnpStatistics()\n"));
716 // Check Snp instance
718 return EFI_INVALID_PARAMETER
;
721 // Check that driver was started and initialised
722 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
723 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
724 return EFI_DEVICE_ERROR
;
725 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
726 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
727 return EFI_NOT_STARTED
;
730 // Check pointless condition
731 if ((!Reset
) && (StatSize
== NULL
) && (Statistics
== NULL
)) {
735 // Check the parameters
736 if ((StatSize
== NULL
) && (Statistics
!= NULL
)) {
737 return EFI_INVALID_PARAMETER
;
740 // Do a reset if required
742 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
746 if (*StatSize
< sizeof(EFI_NETWORK_STATISTICS
)) {
747 *StatSize
= sizeof(EFI_NETWORK_STATISTICS
);
748 return EFI_BUFFER_TOO_SMALL
;
751 // Fill in the statistics
752 CopyMem (Statistics
, &LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
758 * UEFI MCastIPtoMAC() function
764 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
766 IN EFI_IP_ADDRESS
*Ip
,
767 OUT EFI_MAC_ADDRESS
*McastMac
770 DEBUG ((DEBUG_NET
, "SnpMcastIptoMac()\n"));
772 // Check Snp instance
774 return EFI_INVALID_PARAMETER
;
777 // Check that driver was started and initialised
778 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
779 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
780 return EFI_DEVICE_ERROR
;
781 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
782 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
783 return EFI_NOT_STARTED
;
787 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
788 return EFI_INVALID_PARAMETER
;
791 // Make sure MAC address is empty
792 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
794 // If we need ipv4 address
796 // Most significant 25 bits of a multicast HW address are set.
797 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
798 McastMac
->Addr
[0] = 0x01;
799 McastMac
->Addr
[1] = 0x00;
800 McastMac
->Addr
[2] = 0x5E;
802 // Lower 23 bits from ipv4 address
803 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
804 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
805 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
807 // Most significant 16 bits of multicast v6 HW address are set
808 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
809 McastMac
->Addr
[0] = 0x33;
810 McastMac
->Addr
[1] = 0x33;
812 // lower four octets are taken from ipv6 address
813 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
814 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
815 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
816 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
823 * UEFI NvData() function
829 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
830 IN BOOLEAN read_write
,
836 DEBUG ((DEBUG_NET
, "SnpNvData()\n"));
838 return EFI_UNSUPPORTED
;
843 * UEFI GetStatus () function
849 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
850 OUT UINT32
*IrqStat OPTIONAL
,
851 OUT VOID
**TxBuff OPTIONAL
856 UINTN NumTxStatusEntries
;
860 LAN9118_DRIVER
*LanDriver
;
862 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
864 // Check preliminaries
866 return EFI_INVALID_PARAMETER
;
869 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
870 return EFI_NOT_STARTED
;
873 // Check and acknowledge TX Status interrupt (this will happen if the
874 // consumer of SNP does not call GetStatus.)
875 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
876 // should check for it and dump the TX Status FIFO.
877 FifoInt
= MmioRead32 (LAN9118_FIFO_INT
);
879 // Clear the TX Status FIFO Overflow
880 if ((FifoInt
& INSTS_TXSO
) == 0) {
881 FifoInt
|= INSTS_TXSO
;
882 MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
885 // Read interrupt status if IrqStat is not NULL
886 if (IrqStat
!= NULL
) {
888 // Check for receive interrupt
889 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
890 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
891 MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
893 *IrqStat
&= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
896 // Check for transmit interrupt
897 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
898 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
899 MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
901 *IrqStat
&= ~EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
904 // Check for software interrupt
905 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
906 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
907 MmioWrite32 (LAN9118_INT_STS
,INSTS_SW_INT
);
909 *IrqStat
&= ~EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
913 // Check Status of transmitted packets
914 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
916 NumTxStatusEntries
= MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
917 if (NumTxStatusEntries
> 0) {
918 TxStatus
= MmioRead32 (LAN9118_TX_STATUS
);
919 PacketTag
= TxStatus
>> 16;
920 TxStatus
= TxStatus
& 0xFFFF;
921 if ((TxStatus
& TXSTATUS_ES
) && TxStatus
!= (TXSTATUS_ES
| TXSTATUS_NO_CA
)) {
922 DEBUG ((EFI_D_ERROR
, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus
));
923 if (TxStatus
& TXSTATUS_NO_CA
) {
924 DEBUG ((EFI_D_ERROR
, "- No carrier\n"));
926 if (TxStatus
& TXSTATUS_DEF
) {
927 DEBUG ((EFI_D_ERROR
, "- Packet tx was deferred\n"));
929 if (TxStatus
& TXSTATUS_EDEF
) {
930 DEBUG ((EFI_D_ERROR
, "- Tx ended because of excessive deferral\n"));
932 if (TxStatus
& TXSTATUS_ECOLL
) {
933 DEBUG ((EFI_D_ERROR
, "- Tx ended because of Excessive Collisions\n"));
935 if (TxStatus
& TXSTATUS_LCOLL
) {
936 DEBUG ((EFI_D_ERROR
, "- Packet Tx aborted after coll window of 64 bytes\n"));
938 if (TxStatus
& TXSTATUS_LOST_CA
) {
939 DEBUG ((EFI_D_ERROR
, "- Lost carrier during Tx\n"));
941 return EFI_DEVICE_ERROR
;
943 LanDriver
->Stats
.TxTotalFrames
+= 1;
944 *TxBuff
= LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
];
948 // Check for a TX Error interrupt
949 Interrupts
= MmioRead32 (LAN9118_INT_STS
);
950 if (Interrupts
& INSTS_TXE
) {
951 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
953 // Initiate a software reset
954 Status
= SoftReset (0, Snp
);
955 if (EFI_ERROR (Status
)) {
956 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
957 return EFI_DEVICE_ERROR
;
960 // Acknowledge the TXE
961 MmioWrite32 (LAN9118_INT_STS
, INSTS_TXE
);
962 gBS
->Stall (LAN9118_STALL
);
964 // Restart the transmitter
965 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
968 // Update the media status
969 Status
= CheckLinkStatus (0, Snp
);
970 if (EFI_ERROR(Status
)) {
971 Snp
->Mode
->MediaPresent
= FALSE
;
973 Snp
->Mode
->MediaPresent
= TRUE
;
981 * UEFI Transmit() function
987 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
991 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
992 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
993 IN UINT16
*Protocol OPTIONAL
996 LAN9118_DRIVER
*LanDriver
;
998 UINT32 TxStatusSpace
;
1002 UINT16 LocalProtocol
;
1006 #if defined(EVAL_PERFORMANCE)
1011 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1012 StartClock
= GetPerformanceCounter ();
1015 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1017 // Check preliminaries
1018 if ((Snp
== NULL
) || (Data
== NULL
)) {
1019 return EFI_INVALID_PARAMETER
;
1021 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
1022 return EFI_NOT_STARTED
;
1025 // Ensure header is correct size if non-zero
1027 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1028 return EFI_INVALID_PARAMETER
;
1031 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1032 return EFI_INVALID_PARAMETER
;
1036 // Before transmitting check the link status
1037 /*if (CheckLinkStatus (0, Snp) < 0) {
1038 return EFI_NOT_READY;
1041 // Get DATA FIFO free space in bytes
1042 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1043 if (TxFreeSpace
< BuffSize
) {
1044 return EFI_NOT_READY
;
1047 // Get STATUS FIFO used space in bytes
1048 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1049 if (TxStatusSpace
> 500) {
1050 return EFI_NOT_READY
;
1053 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1054 // has provided a well-formed frame).
1055 if (DstAddr
== NULL
) {
1056 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1059 // Check for the nature of the frame
1060 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1061 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1063 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1066 // Check if broadcast
1067 if (DstAddr
->Addr
[0] == 0xFF) {
1068 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1071 PacketTag
= LanDriver
->NextPacketTag
;
1072 LanDriver
->NextPacketTag
++;
1077 LocalData
= (UINT32
*) Data
;
1078 LocalProtocol
= *Protocol
;
1080 // Create first buffer to pass to controller (for the header)
1081 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1082 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1084 // Write the commands first
1085 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1086 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1088 // Write the destination address
1089 MmioWrite32 (LAN9118_TX_DATA
,
1090 (DstAddr
->Addr
[0]) |
1091 (DstAddr
->Addr
[1] << 8) |
1092 (DstAddr
->Addr
[2] << 16) |
1093 (DstAddr
->Addr
[3] << 24)
1096 MmioWrite32 (LAN9118_TX_DATA
,
1097 (DstAddr
->Addr
[4]) |
1098 (DstAddr
->Addr
[5] << 8) |
1099 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1100 (SrcAddr
->Addr
[1] << 24)
1103 MmioWrite32 (LAN9118_TX_DATA
,
1104 (SrcAddr
->Addr
[2]) |
1105 (SrcAddr
->Addr
[3] << 8) |
1106 (SrcAddr
->Addr
[4] << 16) |
1107 (SrcAddr
->Addr
[5] << 24)
1110 // Write the Protocol
1111 MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1113 // Next buffer is the payload
1114 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
1116 // Write the commands
1117 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1118 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1120 // Write the payload
1121 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1122 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1126 LocalData
= (UINT32
*) Data
;
1128 // Create a buffer to pass to controller
1129 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1130 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1132 // Write the commands first
1133 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1134 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1136 // Write all the data
1137 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1138 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1142 // Save the address of the submitted packet so we can notify the consumer that
1143 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1144 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1145 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1147 #if defined(EVAL_PERFORMANCE)
1148 EndClock
= GetPerformanceCounter ();
1149 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1152 LanDriver
->Stats
.TxGoodFrames
+= 1;
1159 * UEFI Receive() function
1165 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1166 OUT UINTN
*HdrSize OPTIONAL
,
1167 IN OUT UINTN
*BuffSize
,
1169 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1170 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1171 OUT UINT16
*Protocol OPTIONAL
1174 LAN9118_DRIVER
*LanDriver
;
1175 UINT32 RxFifoStatus
;
1178 UINT32 PLength
; // Packet length
1183 EFI_MAC_ADDRESS Dst
;
1184 EFI_MAC_ADDRESS Src
;
1185 UINTN DroppedFrames
;
1188 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1190 #if defined(EVAL_PERFORMANCE)
1191 UINT64 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1192 UINT64 StartClock
= GetPerformanceCounter ();
1195 // Check preliminaries
1196 if ((Snp
== NULL
) || (Data
== NULL
)) {
1197 return EFI_INVALID_PARAMETER
;
1200 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
1201 return EFI_NOT_STARTED
;
1204 // Count dropped frames
1205 DroppedFrames
= MmioRead32 (LAN9118_RX_DROP
);
1206 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1208 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1210 return EFI_NOT_READY
;
1213 // Read Rx Status (only if not empty)
1214 RxFifoStatus
= MmioRead32 (LAN9118_RX_STATUS
);
1215 LanDriver
->Stats
.RxTotalFrames
+= 1;
1217 // First check for errors
1218 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1219 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1220 (RxFifoStatus
& RXSTATUS_FTL
) ||
1221 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1222 (RxFifoStatus
& RXSTATUS_LE
) ||
1223 (RxFifoStatus
& RXSTATUS_DB
))
1225 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1226 return EFI_DEVICE_ERROR
;
1229 // Check if we got a CRC error
1230 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1231 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1232 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1233 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1234 return EFI_DEVICE_ERROR
;
1237 // Check if we got a runt frame
1238 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1239 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1240 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1241 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1242 return EFI_DEVICE_ERROR
;
1245 // Check filtering status for this packet
1246 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1247 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1251 // Check if we got a broadcast frame
1252 if (RxFifoStatus
& RXSTATUS_BCF
) {
1253 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1256 // Check if we got a multicast frame
1257 if (RxFifoStatus
& RXSTATUS_MCF
) {
1258 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1261 // Check if we got a unicast frame
1262 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1263 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1266 // Get the received packet length
1267 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1268 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1270 // Check buffer size
1271 if (*BuffSize
< PLength
) {
1272 *BuffSize
= PLength
;
1273 return EFI_BUFFER_TOO_SMALL
;
1276 // If padding is applied, read more DWORDs
1278 Padding
= 4 - (PLength
% 4);
1279 ReadLimit
= (PLength
+ Padding
)/4;
1281 ReadLimit
= PLength
/4;
1285 // Set the amount of data to be transfered out of FIFO for THIS packet
1286 // This can be used to trigger an interrupt, and status can be checked
1287 RxCfgValue
= MmioRead32 (LAN9118_RX_CFG
);
1288 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1289 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1291 // Set end alignment to 4-bytes
1292 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1293 MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1295 // Update buffer size
1296 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1297 // 4 bytes longer than packet actually is, unless
1298 // packet is < 64 bytes
1300 if (HdrSize
!= NULL
)
1301 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1303 // Format the pointer
1304 RawData
= (UINT32
*)Data
;
1307 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1308 RawData
[Count
] = MmioRead32 (LAN9118_RX_DATA
);
1311 // Check for Rx errors (worst possible error)
1312 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1313 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1315 // Initiate a software reset
1316 Status
= SoftReset (0, Snp
);
1317 if (EFI_ERROR (Status
)) {
1318 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1319 return EFI_DEVICE_ERROR
;
1322 // Acknowledge the RXE
1323 MmioWrite32 (LAN9118_INT_STS
, INSTS_RXE
);
1324 gBS
->Stall (LAN9118_STALL
);
1326 // Restart the rx (and do not clear FIFO)
1329 // Say that command could not be sent
1330 return EFI_DEVICE_ERROR
;
1333 // Get the destination address
1334 if (DstAddr
!= NULL
) {
1335 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1336 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1337 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1338 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1339 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1340 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1341 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1344 // Get the source address
1345 if (SrcAddr
!= NULL
) {
1346 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1347 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1348 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1349 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1350 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1351 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1352 CopyMem (SrcAddr
,&Src
, NET_ETHER_ADDR_LEN
);
1356 if (Protocol
!= NULL
) {
1357 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1360 #if defined(EVAL_PERFORMANCE)
1361 UINT64 EndClock
= GetPerformanceCounter ();
1362 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1365 LanDriver
->Stats
.RxGoodFrames
+= 1;