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"
18 MAC_ADDR_DEVICE_PATH Lan9118
;
19 EFI_DEVICE_PATH_PROTOCOL End
;
20 } LAN9118_DEVICE_PATH
;
22 LAN9118_DEVICE_PATH Lan9118PathTemplate
= {
25 MESSAGING_DEVICE_PATH
, MSG_MAC_ADDR_DP
,
26 { (UINT8
) (sizeof(MAC_ADDR_DEVICE_PATH
)), (UINT8
) ((sizeof(MAC_ADDR_DEVICE_PATH
)) >> 8) }
33 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
34 { sizeof(EFI_DEVICE_PATH_PROTOCOL
), 0 }
39 ** Entry point for the LAN9118 driver
45 IN EFI_SYSTEM_TABLE
*SystemTable
49 LAN9118_DRIVER
*LanDriver
;
50 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
51 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
52 LAN9118_DEVICE_PATH
*Lan9118Path
;
53 EFI_HANDLE ControllerHandle
;
55 // The PcdLan9118DxeBaseAddress PCD must be defined
56 ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress
) != 0);
59 LanDriver
= AllocateZeroPool (sizeof (LAN9118_DRIVER
));
60 if (LanDriver
== NULL
) {
61 return EFI_OUT_OF_RESOURCES
;
63 Lan9118Path
= (LAN9118_DEVICE_PATH
*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH
), &Lan9118PathTemplate
);
64 if (Lan9118Path
== NULL
) {
65 return EFI_OUT_OF_RESOURCES
;
68 // Initialize pointers
69 Snp
= &(LanDriver
->Snp
);
70 SnpMode
= &(LanDriver
->SnpMode
);
73 // Set the signature of the LAN Driver structure
74 LanDriver
->Signature
= LAN9118_SIGNATURE
;
76 // Assign fields and func pointers
77 Snp
->Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
78 Snp
->WaitForPacket
= NULL
;
79 Snp
->Initialize
= SnpInitialize
;
80 Snp
->Start
= SnpStart
;
82 Snp
->Reset
= SnpReset
;
83 Snp
->Shutdown
= SnpShutdown
;
84 Snp
->ReceiveFilters
= SnpReceiveFilters
;
85 Snp
->StationAddress
= SnpStationAddress
;
86 Snp
->Statistics
= SnpStatistics
;
87 Snp
->MCastIpToMac
= SnpMcastIptoMac
;
88 Snp
->NvData
= SnpNvData
;
89 Snp
->GetStatus
= SnpGetStatus
;
90 Snp
->Transmit
= SnpTransmit
;
91 Snp
->Receive
= SnpReceive
;
93 // Start completing simple network mode structure
94 SnpMode
->State
= EfiSimpleNetworkStopped
;
95 SnpMode
->HwAddressSize
= NET_ETHER_ADDR_LEN
; // HW address is 6 bytes
96 SnpMode
->MediaHeaderSize
= sizeof(ETHER_HEAD
); // Not sure of this
97 SnpMode
->MaxPacketSize
= EFI_PAGE_SIZE
; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
98 SnpMode
->NvRamSize
= 0; // No NVRAM with this device
99 SnpMode
->NvRamAccessSize
= 0; // No NVRAM with this device
102 // Claim that all receive filter settings are supported, though the MULTICAST mode
103 // is not completely supported. The LAN9118 Ethernet controller is only able to
104 // do a "hash filtering" and not a perfect filtering on multicast addresses. The
105 // controller does not filter the multicast addresses directly but a hash value
106 // of them. The hash value of a multicast address is derived from its CRC and
107 // ranges from 0 to 63 included.
108 // We claim that the perfect MULTICAST filtering mode is supported because
109 // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode
110 // and thus not being able to take advantage of the hash filtering.
112 SnpMode
->ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
113 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
114 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
115 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
|
116 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
118 // We do not intend to receive anything for the time being.
119 SnpMode
->ReceiveFilterSetting
= 0;
121 // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses
122 SnpMode
->MaxMCastFilterCount
= MAX_MCAST_FILTER_CNT
;
123 SnpMode
->MCastFilterCount
= 0;
124 ZeroMem (&SnpMode
->MCastFilter
, MAX_MCAST_FILTER_CNT
* sizeof(EFI_MAC_ADDRESS
));
126 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
127 SnpMode
->IfType
= NET_IFTYPE_ETHERNET
;
129 // Mac address is changeable as it is loaded from erasable memory
130 SnpMode
->MacAddressChangeable
= TRUE
;
132 // Can only transmit one packet at a time
133 SnpMode
->MultipleTxSupported
= FALSE
;
135 // MediaPresent checks for cable connection and partner link
136 SnpMode
->MediaPresentSupported
= TRUE
;
137 SnpMode
->MediaPresent
= FALSE
;
139 // Set broadcast address
140 SetMem (&SnpMode
->BroadcastAddress
, sizeof (EFI_MAC_ADDRESS
), 0xFF);
142 // Power up the device so we can find the MAC address
143 Status
= Lan9118Initialize (Snp
);
144 if (EFI_ERROR (Status
)) {
145 DEBUG ((EFI_D_ERROR
, "LAN9118: Error initialising hardware\n"));
146 return EFI_DEVICE_ERROR
;
149 // Assign fields for device path
150 CopyMem (&Lan9118Path
->Lan9118
.MacAddress
, &Snp
->Mode
->CurrentAddress
, NET_ETHER_ADDR_LEN
);
151 Lan9118Path
->Lan9118
.IfType
= Snp
->Mode
->IfType
;
153 // Initialise the protocol
154 ControllerHandle
= NULL
;
155 Status
= gBS
->InstallMultipleProtocolInterfaces (
157 &gEfiSimpleNetworkProtocolGuid
, Snp
,
158 &gEfiDevicePathProtocolGuid
, Lan9118Path
,
161 // Say what the status of loading the protocol structure is
162 if (EFI_ERROR(Status
)) {
163 FreePool (LanDriver
);
165 LanDriver
->ControllerHandle
= ControllerHandle
;
172 * UEFI Start() function
176 * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
180 * This function starts a network interface. If the network interface successfully starts, then
181 * EFI_SUCCESS will be returned.
186 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
189 // Check Snp instance
191 return EFI_INVALID_PARAMETER
;
195 if ((Snp
->Mode
->State
== EfiSimpleNetworkStarted
) ||
196 (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) ) {
197 return EFI_ALREADY_STARTED
;
201 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
206 * UEFI Stop() function
212 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
215 // Check Snp Instance
217 return EFI_INVALID_PARAMETER
;
220 // Check state of the driver
221 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
222 return EFI_NOT_STARTED
;
225 // Stop the Tx and Rx
226 StopTx (STOP_TX_CFG
| STOP_TX_MAC
, Snp
);
230 switch (Snp
->Mode
->State
) {
231 case EfiSimpleNetworkStarted
:
232 case EfiSimpleNetworkInitialized
:
233 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
236 return EFI_DEVICE_ERROR
;
239 // Put the device into a power saving mode ?
244 // Allocated receive and transmit buffers
245 STATIC UINT32 gTxBuffer
= 0;
248 * UEFI Initialize() function
254 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
255 IN UINTN RxBufferSize OPTIONAL
,
256 IN UINTN TxBufferSize OPTIONAL
265 // Initialize variables
266 // Global variables to hold tx and rx FIFO allocation
269 // Check Snp Instance
271 return EFI_INVALID_PARAMETER
;
274 // First check that driver has not already been initialized
275 if (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) {
276 DEBUG ((EFI_D_WARN
, "LAN9118 Driver already initialized\n"));
279 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
280 DEBUG ((EFI_D_WARN
, "LAN9118 Driver not started\n"));
281 return EFI_NOT_STARTED
;
284 // Initiate a PHY reset
285 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
286 if (EFI_ERROR (Status
)) {
287 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
288 DEBUG ((EFI_D_WARN
, "Warning: Link not ready after TimeOut. Check ethernet cable\n"));
289 return EFI_NOT_STARTED
;
292 // Initiate a software reset
293 Status
= SoftReset (0, Snp
);
294 if (EFI_ERROR(Status
)) {
295 DEBUG ((EFI_D_WARN
, "Soft Reset Failed: Hardware Error\n"));
296 return EFI_DEVICE_ERROR
;
299 // Read the PM register
300 PmConf
= Lan9118MmioRead32 (LAN9118_PMT_CTRL
);
302 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
303 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
304 // MPTCTRL_PME_EN: Allow Power Management Events
306 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
308 // Write the current configuration to the register
309 Lan9118MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
311 // Configure GPIO and HW
312 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
313 if (EFI_ERROR(Status
)) {
317 // Assign the transmitter buffer size (default values)
318 TxStatusSize
= LAN9118_TX_STATUS_SIZE
;
319 RxStatusSize
= LAN9118_RX_STATUS_SIZE
;
321 // Check that a buff size was specified
322 if (TxBufferSize
> 0) {
323 if (RxBufferSize
== 0) {
324 RxBufferSize
= LAN9118_RX_DATA_SIZE
;
327 AllocResult
= ChangeFifoAllocation (
336 if (AllocResult
< 0) {
337 return EFI_OUT_OF_RESOURCES
;
341 // Do auto-negotiation if supported
342 Status
= AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL
, Snp
);
343 if (EFI_ERROR(Status
)) {
344 DEBUG ((EFI_D_WARN
, "LAN9118: Auto Negotiation failed.\n"));
347 // Configure flow control depending on speed capabilities
348 Status
= ConfigureFlow (0, 0, 0, 0, Snp
);
349 if (EFI_ERROR(Status
)) {
353 // Enable the transmitter
354 Status
= StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
355 if (EFI_ERROR(Status
)) {
359 // Now acknowledge all interrupts
360 Lan9118MmioWrite32 (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
, 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
= Lan9118MmioRead32 (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 Lan9118MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
433 // Reactivate the LEDs
434 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
435 if (EFI_ERROR (Status
)) {
439 // Check that a buffer size was specified in SnpInitialize
440 if (gTxBuffer
!= 0) {
441 HwConf
= Lan9118MmioRead32 (LAN9118_HW_CFG
); // Read the HW register
442 HwConf
&= ~HW_CFG_TX_FIFO_SIZE_MASK
; // Clear buffer bits first
443 HwConf
|= HW_CFG_TX_FIFO_SIZE(gTxBuffer
); // assign size chosen in SnpInitialize
445 Lan9118MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
448 // Enable the receiver and transmitter and clear their contents
449 StartRx (START_RX_CLEAR
, Snp
);
450 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
452 // Now acknowledge all interrupts
453 Lan9118MmioWrite32 (LAN9118_INT_STS
, ~0);
459 * UEFI Shutdown () function
465 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
470 // Check Snp Instance
472 return EFI_INVALID_PARAMETER
;
475 // First check that driver has not already been initialized
476 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
477 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
478 return EFI_DEVICE_ERROR
;
479 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
480 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
481 return EFI_NOT_STARTED
;
484 // Initiate a PHY reset
485 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
486 if (EFI_ERROR (Status
)) {
490 // Initiate a software reset
491 Status
= SoftReset (0, Snp
);
492 if (EFI_ERROR (Status
)) {
493 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
497 // Back to the started and thus not initialized state
498 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
504 Enable and/or disable the receive filters of the LAN9118
506 Please refer to the UEFI specification for the precedence rules among the
507 Enable, Disable and ResetMCastFilter parameters.
509 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
511 @param[in] Enable A bit mask of receive filters to enable.
512 @param[in] Disable A bit mask of receive filters to disable.
513 @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast
514 receive filters on the network interface to
515 their default values.
516 @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new
517 MCastFilter list. This value must be less than or
518 equal to the MCastFilterCnt field of
519 EFI_SIMPLE_NETWORK_MODE. This field is optional if
520 ResetMCastFilter is TRUE.
521 @param[in] MCastFilter A pointer to a list of new multicast receive
522 filter HW MAC addresses. This list will replace
523 any existing multicast HW MAC address list. This
524 field is optional if ResetMCastFilter is TRUE.
526 @retval EFI_SUCCESS The receive filters of the LAN9118 were updated.
527 @retval EFI_NOT_STARTED The LAN9118 has not been started.
528 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
530 . Multicast is being enabled (the
531 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in
532 Enable, it is not set in Disable, and ResetMCastFilter
533 is FALSE) and MCastFilterCount is zero.
534 . Multicast is being enabled and MCastFilterCount is
535 greater than Snp->Mode->MaxMCastFilterCount.
536 . Multicast is being enabled and MCastFilter is NULL
537 . Multicast is being enabled and one or more of the
538 addresses in the MCastFilter list are not valid
539 multicast MAC addresses.
540 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
546 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
549 IN BOOLEAN ResetMCastFilter
,
550 IN UINTN MCastFilterCnt OPTIONAL
,
551 IN EFI_MAC_ADDRESS
*MCastFilter OPTIONAL
554 EFI_SIMPLE_NETWORK_MODE
*Mode
;
555 UINT32 MultHashTableHigh
;
556 UINT32 MultHashTableLow
;
561 UINT32 ReceiveFilterSetting
;
562 EFI_MAC_ADDRESS
*Mac
;
563 EFI_MAC_ADDRESS ZeroMac
;
565 // Check Snp Instance
567 return EFI_INVALID_PARAMETER
;
571 // Check that driver was started and initialised
572 if (Mode
->State
== EfiSimpleNetworkStarted
) {
573 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
574 return EFI_DEVICE_ERROR
;
575 } else if (Mode
->State
== EfiSimpleNetworkStopped
) {
576 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
577 return EFI_NOT_STARTED
;
580 if ((Enable
& (~Mode
->ReceiveFilterMask
)) ||
581 (Disable
& (~Mode
->ReceiveFilterMask
)) ) {
582 return EFI_INVALID_PARAMETER
;
586 // Check the validity of the multicast setting and compute the
587 // hash values of the multicast mac addresses to listen to.
590 MultHashTableHigh
= 0;
591 MultHashTableLow
= 0;
592 if ((!ResetMCastFilter
) &&
593 ((Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) == 0) &&
594 ((Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) != 0) ) {
595 if ((MCastFilterCnt
== 0) ||
596 (MCastFilterCnt
> Mode
->MaxMCastFilterCount
) ||
597 (MCastFilter
== NULL
) ) {
598 return EFI_INVALID_PARAMETER
;
601 // Check the validity of all multicast addresses before to change
604 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
605 if ((MCastFilter
[Count
].Addr
[0] & 1) == 0) {
606 return EFI_INVALID_PARAMETER
;
611 // Go through each filter address and set appropriate bits on hash table
613 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
614 Mac
= &(MCastFilter
[Count
]);
615 CopyMem (&Mode
->MCastFilter
[Count
], Mac
, sizeof(EFI_MAC_ADDRESS
));
617 Crc
= GenEtherCrc32 (Mac
, NET_ETHER_ADDR_LEN
);
618 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
621 // The most significant 6 bits of the MAC address CRC constitute the hash
622 // value of the MAC address.
624 HashValue
= (Crc
>> 26) & 0x3F;
626 // Select hashlow register if MSB is not set
627 if ((HashValue
& 0x20) == 0) {
628 MultHashTableLow
|= (1 << HashValue
);
630 MultHashTableHigh
|= (1 << (HashValue
& 0x1F));
633 Mode
->MCastFilterCount
= MCastFilterCnt
;
634 } else if (ResetMCastFilter
) {
635 Mode
->MCastFilterCount
= 0;
637 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
638 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
642 // Before to change anything, stop and reset the reception of
645 StopRx (STOP_RX_CLEAR
, Snp
);
648 // Write the mask of the selected hash values for the multicast filtering.
649 // The two masks are set to zero if the multicast filtering is not enabled.
651 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
652 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
654 ReceiveFilterSetting
= (Mode
->ReceiveFilterSetting
| Enable
) & (~Disable
);
657 // Read MAC controller
659 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
660 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_BCAST
| MACCR_PRMS
| MACCR_MCPAS
);
662 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
663 Lan9118SetMacAddress (&Mode
->CurrentAddress
, Snp
);
664 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
667 // The Unicast packets do not have to be listen to, set the MAC
668 // address of the LAN9118 to be the "not configured" all zeroes
669 // ethernet MAC address.
671 ZeroMem (&ZeroMac
, NET_ETHER_ADDR_LEN
);
672 Lan9118SetMacAddress (&ZeroMac
, Snp
);
675 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
676 MacCSRValue
|= MACCR_HPFILT
;
677 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
680 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
681 MacCSRValue
|= MACCR_MCPAS
;
682 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
685 if ((ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) == 0) {
686 MacCSRValue
|= MACCR_BCAST
;
688 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
691 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
692 MacCSRValue
|= MACCR_PRMS
;
693 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
697 // Write the options to the MAC_CSR
699 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
702 // If we have to retrieve something, start packet reception.
704 Mode
->ReceiveFilterSetting
= ReceiveFilterSetting
;
705 if (ReceiveFilterSetting
!= 0) {
713 Modify of reset the current station address
715 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
717 @param[in] Reset Flag used to reset the station address to the
718 LAN9118's permanent address.
719 @param[in] New New station address to be used for the network interface.
721 @retval EFI_SUCCESS The LAN9118's station address was updated.
722 @retval EFI_NOT_STARTED The LAN9118 has not been started.
723 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
724 . The "New" station address is invalid.
725 . "Reset" is FALSE and "New" is NULL.
726 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
732 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
734 IN EFI_MAC_ADDRESS
*New
738 UINT8 PermAddr
[NET_ETHER_ADDR_LEN
];
740 DEBUG ((DEBUG_NET
, "SnpStationAddress()\n"));
742 // Check Snp instance
744 return EFI_INVALID_PARAMETER
;
747 // Check that driver was started and initialised
748 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
749 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
750 return EFI_DEVICE_ERROR
;
751 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
752 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
753 return EFI_NOT_STARTED
;
756 // Get the Permanent MAC address if need reset
758 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
759 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM
) {
760 for (Count
= 0; Count
< NET_ETHER_ADDR_LEN
; Count
++) {
761 PermAddr
[Count
] = IndirectEEPROMRead32 (Count
+ 1);
763 New
= (EFI_MAC_ADDRESS
*) PermAddr
;
764 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) PermAddr
, Snp
);
766 DEBUG ((EFI_D_ERROR
, "LAN9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
767 New
= (EFI_MAC_ADDRESS
*) (FixedPcdGet64 (PcdLan9118DefaultMacAddress
));
770 // Otherwise use the specified new MAC address
772 return EFI_INVALID_PARAMETER
;
775 // If it is a multicast address, it is not valid.
777 if (New
->Addr
[0] & 0x01) {
778 return EFI_INVALID_PARAMETER
;
782 CopyMem (&Snp
->Mode
->CurrentAddress
, New
, NET_ETHER_ADDR_LEN
);
785 // If packet reception is currently activated, stop and reset it,
786 // set the new ethernet address and restart the packet reception.
787 // Otherwise, nothing to do, the MAC address will be updated in
788 // SnpReceiveFilters() when the UNICAST packet reception will be
791 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
792 StopRx (STOP_RX_CLEAR
, Snp
);
793 Lan9118SetMacAddress (New
, Snp
);
801 * UEFI Statistics() function
807 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
809 IN OUT UINTN
*StatSize
,
810 OUT EFI_NETWORK_STATISTICS
*Statistics
813 LAN9118_DRIVER
*LanDriver
;
816 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
818 DEBUG ((DEBUG_NET
, "SnpStatistics()\n"));
820 // Check Snp instance
822 return EFI_INVALID_PARAMETER
;
825 // Check that driver was started and initialised
826 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
827 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
828 return EFI_DEVICE_ERROR
;
829 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
830 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
831 return EFI_NOT_STARTED
;
835 // Do a reset if required. It is not clearly stated in the UEFI specification
836 // whether the reset has to be done before to copy the statistics in "Statictics"
837 // or after. It is a bit strange to do it before but that is what is expected by
838 // the SCT test on Statistics() with reset : "0x3de76704,0x4bf5,0x42cd,0x8c,0x89,
839 // 0x54,0x7e,0x4f,0xad,0x4f,0x24".
842 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
845 Status
= EFI_SUCCESS
;
846 if (StatSize
== NULL
) {
847 if (Statistics
!= NULL
) {
848 return EFI_INVALID_PARAMETER
;
851 if (Statistics
== NULL
) {
852 Status
= EFI_BUFFER_TOO_SMALL
;
854 // Fill in the statistics
856 Statistics
, &LanDriver
->Stats
,
857 MIN (*StatSize
, sizeof (EFI_NETWORK_STATISTICS
))
859 if (*StatSize
< sizeof (EFI_NETWORK_STATISTICS
)) {
860 Status
= EFI_BUFFER_TOO_SMALL
;
863 *StatSize
= sizeof (EFI_NETWORK_STATISTICS
);
870 * UEFI MCastIPtoMAC() function
876 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
878 IN EFI_IP_ADDRESS
*Ip
,
879 OUT EFI_MAC_ADDRESS
*McastMac
882 DEBUG ((DEBUG_NET
, "SnpMcastIptoMac()\n"));
884 // Check Snp instance
886 return EFI_INVALID_PARAMETER
;
889 // Check that driver was started and initialised
890 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
891 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
892 return EFI_DEVICE_ERROR
;
893 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
894 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
895 return EFI_NOT_STARTED
;
899 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
900 return EFI_INVALID_PARAMETER
;
903 // Make sure MAC address is empty
904 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
906 // If we need ipv4 address
908 // Most significant 25 bits of a multicast HW address are set.
909 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
910 McastMac
->Addr
[0] = 0x01;
911 McastMac
->Addr
[1] = 0x00;
912 McastMac
->Addr
[2] = 0x5E;
914 // Lower 23 bits from ipv4 address
915 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
916 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
917 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
919 // Most significant 16 bits of multicast v6 HW address are set
920 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
921 McastMac
->Addr
[0] = 0x33;
922 McastMac
->Addr
[1] = 0x33;
924 // lower four octets are taken from ipv6 address
925 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
926 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
927 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
928 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
935 * UEFI NvData() function
941 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
942 IN BOOLEAN read_write
,
948 DEBUG ((DEBUG_NET
, "SnpNvData()\n"));
950 return EFI_UNSUPPORTED
;
955 * UEFI GetStatus () function
961 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
962 OUT UINT32
*IrqStat OPTIONAL
,
963 OUT VOID
**TxBuff OPTIONAL
968 UINTN NumTxStatusEntries
;
972 LAN9118_DRIVER
*LanDriver
;
974 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
976 // Check preliminaries
978 return EFI_INVALID_PARAMETER
;
981 // Check that driver was started and initialised
982 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
983 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
984 return EFI_DEVICE_ERROR
;
985 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
986 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
987 return EFI_NOT_STARTED
;
990 // Check and acknowledge TX Status interrupt (this will happen if the
991 // consumer of SNP does not call GetStatus.)
992 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
993 // should check for it and dump the TX Status FIFO.
994 FifoInt
= Lan9118MmioRead32 (LAN9118_FIFO_INT
);
996 // Clear the TX Status FIFO Overflow
997 if ((FifoInt
& INSTS_TXSO
) == 0) {
998 FifoInt
|= INSTS_TXSO
;
999 Lan9118MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
1002 // Read interrupt status if IrqStat is not NULL
1003 if (IrqStat
!= NULL
) {
1006 // Check for receive interrupt
1007 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
1008 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
1009 Lan9118MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
1012 // Check for transmit interrupt
1013 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
1014 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
1015 Lan9118MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
1018 // Check for software interrupt
1019 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
1020 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
1021 Lan9118MmioWrite32 (LAN9118_INT_STS
,INSTS_SW_INT
);
1025 // Check Status of transmitted packets
1026 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
1028 NumTxStatusEntries
= Lan9118MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
1029 if (NumTxStatusEntries
> 0) {
1030 TxStatus
= Lan9118MmioRead32 (LAN9118_TX_STATUS
);
1031 PacketTag
= TxStatus
>> 16;
1032 TxStatus
= TxStatus
& 0xFFFF;
1033 if ((TxStatus
& TXSTATUS_ES
) && (TxStatus
!= (TXSTATUS_ES
| TXSTATUS_NO_CA
))) {
1034 DEBUG ((EFI_D_ERROR
, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus
));
1035 if (TxStatus
& TXSTATUS_NO_CA
) {
1036 DEBUG ((EFI_D_ERROR
, "- No carrier\n"));
1038 if (TxStatus
& TXSTATUS_DEF
) {
1039 DEBUG ((EFI_D_ERROR
, "- Packet tx was deferred\n"));
1041 if (TxStatus
& TXSTATUS_EDEF
) {
1042 DEBUG ((EFI_D_ERROR
, "- Tx ended because of excessive deferral\n"));
1044 if (TxStatus
& TXSTATUS_ECOLL
) {
1045 DEBUG ((EFI_D_ERROR
, "- Tx ended because of Excessive Collisions\n"));
1047 if (TxStatus
& TXSTATUS_LCOLL
) {
1048 DEBUG ((EFI_D_ERROR
, "- Packet Tx aborted after coll window of 64 bytes\n"));
1050 if (TxStatus
& TXSTATUS_LOST_CA
) {
1051 DEBUG ((EFI_D_ERROR
, "- Lost carrier during Tx\n"));
1053 return EFI_DEVICE_ERROR
;
1054 } else if (TxBuff
!= NULL
) {
1055 LanDriver
->Stats
.TxTotalFrames
+= 1;
1056 *TxBuff
= LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
];
1058 } else if (TxBuff
!= NULL
) {
1062 // Check for a TX Error interrupt
1063 Interrupts
= Lan9118MmioRead32 (LAN9118_INT_STS
);
1064 if (Interrupts
& INSTS_TXE
) {
1065 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
1067 // Software reset, the TXE interrupt is cleared by the reset.
1068 Status
= SoftReset (0, Snp
);
1069 if (EFI_ERROR (Status
)) {
1070 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
1071 return EFI_DEVICE_ERROR
;
1074 // Reactivate the LEDs
1075 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1076 if (EFI_ERROR (Status
)) {
1081 // Restart the transmitter and if necessary the receiver.
1082 // Do not ask for FIFO reset as it has already been done
1085 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1086 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
1091 // Update the media status
1092 Status
= CheckLinkStatus (0, Snp
);
1093 if (EFI_ERROR(Status
)) {
1094 Snp
->Mode
->MediaPresent
= FALSE
;
1096 Snp
->Mode
->MediaPresent
= TRUE
;
1104 * UEFI Transmit() function
1110 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1114 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1115 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1116 IN UINT16
*Protocol OPTIONAL
1119 LAN9118_DRIVER
*LanDriver
;
1121 UINT32 TxStatusSpace
;
1125 UINT16 LocalProtocol
;
1129 #if defined(EVAL_PERFORMANCE)
1134 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1135 StartClock
= GetPerformanceCounter ();
1138 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1140 // Check preliminaries
1141 if ((Snp
== NULL
) || (Data
== NULL
)) {
1142 return EFI_INVALID_PARAMETER
;
1145 // Check that driver was started and initialised
1146 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1147 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1148 return EFI_DEVICE_ERROR
;
1149 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1150 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1151 return EFI_NOT_STARTED
;
1154 // Ensure header is correct size if non-zero
1156 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1157 return EFI_INVALID_PARAMETER
;
1160 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1161 return EFI_INVALID_PARAMETER
;
1166 // Check validity of BufferSize
1168 if (BuffSize
< Snp
->Mode
->MediaHeaderSize
) {
1169 return EFI_BUFFER_TOO_SMALL
;
1172 // Before transmitting check the link status
1173 /*if (CheckLinkStatus (0, Snp) < 0) {
1174 return EFI_NOT_READY;
1177 // Get DATA FIFO free space in bytes
1178 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1179 if (TxFreeSpace
< BuffSize
) {
1180 return EFI_NOT_READY
;
1183 // Get STATUS FIFO used space in bytes
1184 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1185 if (TxStatusSpace
> 500) {
1186 return EFI_NOT_READY
;
1189 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1190 // has provided a well-formed frame).
1191 if (DstAddr
== NULL
) {
1192 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1195 // Check for the nature of the frame
1196 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1197 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1199 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1202 // Check if broadcast
1203 if (DstAddr
->Addr
[0] == 0xFF) {
1204 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1207 PacketTag
= LanDriver
->NextPacketTag
;
1208 LanDriver
->NextPacketTag
++;
1213 LocalData
= (UINT32
*) Data
;
1214 LocalProtocol
= *Protocol
;
1216 // Create first buffer to pass to controller (for the header)
1217 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1218 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1220 // Write the commands first
1221 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1222 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1224 // Write the destination address
1225 Lan9118MmioWrite32 (LAN9118_TX_DATA
,
1226 (DstAddr
->Addr
[0]) |
1227 (DstAddr
->Addr
[1] << 8) |
1228 (DstAddr
->Addr
[2] << 16) |
1229 (DstAddr
->Addr
[3] << 24)
1232 Lan9118MmioWrite32 (LAN9118_TX_DATA
,
1233 (DstAddr
->Addr
[4]) |
1234 (DstAddr
->Addr
[5] << 8) |
1235 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1236 (SrcAddr
->Addr
[1] << 24)
1239 Lan9118MmioWrite32 (LAN9118_TX_DATA
,
1240 (SrcAddr
->Addr
[2]) |
1241 (SrcAddr
->Addr
[3] << 8) |
1242 (SrcAddr
->Addr
[4] << 16) |
1243 (SrcAddr
->Addr
[5] << 24)
1246 // Write the Protocol
1247 Lan9118MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1249 // Next buffer is the payload
1250 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
1252 // Write the commands
1253 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1254 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1256 // Write the payload
1257 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1258 Lan9118MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1262 LocalData
= (UINT32
*) Data
;
1264 // Create a buffer to pass to controller
1265 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1266 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1268 // Write the commands first
1269 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1270 Lan9118MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1272 // Write all the data
1273 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1274 Lan9118MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1278 // Save the address of the submitted packet so we can notify the consumer that
1279 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1280 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1281 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1283 #if defined(EVAL_PERFORMANCE)
1284 EndClock
= GetPerformanceCounter ();
1285 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1288 LanDriver
->Stats
.TxGoodFrames
+= 1;
1295 * UEFI Receive() function
1301 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1302 OUT UINTN
*HdrSize OPTIONAL
,
1303 IN OUT UINTN
*BuffSize
,
1305 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1306 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1307 OUT UINT16
*Protocol OPTIONAL
1310 LAN9118_DRIVER
*LanDriver
;
1312 UINT32 RxFifoStatus
;
1315 UINT32 PLength
; // Packet length
1320 EFI_MAC_ADDRESS Dst
;
1321 EFI_MAC_ADDRESS Src
;
1322 UINTN DroppedFrames
;
1325 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1327 #if defined(EVAL_PERFORMANCE)
1328 UINT64 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1329 UINT64 StartClock
= GetPerformanceCounter ();
1332 // Check preliminaries
1333 if ((Snp
== NULL
) || (Data
== NULL
) || (BuffSize
== NULL
)) {
1334 return EFI_INVALID_PARAMETER
;
1337 // Check that driver was started and initialised
1338 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1339 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1340 return EFI_DEVICE_ERROR
;
1341 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1342 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1343 return EFI_NOT_STARTED
;
1347 // If the receiver raised the RXE error bit, check if the receiver status
1348 // FIFO is full and if not just acknowledge the error. The two other
1349 // conditions to get a RXE error are :
1350 // . the RX data FIFO is read whereas being empty.
1351 // . the RX status FIFO is read whereas being empty.
1352 // The RX data and status FIFO are read by this driver only in the following
1353 // code of this function. After the readings, the RXE error bit is checked
1354 // and if raised, the controller is reset. Thus, at this point, we consider
1355 // that the only valid reason to get an RXE error is the receiver status
1356 // FIFO being full. And if this is not the case, we consider that this is
1357 // a spurious error and we just get rid of it. We experienced such 'spurious'
1358 // errors when running the driver on an A57 on Juno. No valid reason to
1359 // explain those errors has been found so far and everything seems to
1360 // work perfectly when they are just ignored.
1362 IntSts
= Lan9118MmioRead32 (LAN9118_INT_STS
);
1363 if ((IntSts
& INSTS_RXE
) && (!(IntSts
& INSTS_RSFF
))) {
1364 Lan9118MmioWrite32 (LAN9118_INT_STS
, INSTS_RXE
);
1367 // Count dropped frames
1368 DroppedFrames
= Lan9118MmioRead32 (LAN9118_RX_DROP
);
1369 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1371 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1373 return EFI_NOT_READY
;
1376 // Read Rx Status (only if not empty)
1377 RxFifoStatus
= Lan9118MmioRead32 (LAN9118_RX_STATUS
);
1378 LanDriver
->Stats
.RxTotalFrames
+= 1;
1380 // First check for errors
1381 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1382 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1383 (RxFifoStatus
& RXSTATUS_FTL
) ||
1384 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1385 (RxFifoStatus
& RXSTATUS_LE
) ||
1386 (RxFifoStatus
& RXSTATUS_DB
))
1388 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1389 return EFI_DEVICE_ERROR
;
1392 // Check if we got a CRC error
1393 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1394 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1395 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1396 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1397 return EFI_DEVICE_ERROR
;
1400 // Check if we got a runt frame
1401 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1402 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1403 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1404 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1405 return EFI_DEVICE_ERROR
;
1408 // Check filtering status for this packet
1409 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1410 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1414 // Check if we got a broadcast frame
1415 if (RxFifoStatus
& RXSTATUS_BCF
) {
1416 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1419 // Check if we got a multicast frame
1420 if (RxFifoStatus
& RXSTATUS_MCF
) {
1421 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1424 // Check if we got a unicast frame
1425 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1426 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1429 // Get the received packet length
1430 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1431 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1433 // If padding is applied, read more DWORDs
1435 Padding
= 4 - (PLength
% 4);
1436 ReadLimit
= (PLength
+ Padding
)/4;
1438 ReadLimit
= PLength
/4;
1442 // Check buffer size
1443 if (*BuffSize
< (PLength
+ Padding
)) {
1444 *BuffSize
= PLength
+ Padding
;
1445 return EFI_BUFFER_TOO_SMALL
;
1448 // Set the amount of data to be transfered out of FIFO for THIS packet
1449 // This can be used to trigger an interrupt, and status can be checked
1450 RxCfgValue
= Lan9118MmioRead32 (LAN9118_RX_CFG
);
1451 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1452 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1454 // Set end alignment to 4-bytes
1455 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1456 Lan9118MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1458 // Update buffer size
1459 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1460 // 4 bytes longer than packet actually is, unless
1461 // packet is < 64 bytes
1463 if (HdrSize
!= NULL
)
1464 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1466 // Format the pointer
1467 RawData
= (UINT32
*)Data
;
1470 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1471 RawData
[Count
] = Lan9118MmioRead32 (LAN9118_RX_DATA
);
1474 // Get the destination address
1475 if (DstAddr
!= NULL
) {
1476 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1477 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1478 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1479 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1480 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1481 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1482 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1485 // Get the source address
1486 if (SrcAddr
!= NULL
) {
1487 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1488 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1489 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1490 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1491 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1492 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1493 CopyMem (SrcAddr
, &Src
, NET_ETHER_ADDR_LEN
);
1497 if (Protocol
!= NULL
) {
1498 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1501 // Check for Rx errors (worst possible error)
1502 if (Lan9118MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1503 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1505 // Software reset, the RXE interrupt is cleared by the reset.
1506 Status
= SoftReset (0, Snp
);
1507 if (EFI_ERROR (Status
)) {
1508 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1509 return EFI_DEVICE_ERROR
;
1512 // Reactivate the LEDs
1513 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1514 if (EFI_ERROR (Status
)) {
1519 // Restart the receiver and the transmitter without reseting the FIFOs
1520 // as it has been done by SoftReset().
1523 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1525 // Say that command could not be sent
1526 return EFI_DEVICE_ERROR
;
1529 #if defined(EVAL_PERFORMANCE)
1530 UINT64 EndClock
= GetPerformanceCounter ();
1531 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1534 LanDriver
->Stats
.RxGoodFrames
+= 1;