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 // Check that a buffer size was specified in SnpInitialize
438 if (gTxBuffer
!= 0) {
439 HwConf
= MmioRead32 (LAN9118_HW_CFG
); // Read the HW register
440 HwConf
&= ~HW_CFG_TX_FIFO_SIZE_MASK
; // Clear buffer bits first
441 HwConf
|= HW_CFG_TX_FIFO_SIZE(gTxBuffer
); // assign size chosen in SnpInitialize
443 MmioWrite32 (LAN9118_HW_CFG
, HwConf
); // Write the conf
444 gBS
->Stall (LAN9118_STALL
);
447 // Enable the receiver and transmitter and clear their contents
448 StartRx (START_RX_CLEAR
, Snp
);
449 StartTx (START_TX_MAC
| START_TX_CFG
| START_TX_CLEAR
, Snp
);
451 // Now acknowledge all interrupts
452 MmioWrite32 (LAN9118_INT_STS
, ~0);
458 * UEFI Shutdown () function
464 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
469 // Check Snp Instance
471 return EFI_INVALID_PARAMETER
;
474 // First check that driver has not already been initialized
475 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
476 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not yet initialized\n"));
477 return EFI_DEVICE_ERROR
;
478 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
479 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not started\n"));
480 return EFI_NOT_STARTED
;
483 // Initiate a PHY reset
484 Status
= PhySoftReset (PHY_RESET_PMT
, Snp
);
485 if (EFI_ERROR (Status
)) {
489 // Initiate a software reset
490 Status
= SoftReset (0, Snp
);
491 if (EFI_ERROR (Status
)) {
492 DEBUG ((EFI_D_WARN
, "Warning: Soft Reset Failed: Hardware Error\n"));
496 // Back to the started and thus not initialized state
497 Snp
->Mode
->State
= EfiSimpleNetworkStarted
;
503 Enable and/or disable the receive filters of the LAN9118
505 Please refer to the UEFI specification for the precedence rules among the
506 Enable, Disable and ResetMCastFilter parameters.
508 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
510 @param[in] Enable A bit mask of receive filters to enable.
511 @param[in] Disable A bit mask of receive filters to disable.
512 @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast
513 receive filters on the network interface to
514 their default values.
515 @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new
516 MCastFilter list. This value must be less than or
517 equal to the MCastFilterCnt field of
518 EFI_SIMPLE_NETWORK_MODE. This field is optional if
519 ResetMCastFilter is TRUE.
520 @param[in] MCastFilter A pointer to a list of new multicast receive
521 filter HW MAC addresses. This list will replace
522 any existing multicast HW MAC address list. This
523 field is optional if ResetMCastFilter is TRUE.
525 @retval EFI_SUCCESS The receive filters of the LAN9118 were updated.
526 @retval EFI_NOT_STARTED The LAN9118 has not been started.
527 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :
529 . Multicast is being enabled (the
530 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in
531 Enable, it is not set in Disable, and ResetMCastFilter
532 is FALSE) and MCastFilterCount is zero.
533 . Multicast is being enabled and MCastFilterCount is
534 greater than Snp->Mode->MaxMCastFilterCount.
535 . Multicast is being enabled and MCastFilter is NULL
536 . Multicast is being enabled and one or more of the
537 addresses in the MCastFilter list are not valid
538 multicast MAC addresses.
539 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.
545 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
548 IN BOOLEAN ResetMCastFilter
,
549 IN UINTN MCastFilterCnt OPTIONAL
,
550 IN EFI_MAC_ADDRESS
*MCastFilter OPTIONAL
553 EFI_SIMPLE_NETWORK_MODE
*Mode
;
554 UINT32 MultHashTableHigh
;
555 UINT32 MultHashTableLow
;
560 UINT32 ReceiveFilterSetting
;
561 EFI_MAC_ADDRESS
*Mac
;
562 EFI_MAC_ADDRESS ZeroMac
;
564 // Check Snp Instance
566 return EFI_INVALID_PARAMETER
;
570 // Check that driver was started and initialised
571 if (Mode
->State
== EfiSimpleNetworkStarted
) {
572 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
573 return EFI_DEVICE_ERROR
;
574 } else if (Mode
->State
== EfiSimpleNetworkStopped
) {
575 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
576 return EFI_NOT_STARTED
;
579 if ((Enable
& (~Mode
->ReceiveFilterMask
)) ||
580 (Disable
& (~Mode
->ReceiveFilterMask
)) ) {
581 return EFI_INVALID_PARAMETER
;
585 // Check the validity of the multicast setting and compute the
586 // hash values of the multicast mac addresses to listen to.
589 MultHashTableHigh
= 0;
590 MultHashTableLow
= 0;
591 if ((!ResetMCastFilter
) &&
592 ((Disable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) == 0) &&
593 ((Enable
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) != 0) ) {
594 if ((MCastFilterCnt
== 0) ||
595 (MCastFilterCnt
> Mode
->MaxMCastFilterCount
) ||
596 (MCastFilter
== NULL
) ) {
597 return EFI_INVALID_PARAMETER
;
600 // Check the validity of all multicast addresses before to change
603 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
604 if ((MCastFilter
[Count
].Addr
[0] & 1) == 0) {
605 return EFI_INVALID_PARAMETER
;
610 // Go through each filter address and set appropriate bits on hash table
612 for (Count
= 0; Count
< MCastFilterCnt
; Count
++) {
613 Mac
= &(MCastFilter
[Count
]);
614 CopyMem (&Mode
->MCastFilter
[Count
], Mac
, sizeof(EFI_MAC_ADDRESS
));
616 Crc
= GenEtherCrc32 (Mac
, NET_ETHER_ADDR_LEN
);
617 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired
620 // The most significant 6 bits of the MAC address CRC constitute the hash
621 // value of the MAC address.
623 HashValue
= (Crc
>> 26) & 0x3F;
625 // Select hashlow register if MSB is not set
626 if ((HashValue
& 0x20) == 0) {
627 MultHashTableLow
|= (1 << HashValue
);
629 MultHashTableHigh
|= (1 << (HashValue
& 0x1F));
632 Mode
->MCastFilterCount
= MCastFilterCnt
;
633 } else if (ResetMCastFilter
) {
634 Mode
->MCastFilterCount
= 0;
636 MultHashTableLow
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL
);
637 MultHashTableHigh
= IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH
);
641 // Before to change anything, stop and reset the reception of
644 StopRx (STOP_RX_CLEAR
, Snp
);
647 // Write the mask of the selected hash values for the multicast filtering.
648 // The two masks are set to zero if the multicast filtering is not enabled.
650 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL
, MultHashTableLow
);
651 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH
, MultHashTableHigh
);
653 ReceiveFilterSetting
= (Mode
->ReceiveFilterSetting
| Enable
) & (~Disable
);
656 // Read MAC controller
658 MacCSRValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
659 MacCSRValue
&= ~(MACCR_HPFILT
| MACCR_BCAST
| MACCR_PRMS
| MACCR_MCPAS
);
661 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
) {
662 Lan9118SetMacAddress (&Mode
->CurrentAddress
, Snp
);
663 DEBUG ((DEBUG_NET
, "Allowing Unicast Frame Reception\n"));
666 // The Unicast packets do not have to be listen to, set the MAC
667 // address of the LAN9118 to be the "not configured" all zeroes
668 // ethernet MAC address.
670 ZeroMem (&ZeroMac
, NET_ETHER_ADDR_LEN
);
671 Lan9118SetMacAddress (&ZeroMac
, Snp
);
674 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
) {
675 MacCSRValue
|= MACCR_HPFILT
;
676 DEBUG ((DEBUG_NET
, "Allowing Multicast Frame Reception\n"));
679 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
680 MacCSRValue
|= MACCR_MCPAS
;
681 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Multicast Mode\n"));
684 if ((ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
) == 0) {
685 MacCSRValue
|= MACCR_BCAST
;
687 DEBUG ((DEBUG_NET
, "Allowing Broadcast Frame Reception\n"));
690 if (ReceiveFilterSetting
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) {
691 MacCSRValue
|= MACCR_PRMS
;
692 DEBUG ((DEBUG_NET
, "Enabling Promiscuous Mode\n"));
696 // Write the options to the MAC_CSR
698 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCSRValue
);
699 gBS
->Stall (LAN9118_STALL
);
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
= MmioRead32 (LAN9118_FIFO_INT
);
996 // Clear the TX Status FIFO Overflow
997 if ((FifoInt
& INSTS_TXSO
) == 0) {
998 FifoInt
|= INSTS_TXSO
;
999 MmioWrite32 (LAN9118_FIFO_INT
, FifoInt
);
1002 // Read interrupt status if IrqStat is not NULL
1003 if (IrqStat
!= NULL
) {
1006 // Check for receive interrupt
1007 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RSFL
) { // Data moved from rx FIFO
1008 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
1009 MmioWrite32 (LAN9118_INT_STS
,INSTS_RSFL
);
1012 // Check for transmit interrupt
1013 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_TSFL
) {
1014 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
1015 MmioWrite32 (LAN9118_INT_STS
,INSTS_TSFL
);
1018 // Check for software interrupt
1019 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_SW_INT
) {
1020 *IrqStat
|= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT
;
1021 MmioWrite32 (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
= MmioRead32(LAN9118_TX_FIFO_INF
) & TXFIFOINF_TXSUSED_MASK
;
1029 if (NumTxStatusEntries
> 0) {
1030 TxStatus
= MmioRead32 (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
];
1060 // Check for a TX Error interrupt
1061 Interrupts
= MmioRead32 (LAN9118_INT_STS
);
1062 if (Interrupts
& INSTS_TXE
) {
1063 DEBUG ((EFI_D_ERROR
, "LAN9118: Transmitter error. Restarting..."));
1065 // Initiate a software reset
1066 Status
= SoftReset (0, Snp
);
1067 if (EFI_ERROR (Status
)) {
1068 DEBUG ((EFI_D_ERROR
, "\n\tSoft Reset Failed: Hardware Error\n"));
1069 return EFI_DEVICE_ERROR
;
1072 // Acknowledge the TXE
1073 MmioWrite32 (LAN9118_INT_STS
, INSTS_TXE
);
1074 gBS
->Stall (LAN9118_STALL
);
1076 // Restart the transmitter
1077 StartTx (START_TX_MAC
| START_TX_CFG
, Snp
);
1080 // Update the media status
1081 Status
= CheckLinkStatus (0, Snp
);
1082 if (EFI_ERROR(Status
)) {
1083 Snp
->Mode
->MediaPresent
= FALSE
;
1085 Snp
->Mode
->MediaPresent
= TRUE
;
1093 * UEFI Transmit() function
1099 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1103 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1104 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1105 IN UINT16
*Protocol OPTIONAL
1108 LAN9118_DRIVER
*LanDriver
;
1110 UINT32 TxStatusSpace
;
1114 UINT16 LocalProtocol
;
1118 #if defined(EVAL_PERFORMANCE)
1123 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1124 StartClock
= GetPerformanceCounter ();
1127 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1129 // Check preliminaries
1130 if ((Snp
== NULL
) || (Data
== NULL
)) {
1131 return EFI_INVALID_PARAMETER
;
1134 // Check that driver was started and initialised
1135 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1136 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1137 return EFI_DEVICE_ERROR
;
1138 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1139 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1140 return EFI_NOT_STARTED
;
1143 // Ensure header is correct size if non-zero
1145 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1146 return EFI_INVALID_PARAMETER
;
1149 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1150 return EFI_INVALID_PARAMETER
;
1155 // Check validity of BufferSize
1157 if (BuffSize
< Snp
->Mode
->MediaHeaderSize
) {
1158 return EFI_BUFFER_TOO_SMALL
;
1161 // Before transmitting check the link status
1162 /*if (CheckLinkStatus (0, Snp) < 0) {
1163 return EFI_NOT_READY;
1166 // Get DATA FIFO free space in bytes
1167 TxFreeSpace
= TxDataFreeSpace (0, Snp
);
1168 if (TxFreeSpace
< BuffSize
) {
1169 return EFI_NOT_READY
;
1172 // Get STATUS FIFO used space in bytes
1173 TxStatusSpace
= TxStatusUsedSpace (0, Snp
);
1174 if (TxStatusSpace
> 500) {
1175 return EFI_NOT_READY
;
1178 // If DstAddr is not provided, get it from Buffer (we trust that the caller
1179 // has provided a well-formed frame).
1180 if (DstAddr
== NULL
) {
1181 DstAddr
= (EFI_MAC_ADDRESS
*) Data
;
1184 // Check for the nature of the frame
1185 if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1186 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1188 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1191 // Check if broadcast
1192 if (DstAddr
->Addr
[0] == 0xFF) {
1193 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1196 PacketTag
= LanDriver
->NextPacketTag
;
1197 LanDriver
->NextPacketTag
++;
1202 LocalData
= (UINT32
*) Data
;
1203 LocalProtocol
= *Protocol
;
1205 // Create first buffer to pass to controller (for the header)
1206 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_BUFF_SIZE (HdrSize
);
1207 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1209 // Write the commands first
1210 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1211 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1213 // Write the destination address
1214 MmioWrite32 (LAN9118_TX_DATA
,
1215 (DstAddr
->Addr
[0]) |
1216 (DstAddr
->Addr
[1] << 8) |
1217 (DstAddr
->Addr
[2] << 16) |
1218 (DstAddr
->Addr
[3] << 24)
1221 MmioWrite32 (LAN9118_TX_DATA
,
1222 (DstAddr
->Addr
[4]) |
1223 (DstAddr
->Addr
[5] << 8) |
1224 (SrcAddr
->Addr
[0] << 16) | // Write the Source Address
1225 (SrcAddr
->Addr
[1] << 24)
1228 MmioWrite32 (LAN9118_TX_DATA
,
1229 (SrcAddr
->Addr
[2]) |
1230 (SrcAddr
->Addr
[3] << 8) |
1231 (SrcAddr
->Addr
[4] << 16) |
1232 (SrcAddr
->Addr
[5] << 24)
1235 // Write the Protocol
1236 MmioWrite32 (LAN9118_TX_DATA
, (UINT32
)(HTONS (LocalProtocol
)));
1238 // Next buffer is the payload
1239 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
1241 // Write the commands
1242 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1243 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1245 // Write the payload
1246 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2) - 3; Count
++) {
1247 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
+ 3]);
1251 LocalData
= (UINT32
*) Data
;
1253 // Create a buffer to pass to controller
1254 CommandA
= TX_CMD_A_FIRST_SEGMENT
| TX_CMD_A_LAST_SEGMENT
| TX_CMD_A_BUFF_SIZE (BuffSize
) | TX_CMD_A_COMPLETION_INT
;
1255 CommandB
= TX_CMD_B_PACKET_TAG (PacketTag
) | TX_CMD_B_PACKET_LENGTH (BuffSize
);
1257 // Write the commands first
1258 MmioWrite32 (LAN9118_TX_DATA
, CommandA
);
1259 MmioWrite32 (LAN9118_TX_DATA
, CommandB
);
1261 // Write all the data
1262 for (Count
= 0; Count
< ((BuffSize
+ 3) >> 2); Count
++) {
1263 MmioWrite32 (LAN9118_TX_DATA
, LocalData
[Count
]);
1267 // Save the address of the submitted packet so we can notify the consumer that
1268 // it has been sent in GetStatus. When the packet tag appears in the Tx Status
1269 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.
1270 LanDriver
->TxRing
[PacketTag
% LAN9118_TX_RING_NUM_ENTRIES
] = Data
;
1272 #if defined(EVAL_PERFORMANCE)
1273 EndClock
= GetPerformanceCounter ();
1274 DEBUG ((EFI_D_ERROR
, "Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1277 LanDriver
->Stats
.TxGoodFrames
+= 1;
1284 * UEFI Receive() function
1290 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1291 OUT UINTN
*HdrSize OPTIONAL
,
1292 IN OUT UINTN
*BuffSize
,
1294 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1295 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1296 OUT UINT16
*Protocol OPTIONAL
1299 LAN9118_DRIVER
*LanDriver
;
1300 UINT32 RxFifoStatus
;
1303 UINT32 PLength
; // Packet length
1308 EFI_MAC_ADDRESS Dst
;
1309 EFI_MAC_ADDRESS Src
;
1310 UINTN DroppedFrames
;
1313 LanDriver
= INSTANCE_FROM_SNP_THIS (Snp
);
1315 #if defined(EVAL_PERFORMANCE)
1316 UINT64 Perf
= GetPerformanceCounterProperties (NULL
, NULL
);
1317 UINT64 StartClock
= GetPerformanceCounter ();
1320 // Check preliminaries
1321 if ((Snp
== NULL
) || (Data
== NULL
) || (BuffSize
== NULL
)) {
1322 return EFI_INVALID_PARAMETER
;
1325 // Check that driver was started and initialised
1326 if (Snp
->Mode
->State
== EfiSimpleNetworkStarted
) {
1327 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver not initialized\n"));
1328 return EFI_DEVICE_ERROR
;
1329 } else if (Snp
->Mode
->State
== EfiSimpleNetworkStopped
) {
1330 DEBUG ((EFI_D_WARN
, "Warning: LAN9118 Driver in stopped state\n"));
1331 return EFI_NOT_STARTED
;
1334 // Count dropped frames
1335 DroppedFrames
= MmioRead32 (LAN9118_RX_DROP
);
1336 LanDriver
->Stats
.RxDroppedFrames
+= DroppedFrames
;
1338 NumPackets
= RxStatusUsedSpace (0, Snp
) / 4;
1340 return EFI_NOT_READY
;
1343 // Read Rx Status (only if not empty)
1344 RxFifoStatus
= MmioRead32 (LAN9118_RX_STATUS
);
1345 LanDriver
->Stats
.RxTotalFrames
+= 1;
1347 // First check for errors
1348 if ((RxFifoStatus
& RXSTATUS_MII_ERROR
) ||
1349 (RxFifoStatus
& RXSTATUS_RXW_TO
) ||
1350 (RxFifoStatus
& RXSTATUS_FTL
) ||
1351 (RxFifoStatus
& RXSTATUS_LCOLL
) ||
1352 (RxFifoStatus
& RXSTATUS_LE
) ||
1353 (RxFifoStatus
& RXSTATUS_DB
))
1355 DEBUG ((EFI_D_WARN
, "Warning: There was an error on frame reception.\n"));
1356 return EFI_DEVICE_ERROR
;
1359 // Check if we got a CRC error
1360 if (RxFifoStatus
& RXSTATUS_CRC_ERROR
) {
1361 DEBUG ((EFI_D_WARN
, "Warning: Crc Error\n"));
1362 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1363 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1364 return EFI_DEVICE_ERROR
;
1367 // Check if we got a runt frame
1368 if (RxFifoStatus
& RXSTATUS_RUNT
) {
1369 DEBUG ((EFI_D_WARN
, "Warning: Runt Frame\n"));
1370 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1371 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1372 return EFI_DEVICE_ERROR
;
1375 // Check filtering status for this packet
1376 if (RxFifoStatus
& RXSTATUS_FILT_FAIL
) {
1377 DEBUG ((EFI_D_WARN
, "Warning: Frame Failed Filtering\n"));
1381 // Check if we got a broadcast frame
1382 if (RxFifoStatus
& RXSTATUS_BCF
) {
1383 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
1386 // Check if we got a multicast frame
1387 if (RxFifoStatus
& RXSTATUS_MCF
) {
1388 LanDriver
->Stats
.RxMulticastFrames
+= 1;
1391 // Check if we got a unicast frame
1392 if ((RxFifoStatus
& RXSTATUS_BCF
) && ((RxFifoStatus
& RXSTATUS_MCF
) == 0)) {
1393 LanDriver
->Stats
.RxUnicastFrames
+= 1;
1396 // Get the received packet length
1397 PLength
= GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus
);
1398 LanDriver
->Stats
.RxTotalBytes
+= (PLength
- 4);
1400 // Check buffer size
1401 if (*BuffSize
< PLength
) {
1402 *BuffSize
= PLength
;
1403 return EFI_BUFFER_TOO_SMALL
;
1406 // If padding is applied, read more DWORDs
1408 Padding
= 4 - (PLength
% 4);
1409 ReadLimit
= (PLength
+ Padding
)/4;
1411 ReadLimit
= PLength
/4;
1415 // Set the amount of data to be transfered out of FIFO for THIS packet
1416 // This can be used to trigger an interrupt, and status can be checked
1417 RxCfgValue
= MmioRead32 (LAN9118_RX_CFG
);
1418 RxCfgValue
&= ~(RXCFG_RX_DMA_CNT_MASK
);
1419 RxCfgValue
|= RXCFG_RX_DMA_CNT (ReadLimit
);
1421 // Set end alignment to 4-bytes
1422 RxCfgValue
&= ~(RXCFG_RX_END_ALIGN_MASK
);
1423 MmioWrite32 (LAN9118_RX_CFG
, RxCfgValue
);
1425 // Update buffer size
1426 *BuffSize
= PLength
; // -4 bytes may be needed: Received in buffer as
1427 // 4 bytes longer than packet actually is, unless
1428 // packet is < 64 bytes
1430 if (HdrSize
!= NULL
)
1431 *HdrSize
= Snp
->Mode
->MediaHeaderSize
;
1433 // Format the pointer
1434 RawData
= (UINT32
*)Data
;
1437 for (Count
= 0; Count
< ReadLimit
; Count
++) {
1438 RawData
[Count
] = MmioRead32 (LAN9118_RX_DATA
);
1441 // Check for Rx errors (worst possible error)
1442 if (MmioRead32 (LAN9118_INT_STS
) & INSTS_RXE
) {
1443 DEBUG ((EFI_D_WARN
, "Warning: Receiver Error. Restarting...\n"));
1445 // Initiate a software reset
1446 Status
= SoftReset (0, Snp
);
1447 if (EFI_ERROR (Status
)) {
1448 DEBUG ((EFI_D_ERROR
, "Error: Soft Reset Failed: Hardware Error.\n"));
1449 return EFI_DEVICE_ERROR
;
1452 // Acknowledge the RXE
1453 MmioWrite32 (LAN9118_INT_STS
, INSTS_RXE
);
1454 gBS
->Stall (LAN9118_STALL
);
1456 // Restart the rx (and do not clear FIFO)
1459 // Say that command could not be sent
1460 return EFI_DEVICE_ERROR
;
1463 // Get the destination address
1464 if (DstAddr
!= NULL
) {
1465 Dst
.Addr
[0] = (RawData
[0] & 0xFF);
1466 Dst
.Addr
[1] = (RawData
[0] & 0xFF00) >> 8;
1467 Dst
.Addr
[2] = (RawData
[0] & 0xFF0000) >> 16;
1468 Dst
.Addr
[3] = (RawData
[0] & 0xFF000000) >> 24;
1469 Dst
.Addr
[4] = (RawData
[1] & 0xFF);
1470 Dst
.Addr
[5] = (RawData
[1] & 0xFF00) >> 8;
1471 CopyMem (DstAddr
, &Dst
, NET_ETHER_ADDR_LEN
);
1474 // Get the source address
1475 if (SrcAddr
!= NULL
) {
1476 Src
.Addr
[0] = (RawData
[1] & 0xFF0000) >> 16;
1477 Src
.Addr
[1] = (RawData
[1] & 0xFF000000) >> 24;
1478 Src
.Addr
[2] = (RawData
[2] & 0xFF);
1479 Src
.Addr
[3] = (RawData
[2] & 0xFF00) >> 8;
1480 Src
.Addr
[4] = (RawData
[2] & 0xFF0000) >> 16;
1481 Src
.Addr
[5] = (RawData
[2] & 0xFF000000) >> 24;
1482 CopyMem (SrcAddr
,&Src
, NET_ETHER_ADDR_LEN
);
1486 if (Protocol
!= NULL
) {
1487 *Protocol
= NTOHS (RawData
[3] & 0xFFFF);
1490 #if defined(EVAL_PERFORMANCE)
1491 UINT64 EndClock
= GetPerformanceCounter ();
1492 DEBUG ((EFI_D_ERROR
, "Receive Time processing: %d counts @ %d Hz\n", StartClock
- EndClock
,Perf
));
1495 LanDriver
->Stats
.RxGoodFrames
+= 1;