3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "Lan9118Dxe.h"
19 MAC_ADDR_DEVICE_PATH Lan9118
;
20 EFI_DEVICE_PATH_PROTOCOL End
;
21 } LAN9118_DEVICE_PATH
;
23 LAN9118_DEVICE_PATH Lan9118PathTemplate
= {
26 MESSAGING_DEVICE_PATH
, MSG_MAC_ADDR_DP
,
27 { (UINT8
) (sizeof(MAC_ADDR_DEVICE_PATH
)), (UINT8
) ((sizeof(MAC_ADDR_DEVICE_PATH
)) >> 8) }
34 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
35 { sizeof(EFI_DEVICE_PATH_PROTOCOL
), 0 }
40 ** Entry point for the LAN9118 driver
46 IN EFI_SYSTEM_TABLE
*SystemTable
50 LAN9118_DRIVER
*LanDriver
;
51 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
52 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
53 LAN9118_DEVICE_PATH
*Lan9118Path
;
54 EFI_HANDLE ControllerHandle
;
56 // The PcdLan9118DxeBaseAddress PCD must be defined
57 ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress
) != 0);
60 LanDriver
= AllocateZeroPool (sizeof (LAN9118_DRIVER
));
61 if (LanDriver
== NULL
) {
62 return EFI_OUT_OF_RESOURCES
;
64 Lan9118Path
= (LAN9118_DEVICE_PATH
*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH
), &Lan9118PathTemplate
);
65 if (Lan9118Path
== NULL
) {
66 return EFI_OUT_OF_RESOURCES
;
69 // Initialize pointers
70 Snp
= &(LanDriver
->Snp
);
71 SnpMode
= &(LanDriver
->SnpMode
);
74 // Set the signature of the LAN Driver structure
75 LanDriver
->Signature
= LAN9118_SIGNATURE
;
77 // Assign fields and func pointers
78 Snp
->Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
79 Snp
->WaitForPacket
= NULL
;
80 Snp
->Initialize
= SnpInitialize
;
81 Snp
->Start
= SnpStart
;
83 Snp
->Reset
= SnpReset
;
84 Snp
->Shutdown
= SnpShutdown
;
85 Snp
->ReceiveFilters
= SnpReceiveFilters
;
86 Snp
->StationAddress
= SnpStationAddress
;
87 Snp
->Statistics
= SnpStatistics
;
88 Snp
->MCastIpToMac
= SnpMcastIptoMac
;
89 Snp
->NvData
= SnpNvData
;
90 Snp
->GetStatus
= SnpGetStatus
;
91 Snp
->Transmit
= SnpTransmit
;
92 Snp
->Receive
= SnpReceive
;
94 // Start completing simple network mode structure
95 SnpMode
->State
= EfiSimpleNetworkStopped
;
96 SnpMode
->HwAddressSize
= NET_ETHER_ADDR_LEN
; // HW address is 6 bytes
97 SnpMode
->MediaHeaderSize
= sizeof(ETHER_HEAD
); // Not sure of this
98 SnpMode
->MaxPacketSize
= EFI_PAGE_SIZE
; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
99 SnpMode
->NvRamSize
= 0; // No NVRAM with this device
100 SnpMode
->NvRamAccessSize
= 0; // No NVRAM with this device
103 // Claim that all receive filter settings are supported, though the MULTICAST mode
104 // is not completely supported. The LAN9118 Ethernet controller is only able to
105 // do a "hash filtering" and not a perfect filtering on multicast addresses. The
106 // controller does not filter the multicast addresses directly but a hash value
107 // of them. The hash value of a multicast address is derived from its CRC and
108 // ranges from 0 to 63 included.
109 // We claim that the perfect MULTICAST filtering mode is supported because
110 // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode
111 // and thus not being able to take advantage of the hash filtering.
113 SnpMode
->ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
114 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
115 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
116 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
|
117 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
119 // We do not intend to receive anything for the time being.
120 SnpMode
->ReceiveFilterSetting
= 0;
122 // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses
123 SnpMode
->MaxMCastFilterCount
= MAX_MCAST_FILTER_CNT
;
124 SnpMode
->MCastFilterCount
= 0;
125 ZeroMem (&SnpMode
->MCastFilter
, MAX_MCAST_FILTER_CNT
* sizeof(EFI_MAC_ADDRESS
));
127 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
128 SnpMode
->IfType
= NET_IFTYPE_ETHERNET
;
130 // Mac address is changeable as it is loaded from erasable memory
131 SnpMode
->MacAddressChangeable
= TRUE
;
133 // Can only transmit one packet at a time
134 SnpMode
->MultipleTxSupported
= FALSE
;
136 // MediaPresent checks for cable connection and partner link
137 SnpMode
->MediaPresentSupported
= TRUE
;
138 SnpMode
->MediaPresent
= FALSE
;
140 // Set broadcast address
141 SetMem (&SnpMode
->BroadcastAddress
, sizeof (EFI_MAC_ADDRESS
), 0xFF);
143 // Power up the device so we can find the MAC address
144 Status
= Lan9118Initialize (Snp
);
145 if (EFI_ERROR (Status
)) {
146 DEBUG ((EFI_D_ERROR
, "Lan9118: Error initialising hardware\n"));
147 return EFI_DEVICE_ERROR
;
150 // Assign fields for device path
151 CopyMem (&Lan9118Path
->Lan9118
.MacAddress
, &Snp
->Mode
->CurrentAddress
, NET_ETHER_ADDR_LEN
);
152 Lan9118Path
->Lan9118
.IfType
= Snp
->Mode
->IfType
;
154 // Initialise the protocol
155 ControllerHandle
= NULL
;
156 Status
= gBS
->InstallMultipleProtocolInterfaces (
158 &gEfiSimpleNetworkProtocolGuid
, Snp
,
159 &gEfiDevicePathProtocolGuid
, Lan9118Path
,
162 // Say what the status of loading the protocol structure is
163 if (EFI_ERROR(Status
)) {
164 FreePool (LanDriver
);
166 LanDriver
->ControllerHandle
= ControllerHandle
;
173 * UEFI Start() function
177 * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
181 * This function starts a network interface. If the network interface successfully starts, then
182 * EFI_SUCCESS will be returned.
187 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
190 // Check Snp instance
192 return EFI_INVALID_PARAMETER
;
196 if ((Snp
->Mode
->State
== EfiSimpleNetworkStarted
) ||
197 (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) ) {
198 return EFI_ALREADY_STARTED
;
202 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
207 * UEFI Stop() function
213 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
216 // Check Snp Instance
218 return EFI_INVALID_PARAMETER
;
221 // Check state of the driver
222 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
223 return EFI_NOT_STARTED
;
226 // Stop the Tx and Rx
227 StopTx (STOP_TX_CFG
| STOP_TX_MAC
, Snp
);
231 switch (Snp
->Mode
->State
) {
232 case EfiSimpleNetworkStarted
:
233 case EfiSimpleNetworkInitialized
:
234 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
237 return EFI_DEVICE_ERROR
;
240 // Put the device into a power saving mode ?
245 // Allocated receive and transmit buffers
246 STATIC UINT32 gTxBuffer
= 0;
249 * UEFI Initialize() function
255 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
256 IN UINTN RxBufferSize OPTIONAL
,
257 IN UINTN TxBufferSize OPTIONAL
266 // Initialize variables
267 // Global variables to hold tx and rx FIFO allocation
270 // Check Snp Instance
272 return EFI_INVALID_PARAMETER
;
275 // First check that driver has not already been initialized
276 if (Snp
->Mode
->State
== EfiSimpleNetworkInitialized
) {
277 DEBUG ((EFI_D_WARN
, "LAN9118 Driver already initialized\n"));
280 if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
281 DEBUG ((EFI_D_WARN
, "LAN9118 Driver not started\n"));
282 return EFI_NOT_STARTED
;
285 // Initiate a PHY reset
286 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
287 if (EFI_ERROR (Status
)) {
288 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
289 DEBUG ((EFI_D_WARN
, "Warning: Link not ready after TimeOut. Check ethernet cable\n"));
290 return EFI_NOT_STARTED
;
293 // Initiate a software reset
294 Status
= SoftReset (0, Snp
);
295 if (EFI_ERROR(Status
)) {
296 DEBUG ((EFI_D_WARN
, "Soft Reset Failed: Hardware Error\n"));
297 return EFI_DEVICE_ERROR
;
300 // Read the PM register
301 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
303 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
304 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
305 // MPTCTRL_PME_EN: Allow Power Management Events
307 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
309 // Write the current configuration to the register
310 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
311 gBS
->Stall (LAN9118_STALL
);
312 gBS
->Stall (LAN9118_STALL
);
314 // Configure GPIO and HW
315 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
316 if (EFI_ERROR(Status
)) {
320 // Assign the transmitter buffer size (default values)
321 TxStatusSize
= LAN9118_TX_STATUS_SIZE
;
322 RxStatusSize
= LAN9118_RX_STATUS_SIZE
;
324 // Check that a buff size was specified
325 if (TxBufferSize
> 0) {
326 if (RxBufferSize
== 0) {
327 RxBufferSize
= LAN9118_RX_DATA_SIZE
;
330 AllocResult
= ChangeFifoAllocation (
339 if (AllocResult
< 0) {
340 return EFI_OUT_OF_RESOURCES
;
344 // Do auto-negotiation if supported
345 Status
= AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL
, Snp
);
346 if (EFI_ERROR(Status
)) {
347 DEBUG ((EFI_D_WARN
, "Lan9118: Auto Negociation not supported.\n"));
350 // Configure flow control depending on speed capabilities
351 Status
= ConfigureFlow (0, 0, 0, 0, Snp
);
352 if (EFI_ERROR(Status
)) {
356 // Enable the transmitter
357 Status
= StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
358 if (EFI_ERROR(Status
)) {
362 // Now acknowledge all interrupts
363 MmioWrite32 (LAN9118_INT_STS
, ~0);
365 // Declare the driver as initialized
366 Snp
->Mode
->State
= EfiSimpleNetworkInitialized
;
372 * UEFI Reset () function
378 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
379 IN BOOLEAN Verification
391 // Check Snp Instance
393 return EFI_INVALID_PARAMETER
;
396 // First check that driver has not already been initialized
397 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
398 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
399 return EFI_DEVICE_ERROR
;
400 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
401 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
402 return EFI_NOT_STARTED
;
405 // Initiate a PHY reset
406 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
407 if (EFI_ERROR (Status
)) {
408 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
409 return EFI_NOT_STARTED
;
412 // Initiate a software reset
413 ResetFlags
|= SOFT_RESET_CHECK_MAC_ADDR_LOAD
| SOFT_RESET_CLEAR_INT
;
416 ResetFlags
|= SOFT_RESET_SELF_TEST
;
419 Status
= SoftReset (ResetFlags
, Snp
);
420 if (EFI_ERROR (Status
)) {
421 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
422 return EFI_DEVICE_ERROR
;
425 // Read the PM register
426 PmConf
= MmioRead32 (LAN9118_PMT_CTRL
);
428 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets
429 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode
430 // MPTCTRL_PME_EN: Allow Power Management Events
431 PmConf
|= (MPTCTRL_WOL_EN
| MPTCTRL_ED_EN
| MPTCTRL_PME_EN
);
433 // Write the current configuration to the register
434 MmioWrite32 (LAN9118_PMT_CTRL
, PmConf
);
435 gBS
->Stall (LAN9118_STALL
);
437 // Reactivate the LEDs
438 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
439 if (EFI_ERROR (Status
)) {
443 // Check that a buffer size was specified in SnpInitialize
444 if (gTxBuffer
!= 0) {
445 HwConf
= MmioRead32 (LAN9118_HW_CFG
); // Read the HW register
446 HwConf
&= ~HW_CFG_TX_FIFO_SIZE_MASK
; // Clear buffer bits first
447 HwConf
|= HW_CFG_TX_FIFO_SIZE(gTxBuffer
); // assign size chosen in SnpInitialize
449 MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
450 gBS
->Stall (LAN9118_STALL
);
453 // Enable the receiver and transmitter and clear their contents
454 StartRx (START_RX_CLEAR
, Snp
);
455 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
457 // Now acknowledge all interrupts
458 MmioWrite32 (LAN9118_INT_STS
, ~0);
464 * UEFI Shutdown () function
470 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
475 // Check Snp Instance
477 return EFI_INVALID_PARAMETER
;
480 // First check that driver has not already been initialized
481 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
482 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
483 return EFI_DEVICE_ERROR
;
484 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
485 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
486 return EFI_NOT_STARTED
;
489 // Initiate a PHY reset
490 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
491 if (EFI_ERROR (Status
)) {
495 // Initiate a software reset
496 Status
= SoftReset (0, Snp
);
497 if (EFI_ERROR (Status
)) {
498 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
502 // Back to the started and thus not initialized state
503 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
509 Enable and/or disable the receive filters of the LAN9118
511 Please refer to the UEFI specification for the precedence rules among the
512 Enable, Disable and ResetMCastFilter parameters.
514 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
516 @param[in] Enable A bit mask of receive filters to enable.
517 @param[in] Disable A bit mask of receive filters to disable.
518 @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast
519 receive filters on the network interface to
520 their default values.
521 @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new
522 MCastFilter list. This value must be less than or
523 equal to the MCastFilterCnt field of
524 EFI_SIMPLE_NETWORK_MODE. This field is optional if
525 ResetMCastFilter is TRUE.
526 @param[in] MCastFilter A pointer to a list of new multicast receive
527 filter HW MAC addresses. This list will replace
528 any existing multicast HW MAC address list. This
529 field is optional if ResetMCastFilter is TRUE.
531 @retval EFI_SUCCESS The receive filters of the LAN9118 were updated.
532 @retval EFI_NOT_STARTED The LAN9118 has not been started.
533 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
535 . Multicast is being enabled (the
536 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in
537 Enable, it is not set in Disable, and ResetMCastFilter
538 is FALSE) and MCastFilterCount is zero.
539 . Multicast is being enabled and MCastFilterCount is
540 greater than Snp->Mode->MaxMCastFilterCount.
541 . Multicast is being enabled and MCastFilter is NULL
542 . Multicast is being enabled and one or more of the
543 addresses in the MCastFilter list are not valid
544 multicast MAC addresses.
545 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
551 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
554 IN BOOLEAN ResetMCastFilter
,
555 IN UINTN MCastFilterCnt OPTIONAL
,
556 IN EFI_MAC_ADDRESS
*MCastFilter OPTIONAL
559 EFI_SIMPLE_NETWORK_MODE
*Mode
;
560 UINT32 MultHashTableHigh
;
561 UINT32 MultHashTableLow
;
566 UINT32 ReceiveFilterSetting
;
567 EFI_MAC_ADDRESS
*Mac
;
568 EFI_MAC_ADDRESS ZeroMac
;
570 // Check Snp Instance
572 return EFI_INVALID_PARAMETER
;
576 // Check that driver was started and initialised
577 if (Mode
->State
== EfiSimpleNetworkStarted
) {
578 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
579 return EFI_DEVICE_ERROR
;
580 } else if (Mode
->State
== EfiSimpleNetworkStopped
) {
581 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
582 return EFI_NOT_STARTED
;
585 if ((Enable
& (~Mode
->ReceiveFilterMask
)) ||
586 (Disable
& (~Mode
->ReceiveFilterMask
)) ) {
587 return EFI_INVALID_PARAMETER
;
591 // Check the validity of the multicast setting and compute the
592 // hash values of the multicast mac addresses to listen to.
595 MultHashTableHigh
= 0;
596 MultHashTableLow
= 0;
597 if ((!ResetMCastFilter
) &&
598 ((Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) == 0) &&
599 ((Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) != 0) ) {
600 if ((MCastFilterCnt
== 0) ||
601 (MCastFilterCnt
> Mode
->MaxMCastFilterCount
) ||
602 (MCastFilter
== NULL
) ) {
603 return EFI_INVALID_PARAMETER
;
606 // Check the validity of all multicast addresses before to change
609 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
610 if ((MCastFilter
[Count
].Addr
[0] & 1) == 0) {
611 return EFI_INVALID_PARAMETER
;
616 // Go through each filter address and set appropriate bits on hash table
618 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
619 Mac
= &(MCastFilter
[Count
]);
620 CopyMem (&Mode
->MCastFilter
[Count
], Mac
, sizeof(EFI_MAC_ADDRESS
));
622 Crc
= GenEtherCrc32 (Mac
, NET_ETHER_ADDR_LEN
);
623 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
626 // The most significant 6 bits of the MAC address CRC constitute the hash
627 // value of the MAC address.
629 HashValue
= (Crc
>> 26) & 0x3F;
631 // Select hashlow register if MSB is not set
632 if ((HashValue
& 0x20) == 0) {
633 MultHashTableLow
|= (1 << HashValue
);
635 MultHashTableHigh
|= (1 << (HashValue
& 0x1F));
638 Mode
->MCastFilterCount
= MCastFilterCnt
;
639 } else if (ResetMCastFilter
) {
640 Mode
->MCastFilterCount
= 0;
642 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
643 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
647 // Before to change anything, stop and reset the reception of
650 StopRx (STOP_RX_CLEAR
, Snp
);
653 // Write the mask of the selected hash values for the multicast filtering.
654 // The two masks are set to zero if the multicast filtering is not enabled.
656 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
657 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
659 ReceiveFilterSetting
= (Mode
->ReceiveFilterSetting
| Enable
) & (~Disable
);
662 // Read MAC controller
664 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
665 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_BCAST
| MACCR_PRMS
| MACCR_MCPAS
);
667 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
668 Lan9118SetMacAddress (&Mode
->CurrentAddress
, Snp
);
669 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
672 // The Unicast packets do not have to be listen to, set the MAC
673 // address of the LAN9118 to be the "not configured" all zeroes
674 // ethernet MAC address.
676 ZeroMem (&ZeroMac
, NET_ETHER_ADDR_LEN
);
677 Lan9118SetMacAddress (&ZeroMac
, Snp
);
680 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
681 MacCSRValue
|= MACCR_HPFILT
;
682 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
685 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
686 MacCSRValue
|= MACCR_MCPAS
;
687 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
690 if ((ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) == 0) {
691 MacCSRValue
|= MACCR_BCAST
;
693 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
696 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
697 MacCSRValue
|= MACCR_PRMS
;
698 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
702 // Write the options to the MAC_CSR
704 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
705 gBS
->Stall (LAN9118_STALL
);
708 // If we have to retrieve something, start packet reception.
710 Mode
->ReceiveFilterSetting
= ReceiveFilterSetting
;
711 if (ReceiveFilterSetting
!= 0) {
719 Modify of reset the current station address
721 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
723 @param[in] Reset Flag used to reset the station address to the
724 LAN9118's permanent address.
725 @param[in] New New station address to be used for the network interface.
727 @retval EFI_SUCCESS The LAN9118's station address was updated.
728 @retval EFI_NOT_STARTED The LAN9118 has not been started.
729 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
730 . The "New" station address is invalid.
731 . "Reset" is FALSE and "New" is NULL.
732 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
738 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
740 IN EFI_MAC_ADDRESS
*New
744 UINT8 PermAddr
[NET_ETHER_ADDR_LEN
];
746 DEBUG ((DEBUG_NET
, "SnpStationAddress()\n"));
748 // Check Snp instance
750 return EFI_INVALID_PARAMETER
;
753 // Check that driver was started and initialised
754 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
755 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
756 return EFI_DEVICE_ERROR
;
757 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
758 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
759 return EFI_NOT_STARTED
;
762 // Get the Permanent MAC address if need reset
764 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0
765 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM
) {
766 for (Count
= 0; Count
< NET_ETHER_ADDR_LEN
; Count
++) {
767 PermAddr
[Count
] = IndirectEEPROMRead32 (Count
+ 1);
769 New
= (EFI_MAC_ADDRESS
*) PermAddr
;
770 Lan9118SetMacAddress ((EFI_MAC_ADDRESS
*) PermAddr
, Snp
);
772 DEBUG ((EFI_D_ERROR
, "Lan9118: Warning: No valid MAC address in EEPROM, using fallback\n"));
773 New
= (EFI_MAC_ADDRESS
*) (FixedPcdGet64 (PcdLan9118DefaultMacAddress
));
776 // Otherwise use the specified new MAC address
778 return EFI_INVALID_PARAMETER
;
781 // If it is a multicast address, it is not valid.
783 if (New
->Addr
[0] & 0x01) {
784 return EFI_INVALID_PARAMETER
;
788 CopyMem (&Snp
->Mode
->CurrentAddress
, New
, NET_ETHER_ADDR_LEN
);
791 // If packet reception is currently activated, stop and reset it,
792 // set the new ethernet address and restart the packet reception.
793 // Otherwise, nothing to do, the MAC address will be updated in
794 // SnpReceiveFilters() when the UNICAST packet reception will be
797 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
798 StopRx (STOP_RX_CLEAR
, Snp
);
799 Lan9118SetMacAddress (New
, Snp
);
807 * UEFI Statistics() function
813 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
815 IN OUT UINTN
*StatSize
,
816 OUT EFI_NETWORK_STATISTICS
*Statistics
819 LAN9118_DRIVER
*LanDriver
;
822 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
824 DEBUG ((DEBUG_NET
, "SnpStatistics()\n"));
826 // Check Snp instance
828 return EFI_INVALID_PARAMETER
;
831 // Check that driver was started and initialised
832 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
833 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
834 return EFI_DEVICE_ERROR
;
835 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
836 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
837 return EFI_NOT_STARTED
;
841 // Do a reset if required. It is not clearly stated in the UEFI specification
842 // whether the reset has to be done before to copy the statistics in "Statictics"
843 // or after. It is a bit strange to do it before but that is what is expected by
844 // the SCT test on Statistics() with reset : "0x3de76704,0x4bf5,0x42cd,0x8c,0x89,
845 // 0x54,0x7e,0x4f,0xad,0x4f,0x24".
848 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
851 Status
= EFI_SUCCESS
;
852 if (StatSize
== NULL
) {
853 if (Statistics
!= NULL
) {
854 return EFI_INVALID_PARAMETER
;
857 if (Statistics
== NULL
) {
858 Status
= EFI_BUFFER_TOO_SMALL
;
860 // Fill in the statistics
862 Statistics
, &LanDriver
->Stats
,
863 MIN (*StatSize
, sizeof (EFI_NETWORK_STATISTICS
))
865 if (*StatSize
< sizeof (EFI_NETWORK_STATISTICS
)) {
866 Status
= EFI_BUFFER_TOO_SMALL
;
869 *StatSize
= sizeof (EFI_NETWORK_STATISTICS
);
876 * UEFI MCastIPtoMAC() function
882 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
884 IN EFI_IP_ADDRESS
*Ip
,
885 OUT EFI_MAC_ADDRESS
*McastMac
888 DEBUG ((DEBUG_NET
, "SnpMcastIptoMac()\n"));
890 // Check Snp instance
892 return EFI_INVALID_PARAMETER
;
895 // Check that driver was started and initialised
896 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
897 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
898 return EFI_DEVICE_ERROR
;
899 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
900 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
901 return EFI_NOT_STARTED
;
905 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
906 return EFI_INVALID_PARAMETER
;
909 // Make sure MAC address is empty
910 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
912 // If we need ipv4 address
914 // Most significant 25 bits of a multicast HW address are set.
915 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)
916 McastMac
->Addr
[0] = 0x01;
917 McastMac
->Addr
[1] = 0x00;
918 McastMac
->Addr
[2] = 0x5E;
920 // Lower 23 bits from ipv4 address
921 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)
922 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
923 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
925 // Most significant 16 bits of multicast v6 HW address are set
926 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)
927 McastMac
->Addr
[0] = 0x33;
928 McastMac
->Addr
[1] = 0x33;
930 // lower four octets are taken from ipv6 address
931 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
932 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
933 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
934 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
941 * UEFI NvData() function
947 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
948 IN BOOLEAN read_write
,
954 DEBUG ((DEBUG_NET
, "SnpNvData()\n"));
956 return EFI_UNSUPPORTED
;
961 * UEFI GetStatus () function
967 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
968 OUT UINT32
*IrqStat OPTIONAL
,
969 OUT VOID
**TxBuff OPTIONAL
974 UINTN NumTxStatusEntries
;
978 LAN9118_DRIVER
*LanDriver
;
980 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
982 // Check preliminaries
984 return EFI_INVALID_PARAMETER
;
987 // Check that driver was started and initialised
988 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
989 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
990 return EFI_DEVICE_ERROR
;
991 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
992 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
993 return EFI_NOT_STARTED
;
996 // Check and acknowledge TX Status interrupt (this will happen if the
997 // consumer of SNP does not call GetStatus.)
998 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we
999 // should check for it and dump the TX Status FIFO.
1000 FifoInt
= MmioRead32 (LAN9118_FIFO_INT
);
1002 // Clear the TX Status FIFO Overflow
1003 if ((FifoInt
& INSTS_TXSO
) == 0) {
1004 FifoInt
|= INSTS_TXSO
;
1005 MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
1008 // Read interrupt status if IrqStat is not NULL
1009 if (IrqStat
!= NULL
) {
1012 // Check for receive interrupt
1013 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
1014 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
1015 MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
1018 // Check for transmit interrupt
1019 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
1020 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
1021 MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
1024 // Check for software interrupt
1025 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
1026 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
1027 MmioWrite32 (LAN9118_INT_STS
,INSTS_SW_INT
);
1031 // Check Status of transmitted packets
1032 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)
1034 NumTxStatusEntries
= MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
1035 if (NumTxStatusEntries
> 0) {
1036 TxStatus
= MmioRead32 (LAN9118_TX_STATUS
);
1037 PacketTag
= TxStatus
>> 16;
1038 TxStatus
= TxStatus
& 0xFFFF;
1039 if ((TxStatus
& TXSTATUS_ES
) && (TxStatus
!= (TXSTATUS_ES
| TXSTATUS_NO_CA
))) {
1040 DEBUG ((EFI_D_ERROR
, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus
));
1041 if (TxStatus
& TXSTATUS_NO_CA
) {
1042 DEBUG ((EFI_D_ERROR
, "- No carrier\n"));
1044 if (TxStatus
& TXSTATUS_DEF
) {
1045 DEBUG ((EFI_D_ERROR
, "- Packet tx was deferred\n"));
1047 if (TxStatus
& TXSTATUS_EDEF
) {
1048 DEBUG ((EFI_D_ERROR
, "- Tx ended because of excessive deferral\n"));
1050 if (TxStatus
& TXSTATUS_ECOLL
) {
1051 DEBUG ((EFI_D_ERROR
, "- Tx ended because of Excessive Collisions\n"));
1053 if (TxStatus
& TXSTATUS_LCOLL
) {
1054 DEBUG ((EFI_D_ERROR
, "- Packet Tx aborted after coll window of 64 bytes\n"));
1056 if (TxStatus
& TXSTATUS_LOST_CA
) {
1057 DEBUG ((EFI_D_ERROR
, "- Lost carrier during Tx\n"));
1059 return EFI_DEVICE_ERROR
;
1060 } else if (TxBuff
!= NULL
) {
1061 LanDriver
->Stats
.TxTotalFrames
+= 1;
1062 *TxBuff
= LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
];
1066 // Check for a TX Error interrupt
1067 Interrupts
= MmioRead32 (LAN9118_INT_STS
);
1068 if (Interrupts
& INSTS_TXE
) {
1069 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
1071 // Software reset, the TXE interrupt is cleared by the reset.
1072 Status
= SoftReset (0, Snp
);
1073 if (EFI_ERROR (Status
)) {
1074 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
1075 return EFI_DEVICE_ERROR
;
1078 // Reactivate the LEDs
1079 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1080 if (EFI_ERROR (Status
)) {
1085 // Restart the transmitter and if necessary the receiver.
1086 // Do not ask for FIFO reset as it has already been done
1089 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1090 if (Snp
->Mode
->ReceiveFilterSetting
!= 0) {
1095 // Update the media status
1096 Status
= CheckLinkStatus (0, Snp
);
1097 if (EFI_ERROR(Status
)) {
1098 Snp
->Mode
->MediaPresent
= FALSE
;
1100 Snp
->Mode
->MediaPresent
= TRUE
;
1108 * UEFI Transmit() function
1114 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1118 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1119 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1120 IN UINT16
*Protocol OPTIONAL
1123 LAN9118_DRIVER
*LanDriver
;
1125 UINT32 TxStatusSpace
;
1129 UINT16 LocalProtocol
;
1133 #if defined(EVAL_PERFORMANCE)
1138 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1139 StartClock
= GetPerformanceCounter ();
1142 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1144 // Check preliminaries
1145 if ((Snp
== NULL
) || (Data
== NULL
)) {
1146 return EFI_INVALID_PARAMETER
;
1149 // Check that driver was started and initialised
1150 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1151 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1152 return EFI_DEVICE_ERROR
;
1153 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1154 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1155 return EFI_NOT_STARTED
;
1158 // Ensure header is correct size if non-zero
1160 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1161 return EFI_INVALID_PARAMETER
;
1164 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1165 return EFI_INVALID_PARAMETER
;
1170 // Check validity of BufferSize
1172 if (BuffSize
< Snp
->Mode
->MediaHeaderSize
) {
1173 return EFI_BUFFER_TOO_SMALL
;
1176 // Before transmitting check the link status
1177 /*if (CheckLinkStatus (0, Snp) < 0) {
1178 return EFI_NOT_READY;
1181 // Get DATA FIFO free space in bytes
1182 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1183 if (TxFreeSpace
< BuffSize
) {
1184 return EFI_NOT_READY
;
1187 // Get STATUS FIFO used space in bytes
1188 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1189 if (TxStatusSpace
> 500) {
1190 return EFI_NOT_READY
;
1193 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1194 // has provided a well-formed frame).
1195 if (DstAddr
== NULL
) {
1196 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1199 // Check for the nature of the frame
1200 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1201 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1203 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1206 // Check if broadcast
1207 if (DstAddr
->Addr
[0] == 0xFF) {
1208 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1211 PacketTag
= LanDriver
->NextPacketTag
;
1212 LanDriver
->NextPacketTag
++;
1217 LocalData
= (UINT32
*) Data
;
1218 LocalProtocol
= *Protocol
;
1220 // Create first buffer to pass to controller (for the header)
1221 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1222 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1224 // Write the commands first
1225 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1226 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1228 // Write the destination address
1229 MmioWrite32 (LAN9118_TX_DATA
,
1230 (DstAddr
->Addr
[0]) |
1231 (DstAddr
->Addr
[1] << 8) |
1232 (DstAddr
->Addr
[2] << 16) |
1233 (DstAddr
->Addr
[3] << 24)
1236 MmioWrite32 (LAN9118_TX_DATA
,
1237 (DstAddr
->Addr
[4]) |
1238 (DstAddr
->Addr
[5] << 8) |
1239 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1240 (SrcAddr
->Addr
[1] << 24)
1243 MmioWrite32 (LAN9118_TX_DATA
,
1244 (SrcAddr
->Addr
[2]) |
1245 (SrcAddr
->Addr
[3] << 8) |
1246 (SrcAddr
->Addr
[4] << 16) |
1247 (SrcAddr
->Addr
[5] << 24)
1250 // Write the Protocol
1251 MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1253 // Next buffer is the payload
1254 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
1256 // Write the commands
1257 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1258 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1260 // Write the payload
1261 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1262 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1266 LocalData
= (UINT32
*) Data
;
1268 // Create a buffer to pass to controller
1269 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1270 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1272 // Write the commands first
1273 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1274 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1276 // Write all the data
1277 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1278 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1282 // Save the address of the submitted packet so we can notify the consumer that
1283 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1284 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1285 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1287 #if defined(EVAL_PERFORMANCE)
1288 EndClock
= GetPerformanceCounter ();
1289 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1292 LanDriver
->Stats
.TxGoodFrames
+= 1;
1299 * UEFI Receive() function
1305 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1306 OUT UINTN
*HdrSize OPTIONAL
,
1307 IN OUT UINTN
*BuffSize
,
1309 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1310 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1311 OUT UINT16
*Protocol OPTIONAL
1314 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
;
1349 // Count dropped frames
1350 DroppedFrames
= MmioRead32 (LAN9118_RX_DROP
);
1351 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1353 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1355 return EFI_NOT_READY
;
1358 // Read Rx Status (only if not empty)
1359 RxFifoStatus
= MmioRead32 (LAN9118_RX_STATUS
);
1360 LanDriver
->Stats
.RxTotalFrames
+= 1;
1362 // First check for errors
1363 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1364 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1365 (RxFifoStatus
& RXSTATUS_FTL
) ||
1366 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1367 (RxFifoStatus
& RXSTATUS_LE
) ||
1368 (RxFifoStatus
& RXSTATUS_DB
))
1370 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1371 return EFI_DEVICE_ERROR
;
1374 // Check if we got a CRC error
1375 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1376 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1377 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1378 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1379 return EFI_DEVICE_ERROR
;
1382 // Check if we got a runt frame
1383 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1384 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1385 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1386 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1387 return EFI_DEVICE_ERROR
;
1390 // Check filtering status for this packet
1391 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1392 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1396 // Check if we got a broadcast frame
1397 if (RxFifoStatus
& RXSTATUS_BCF
) {
1398 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1401 // Check if we got a multicast frame
1402 if (RxFifoStatus
& RXSTATUS_MCF
) {
1403 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1406 // Check if we got a unicast frame
1407 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1408 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1411 // Get the received packet length
1412 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1413 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1415 // If padding is applied, read more DWORDs
1417 Padding
= 4 - (PLength
% 4);
1418 ReadLimit
= (PLength
+ Padding
)/4;
1420 ReadLimit
= PLength
/4;
1424 // Check buffer size
1425 if (*BuffSize
< (PLength
+ Padding
)) {
1426 *BuffSize
= PLength
+ Padding
;
1427 return EFI_BUFFER_TOO_SMALL
;
1430 // Set the amount of data to be transfered out of FIFO for THIS packet
1431 // This can be used to trigger an interrupt, and status can be checked
1432 RxCfgValue
= MmioRead32 (LAN9118_RX_CFG
);
1433 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1434 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1436 // Set end alignment to 4-bytes
1437 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1438 MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1440 // Update buffer size
1441 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1442 // 4 bytes longer than packet actually is, unless
1443 // packet is < 64 bytes
1445 if (HdrSize
!= NULL
)
1446 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1448 // Format the pointer
1449 RawData
= (UINT32
*)Data
;
1452 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1453 RawData
[Count
] = MmioRead32 (LAN9118_RX_DATA
);
1456 // Check for Rx errors (worst possible error)
1457 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1458 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1460 // Software reset, the RXE interrupt is cleared by the reset.
1461 Status
= SoftReset (0, Snp
);
1462 if (EFI_ERROR (Status
)) {
1463 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1464 return EFI_DEVICE_ERROR
;
1467 // Reactivate the LEDs
1468 Status
= ConfigureHardware (HW_CONF_USE_LEDS
, Snp
);
1469 if (EFI_ERROR (Status
)) {
1474 // Restart the receiver and the transmitter without reseting the FIFOs
1475 // as it has been done by SoftReset().
1478 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1480 // Say that command could not be sent
1481 return EFI_DEVICE_ERROR
;
1484 // Get the destination address
1485 if (DstAddr
!= NULL
) {
1486 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1487 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1488 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1489 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1490 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1491 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1492 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1495 // Get the source address
1496 if (SrcAddr
!= NULL
) {
1497 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1498 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1499 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1500 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1501 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1502 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1503 CopyMem (SrcAddr
,&Src
, NET_ETHER_ADDR_LEN
);
1507 if (Protocol
!= NULL
) {
1508 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1511 #if defined(EVAL_PERFORMANCE)
1512 UINT64 EndClock
= GetPerformanceCounter ();
1513 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1516 LanDriver
->Stats
.RxGoodFrames
+= 1;