3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
5 * SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "Lan9118Dxe.h"
11 STATIC EFI_MAC_ADDRESS mZeroMac
= { { 0 } };
14 This internal function reverses bits for 32bit data.
16 @param Value The data to be reversed.
18 @return Data reversed.
30 for (Index
= 0; Index
< 32; Index
++) {
31 if ((Value
& (1 << Index
)) != 0) {
32 NewValue
= NewValue
| (1 << (31 - Index
));
40 ** Create Ethernet CRC
43 ** 1: http://en.wikipedia.org/wiki/Cyclic_redundancy_check
45 ** 2: http://www.erg.abdn.ac.uk/~gorry/eg3567/dl-pages/crc.html
47 ** 3: http://en.wikipedia.org/wiki/Computation_of_CRC
51 IN EFI_MAC_ADDRESS
*Mac
,
60 Remainder
= 0xFFFFFFFF; // 0xFFFFFFFF is standard seed for Ethernet
62 // Convert Mac Address to array of bytes
65 // Generate the Crc bit-by-bit (LSB first)
68 for (Iter
= 0;Iter
< 8;Iter
++) {
69 // Check if exponent is set
71 Remainder
= (Remainder
>> 1) ^ CRC_POLYNOMIAL
;
73 Remainder
= (Remainder
>> 1) ^ 0;
78 // Reverse the bits before returning (to Big Endian)
79 //TODO: Need to be reviewed. Do we want to do a bit reverse or a byte reverse (in this case use SwapBytes32())
80 return ReverseBits (Remainder
);
83 // Function to read from MAC indirect registers
91 // Check index is in the range
94 // Wait until CSR busy bit is cleared
95 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
97 // Set CSR busy bit to ensure read will occur
98 // Set the R/W bit to indicate we are reading
99 // Set the index of CSR Address to access desired register
100 MacCSR
= MAC_CSR_BUSY
| MAC_CSR_READ
| MAC_CSR_ADDR(Index
);
102 // Write to the register
103 Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD
, MacCSR
);
105 // Wait until CSR busy bit is cleared
106 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
108 // Now read from data register to get read value
109 return Lan9118MmioRead32 (LAN9118_MAC_CSR_DATA
);
113 * LAN9118 chips have special restrictions on some back-to-back Write/Read or
114 * Read/Read pairs of accesses. After a read or write that changes the state of
115 * the device, there is a period in which stale values may be returned in
116 * response to a read. This period is dependent on the registers accessed.
118 * We must delay prior reads by this period. This can either be achieved by
119 * timer-based delays, or by performing dummy reads of the BYTE_TEST register,
120 * for which the recommended number of reads is described in the LAN9118 data
121 * sheet. This is required in addition to any memory barriers.
123 * This function performs a number of dummy reads of the BYTE_TEST register, as
124 * a building block for the above.
132 MmioRead32(LAN9118_BYTE_TEST
);
136 Lan9118RawMmioRead32(
143 Value
= MmioRead32(Address
);
144 WaitDummyReads(Delay
);
149 Lan9118RawMmioWrite32(
155 MmioWrite32(Address
, Value
);
156 WaitDummyReads(Delay
);
160 // Function to write to MAC indirect registers
170 // Check index is in the range
173 // Wait until CSR busy bit is cleared
174 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
176 // Set CSR busy bit to ensure read will occur
177 // Set the R/W bit to indicate we are writing
178 // Set the index of CSR Address to access desired register
179 MacCSR
= MAC_CSR_BUSY
| MAC_CSR_WRITE
| MAC_CSR_ADDR(Index
);
181 // Now write the value to the register before issuing the write command
182 ValueWritten
= Lan9118MmioWrite32 (LAN9118_MAC_CSR_DATA
, Value
);
184 // Write the config to the register
185 Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD
, MacCSR
);
187 // Wait until CSR busy bit is cleared
188 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
193 // Function to read from MII register (PHY Access)
202 // Check it is a valid index
205 // Wait for busy bit to clear
206 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
208 // Clear the R/W bit to indicate we are reading
209 // Set the index of the MII register
210 // Set the PHY Address
211 // Set the MII busy bit to allow read
212 MiiAcc
= MII_ACC_MII_READ
| MII_ACC_MII_REG_INDEX(Index
) | MII_ACC_PHY_VALUE
| MII_ACC_MII_BUSY
;
214 // Now write this config to register
215 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC
, MiiAcc
& 0xFFFF);
217 // Wait for busy bit to clear
218 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
220 // Now read the value of the register
221 ValueRead
= (IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_DATA
) & 0xFFFF); // only lower 16 bits are valid for any PHY register
227 // Function to write to the MII register (PHY Access)
237 // Check it is a valid index
240 // Wait for busy bit to clear
241 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
243 // Clear the R/W bit to indicate we are reading
244 // Set the index of the MII register
245 // Set the PHY Address
246 // Set the MII busy bit to allow read
247 MiiAcc
= MII_ACC_MII_WRITE
| MII_ACC_MII_REG_INDEX(Index
) | MII_ACC_PHY_VALUE
| MII_ACC_MII_BUSY
;
249 // Write the desired value to the register first
250 ValueWritten
= IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_DATA
, (Value
& 0xFFFF));
252 // Now write the config to register
253 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC
, MiiAcc
& 0xFFFF);
255 // Wait for operation to terminate
256 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
262 /* ---------------- EEPROM Operations ------------------ */
265 // Function to read from EEPROM memory
267 IndirectEEPROMRead32 (
273 // Set the busy bit to ensure read will occur
274 EepromCmd
= E2P_EPC_BUSY
| E2P_EPC_CMD_READ
;
276 // Set the index to access desired EEPROM memory location
277 EepromCmd
|= E2P_EPC_ADDRESS(Index
);
279 // Write to Eeprom command register
280 Lan9118MmioWrite32 (LAN9118_E2P_CMD
, EepromCmd
);
282 // Wait until operation has completed
283 while (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
285 // Check that operation didn't time out
286 if (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_TIMEOUT
) {
287 DEBUG ((EFI_D_ERROR
, "EEPROM Operation Timed out: Read command on index %x\n",Index
));
291 // Wait until operation has completed
292 while (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
294 // Finally read the value
295 return Lan9118MmioRead32 (LAN9118_E2P_DATA
);
298 // Function to write to EEPROM memory
300 IndirectEEPROMWrite32 (
310 // Read the EEPROM Command register
311 EepromCmd
= Lan9118MmioRead32 (LAN9118_E2P_CMD
);
313 // Set the busy bit to ensure read will occur
314 EepromCmd
|= ((UINT32
)1 << 31);
316 // Set the EEPROM command to write(0b011)
317 EepromCmd
&= ~(7 << 28); // Clear the command first
318 EepromCmd
|= (3 << 28); // Write 011
320 // Set the index to access desired EEPROM memory location
321 EepromCmd
|= (Index
& 0xF);
323 // Write the value to the data register first
324 ValueWritten
= Lan9118MmioWrite32 (LAN9118_E2P_DATA
, Value
);
326 // Write to Eeprom command register
327 Lan9118MmioWrite32 (LAN9118_E2P_CMD
, EepromCmd
);
329 // Wait until operation has completed
330 while (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
332 // Check that operation didn't time out
333 if (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_TIMEOUT
) {
334 DEBUG ((EFI_D_ERROR
, "EEPROM Operation Timed out: Write command at memloc 0x%x, with value 0x%x\n",Index
, Value
));
338 // Wait until operation has completed
339 while (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
344 /* ---------------- General Operations ----------------- */
347 Lan9118SetMacAddress (
348 EFI_MAC_ADDRESS
*Mac
,
349 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
352 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRL
,
353 (Mac
->Addr
[0] & 0xFF) |
354 ((Mac
->Addr
[1] & 0xFF) << 8) |
355 ((Mac
->Addr
[2] & 0xFF) << 16) |
356 ((Mac
->Addr
[3] & 0xFF) << 24)
359 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRH
,
360 (UINT32
)(Mac
->Addr
[4] & 0xFF) |
361 ((Mac
->Addr
[5] & 0xFF) << 8)
366 Lan9118ReadMacAddress (
367 OUT EFI_MAC_ADDRESS
*MacAddress
370 UINT32 MacAddrHighValue
;
371 UINT32 MacAddrLowValue
;
373 // Read the Mac Addr high register
374 MacAddrHighValue
= (IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRH
) & 0xFFFF);
375 // Read the Mac Addr low register
376 MacAddrLowValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRL
);
378 SetMem (MacAddress
, sizeof(*MacAddress
), 0);
379 MacAddress
->Addr
[0] = (MacAddrLowValue
& 0xFF);
380 MacAddress
->Addr
[1] = (MacAddrLowValue
& 0xFF00) >> 8;
381 MacAddress
->Addr
[2] = (MacAddrLowValue
& 0xFF0000) >> 16;
382 MacAddress
->Addr
[3] = (MacAddrLowValue
& 0xFF000000) >> 24;
383 MacAddress
->Addr
[4] = (MacAddrHighValue
& 0xFF);
384 MacAddress
->Addr
[5] = (MacAddrHighValue
& 0xFF00) >> 8;
388 * Power up the 9118 and find its MAC address.
390 * This operation can be carried out when the LAN9118 is in any power state
395 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
399 UINT64 DefaultMacAddress
;
401 // Attempt to wake-up the device if it is in a lower power state
402 if (((Lan9118MmioRead32 (LAN9118_PMT_CTRL
) & MPTCTRL_PM_MODE_MASK
) >> 12) != 0) {
403 DEBUG ((DEBUG_NET
, "Waking from reduced power state.\n"));
404 Lan9118MmioWrite32 (LAN9118_BYTE_TEST
, 0xFFFFFFFF);
407 // Check that device is active
409 while ((Lan9118MmioRead32 (LAN9118_PMT_CTRL
) & MPTCTRL_READY
) == 0 && --Retries
) {
410 gBS
->Stall (LAN9118_STALL
);
416 // Check that EEPROM isn't active
418 while ((Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
) && --Retries
){
419 gBS
->Stall (LAN9118_STALL
);
425 // Check if a MAC address was loaded from EEPROM, and if it was, set it as the
427 if ((Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_MAC_ADDRESS_LOADED
) == 0) {
428 DEBUG ((EFI_D_ERROR
, "Warning: There was an error detecting EEPROM or loading the MAC Address.\n"));
430 // If we had an address before (set by StationAddress), continue to use it
431 if (CompareMem (&Snp
->Mode
->CurrentAddress
, &mZeroMac
, NET_ETHER_ADDR_LEN
)) {
432 Lan9118SetMacAddress (&Snp
->Mode
->CurrentAddress
, Snp
);
434 // If there are no cached addresses, then fall back to a default
435 DEBUG ((EFI_D_WARN
, "Warning: using driver-default MAC address\n"));
436 DefaultMacAddress
= FixedPcdGet64 (PcdLan9118DefaultMacAddress
);
437 Lan9118SetMacAddress((EFI_MAC_ADDRESS
*) &DefaultMacAddress
, Snp
);
438 CopyMem (&Snp
->Mode
->CurrentAddress
, &DefaultMacAddress
, NET_ETHER_ADDR_LEN
);
441 // Store the MAC address that was loaded from EEPROM
442 Lan9118ReadMacAddress (&Snp
->Mode
->CurrentAddress
);
443 CopyMem (&Snp
->Mode
->PermanentAddress
, &Snp
->Mode
->CurrentAddress
, NET_ETHER_ADDR_LEN
);
446 // Clear and acknowledge interrupts
447 Lan9118MmioWrite32 (LAN9118_INT_EN
, 0);
448 Lan9118MmioWrite32 (LAN9118_IRQ_CFG
, 0);
449 Lan9118MmioWrite32 (LAN9118_INT_STS
, 0xFFFFFFFF);
451 // Do self tests here?
457 // Perform software reset on the LAN9118
458 // Return 0 on success, -1 on error
462 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
468 // Initialize variable
472 StopTx (STOP_TX_MAC
| STOP_TX_CFG
| STOP_TX_CLEAR
, Snp
);
473 StopRx (STOP_RX_CLEAR
, Snp
); // Clear receiver FIFO
476 HwConf
= Lan9118MmioRead32 (LAN9118_HW_CFG
);
479 // Set the Must Be One (MBO) bit
480 if (((HwConf
& HWCFG_MBO
) >> 20) == 0) {
484 // Check that EEPROM isn't active
485 while (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
487 // Write the configuration
488 Lan9118MmioWrite32 (LAN9118_HW_CFG
, HwConf
);
490 // Wait for reset to complete
491 while (Lan9118MmioRead32 (LAN9118_HW_CFG
) & HWCFG_SRST
) {
493 gBS
->Stall (LAN9118_STALL
);
496 // If time taken exceeds 100us, then there was an error condition
497 if (ResetTime
> 1000) {
498 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
503 // Check that EEPROM isn't active
504 while (Lan9118MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
506 // TODO we probably need to re-set the mac address here.
508 // Clear and acknowledge all interrupts
509 if (Flags
& SOFT_RESET_CLEAR_INT
) {
510 Lan9118MmioWrite32 (LAN9118_INT_EN
, 0);
511 Lan9118MmioWrite32 (LAN9118_IRQ_CFG
, 0);
512 Lan9118MmioWrite32 (LAN9118_INT_STS
, 0xFFFFFFFF);
515 // Do self tests here?
516 if (Flags
& SOFT_RESET_SELF_TEST
) {
524 // Perform PHY software reset
528 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
533 // PMT PHY reset takes precedence over BCR
534 if (Flags
& PHY_RESET_PMT
) {
535 PmtCtrl
= Lan9118MmioRead32 (LAN9118_PMT_CTRL
);
536 PmtCtrl
|= MPTCTRL_PHY_RST
;
537 Lan9118MmioWrite32 (LAN9118_PMT_CTRL
,PmtCtrl
);
539 // Wait for completion
540 while (Lan9118MmioRead32 (LAN9118_PMT_CTRL
) & MPTCTRL_PHY_RST
) {
541 gBS
->Stall (LAN9118_STALL
);
543 // PHY Basic Control Register reset
544 } else if (Flags
& PHY_RESET_BCR
) {
545 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL
, PHYCR_RESET
);
547 // Wait for completion
548 while (IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL
) & PHYCR_RESET
) {
549 gBS
->Stall (LAN9118_STALL
);
553 // Clear and acknowledge all interrupts
554 if (Flags
& PHY_SOFT_RESET_CLEAR_INT
) {
555 Lan9118MmioWrite32 (LAN9118_INT_EN
, 0);
556 Lan9118MmioWrite32 (LAN9118_IRQ_CFG
, 0);
557 Lan9118MmioWrite32 (LAN9118_INT_STS
, 0xFFFFFFFF);
564 // Configure hardware for LAN9118
568 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
573 // Check if we want to use LEDs on GPIO
574 if (Flags
& HW_CONF_USE_LEDS
) {
575 GpioConf
= Lan9118MmioRead32 (LAN9118_GPIO_CFG
);
577 // Enable GPIO as LEDs and Config as Push-Pull driver
578 GpioConf
|= GPIO_GPIO0_PUSH_PULL
| GPIO_GPIO1_PUSH_PULL
| GPIO_GPIO2_PUSH_PULL
|
579 GPIO_LED1_ENABLE
| GPIO_LED2_ENABLE
| GPIO_LED3_ENABLE
;
581 // Write the configuration
582 Lan9118MmioWrite32 (LAN9118_GPIO_CFG
, GpioConf
);
588 // Configure flow control
595 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
601 // Do auto-negotiation
605 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
613 // First check that auto-negotiation is supported
614 PhyStatus
= IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
);
615 if ((PhyStatus
& PHYSTS_AUTO_CAP
) == 0) {
616 DEBUG ((EFI_D_ERROR
, "Auto-negotiation not supported.\n"));
617 return EFI_DEVICE_ERROR
;
620 // Check that link is up first
621 if ((PhyStatus
& PHYSTS_LINK_STS
) == 0) {
622 // Wait until it is up or until Time Out
623 Retries
= FixedPcdGet32 (PcdLan9118DefaultNegotiationTimeout
) / LAN9118_STALL
;
624 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
) & PHYSTS_LINK_STS
) == 0) {
625 gBS
->Stall (LAN9118_STALL
);
628 DEBUG ((EFI_D_ERROR
, "Link timeout in auto-negotiation.\n"));
634 // Configure features to advertise
635 Features
= IndirectPHYRead32 (PHY_INDEX_AUTO_NEG_ADVERT
);
637 if ((Flags
& AUTO_NEGOTIATE_ADVERTISE_ALL
) > 0) {
638 // Link speed capabilities
639 Features
|= (PHYANA_10BASET
| PHYANA_10BASETFD
| PHYANA_100BASETX
| PHYANA_100BASETXFD
);
641 // Pause frame capabilities
642 Features
&= ~(PHYANA_PAUSE_OP_MASK
);
645 Features
&= FixedPcdGet32 (PcdLan9118NegotiationFeatureMask
);
647 // Write the features
648 IndirectPHYWrite32 (PHY_INDEX_AUTO_NEG_ADVERT
, Features
);
650 // Read control register
651 PhyControl
= IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL
);
653 // Enable Auto-Negotiation
654 if ((PhyControl
& PHYCR_AUTO_EN
) == 0) {
655 PhyControl
|= PHYCR_AUTO_EN
;
658 // Restart auto-negotiation
659 PhyControl
|= PHYCR_RST_AUTO
;
661 // Enable collision test if required to do so
662 if (Flags
& AUTO_NEGOTIATE_COLLISION_TEST
) {
663 PhyControl
|= PHYCR_COLL_TEST
;
665 PhyControl
&= ~ PHYCR_COLL_TEST
;
668 // Write this configuration
669 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL
, PhyControl
);
671 // Wait until process has completed
672 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
) & PHYSTS_AUTO_COMP
) == 0);
677 // Check the Link Status and take appropriate action
681 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
684 // Get the PHY Status
685 UINT32 PhyBStatus
= IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
);
687 if (PhyBStatus
& PHYSTS_LINK_STS
) {
690 return EFI_DEVICE_ERROR
;
694 // Stop the transmitter
698 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
707 // Check if we want to clear tx
708 if (Flags
& STOP_TX_CLEAR
) {
709 TxCfg
= Lan9118MmioRead32 (LAN9118_TX_CFG
);
710 TxCfg
|= TXCFG_TXS_DUMP
| TXCFG_TXD_DUMP
;
711 Lan9118MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
714 // Check if already stopped
715 if (Flags
& STOP_TX_MAC
) {
716 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
718 if (MacCsr
& MACCR_TX_EN
) {
719 MacCsr
&= ~MACCR_TX_EN
;
720 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
724 if (Flags
& STOP_TX_CFG
) {
725 TxCfg
= Lan9118MmioRead32 (LAN9118_TX_CFG
);
727 if (TxCfg
& TXCFG_TX_ON
) {
728 TxCfg
|= TXCFG_STOP_TX
;
729 Lan9118MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
731 // Wait for Tx to finish transmitting
732 while (Lan9118MmioRead32 (LAN9118_TX_CFG
) & TXCFG_STOP_TX
);
743 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
751 // Check if already stopped
752 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
754 if (MacCsr
& MACCR_RX_EN
) {
755 MacCsr
&= ~ MACCR_RX_EN
;
756 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
759 // Check if we want to clear receiver FIFOs
760 if (Flags
& STOP_RX_CLEAR
) {
761 RxCfg
= Lan9118MmioRead32 (LAN9118_RX_CFG
);
762 RxCfg
|= RXCFG_RX_DUMP
;
763 Lan9118MmioWrite32 (LAN9118_RX_CFG
, RxCfg
);
765 while (Lan9118MmioRead32 (LAN9118_RX_CFG
) & RXCFG_RX_DUMP
);
771 // Start the transmitter
775 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
784 // Check if we want to clear tx
785 if (Flags
& START_TX_CLEAR
) {
786 TxCfg
= Lan9118MmioRead32 (LAN9118_TX_CFG
);
787 TxCfg
|= TXCFG_TXS_DUMP
| TXCFG_TXD_DUMP
;
788 Lan9118MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
791 // Check if tx was started from MAC and enable if not
792 if (Flags
& START_TX_MAC
) {
793 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
794 if ((MacCsr
& MACCR_TX_EN
) == 0) {
795 MacCsr
|= MACCR_TX_EN
;
796 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
800 // Check if tx was started from TX_CFG and enable if not
801 if (Flags
& START_TX_CFG
) {
802 TxCfg
= Lan9118MmioRead32 (LAN9118_TX_CFG
);
803 if ((TxCfg
& TXCFG_TX_ON
) == 0) {
804 TxCfg
|= TXCFG_TX_ON
;
805 Lan9118MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
809 // Set the tx data trigger level
814 // Start the receiver
818 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
826 // Check if already started
827 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
829 if ((MacCsr
& MACCR_RX_EN
) == 0) {
830 // Check if we want to clear receiver FIFOs before starting
831 if (Flags
& START_RX_CLEAR
) {
832 RxCfg
= Lan9118MmioRead32 (LAN9118_RX_CFG
);
833 RxCfg
|= RXCFG_RX_DUMP
;
834 Lan9118MmioWrite32 (LAN9118_RX_CFG
, RxCfg
);
836 while (Lan9118MmioRead32 (LAN9118_RX_CFG
) & RXCFG_RX_DUMP
);
839 MacCsr
|= MACCR_RX_EN
;
840 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
846 // Check Tx Data available space
850 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
856 // Get the amount of free space from information register
857 TxInf
= Lan9118MmioRead32 (LAN9118_TX_FIFO_INF
);
858 FreeSpace
= (TxInf
& TXFIFOINF_TDFREE_MASK
);
860 return FreeSpace
; // Value in bytes
863 // Check Tx Status used space
867 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
873 // Get the amount of used space from information register
874 TxInf
= Lan9118MmioRead32 (LAN9118_TX_FIFO_INF
);
875 UsedSpace
= (TxInf
& TXFIFOINF_TXSUSED_MASK
) >> 16;
877 return UsedSpace
<< 2; // Value in bytes
880 // Check Rx Data used space
884 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
890 // Get the amount of used space from information register
891 RxInf
= Lan9118MmioRead32 (LAN9118_RX_FIFO_INF
);
892 UsedSpace
= (RxInf
& RXFIFOINF_RXDUSED_MASK
);
894 return UsedSpace
; // Value in bytes (rounded up to nearest DWORD)
897 // Check Rx Status used space
901 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
907 // Get the amount of used space from information register
908 RxInf
= Lan9118MmioRead32 (LAN9118_RX_FIFO_INF
);
909 UsedSpace
= (RxInf
& RXFIFOINF_RXSUSED_MASK
) >> 16;
911 return UsedSpace
<< 2; // Value in bytes
915 // Change the allocation of FIFOs
917 ChangeFifoAllocation (
919 IN OUT UINTN
*TxDataSize OPTIONAL
,
920 IN OUT UINTN
*RxDataSize OPTIONAL
,
921 IN OUT UINT32
*TxStatusSize OPTIONAL
,
922 IN OUT UINT32
*RxStatusSize OPTIONAL
,
923 IN OUT EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
929 // Check that desired sizes don't exceed limits
930 if (*TxDataSize
> TX_FIFO_MAX_SIZE
)
931 return EFI_INVALID_PARAMETER
;
933 #if defined(RX_FIFO_MIN_SIZE) && defined(RX_FIFO_MAX_SIZE)
934 if (*RxDataSize
> RX_FIFO_MAX_SIZE
) {
935 return EFI_INVALID_PARAMETER
;
939 if (Flags
& ALLOC_USE_DEFAULT
) {
943 // If we use the FIFOs (always use this first)
944 if (Flags
& ALLOC_USE_FIFOS
) {
945 // Read the current value of allocation
946 HwConf
= Lan9118MmioRead32 (LAN9118_HW_CFG
);
947 TxFifoOption
= (HwConf
>> 16) & 0xF;
949 // Choose the correct size (always use larger than requested if possible)
950 if (*TxDataSize
< TX_FIFO_MIN_SIZE
) {
951 *TxDataSize
= TX_FIFO_MIN_SIZE
;
955 } else if ((*TxDataSize
> TX_FIFO_MIN_SIZE
) && (*TxDataSize
<= 2560)) {
960 } else if ((*TxDataSize
> 2560) && (*TxDataSize
<= 3584)) {
965 } else if ((*TxDataSize
> 3584) && (*TxDataSize
<= 4608)) { // default option
970 } else if ((*TxDataSize
> 4608) && (*TxDataSize
<= 5632)) {
975 } else if ((*TxDataSize
> 5632) && (*TxDataSize
<= 6656)) {
980 } else if ((*TxDataSize
> 6656) && (*TxDataSize
<= 7680)) {
985 } else if ((*TxDataSize
> 7680) && (*TxDataSize
<= 8704)) {
990 } else if ((*TxDataSize
> 8704) && (*TxDataSize
<= 9728)) {
995 } else if ((*TxDataSize
> 9728) && (*TxDataSize
<= 10752)) {
1000 } else if ((*TxDataSize
> 10752) && (*TxDataSize
<= 11776)) {
1001 *TxDataSize
= 11776;
1003 *RxStatusSize
= 256;
1005 } else if ((*TxDataSize
> 11776) && (*TxDataSize
<= 12800)) {
1006 *TxDataSize
= 12800;
1008 *RxStatusSize
= 192;
1010 } else if ((*TxDataSize
> 12800) && (*TxDataSize
<= 13824)) {
1011 *TxDataSize
= 13824;
1013 *RxStatusSize
= 128;
1017 ASSERT(0); // Untested code path
1023 if (Flags
& ALLOC_USE_DMA
) {
1024 return EFI_UNSUPPORTED
; // Unsupported as of now
1026 // Clear and assign the new size option
1027 HwConf
&= ~(0xF0000);
1028 HwConf
|= ((TxFifoOption
& 0xF) << 16);
1029 Lan9118MmioWrite32 (LAN9118_HW_CFG
, HwConf
);