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
= MmioRead32 (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 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
310 gBS
->Stall (LAN9118_STALL
);
311 gBS
->Stall (LAN9118_STALL
);
313 // Configure GPIO and HW
314 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
315 if (EFI_ERROR(Status
)) {
319 // Assign the transmitter buffer size (default values)
320 TxStatusSize
= LAN9118_TX_STATUS_SIZE
;
321 RxStatusSize
= LAN9118_RX_STATUS_SIZE
;
323 // Check that a buff size was specified
324 if (TxBufferSize
> 0) {
325 if (RxBufferSize
== 0) {
326 RxBufferSize
= LAN9118_RX_DATA_SIZE
;
329 AllocResult
= ChangeFifoAllocation (
338 if (AllocResult
< 0) {
339 return EFI_OUT_OF_RESOURCES
;
343 // Do auto-negotiation if supported
344 Status
= AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL
, Snp
);
345 if (EFI_ERROR(Status
)) {
346 DEBUG ((EFI_D_WARN
, "LAN9118: Auto Negotiation failed.\n"));
349 // Configure flow control depending on speed capabilities
350 Status
= ConfigureFlow (0, 0, 0, 0, Snp
);
351 if (EFI_ERROR(Status
)) {
355 // Enable the transmitter
356 Status
= StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
357 if (EFI_ERROR(Status
)) {
361 // Now acknowledge all interrupts
362 MmioWrite32 (LAN9118_INT_STS
, ~0);
364 // Declare the driver as initialized
365 Snp
->Mode
->State
= EfiSimpleNetworkInitialized
;
371 * UEFI Reset () function
377 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
378 IN BOOLEAN Verification
390 // Check Snp Instance
392 return EFI_INVALID_PARAMETER
;
395 // First check that driver has not already been initialized
396 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
397 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
398 return EFI_DEVICE_ERROR
;
399 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
400 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
401 return EFI_NOT_STARTED
;
404 // Initiate a PHY reset
405 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
406 if (EFI_ERROR (Status
)) {
407 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
408 return EFI_NOT_STARTED
;
411 // Initiate a software reset
412 ResetFlags
|= SOFT_RESET_CHECK_MAC_ADDR_LOAD
| SOFT_RESET_CLEAR_INT
;
415 ResetFlags
|= SOFT_RESET_SELF_TEST
;
418 Status
= SoftReset (ResetFlags
, Snp
);
419 if (EFI_ERROR (Status
)) {
420 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
421 return EFI_DEVICE_ERROR
;
424 // Read the PM register
425 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
427 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
428 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
429 // MPTCTRL_PME_EN: Allow Power Management Events
430 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
432 // Write the current configuration to the register
433 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
434 gBS
->Stall (LAN9118_STALL
);
436 // Reactivate the LEDs
437 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
438 if (EFI_ERROR (Status
)) {
442 // Check that a buffer size was specified in SnpInitialize
443 if (gTxBuffer
!= 0) {
444 HwConf
= MmioRead32 (LAN9118_HW_CFG
); // Read the HW register
445 HwConf
&= ~HW_CFG_TX_FIFO_SIZE_MASK
; // Clear buffer bits first
446 HwConf
|= HW_CFG_TX_FIFO_SIZE(gTxBuffer
); // assign size chosen in SnpInitialize
448 MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
449 gBS
->Stall (LAN9118_STALL
);
452 // Enable the receiver and transmitter and clear their contents
453 StartRx (START_RX_CLEAR
, Snp
);
454 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
456 // Now acknowledge all interrupts
457 MmioWrite32 (LAN9118_INT_STS
, ~0);
463 * UEFI Shutdown () function
469 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
474 // Check Snp Instance
476 return EFI_INVALID_PARAMETER
;
479 // First check that driver has not already been initialized
480 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
481 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
482 return EFI_DEVICE_ERROR
;
483 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
484 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
485 return EFI_NOT_STARTED
;
488 // Initiate a PHY reset
489 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
490 if (EFI_ERROR (Status
)) {
494 // Initiate a software reset
495 Status
= SoftReset (0, Snp
);
496 if (EFI_ERROR (Status
)) {
497 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
501 // Back to the started and thus not initialized state
502 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
508 Enable and/or disable the receive filters of the LAN9118
510 Please refer to the UEFI specification for the precedence rules among the
511 Enable, Disable and ResetMCastFilter parameters.
513 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
515 @param[in] Enable A bit mask of receive filters to enable.
516 @param[in] Disable A bit mask of receive filters to disable.
517 @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast
518 receive filters on the network interface to
519 their default values.
520 @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new
521 MCastFilter list. This value must be less than or
522 equal to the MCastFilterCnt field of
523 EFI_SIMPLE_NETWORK_MODE. This field is optional if
524 ResetMCastFilter is TRUE.
525 @param[in] MCastFilter A pointer to a list of new multicast receive
526 filter HW MAC addresses. This list will replace
527 any existing multicast HW MAC address list. This
528 field is optional if ResetMCastFilter is TRUE.
530 @retval EFI_SUCCESS The receive filters of the LAN9118 were updated.
531 @retval EFI_NOT_STARTED The LAN9118 has not been started.
532 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
534 . Multicast is being enabled (the
535 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in
536 Enable, it is not set in Disable, and ResetMCastFilter
537 is FALSE) and MCastFilterCount is zero.
538 . Multicast is being enabled and MCastFilterCount is
539 greater than Snp->Mode->MaxMCastFilterCount.
540 . Multicast is being enabled and MCastFilter is NULL
541 . Multicast is being enabled and one or more of the
542 addresses in the MCastFilter list are not valid
543 multicast MAC addresses.
544 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
550 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
553 IN BOOLEAN ResetMCastFilter
,
554 IN UINTN MCastFilterCnt OPTIONAL
,
555 IN EFI_MAC_ADDRESS
*MCastFilter OPTIONAL
558 EFI_SIMPLE_NETWORK_MODE
*Mode
;
559 UINT32 MultHashTableHigh
;
560 UINT32 MultHashTableLow
;
565 UINT32 ReceiveFilterSetting
;
566 EFI_MAC_ADDRESS
*Mac
;
567 EFI_MAC_ADDRESS ZeroMac
;
569 // Check Snp Instance
571 return EFI_INVALID_PARAMETER
;
575 // Check that driver was started and initialised
576 if (Mode
->State
== EfiSimpleNetworkStarted
) {
577 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
578 return EFI_DEVICE_ERROR
;
579 } else if (Mode
->State
== EfiSimpleNetworkStopped
) {
580 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
581 return EFI_NOT_STARTED
;
584 if ((Enable
& (~Mode
->ReceiveFilterMask
)) ||
585 (Disable
& (~Mode
->ReceiveFilterMask
)) ) {
586 return EFI_INVALID_PARAMETER
;
590 // Check the validity of the multicast setting and compute the
591 // hash values of the multicast mac addresses to listen to.
594 MultHashTableHigh
= 0;
595 MultHashTableLow
= 0;
596 if ((!ResetMCastFilter
) &&
597 ((Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) == 0) &&
598 ((Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) != 0) ) {
599 if ((MCastFilterCnt
== 0) ||
600 (MCastFilterCnt
> Mode
->MaxMCastFilterCount
) ||
601 (MCastFilter
== NULL
) ) {
602 return EFI_INVALID_PARAMETER
;
605 // Check the validity of all multicast addresses before to change
608 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
609 if ((MCastFilter
[Count
].Addr
[0] & 1) == 0) {
610 return EFI_INVALID_PARAMETER
;
615 // Go through each filter address and set appropriate bits on hash table
617 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
618 Mac
= &(MCastFilter
[Count
]);
619 CopyMem (&Mode
->MCastFilter
[Count
], Mac
, sizeof(EFI_MAC_ADDRESS
));
621 Crc
= GenEtherCrc32 (Mac
, NET_ETHER_ADDR_LEN
);
622 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
625 // The most significant 6 bits of the MAC address CRC constitute the hash
626 // value of the MAC address.
628 HashValue
= (Crc
>> 26) & 0x3F;
630 // Select hashlow register if MSB is not set
631 if ((HashValue
& 0x20) == 0) {
632 MultHashTableLow
|= (1 << HashValue
);
634 MultHashTableHigh
|= (1 << (HashValue
& 0x1F));
637 Mode
->MCastFilterCount
= MCastFilterCnt
;
638 } else if (ResetMCastFilter
) {
639 Mode
->MCastFilterCount
= 0;
641 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
642 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
646 // Before to change anything, stop and reset the reception of
649 StopRx (STOP_RX_CLEAR
, Snp
);
652 // Write the mask of the selected hash values for the multicast filtering.
653 // The two masks are set to zero if the multicast filtering is not enabled.
655 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
656 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
658 ReceiveFilterSetting
= (Mode
->ReceiveFilterSetting
| Enable
) & (~Disable
);
661 // Read MAC controller
663 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
664 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_BCAST
| MACCR_PRMS
| MACCR_MCPAS
);
666 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
667 Lan9118SetMacAddress (&Mode
->CurrentAddress
, Snp
);
668 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
671 // The Unicast packets do not have to be listen to, set the MAC
672 // address of the LAN9118 to be the "not configured" all zeroes
673 // ethernet MAC address.
675 ZeroMem (&ZeroMac
, NET_ETHER_ADDR_LEN
);
676 Lan9118SetMacAddress (&ZeroMac
, Snp
);
679 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
680 MacCSRValue
|= MACCR_HPFILT
;
681 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
684 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
685 MacCSRValue
|= MACCR_MCPAS
;
686 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
689 if ((ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) == 0) {
690 MacCSRValue
|= MACCR_BCAST
;
692 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
695 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
696 MacCSRValue
|= MACCR_PRMS
;
697 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
701 // Write the options to the MAC_CSR
703 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
704 gBS
->Stall (LAN9118_STALL
);
707 // If we have to retrieve something, start packet reception.
709 Mode
->ReceiveFilterSetting
= ReceiveFilterSetting
;
710 if (ReceiveFilterSetting
!= 0) {
718 Modify of reset the current station address
720 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
722 @param[in] Reset Flag used to reset the station address to the
723 LAN9118's permanent address.
724 @param[in] New New station address to be used for the network interface.
726 @retval EFI_SUCCESS The LAN9118's station address was updated.
727 @retval EFI_NOT_STARTED The LAN9118 has not been started.
728 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
729 . The "New" station address is invalid.
730 . "Reset" is FALSE and "New" is NULL.
731 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
737 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
739 IN EFI_MAC_ADDRESS
*New
743 UINT8 PermAddr
[NET_ETHER_ADDR_LEN
];
745 DEBUG ((DEBUG_NET
, "SnpStationAddress()\n"));
747 // Check Snp instance
749 return EFI_INVALID_PARAMETER
;
752 // Check that driver was started and initialised
753 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
754 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
755 return EFI_DEVICE_ERROR
;
756 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
757 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
758 return EFI_NOT_STARTED
;
761 // Get the Permanent MAC address if need reset
763 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
764 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM
) {
765 for (Count
= 0; Count
< NET_ETHER_ADDR_LEN
; Count
++) {
766 PermAddr
[Count
] = IndirectEEPROMRead32 (Count
+ 1);
768 New
= (EFI_MAC_ADDRESS
*) PermAddr
;
769 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) PermAddr
, Snp
);
771 DEBUG ((EFI_D_ERROR
, "LAN9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
772 New
= (EFI_MAC_ADDRESS
*) (FixedPcdGet64 (PcdLan9118DefaultMacAddress
));
775 // Otherwise use the specified new MAC address
777 return EFI_INVALID_PARAMETER
;
780 // If it is a multicast address, it is not valid.
782 if (New
->Addr
[0] & 0x01) {
783 return EFI_INVALID_PARAMETER
;
787 CopyMem (&Snp
->Mode
->CurrentAddress
, New
, NET_ETHER_ADDR_LEN
);
790 // If packet reception is currently activated, stop and reset it,
791 // set the new ethernet address and restart the packet reception.
792 // Otherwise, nothing to do, the MAC address will be updated in
793 // SnpReceiveFilters() when the UNICAST packet reception will be
796 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
797 StopRx (STOP_RX_CLEAR
, Snp
);
798 Lan9118SetMacAddress (New
, Snp
);
806 * UEFI Statistics() function
812 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
814 IN OUT UINTN
*StatSize
,
815 OUT EFI_NETWORK_STATISTICS
*Statistics
818 LAN9118_DRIVER
*LanDriver
;
821 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
823 DEBUG ((DEBUG_NET
, "SnpStatistics()\n"));
825 // Check Snp instance
827 return EFI_INVALID_PARAMETER
;
830 // Check that driver was started and initialised
831 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
832 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
833 return EFI_DEVICE_ERROR
;
834 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
835 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
836 return EFI_NOT_STARTED
;
840 // Do a reset if required. It is not clearly stated in the UEFI specification
841 // whether the reset has to be done before to copy the statistics in "Statictics"
842 // or after. It is a bit strange to do it before but that is what is expected by
843 // the SCT test on Statistics() with reset : "0x3de76704,0x4bf5,0x42cd,0x8c,0x89,
844 // 0x54,0x7e,0x4f,0xad,0x4f,0x24".
847 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
850 Status
= EFI_SUCCESS
;
851 if (StatSize
== NULL
) {
852 if (Statistics
!= NULL
) {
853 return EFI_INVALID_PARAMETER
;
856 if (Statistics
== NULL
) {
857 Status
= EFI_BUFFER_TOO_SMALL
;
859 // Fill in the statistics
861 Statistics
, &LanDriver
->Stats
,
862 MIN (*StatSize
, sizeof (EFI_NETWORK_STATISTICS
))
864 if (*StatSize
< sizeof (EFI_NETWORK_STATISTICS
)) {
865 Status
= EFI_BUFFER_TOO_SMALL
;
868 *StatSize
= sizeof (EFI_NETWORK_STATISTICS
);
875 * UEFI MCastIPtoMAC() function
881 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
883 IN EFI_IP_ADDRESS
*Ip
,
884 OUT EFI_MAC_ADDRESS
*McastMac
887 DEBUG ((DEBUG_NET
, "SnpMcastIptoMac()\n"));
889 // Check Snp instance
891 return EFI_INVALID_PARAMETER
;
894 // Check that driver was started and initialised
895 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
896 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
897 return EFI_DEVICE_ERROR
;
898 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
899 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
900 return EFI_NOT_STARTED
;
904 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
905 return EFI_INVALID_PARAMETER
;
908 // Make sure MAC address is empty
909 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
911 // If we need ipv4 address
913 // Most significant 25 bits of a multicast HW address are set.
914 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
915 McastMac
->Addr
[0] = 0x01;
916 McastMac
->Addr
[1] = 0x00;
917 McastMac
->Addr
[2] = 0x5E;
919 // Lower 23 bits from ipv4 address
920 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
921 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
922 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
924 // Most significant 16 bits of multicast v6 HW address are set
925 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
926 McastMac
->Addr
[0] = 0x33;
927 McastMac
->Addr
[1] = 0x33;
929 // lower four octets are taken from ipv6 address
930 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
931 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
932 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
933 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
940 * UEFI NvData() function
946 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
947 IN BOOLEAN read_write
,
953 DEBUG ((DEBUG_NET
, "SnpNvData()\n"));
955 return EFI_UNSUPPORTED
;
960 * UEFI GetStatus () function
966 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
967 OUT UINT32
*IrqStat OPTIONAL
,
968 OUT VOID
**TxBuff OPTIONAL
973 UINTN NumTxStatusEntries
;
977 LAN9118_DRIVER
*LanDriver
;
979 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
981 // Check preliminaries
983 return EFI_INVALID_PARAMETER
;
986 // Check that driver was started and initialised
987 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
988 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
989 return EFI_DEVICE_ERROR
;
990 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
991 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
992 return EFI_NOT_STARTED
;
995 // Check and acknowledge TX Status interrupt (this will happen if the
996 // consumer of SNP does not call GetStatus.)
997 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
998 // should check for it and dump the TX Status FIFO.
999 FifoInt
= MmioRead32 (LAN9118_FIFO_INT
);
1001 // Clear the TX Status FIFO Overflow
1002 if ((FifoInt
& INSTS_TXSO
) == 0) {
1003 FifoInt
|= INSTS_TXSO
;
1004 MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
1007 // Read interrupt status if IrqStat is not NULL
1008 if (IrqStat
!= NULL
) {
1011 // Check for receive interrupt
1012 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
1013 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
1014 MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
1017 // Check for transmit interrupt
1018 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
1019 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
1020 MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
1023 // Check for software interrupt
1024 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
1025 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
1026 MmioWrite32 (LAN9118_INT_STS
,INSTS_SW_INT
);
1030 // Check Status of transmitted packets
1031 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
1033 NumTxStatusEntries
= MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
1034 if (NumTxStatusEntries
> 0) {
1035 TxStatus
= MmioRead32 (LAN9118_TX_STATUS
);
1036 PacketTag
= TxStatus
>> 16;
1037 TxStatus
= TxStatus
& 0xFFFF;
1038 if ((TxStatus
& TXSTATUS_ES
) && (TxStatus
!= (TXSTATUS_ES
| TXSTATUS_NO_CA
))) {
1039 DEBUG ((EFI_D_ERROR
, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus
));
1040 if (TxStatus
& TXSTATUS_NO_CA
) {
1041 DEBUG ((EFI_D_ERROR
, "- No carrier\n"));
1043 if (TxStatus
& TXSTATUS_DEF
) {
1044 DEBUG ((EFI_D_ERROR
, "- Packet tx was deferred\n"));
1046 if (TxStatus
& TXSTATUS_EDEF
) {
1047 DEBUG ((EFI_D_ERROR
, "- Tx ended because of excessive deferral\n"));
1049 if (TxStatus
& TXSTATUS_ECOLL
) {
1050 DEBUG ((EFI_D_ERROR
, "- Tx ended because of Excessive Collisions\n"));
1052 if (TxStatus
& TXSTATUS_LCOLL
) {
1053 DEBUG ((EFI_D_ERROR
, "- Packet Tx aborted after coll window of 64 bytes\n"));
1055 if (TxStatus
& TXSTATUS_LOST_CA
) {
1056 DEBUG ((EFI_D_ERROR
, "- Lost carrier during Tx\n"));
1058 return EFI_DEVICE_ERROR
;
1059 } else if (TxBuff
!= NULL
) {
1060 LanDriver
->Stats
.TxTotalFrames
+= 1;
1061 *TxBuff
= LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
];
1065 // Check for a TX Error interrupt
1066 Interrupts
= MmioRead32 (LAN9118_INT_STS
);
1067 if (Interrupts
& INSTS_TXE
) {
1068 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
1070 // Software reset, the TXE interrupt is cleared by the reset.
1071 Status
= SoftReset (0, Snp
);
1072 if (EFI_ERROR (Status
)) {
1073 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
1074 return EFI_DEVICE_ERROR
;
1077 // Reactivate the LEDs
1078 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1079 if (EFI_ERROR (Status
)) {
1084 // Restart the transmitter and if necessary the receiver.
1085 // Do not ask for FIFO reset as it has already been done
1088 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1089 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
1094 // Update the media status
1095 Status
= CheckLinkStatus (0, Snp
);
1096 if (EFI_ERROR(Status
)) {
1097 Snp
->Mode
->MediaPresent
= FALSE
;
1099 Snp
->Mode
->MediaPresent
= TRUE
;
1107 * UEFI Transmit() function
1113 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1117 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1118 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1119 IN UINT16
*Protocol OPTIONAL
1122 LAN9118_DRIVER
*LanDriver
;
1124 UINT32 TxStatusSpace
;
1128 UINT16 LocalProtocol
;
1132 #if defined(EVAL_PERFORMANCE)
1137 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1138 StartClock
= GetPerformanceCounter ();
1141 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1143 // Check preliminaries
1144 if ((Snp
== NULL
) || (Data
== NULL
)) {
1145 return EFI_INVALID_PARAMETER
;
1148 // Check that driver was started and initialised
1149 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1150 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1151 return EFI_DEVICE_ERROR
;
1152 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1153 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1154 return EFI_NOT_STARTED
;
1157 // Ensure header is correct size if non-zero
1159 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1160 return EFI_INVALID_PARAMETER
;
1163 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1164 return EFI_INVALID_PARAMETER
;
1169 // Check validity of BufferSize
1171 if (BuffSize
< Snp
->Mode
->MediaHeaderSize
) {
1172 return EFI_BUFFER_TOO_SMALL
;
1175 // Before transmitting check the link status
1176 /*if (CheckLinkStatus (0, Snp) < 0) {
1177 return EFI_NOT_READY;
1180 // Get DATA FIFO free space in bytes
1181 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1182 if (TxFreeSpace
< BuffSize
) {
1183 return EFI_NOT_READY
;
1186 // Get STATUS FIFO used space in bytes
1187 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1188 if (TxStatusSpace
> 500) {
1189 return EFI_NOT_READY
;
1192 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1193 // has provided a well-formed frame).
1194 if (DstAddr
== NULL
) {
1195 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1198 // Check for the nature of the frame
1199 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1200 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1202 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1205 // Check if broadcast
1206 if (DstAddr
->Addr
[0] == 0xFF) {
1207 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1210 PacketTag
= LanDriver
->NextPacketTag
;
1211 LanDriver
->NextPacketTag
++;
1216 LocalData
= (UINT32
*) Data
;
1217 LocalProtocol
= *Protocol
;
1219 // Create first buffer to pass to controller (for the header)
1220 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1221 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1223 // Write the commands first
1224 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1225 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1227 // Write the destination address
1228 MmioWrite32 (LAN9118_TX_DATA
,
1229 (DstAddr
->Addr
[0]) |
1230 (DstAddr
->Addr
[1] << 8) |
1231 (DstAddr
->Addr
[2] << 16) |
1232 (DstAddr
->Addr
[3] << 24)
1235 MmioWrite32 (LAN9118_TX_DATA
,
1236 (DstAddr
->Addr
[4]) |
1237 (DstAddr
->Addr
[5] << 8) |
1238 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1239 (SrcAddr
->Addr
[1] << 24)
1242 MmioWrite32 (LAN9118_TX_DATA
,
1243 (SrcAddr
->Addr
[2]) |
1244 (SrcAddr
->Addr
[3] << 8) |
1245 (SrcAddr
->Addr
[4] << 16) |
1246 (SrcAddr
->Addr
[5] << 24)
1249 // Write the Protocol
1250 MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1252 // Next buffer is the payload
1253 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
1255 // Write the commands
1256 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1257 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1259 // Write the payload
1260 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1261 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1265 LocalData
= (UINT32
*) Data
;
1267 // Create a buffer to pass to controller
1268 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1269 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1271 // Write the commands first
1272 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1273 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1275 // Write all the data
1276 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1277 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1281 // Save the address of the submitted packet so we can notify the consumer that
1282 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1283 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1284 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1286 #if defined(EVAL_PERFORMANCE)
1287 EndClock
= GetPerformanceCounter ();
1288 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1291 LanDriver
->Stats
.TxGoodFrames
+= 1;
1298 * UEFI Receive() function
1304 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1305 OUT UINTN
*HdrSize OPTIONAL
,
1306 IN OUT UINTN
*BuffSize
,
1308 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1309 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1310 OUT UINT16
*Protocol OPTIONAL
1313 LAN9118_DRIVER
*LanDriver
;
1315 UINT32 RxFifoStatus
;
1318 UINT32 PLength
; // Packet length
1323 EFI_MAC_ADDRESS Dst
;
1324 EFI_MAC_ADDRESS Src
;
1325 UINTN DroppedFrames
;
1328 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1330 #if defined(EVAL_PERFORMANCE)
1331 UINT64 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1332 UINT64 StartClock
= GetPerformanceCounter ();
1335 // Check preliminaries
1336 if ((Snp
== NULL
) || (Data
== NULL
) || (BuffSize
== NULL
)) {
1337 return EFI_INVALID_PARAMETER
;
1340 // Check that driver was started and initialised
1341 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1342 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1343 return EFI_DEVICE_ERROR
;
1344 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1345 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1346 return EFI_NOT_STARTED
;
1350 // If the receiver raised the RXE error bit, check if the receiver status
1351 // FIFO is full and if not just acknowledge the error. The two other
1352 // conditions to get a RXE error are :
1353 // . the RX data FIFO is read whereas being empty.
1354 // . the RX status FIFO is read whereas being empty.
1355 // The RX data and status FIFO are read by this driver only in the following
1356 // code of this function. After the readings, the RXE error bit is checked
1357 // and if raised, the controller is reset. Thus, at this point, we consider
1358 // that the only valid reason to get an RXE error is the receiver status
1359 // FIFO being full. And if this is not the case, we consider that this is
1360 // a spurious error and we just get rid of it. We experienced such 'spurious'
1361 // errors when running the driver on an A57 on Juno. No valid reason to
1362 // explain those errors has been found so far and everything seems to
1363 // work perfectly when they are just ignored.
1365 IntSts
= MmioRead32 (LAN9118_INT_STS
);
1366 if ((IntSts
& INSTS_RXE
) && (!(IntSts
& INSTS_RSFF
))) {
1367 MmioWrite32 (LAN9118_INT_STS
, INSTS_RXE
);
1370 // Count dropped frames
1371 DroppedFrames
= MmioRead32 (LAN9118_RX_DROP
);
1372 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1374 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1376 return EFI_NOT_READY
;
1379 // Read Rx Status (only if not empty)
1380 RxFifoStatus
= MmioRead32 (LAN9118_RX_STATUS
);
1381 LanDriver
->Stats
.RxTotalFrames
+= 1;
1383 // First check for errors
1384 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1385 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1386 (RxFifoStatus
& RXSTATUS_FTL
) ||
1387 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1388 (RxFifoStatus
& RXSTATUS_LE
) ||
1389 (RxFifoStatus
& RXSTATUS_DB
))
1391 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1392 return EFI_DEVICE_ERROR
;
1395 // Check if we got a CRC error
1396 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1397 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1398 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1399 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1400 return EFI_DEVICE_ERROR
;
1403 // Check if we got a runt frame
1404 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1405 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1406 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1407 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1408 return EFI_DEVICE_ERROR
;
1411 // Check filtering status for this packet
1412 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1413 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1417 // Check if we got a broadcast frame
1418 if (RxFifoStatus
& RXSTATUS_BCF
) {
1419 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1422 // Check if we got a multicast frame
1423 if (RxFifoStatus
& RXSTATUS_MCF
) {
1424 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1427 // Check if we got a unicast frame
1428 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1429 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1432 // Get the received packet length
1433 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1434 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1436 // If padding is applied, read more DWORDs
1438 Padding
= 4 - (PLength
% 4);
1439 ReadLimit
= (PLength
+ Padding
)/4;
1441 ReadLimit
= PLength
/4;
1445 // Check buffer size
1446 if (*BuffSize
< (PLength
+ Padding
)) {
1447 *BuffSize
= PLength
+ Padding
;
1448 return EFI_BUFFER_TOO_SMALL
;
1451 // Set the amount of data to be transfered out of FIFO for THIS packet
1452 // This can be used to trigger an interrupt, and status can be checked
1453 RxCfgValue
= MmioRead32 (LAN9118_RX_CFG
);
1454 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1455 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1457 // Set end alignment to 4-bytes
1458 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1459 MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1461 // Update buffer size
1462 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1463 // 4 bytes longer than packet actually is, unless
1464 // packet is < 64 bytes
1466 if (HdrSize
!= NULL
)
1467 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1469 // Format the pointer
1470 RawData
= (UINT32
*)Data
;
1473 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1474 RawData
[Count
] = MmioRead32 (LAN9118_RX_DATA
);
1477 // Get the destination address
1478 if (DstAddr
!= NULL
) {
1479 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1480 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1481 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1482 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1483 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1484 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1485 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1488 // Get the source address
1489 if (SrcAddr
!= NULL
) {
1490 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1491 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1492 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1493 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1494 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1495 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1496 CopyMem (SrcAddr
, &Src
, NET_ETHER_ADDR_LEN
);
1500 if (Protocol
!= NULL
) {
1501 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1504 // Check for Rx errors (worst possible error)
1505 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1506 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1508 // Software reset, the RXE interrupt is cleared by the reset.
1509 Status
= SoftReset (0, Snp
);
1510 if (EFI_ERROR (Status
)) {
1511 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1512 return EFI_DEVICE_ERROR
;
1515 // Reactivate the LEDs
1516 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1517 if (EFI_ERROR (Status
)) {
1522 // Restart the receiver and the transmitter without reseting the FIFOs
1523 // as it has been done by SoftReset().
1526 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1528 // Say that command could not be sent
1529 return EFI_DEVICE_ERROR
;
1532 #if defined(EVAL_PERFORMANCE)
1533 UINT64 EndClock
= GetPerformanceCounter ();
1534 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1537 LanDriver
->Stats
.RxGoodFrames
+= 1;