3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
5 * SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "Lan9118Dxe.h"
12 MAC_ADDR_DEVICE_PATH Lan9118
;
13 EFI_DEVICE_PATH_PROTOCOL End
;
14 } LAN9118_DEVICE_PATH
;
16 LAN9118_DEVICE_PATH Lan9118PathTemplate
= {
19 MESSAGING_DEVICE_PATH
, MSG_MAC_ADDR_DP
,
20 { (UINT8
) (sizeof(MAC_ADDR_DEVICE_PATH
)), (UINT8
) ((sizeof(MAC_ADDR_DEVICE_PATH
)) >> 8) }
27 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
28 { sizeof(EFI_DEVICE_PATH_PROTOCOL
), 0 }
33 ** Entry point for the LAN9118 driver
40 IN EFI_SYSTEM_TABLE
*SystemTable
44 LAN9118_DRIVER
*LanDriver
;
45 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
46 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
47 LAN9118_DEVICE_PATH
*Lan9118Path
;
48 EFI_HANDLE ControllerHandle
;
50 // The PcdLan9118DxeBaseAddress PCD must be defined
51 ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress
) != 0);
54 LanDriver
= AllocateZeroPool (sizeof (LAN9118_DRIVER
));
55 if (LanDriver
== NULL
) {
56 return EFI_OUT_OF_RESOURCES
;
58 Lan9118Path
= (LAN9118_DEVICE_PATH
*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH
), &Lan9118PathTemplate
);
59 if (Lan9118Path
== NULL
) {
60 return EFI_OUT_OF_RESOURCES
;
63 // Initialize pointers
64 Snp
= &(LanDriver
->Snp
);
65 SnpMode
= &(LanDriver
->SnpMode
);
68 // Set the signature of the LAN Driver structure
69 LanDriver
->Signature
= LAN9118_SIGNATURE
;
71 // Assign fields and func pointers
72 Snp
->Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
73 Snp
->WaitForPacket
= NULL
;
74 Snp
->Initialize
= SnpInitialize
;
75 Snp
->Start
= SnpStart
;
77 Snp
->Reset
= SnpReset
;
78 Snp
->Shutdown
= SnpShutdown
;
79 Snp
->ReceiveFilters
= SnpReceiveFilters
;
80 Snp
->StationAddress
= SnpStationAddress
;
81 Snp
->Statistics
= SnpStatistics
;
82 Snp
->MCastIpToMac
= SnpMcastIptoMac
;
83 Snp
->NvData
= SnpNvData
;
84 Snp
->GetStatus
= SnpGetStatus
;
85 Snp
->Transmit
= SnpTransmit
;
86 Snp
->Receive
= SnpReceive
;
88 // Start completing simple network mode structure
89 SnpMode
->State
= EfiSimpleNetworkStopped
;
90 SnpMode
->HwAddressSize
= NET_ETHER_ADDR_LEN
; // HW address is 6 bytes
91 SnpMode
->MediaHeaderSize
= sizeof(ETHER_HEAD
); // Not sure of this
92 SnpMode
->MaxPacketSize
= EFI_PAGE_SIZE
; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
93 SnpMode
->NvRamSize
= 0; // No NVRAM with this device
94 SnpMode
->NvRamAccessSize
= 0; // No NVRAM with this device
97 // Claim that all receive filter settings are supported, though the MULTICAST mode
98 // is not completely supported. The LAN9118 Ethernet controller is only able to
99 // do a "hash filtering" and not a perfect filtering on multicast addresses. The
100 // controller does not filter the multicast addresses directly but a hash value
101 // of them. The hash value of a multicast address is derived from its CRC and
102 // ranges from 0 to 63 included.
103 // We claim that the perfect MULTICAST filtering mode is supported because
104 // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode
105 // and thus not being able to take advantage of the hash filtering.
107 SnpMode
->ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
108 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
109 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
110 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
|
111 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
113 // We do not intend to receive anything for the time being.
114 SnpMode
->ReceiveFilterSetting
= 0;
116 // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses
117 SnpMode
->MaxMCastFilterCount
= MAX_MCAST_FILTER_CNT
;
118 SnpMode
->MCastFilterCount
= 0;
119 ZeroMem (&SnpMode
->MCastFilter
, MAX_MCAST_FILTER_CNT
* sizeof(EFI_MAC_ADDRESS
));
121 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
122 SnpMode
->IfType
= NET_IFTYPE_ETHERNET
;
124 // Mac address is changeable as it is loaded from erasable memory
125 SnpMode
->MacAddressChangeable
= TRUE
;
127 // Can only transmit one packet at a time
128 SnpMode
->MultipleTxSupported
= FALSE
;
130 // MediaPresent checks for cable connection and partner link
131 SnpMode
->MediaPresentSupported
= TRUE
;
132 SnpMode
->MediaPresent
= FALSE
;
134 // Set broadcast address
135 SetMem (&SnpMode
->BroadcastAddress
, sizeof (EFI_MAC_ADDRESS
), 0xFF);
137 // Power up the device so we can find the MAC address
138 Status
= Lan9118Initialize (Snp
);
139 if (EFI_ERROR (Status
)) {
140 DEBUG ((EFI_D_ERROR
, "LAN9118: Error initialising hardware\n"));
141 return EFI_DEVICE_ERROR
;
144 // Assign fields for device path
145 CopyMem (&Lan9118Path
->Lan9118
.MacAddress
, &Snp
->Mode
->CurrentAddress
, NET_ETHER_ADDR_LEN
);
146 Lan9118Path
->Lan9118
.IfType
= Snp
->Mode
->IfType
;
148 // Initialise the protocol
149 ControllerHandle
= NULL
;
150 Status
= gBS
->InstallMultipleProtocolInterfaces (
152 &gEfiSimpleNetworkProtocolGuid
, Snp
,
153 &gEfiDevicePathProtocolGuid
, Lan9118Path
,
156 // Say what the status of loading the protocol structure is
157 if (EFI_ERROR(Status
)) {
158 FreePool (LanDriver
);
160 LanDriver
->ControllerHandle
= ControllerHandle
;
167 * UEFI Start() function
171 * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
175 * This function starts a network interface. If the network interface successfully starts, then
176 * EFI_SUCCESS will be returned.
181 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
184 // Check Snp instance
186 return EFI_INVALID_PARAMETER
;
190 if ((Snp
->Mode
->State
== EfiSimpleNetworkStarted
) ||
191 (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) ) {
192 return EFI_ALREADY_STARTED
;
196 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
201 * UEFI Stop() function
207 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
210 // Check Snp Instance
212 return EFI_INVALID_PARAMETER
;
215 // Check state of the driver
216 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
217 return EFI_NOT_STARTED
;
220 // Stop the Tx and Rx
221 StopTx (STOP_TX_CFG
| STOP_TX_MAC
, Snp
);
225 switch (Snp
->Mode
->State
) {
226 case EfiSimpleNetworkStarted
:
227 case EfiSimpleNetworkInitialized
:
228 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
231 return EFI_DEVICE_ERROR
;
234 // Put the device into a power saving mode ?
239 // Allocated receive and transmit buffers
240 STATIC UINT32 gTxBuffer
= 0;
243 * UEFI Initialize() function
249 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
250 IN UINTN RxBufferSize OPTIONAL
,
251 IN UINTN TxBufferSize OPTIONAL
260 // Initialize variables
261 // Global variables to hold tx and rx FIFO allocation
264 // Check Snp Instance
266 return EFI_INVALID_PARAMETER
;
269 // First check that driver has not already been initialized
270 if (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) {
271 DEBUG ((EFI_D_WARN
, "LAN9118 Driver already initialized\n"));
274 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
275 DEBUG ((EFI_D_WARN
, "LAN9118 Driver not started\n"));
276 return EFI_NOT_STARTED
;
279 // Initiate a PHY reset
280 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
281 if (EFI_ERROR (Status
)) {
282 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
283 DEBUG ((EFI_D_WARN
, "Warning: Link not ready after TimeOut. Check ethernet cable\n"));
284 return EFI_NOT_STARTED
;
287 // Initiate a software reset
288 Status
= SoftReset (0, Snp
);
289 if (EFI_ERROR(Status
)) {
290 DEBUG ((EFI_D_WARN
, "Soft Reset Failed: Hardware Error\n"));
291 return EFI_DEVICE_ERROR
;
294 // Read the PM register
295 PmConf
= Lan9118MmioRead32 (LAN9118_PMT_CTRL
);
297 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
298 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
299 // MPTCTRL_PME_EN: Allow Power Management Events
301 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
303 // Write the current configuration to the register
304 Lan9118MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
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 Negotiation failed.\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 transmitter
349 Status
= StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
350 if (EFI_ERROR(Status
)) {
354 // Now acknowledge all interrupts
355 Lan9118MmioWrite32 (LAN9118_INT_STS
, ~0);
357 // Declare the driver as initialized
358 Snp
->Mode
->State
= EfiSimpleNetworkInitialized
;
364 * UEFI Reset () function
370 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
371 IN BOOLEAN Verification
383 // Check Snp Instance
385 return EFI_INVALID_PARAMETER
;
388 // First check that driver has not already been initialized
389 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
390 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
391 return EFI_DEVICE_ERROR
;
392 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
393 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
394 return EFI_NOT_STARTED
;
397 // Initiate a PHY reset
398 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
399 if (EFI_ERROR (Status
)) {
400 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
401 return EFI_NOT_STARTED
;
404 // Initiate a software reset
405 ResetFlags
|= SOFT_RESET_CHECK_MAC_ADDR_LOAD
| SOFT_RESET_CLEAR_INT
;
408 ResetFlags
|= SOFT_RESET_SELF_TEST
;
411 Status
= SoftReset (ResetFlags
, Snp
);
412 if (EFI_ERROR (Status
)) {
413 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
414 return EFI_DEVICE_ERROR
;
417 // Read the PM register
418 PmConf
= Lan9118MmioRead32 (LAN9118_PMT_CTRL
);
420 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
421 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
422 // MPTCTRL_PME_EN: Allow Power Management Events
423 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
425 // Write the current configuration to the register
426 Lan9118MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
428 // Reactivate the LEDs
429 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
430 if (EFI_ERROR (Status
)) {
434 // Check that a buffer size was specified in SnpInitialize
435 if (gTxBuffer
!= 0) {
436 HwConf
= Lan9118MmioRead32 (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 Lan9118MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
443 // Enable the receiver and transmitter and clear their contents
444 StartRx (START_RX_CLEAR
, Snp
);
445 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
447 // Now acknowledge all interrupts
448 Lan9118MmioWrite32 (LAN9118_INT_STS
, ~0);
454 * UEFI Shutdown () function
460 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
465 // Check Snp Instance
467 return EFI_INVALID_PARAMETER
;
470 // First check that driver has not already been initialized
471 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
472 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
473 return EFI_DEVICE_ERROR
;
474 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
475 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
476 return EFI_NOT_STARTED
;
479 // Initiate a PHY reset
480 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
481 if (EFI_ERROR (Status
)) {
485 // Initiate a software reset
486 Status
= SoftReset (0, Snp
);
487 if (EFI_ERROR (Status
)) {
488 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
492 // Back to the started and thus not initialized state
493 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
499 Enable and/or disable the receive filters of the LAN9118
501 Please refer to the UEFI specification for the precedence rules among the
502 Enable, Disable and ResetMCastFilter parameters.
504 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
506 @param[in] Enable A bit mask of receive filters to enable.
507 @param[in] Disable A bit mask of receive filters to disable.
508 @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast
509 receive filters on the network interface to
510 their default values.
511 @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new
512 MCastFilter list. This value must be less than or
513 equal to the MCastFilterCnt field of
514 EFI_SIMPLE_NETWORK_MODE. This field is optional if
515 ResetMCastFilter is TRUE.
516 @param[in] MCastFilter A pointer to a list of new multicast receive
517 filter HW MAC addresses. This list will replace
518 any existing multicast HW MAC address list. This
519 field is optional if ResetMCastFilter is TRUE.
521 @retval EFI_SUCCESS The receive filters of the LAN9118 were updated.
522 @retval EFI_NOT_STARTED The LAN9118 has not been started.
523 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
525 . Multicast is being enabled (the
526 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in
527 Enable, it is not set in Disable, and ResetMCastFilter
528 is FALSE) and MCastFilterCount is zero.
529 . Multicast is being enabled and MCastFilterCount is
530 greater than Snp->Mode->MaxMCastFilterCount.
531 . Multicast is being enabled and MCastFilter is NULL
532 . Multicast is being enabled and one or more of the
533 addresses in the MCastFilter list are not valid
534 multicast MAC addresses.
535 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
541 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
544 IN BOOLEAN ResetMCastFilter
,
545 IN UINTN MCastFilterCnt OPTIONAL
,
546 IN EFI_MAC_ADDRESS
*MCastFilter OPTIONAL
549 EFI_SIMPLE_NETWORK_MODE
*Mode
;
550 UINT32 MultHashTableHigh
;
551 UINT32 MultHashTableLow
;
556 UINT32 ReceiveFilterSetting
;
557 EFI_MAC_ADDRESS
*Mac
;
558 EFI_MAC_ADDRESS ZeroMac
;
560 // Check Snp Instance
562 return EFI_INVALID_PARAMETER
;
566 // Check that driver was started and initialised
567 if (Mode
->State
== EfiSimpleNetworkStarted
) {
568 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
569 return EFI_DEVICE_ERROR
;
570 } else if (Mode
->State
== EfiSimpleNetworkStopped
) {
571 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
572 return EFI_NOT_STARTED
;
575 if ((Enable
& (~Mode
->ReceiveFilterMask
)) ||
576 (Disable
& (~Mode
->ReceiveFilterMask
)) ) {
577 return EFI_INVALID_PARAMETER
;
581 // Check the validity of the multicast setting and compute the
582 // hash values of the multicast mac addresses to listen to.
585 MultHashTableHigh
= 0;
586 MultHashTableLow
= 0;
587 if ((!ResetMCastFilter
) &&
588 ((Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) == 0) &&
589 ((Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) != 0) ) {
590 if ((MCastFilterCnt
== 0) ||
591 (MCastFilterCnt
> Mode
->MaxMCastFilterCount
) ||
592 (MCastFilter
== NULL
) ) {
593 return EFI_INVALID_PARAMETER
;
596 // Check the validity of all multicast addresses before to change
599 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
600 if ((MCastFilter
[Count
].Addr
[0] & 1) == 0) {
601 return EFI_INVALID_PARAMETER
;
606 // Go through each filter address and set appropriate bits on hash table
608 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
609 Mac
= &(MCastFilter
[Count
]);
610 CopyMem (&Mode
->MCastFilter
[Count
], Mac
, sizeof(EFI_MAC_ADDRESS
));
612 Crc
= GenEtherCrc32 (Mac
, NET_ETHER_ADDR_LEN
);
613 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
616 // The most significant 6 bits of the MAC address CRC constitute the hash
617 // value of the MAC address.
619 HashValue
= (Crc
>> 26) & 0x3F;
621 // Select hashlow register if MSB is not set
622 if ((HashValue
& 0x20) == 0) {
623 MultHashTableLow
|= (1 << HashValue
);
625 MultHashTableHigh
|= (1 << (HashValue
& 0x1F));
628 Mode
->MCastFilterCount
= MCastFilterCnt
;
629 } else if (ResetMCastFilter
) {
630 Mode
->MCastFilterCount
= 0;
632 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
633 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
637 // Before to change anything, stop and reset the reception of
640 StopRx (STOP_RX_CLEAR
, Snp
);
643 // Write the mask of the selected hash values for the multicast filtering.
644 // The two masks are set to zero if the multicast filtering is not enabled.
646 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
647 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
649 ReceiveFilterSetting
= (Mode
->ReceiveFilterSetting
| Enable
) & (~Disable
);
652 // Read MAC controller
654 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
655 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_BCAST
| MACCR_PRMS
| MACCR_MCPAS
);
657 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
658 Lan9118SetMacAddress (&Mode
->CurrentAddress
, Snp
);
659 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
662 // The Unicast packets do not have to be listen to, set the MAC
663 // address of the LAN9118 to be the "not configured" all zeroes
664 // ethernet MAC address.
666 ZeroMem (&ZeroMac
, NET_ETHER_ADDR_LEN
);
667 Lan9118SetMacAddress (&ZeroMac
, Snp
);
670 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
671 MacCSRValue
|= MACCR_HPFILT
;
672 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
675 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
676 MacCSRValue
|= MACCR_MCPAS
;
677 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
680 if ((ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) == 0) {
681 MacCSRValue
|= MACCR_BCAST
;
683 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
686 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
687 MacCSRValue
|= MACCR_PRMS
;
688 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
692 // Write the options to the MAC_CSR
694 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
697 // If we have to retrieve something, start packet reception.
699 Mode
->ReceiveFilterSetting
= ReceiveFilterSetting
;
700 if (ReceiveFilterSetting
!= 0) {
708 Modify of reset the current station address
710 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
712 @param[in] Reset Flag used to reset the station address to the
713 LAN9118's permanent address.
714 @param[in] New New station address to be used for the network interface.
716 @retval EFI_SUCCESS The LAN9118's station address was updated.
717 @retval EFI_NOT_STARTED The LAN9118 has not been started.
718 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
719 . The "New" station address is invalid.
720 . "Reset" is FALSE and "New" is NULL.
721 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
727 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
729 IN EFI_MAC_ADDRESS
*New
733 UINT8 PermAddr
[NET_ETHER_ADDR_LEN
];
735 DEBUG ((DEBUG_NET
, "SnpStationAddress()\n"));
737 // Check Snp instance
739 return EFI_INVALID_PARAMETER
;
742 // Check that driver was started and initialised
743 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
744 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
745 return EFI_DEVICE_ERROR
;
746 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
747 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
748 return EFI_NOT_STARTED
;
751 // Get the Permanent MAC address if need reset
753 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
754 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM
) {
755 for (Count
= 0; Count
< NET_ETHER_ADDR_LEN
; Count
++) {
756 PermAddr
[Count
] = IndirectEEPROMRead32 (Count
+ 1);
758 New
= (EFI_MAC_ADDRESS
*) PermAddr
;
759 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) PermAddr
, Snp
);
761 DEBUG ((EFI_D_ERROR
, "LAN9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
762 New
= (EFI_MAC_ADDRESS
*) (FixedPcdGet64 (PcdLan9118DefaultMacAddress
));
765 // Otherwise use the specified new MAC address
767 return EFI_INVALID_PARAMETER
;
770 // If it is a multicast address, it is not valid.
772 if (New
->Addr
[0] & 0x01) {
773 return EFI_INVALID_PARAMETER
;
777 CopyMem (&Snp
->Mode
->CurrentAddress
, New
, NET_ETHER_ADDR_LEN
);
780 // If packet reception is currently activated, stop and reset it,
781 // set the new ethernet address and restart the packet reception.
782 // Otherwise, nothing to do, the MAC address will be updated in
783 // SnpReceiveFilters() when the UNICAST packet reception will be
786 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
787 StopRx (STOP_RX_CLEAR
, Snp
);
788 Lan9118SetMacAddress (New
, Snp
);
796 * UEFI Statistics() function
802 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
804 IN OUT UINTN
*StatSize
,
805 OUT EFI_NETWORK_STATISTICS
*Statistics
808 LAN9118_DRIVER
*LanDriver
;
811 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
813 DEBUG ((DEBUG_NET
, "SnpStatistics()\n"));
815 // Check Snp instance
817 return EFI_INVALID_PARAMETER
;
820 // Check that driver was started and initialised
821 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
822 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
823 return EFI_DEVICE_ERROR
;
824 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
825 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
826 return EFI_NOT_STARTED
;
830 // Do a reset if required. It is not clearly stated in the UEFI specification
831 // whether the reset has to be done before to copy the statistics in "Statictics"
832 // or after. It is a bit strange to do it before but that is what is expected by
833 // the SCT test on Statistics() with reset : "0x3de76704,0x4bf5,0x42cd,0x8c,0x89,
834 // 0x54,0x7e,0x4f,0xad,0x4f,0x24".
837 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
840 Status
= EFI_SUCCESS
;
841 if (StatSize
== NULL
) {
842 if (Statistics
!= NULL
) {
843 return EFI_INVALID_PARAMETER
;
846 if (Statistics
== NULL
) {
847 Status
= EFI_BUFFER_TOO_SMALL
;
849 // Fill in the statistics
851 Statistics
, &LanDriver
->Stats
,
852 MIN (*StatSize
, sizeof (EFI_NETWORK_STATISTICS
))
854 if (*StatSize
< sizeof (EFI_NETWORK_STATISTICS
)) {
855 Status
= EFI_BUFFER_TOO_SMALL
;
858 *StatSize
= sizeof (EFI_NETWORK_STATISTICS
);
865 * UEFI MCastIPtoMAC() function
871 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
873 IN EFI_IP_ADDRESS
*Ip
,
874 OUT EFI_MAC_ADDRESS
*McastMac
877 DEBUG ((DEBUG_NET
, "SnpMcastIptoMac()\n"));
879 // Check Snp instance
881 return EFI_INVALID_PARAMETER
;
884 // Check that driver was started and initialised
885 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
886 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
887 return EFI_DEVICE_ERROR
;
888 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
889 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
890 return EFI_NOT_STARTED
;
894 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
895 return EFI_INVALID_PARAMETER
;
898 // Make sure MAC address is empty
899 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
901 // If we need ipv4 address
903 // Most significant 25 bits of a multicast HW address are set.
904 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
905 McastMac
->Addr
[0] = 0x01;
906 McastMac
->Addr
[1] = 0x00;
907 McastMac
->Addr
[2] = 0x5E;
909 // Lower 23 bits from ipv4 address
910 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
911 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
912 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
914 // Most significant 16 bits of multicast v6 HW address are set
915 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
916 McastMac
->Addr
[0] = 0x33;
917 McastMac
->Addr
[1] = 0x33;
919 // lower four octets are taken from ipv6 address
920 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
921 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
922 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
923 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
930 * UEFI NvData() function
936 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
937 IN BOOLEAN read_write
,
943 DEBUG ((DEBUG_NET
, "SnpNvData()\n"));
945 return EFI_UNSUPPORTED
;
950 * UEFI GetStatus () function
956 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
957 OUT UINT32
*IrqStat OPTIONAL
,
958 OUT VOID
**TxBuff OPTIONAL
963 UINTN NumTxStatusEntries
;
967 LAN9118_DRIVER
*LanDriver
;
969 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
971 // Check preliminaries
973 return EFI_INVALID_PARAMETER
;
976 // Check that driver was started and initialised
977 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
978 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
979 return EFI_DEVICE_ERROR
;
980 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
981 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
982 return EFI_NOT_STARTED
;
985 // Check and acknowledge TX Status interrupt (this will happen if the
986 // consumer of SNP does not call GetStatus.)
987 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
988 // should check for it and dump the TX Status FIFO.
989 FifoInt
= Lan9118MmioRead32 (LAN9118_FIFO_INT
);
991 // Clear the TX Status FIFO Overflow
992 if ((FifoInt
& INSTS_TXSO
) == 0) {
993 FifoInt
|= INSTS_TXSO
;
994 Lan9118MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
997 // Read interrupt status if IrqStat is not NULL
998 if (IrqStat
!= NULL
) {
1001 // Check for receive interrupt
1002 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
1003 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
1004 Lan9118MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
1007 // Check for transmit interrupt
1008 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
1009 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
1010 Lan9118MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
1013 // Check for software interrupt
1014 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
1015 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
1016 Lan9118MmioWrite32 (LAN9118_INT_STS
,INSTS_SW_INT
);
1020 // Check Status of transmitted packets
1021 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
1023 NumTxStatusEntries
= Lan9118MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
1024 if (NumTxStatusEntries
> 0) {
1025 TxStatus
= Lan9118MmioRead32 (LAN9118_TX_STATUS
);
1026 PacketTag
= TxStatus
>> 16;
1027 TxStatus
= TxStatus
& 0xFFFF;
1028 if ((TxStatus
& TXSTATUS_ES
) && (TxStatus
!= (TXSTATUS_ES
| TXSTATUS_NO_CA
))) {
1029 DEBUG ((EFI_D_ERROR
, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus
));
1030 if (TxStatus
& TXSTATUS_NO_CA
) {
1031 DEBUG ((EFI_D_ERROR
, "- No carrier\n"));
1033 if (TxStatus
& TXSTATUS_DEF
) {
1034 DEBUG ((EFI_D_ERROR
, "- Packet tx was deferred\n"));
1036 if (TxStatus
& TXSTATUS_EDEF
) {
1037 DEBUG ((EFI_D_ERROR
, "- Tx ended because of excessive deferral\n"));
1039 if (TxStatus
& TXSTATUS_ECOLL
) {
1040 DEBUG ((EFI_D_ERROR
, "- Tx ended because of Excessive Collisions\n"));
1042 if (TxStatus
& TXSTATUS_LCOLL
) {
1043 DEBUG ((EFI_D_ERROR
, "- Packet Tx aborted after coll window of 64 bytes\n"));
1045 if (TxStatus
& TXSTATUS_LOST_CA
) {
1046 DEBUG ((EFI_D_ERROR
, "- Lost carrier during Tx\n"));
1048 return EFI_DEVICE_ERROR
;
1049 } else if (TxBuff
!= NULL
) {
1050 LanDriver
->Stats
.TxTotalFrames
+= 1;
1051 *TxBuff
= LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
];
1053 } else if (TxBuff
!= NULL
) {
1057 // Check for a TX Error interrupt
1058 Interrupts
= Lan9118MmioRead32 (LAN9118_INT_STS
);
1059 if (Interrupts
& INSTS_TXE
) {
1060 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
1062 // Software reset, the TXE interrupt is cleared by the reset.
1063 Status
= SoftReset (0, Snp
);
1064 if (EFI_ERROR (Status
)) {
1065 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
1066 return EFI_DEVICE_ERROR
;
1069 // Reactivate the LEDs
1070 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1071 if (EFI_ERROR (Status
)) {
1076 // Restart the transmitter and if necessary the receiver.
1077 // Do not ask for FIFO reset as it has already been done
1080 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1081 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
1086 // Update the media status
1087 Status
= CheckLinkStatus (0, Snp
);
1088 if (EFI_ERROR(Status
)) {
1089 Snp
->Mode
->MediaPresent
= FALSE
;
1091 Snp
->Mode
->MediaPresent
= TRUE
;
1099 * UEFI Transmit() function
1105 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1109 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1110 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1111 IN UINT16
*Protocol OPTIONAL
1114 LAN9118_DRIVER
*LanDriver
;
1116 UINT32 TxStatusSpace
;
1120 UINT16 LocalProtocol
;
1124 #if defined(EVAL_PERFORMANCE)
1129 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1130 StartClock
= GetPerformanceCounter ();
1133 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1135 // Check preliminaries
1136 if ((Snp
== NULL
) || (Data
== NULL
)) {
1137 return EFI_INVALID_PARAMETER
;
1140 // Check that driver was started and initialised
1141 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1142 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1143 return EFI_DEVICE_ERROR
;
1144 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1145 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1146 return EFI_NOT_STARTED
;
1149 // Ensure header is correct size if non-zero
1151 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1152 return EFI_INVALID_PARAMETER
;
1155 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1156 return EFI_INVALID_PARAMETER
;
1161 // Check validity of BufferSize
1163 if (BuffSize
< Snp
->Mode
->MediaHeaderSize
) {
1164 return EFI_BUFFER_TOO_SMALL
;
1167 // Before transmitting check the link status
1168 /*if (CheckLinkStatus (0, Snp) < 0) {
1169 return EFI_NOT_READY;
1172 // Get DATA FIFO free space in bytes
1173 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1174 if (TxFreeSpace
< BuffSize
) {
1175 return EFI_NOT_READY
;
1178 // Get STATUS FIFO used space in bytes
1179 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1180 if (TxStatusSpace
> 500) {
1181 return EFI_NOT_READY
;
1184 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1185 // has provided a well-formed frame).
1186 if (DstAddr
== NULL
) {
1187 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1190 // Check for the nature of the frame
1191 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1192 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1194 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1197 // Check if broadcast
1198 if (DstAddr
->Addr
[0] == 0xFF) {
1199 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1202 PacketTag
= LanDriver
->NextPacketTag
;
1203 LanDriver
->NextPacketTag
++;
1208 LocalData
= (UINT32
*) Data
;
1209 LocalProtocol
= *Protocol
;
1211 // Create first buffer to pass to controller (for the header)
1212 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1213 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1215 // Write the commands first
1216 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1217 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1219 // Write the destination address
1220 Lan9118MmioWrite32 (LAN9118_TX_DATA
,
1221 (DstAddr
->Addr
[0]) |
1222 (DstAddr
->Addr
[1] << 8) |
1223 (DstAddr
->Addr
[2] << 16) |
1224 (DstAddr
->Addr
[3] << 24)
1227 Lan9118MmioWrite32 (LAN9118_TX_DATA
,
1228 (DstAddr
->Addr
[4]) |
1229 (DstAddr
->Addr
[5] << 8) |
1230 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1231 (SrcAddr
->Addr
[1] << 24)
1234 Lan9118MmioWrite32 (LAN9118_TX_DATA
,
1235 (SrcAddr
->Addr
[2]) |
1236 (SrcAddr
->Addr
[3] << 8) |
1237 (SrcAddr
->Addr
[4] << 16) |
1238 (SrcAddr
->Addr
[5] << 24)
1241 // Write the Protocol
1242 Lan9118MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1244 // Next buffer is the payload
1245 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
1247 // Write the commands
1248 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1249 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1251 // Write the payload
1252 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1253 Lan9118MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1257 LocalData
= (UINT32
*) Data
;
1259 // Create a buffer to pass to controller
1260 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1261 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1263 // Write the commands first
1264 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1265 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1267 // Write all the data
1268 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1269 Lan9118MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1273 // Save the address of the submitted packet so we can notify the consumer that
1274 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1275 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1276 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1278 #if defined(EVAL_PERFORMANCE)
1279 EndClock
= GetPerformanceCounter ();
1280 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1283 LanDriver
->Stats
.TxGoodFrames
+= 1;
1290 * UEFI Receive() function
1296 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1297 OUT UINTN
*HdrSize OPTIONAL
,
1298 IN OUT UINTN
*BuffSize
,
1300 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1301 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1302 OUT UINT16
*Protocol OPTIONAL
1305 LAN9118_DRIVER
*LanDriver
;
1307 UINT32 RxFifoStatus
;
1310 UINT32 PLength
; // Packet length
1315 EFI_MAC_ADDRESS Dst
;
1316 EFI_MAC_ADDRESS Src
;
1317 UINTN DroppedFrames
;
1320 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1322 #if defined(EVAL_PERFORMANCE)
1323 UINT64 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1324 UINT64 StartClock
= GetPerformanceCounter ();
1327 // Check preliminaries
1328 if ((Snp
== NULL
) || (Data
== NULL
) || (BuffSize
== NULL
)) {
1329 return EFI_INVALID_PARAMETER
;
1332 // Check that driver was started and initialised
1333 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1334 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1335 return EFI_DEVICE_ERROR
;
1336 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1337 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1338 return EFI_NOT_STARTED
;
1342 // If the receiver raised the RXE error bit, check if the receiver status
1343 // FIFO is full and if not just acknowledge the error. The two other
1344 // conditions to get a RXE error are :
1345 // . the RX data FIFO is read whereas being empty.
1346 // . the RX status FIFO is read whereas being empty.
1347 // The RX data and status FIFO are read by this driver only in the following
1348 // code of this function. After the readings, the RXE error bit is checked
1349 // and if raised, the controller is reset. Thus, at this point, we consider
1350 // that the only valid reason to get an RXE error is the receiver status
1351 // FIFO being full. And if this is not the case, we consider that this is
1352 // a spurious error and we just get rid of it. We experienced such 'spurious'
1353 // errors when running the driver on an A57 on Juno. No valid reason to
1354 // explain those errors has been found so far and everything seems to
1355 // work perfectly when they are just ignored.
1357 IntSts
= Lan9118MmioRead32 (LAN9118_INT_STS
);
1358 if ((IntSts
& INSTS_RXE
) && (!(IntSts
& INSTS_RSFF
))) {
1359 Lan9118MmioWrite32 (LAN9118_INT_STS
, INSTS_RXE
);
1362 // Count dropped frames
1363 DroppedFrames
= Lan9118MmioRead32 (LAN9118_RX_DROP
);
1364 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1366 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1368 return EFI_NOT_READY
;
1371 // Read Rx Status (only if not empty)
1372 RxFifoStatus
= Lan9118MmioRead32 (LAN9118_RX_STATUS
);
1373 LanDriver
->Stats
.RxTotalFrames
+= 1;
1375 // First check for errors
1376 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1377 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1378 (RxFifoStatus
& RXSTATUS_FTL
) ||
1379 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1380 (RxFifoStatus
& RXSTATUS_LE
) ||
1381 (RxFifoStatus
& RXSTATUS_DB
))
1383 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1384 return EFI_DEVICE_ERROR
;
1387 // Check if we got a CRC error
1388 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1389 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1390 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1391 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1392 return EFI_DEVICE_ERROR
;
1395 // Check if we got a runt frame
1396 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1397 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1398 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1399 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1400 return EFI_DEVICE_ERROR
;
1403 // Check filtering status for this packet
1404 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1405 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1409 // Check if we got a broadcast frame
1410 if (RxFifoStatus
& RXSTATUS_BCF
) {
1411 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1414 // Check if we got a multicast frame
1415 if (RxFifoStatus
& RXSTATUS_MCF
) {
1416 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1419 // Check if we got a unicast frame
1420 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1421 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1424 // Get the received packet length
1425 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1426 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1428 // If padding is applied, read more DWORDs
1430 Padding
= 4 - (PLength
% 4);
1431 ReadLimit
= (PLength
+ Padding
)/4;
1433 ReadLimit
= PLength
/4;
1437 // Check buffer size
1438 if (*BuffSize
< (PLength
+ Padding
)) {
1439 *BuffSize
= PLength
+ Padding
;
1440 return EFI_BUFFER_TOO_SMALL
;
1443 // Set the amount of data to be transferred out of FIFO for THIS packet
1444 // This can be used to trigger an interrupt, and status can be checked
1445 RxCfgValue
= Lan9118MmioRead32 (LAN9118_RX_CFG
);
1446 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1447 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1449 // Set end alignment to 4-bytes
1450 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1451 Lan9118MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1453 // Update buffer size
1454 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1455 // 4 bytes longer than packet actually is, unless
1456 // packet is < 64 bytes
1458 if (HdrSize
!= NULL
)
1459 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1461 // Format the pointer
1462 RawData
= (UINT32
*)Data
;
1465 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1466 RawData
[Count
] = Lan9118MmioRead32 (LAN9118_RX_DATA
);
1469 // Get the destination address
1470 if (DstAddr
!= NULL
) {
1471 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1472 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1473 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1474 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1475 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1476 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1477 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1480 // Get the source address
1481 if (SrcAddr
!= NULL
) {
1482 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1483 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1484 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1485 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1486 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1487 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1488 CopyMem (SrcAddr
, &Src
, NET_ETHER_ADDR_LEN
);
1492 if (Protocol
!= NULL
) {
1493 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1496 // Check for Rx errors (worst possible error)
1497 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1498 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1500 // Software reset, the RXE interrupt is cleared by the reset.
1501 Status
= SoftReset (0, Snp
);
1502 if (EFI_ERROR (Status
)) {
1503 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1504 return EFI_DEVICE_ERROR
;
1507 // Reactivate the LEDs
1508 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1509 if (EFI_ERROR (Status
)) {
1514 // Restart the receiver and the transmitter without resetting the FIFOs
1515 // as it has been done by SoftReset().
1518 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1520 // Say that command could not be sent
1521 return EFI_DEVICE_ERROR
;
1524 #if defined(EVAL_PERFORMANCE)
1525 UINT64 EndClock
= GetPerformanceCounter ();
1526 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1529 LanDriver
->Stats
.RxGoodFrames
+= 1;