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"
17 STATIC EFI_MAC_ADDRESS mZeroMac
= { { 0 } };
20 This internal function reverses bits for 32bit data.
22 @param Value The data to be reversed.
24 @return Data reversed.
36 for (Index
= 0; Index
< 32; Index
++) {
37 if ((Value
& (1 << Index
)) != 0) {
38 NewValue
= NewValue
| (1 << (31 - Index
));
46 ** Create Ethernet CRC
49 ** 1: http://en.wikipedia.org/wiki/Cyclic_redundancy_check
51 ** 2: http://www.erg.abdn.ac.uk/~gorry/eg3567/dl-pages/crc.html
53 ** 3: http://en.wikipedia.org/wiki/Computation_of_CRC
57 IN EFI_MAC_ADDRESS
*Mac
,
66 Remainder
= 0xFFFFFFFF; // 0xFFFFFFFF is standard seed for Ethernet
68 // Convert Mac Address to array of bytes
71 // Generate the Crc bit-by-bit (LSB first)
74 for (Iter
= 0;Iter
< 8;Iter
++) {
75 // Check if exponent is set
77 Remainder
= (Remainder
>> 1) ^ CRC_POLYNOMIAL
;
79 Remainder
= (Remainder
>> 1) ^ 0;
84 // Reverse the bits before returning (to Big Endian)
85 //TODO: Need to be reviewed. Do we want to do a bit reverse or a byte reverse (in this case use SwapBytes32())
86 return ReverseBits (Remainder
);
89 // Function to read from MAC indirect registers
97 // Check index is in the range
100 // Wait until CSR busy bit is cleared
101 while ((MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
103 // Set CSR busy bit to ensure read will occur
104 // Set the R/W bit to indicate we are reading
105 // Set the index of CSR Address to access desired register
106 MacCSR
= MAC_CSR_BUSY
| MAC_CSR_READ
| MAC_CSR_ADDR(Index
);
108 // Write to the register
109 MmioWrite32 (LAN9118_MAC_CSR_CMD
, MacCSR
);
111 // Wait until CSR busy bit is cleared
112 while ((MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
114 // Now read from data register to get read value
115 return MmioRead32 (LAN9118_MAC_CSR_DATA
);
118 // Function to write to MAC indirect registers
128 // Check index is in the range
131 // Wait until CSR busy bit is cleared
132 while ((MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
134 // Set CSR busy bit to ensure read will occur
135 // Set the R/W bit to indicate we are writing
136 // Set the index of CSR Address to access desired register
137 MacCSR
= MAC_CSR_BUSY
| MAC_CSR_WRITE
| MAC_CSR_ADDR(Index
);
139 // Now write the value to the register before issuing the write command
140 ValueWritten
= MmioWrite32 (LAN9118_MAC_CSR_DATA
, Value
);
142 // Write the config to the register
143 MmioWrite32 (LAN9118_MAC_CSR_CMD
, MacCSR
);
145 // Wait until CSR busy bit is cleared
146 while ((MmioRead32 (LAN9118_MAC_CSR_CMD
) & MAC_CSR_BUSY
) == MAC_CSR_BUSY
);
151 // Function to read from MII register (PHY Access)
160 // Check it is a valid index
163 // Wait for busy bit to clear
164 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
166 // Clear the R/W bit to indicate we are reading
167 // Set the index of the MII register
168 // Set the PHY Address
169 // Set the MII busy bit to allow read
170 MiiAcc
= MII_ACC_MII_READ
| MII_ACC_MII_REG_INDEX(Index
) | MII_ACC_PHY_VALUE
| MII_ACC_MII_BUSY
;
172 // Now write this config to register
173 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC
, MiiAcc
& 0xFFFF);
175 // Wait for busy bit to clear
176 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
178 // Now read the value of the register
179 ValueRead
= (IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_DATA
) & 0xFFFF); // only lower 16 bits are valid for any PHY register
185 // Function to write to the MII register (PHY Access)
195 // Check it is a valid index
198 // Wait for busy bit to clear
199 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
201 // Clear the R/W bit to indicate we are reading
202 // Set the index of the MII register
203 // Set the PHY Address
204 // Set the MII busy bit to allow read
205 MiiAcc
= MII_ACC_MII_WRITE
| MII_ACC_MII_REG_INDEX(Index
) | MII_ACC_PHY_VALUE
| MII_ACC_MII_BUSY
;
207 // Write the desired value to the register first
208 ValueWritten
= IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_DATA
, (Value
& 0xFFFF));
210 // Now write the config to register
211 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC
, MiiAcc
& 0xFFFF);
213 // Wait for operation to terminate
214 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC
) & MII_ACC_MII_BUSY
) == MII_ACC_MII_BUSY
);
220 /* ---------------- EEPROM Operations ------------------ */
223 // Function to read from EEPROM memory
225 IndirectEEPROMRead32 (
231 // Set the busy bit to ensure read will occur
232 EepromCmd
= E2P_EPC_BUSY
| E2P_EPC_CMD_READ
;
234 // Set the index to access desired EEPROM memory location
235 EepromCmd
|= E2P_EPC_ADDRESS(Index
);
237 // Write to Eeprom command register
238 MmioWrite32 (LAN9118_E2P_CMD
, EepromCmd
);
239 gBS
->Stall (LAN9118_STALL
);
241 // Wait until operation has completed
242 while (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
244 // Check that operation didn't time out
245 if (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_TIMEOUT
) {
246 DEBUG ((EFI_D_ERROR
, "EEPROM Operation Timed out: Read command on index %x\n",Index
));
250 // Wait until operation has completed
251 while (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
253 // Finally read the value
254 return MmioRead32 (LAN9118_E2P_DATA
);
257 // Function to write to EEPROM memory
259 IndirectEEPROMWrite32 (
269 // Read the EEPROM Command register
270 EepromCmd
= MmioRead32 (LAN9118_E2P_CMD
);
272 // Set the busy bit to ensure read will occur
273 EepromCmd
|= ((UINT32
)1 << 31);
275 // Set the EEPROM command to write(0b011)
276 EepromCmd
&= ~(7 << 28); // Clear the command first
277 EepromCmd
|= (3 << 28); // Write 011
279 // Set the index to access desired EEPROM memory location
280 EepromCmd
|= (Index
& 0xF);
282 // Write the value to the data register first
283 ValueWritten
= MmioWrite32 (LAN9118_E2P_DATA
, Value
);
285 // Write to Eeprom command register
286 MmioWrite32 (LAN9118_E2P_CMD
, EepromCmd
);
287 gBS
->Stall (LAN9118_STALL
);
289 // Wait until operation has completed
290 while (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
292 // Check that operation didn't time out
293 if (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_TIMEOUT
) {
294 DEBUG ((EFI_D_ERROR
, "EEPROM Operation Timed out: Write command at memloc 0x%x, with value 0x%x\n",Index
, Value
));
298 // Wait until operation has completed
299 while (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
304 /* ---------------- General Operations ----------------- */
307 Lan9118SetMacAddress (
308 EFI_MAC_ADDRESS
*Mac
,
309 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
312 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRL
,
313 (Mac
->Addr
[0] & 0xFF) |
314 ((Mac
->Addr
[1] & 0xFF) << 8) |
315 ((Mac
->Addr
[2] & 0xFF) << 16) |
316 ((Mac
->Addr
[3] & 0xFF) << 24)
319 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRH
,
320 (UINT32
)(Mac
->Addr
[4] & 0xFF) |
321 ((Mac
->Addr
[5] & 0xFF) << 8)
326 Lan9118ReadMacAddress (
327 OUT EFI_MAC_ADDRESS
*MacAddress
330 UINT32 MacAddrHighValue
;
331 UINT32 MacAddrLowValue
;
333 // Read the Mac Addr high register
334 MacAddrHighValue
= (IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRH
) & 0xFFFF);
335 // Read the Mac Addr low register
336 MacAddrLowValue
= IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRL
);
338 SetMem (MacAddress
, sizeof(*MacAddress
), 0);
339 MacAddress
->Addr
[0] = (MacAddrLowValue
& 0xFF);
340 MacAddress
->Addr
[1] = (MacAddrLowValue
& 0xFF00) >> 8;
341 MacAddress
->Addr
[2] = (MacAddrLowValue
& 0xFF0000) >> 16;
342 MacAddress
->Addr
[3] = (MacAddrLowValue
& 0xFF000000) >> 24;
343 MacAddress
->Addr
[4] = (MacAddrHighValue
& 0xFF);
344 MacAddress
->Addr
[5] = (MacAddrHighValue
& 0xFF00) >> 8;
348 * Power up the 9118 and find its MAC address.
350 * This operation can be carried out when the LAN9118 is in any power state
355 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
359 UINT64 DefaultMacAddress
;
361 // Attempt to wake-up the device if it is in a lower power state
362 if (((MmioRead32 (LAN9118_PMT_CTRL
) & MPTCTRL_PM_MODE_MASK
) >> 12) != 0) {
363 DEBUG ((DEBUG_NET
, "Waking from reduced power state.\n"));
364 MmioWrite32 (LAN9118_BYTE_TEST
, 0xFFFFFFFF);
365 gBS
->Stall (LAN9118_STALL
);
368 // Check that device is active
370 while ((MmioRead32 (LAN9118_PMT_CTRL
) & MPTCTRL_READY
) == 0 && --Timeout
) {
371 gBS
->Stall (LAN9118_STALL
);
377 // Check that EEPROM isn't active
379 while ((MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
) && --Timeout
){
380 gBS
->Stall (LAN9118_STALL
);
386 // Check if a MAC address was loaded from EEPROM, and if it was, set it as the
388 if ((MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_MAC_ADDRESS_LOADED
) == 0) {
389 DEBUG ((EFI_D_ERROR
, "Warning: There was an error detecting EEPROM or loading the MAC Address.\n"));
391 // If we had an address before (set by StationAddess), continue to use it
392 if (CompareMem (&Snp
->Mode
->CurrentAddress
, &mZeroMac
, NET_ETHER_ADDR_LEN
)) {
393 Lan9118SetMacAddress (&Snp
->Mode
->CurrentAddress
, Snp
);
395 // If there are no cached addresses, then fall back to a default
396 DEBUG ((EFI_D_WARN
, "Warning: using driver-default MAC address\n"));
397 DefaultMacAddress
= FixedPcdGet64 (PcdLan9118DefaultMacAddress
);
398 Lan9118SetMacAddress((EFI_MAC_ADDRESS
*) &DefaultMacAddress
, Snp
);
399 CopyMem (&Snp
->Mode
->CurrentAddress
, &DefaultMacAddress
, NET_ETHER_ADDR_LEN
);
402 // Store the MAC address that was loaded from EEPROM
403 Lan9118ReadMacAddress (&Snp
->Mode
->CurrentAddress
);
404 CopyMem (&Snp
->Mode
->PermanentAddress
, &Snp
->Mode
->CurrentAddress
, NET_ETHER_ADDR_LEN
);
407 // Clear and acknowledge interrupts
408 MmioWrite32 (LAN9118_INT_EN
, 0);
409 MmioWrite32 (LAN9118_IRQ_CFG
, 0);
410 MmioWrite32 (LAN9118_INT_STS
, 0xFFFFFFFF);
412 // Do self tests here?
418 // Perform software reset on the LAN9118
419 // Return 0 on success, -1 on error
423 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
429 // Initialize variable
433 StopTx (STOP_TX_MAC
| STOP_TX_CFG
| STOP_TX_CLEAR
, Snp
);
434 StopRx (STOP_RX_CLEAR
, Snp
); // Clear receiver FIFO
437 HwConf
= MmioRead32 (LAN9118_HW_CFG
);
440 // Set the Must Be One (MBO) bit
441 if (((HwConf
& HWCFG_MBO
) >> 20) == 0) {
445 // Check that EEPROM isn't active
446 while (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
448 // Write the configuration
449 MmioWrite32 (LAN9118_HW_CFG
, HwConf
);
450 gBS
->Stall (LAN9118_STALL
);
452 // Wait for reset to complete
453 while (MmioRead32 (LAN9118_HW_CFG
) & HWCFG_SRST
) {
455 gBS
->Stall (LAN9118_STALL
);
458 // If time taken exceeds 100us, then there was an error condition
459 if (ResetTime
> 1000) {
460 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
465 // Check that EEPROM isn't active
466 while (MmioRead32 (LAN9118_E2P_CMD
) & E2P_EPC_BUSY
);
468 // TODO we probably need to re-set the mac address here.
470 // Clear and acknowledge all interrupts
471 if (Flags
& SOFT_RESET_CLEAR_INT
) {
472 MmioWrite32 (LAN9118_INT_EN
, 0);
473 MmioWrite32 (LAN9118_IRQ_CFG
, 0);
474 MmioWrite32 (LAN9118_INT_STS
, 0xFFFFFFFF);
477 // Do self tests here?
478 if (Flags
& SOFT_RESET_SELF_TEST
) {
486 // Perform PHY software reset
490 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
496 // PMT PHY reset takes precedence over BCR
497 if (Flags
& PHY_RESET_PMT
) {
498 PmtCtrl
= MmioRead32 (LAN9118_PMT_CTRL
);
499 PmtCtrl
|= MPTCTRL_PHY_RST
;
500 MmioWrite32 (LAN9118_PMT_CTRL
,PmtCtrl
);
502 // Wait for completion
503 while (MmioRead32 (LAN9118_PMT_CTRL
) & MPTCTRL_PHY_RST
) {
504 gBS
->Stall (LAN9118_STALL
);
506 // PHY Basic Control Register reset
507 } else if (Flags
& PHY_RESET_BCR
) {
508 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL
, PHYCR_RESET
);
510 // Wait for completion
511 while (IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL
) & PHYCR_RESET
) {
512 gBS
->Stall (LAN9118_STALL
);
516 // Check the link status
517 if (Flags
& PHY_RESET_CHECK_LINK
) {
518 LinkTo
= 100000; // 2 second (could be 50% more)
519 while (EFI_ERROR (CheckLinkStatus (0, Snp
)) && (LinkTo
> 0)) {
520 gBS
->Stall (LAN9118_STALL
);
530 // Clear and acknowledge all interrupts
531 if (Flags
& PHY_SOFT_RESET_CLEAR_INT
) {
532 MmioWrite32 (LAN9118_INT_EN
, 0);
533 MmioWrite32 (LAN9118_IRQ_CFG
, 0);
534 MmioWrite32 (LAN9118_INT_STS
, 0xFFFFFFFF);
541 // Configure hardware for LAN9118
545 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
550 // Check if we want to use LEDs on GPIO
551 if (Flags
& HW_CONF_USE_LEDS
) {
552 GpioConf
= MmioRead32 (LAN9118_GPIO_CFG
);
554 // Enable GPIO as LEDs and Config as Push-Pull driver
555 GpioConf
|= GPIO_GPIO0_PUSH_PULL
| GPIO_GPIO1_PUSH_PULL
| GPIO_GPIO2_PUSH_PULL
|
556 GPIO_LED1_ENABLE
| GPIO_LED2_ENABLE
| GPIO_LED3_ENABLE
;
558 // Write the configuration
559 MmioWrite32 (LAN9118_GPIO_CFG
, GpioConf
);
560 gBS
->Stall (LAN9118_STALL
);
566 // Configure flow control
573 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
579 // Do auto-negotiation
583 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
591 // First check that auto-negotiation is supported
592 PhyStatus
= IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
);
593 if ((PhyStatus
& PHYSTS_AUTO_CAP
) == 0) {
594 DEBUG ((EFI_D_ERROR
, "Auto-negotiation not supported.\n"));
595 return EFI_DEVICE_ERROR
;
598 // Check that link is up first
599 if ((PhyStatus
& PHYSTS_LINK_STS
) == 0) {
600 // Wait until it is up or until Time Out
602 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
) & PHYSTS_LINK_STS
) == 0) {
603 gBS
->Stall (LAN9118_STALL
);
606 DEBUG ((EFI_D_ERROR
, "Link timeout in auto-negotiation.\n"));
612 // Configure features to advertise
613 Features
= IndirectPHYRead32 (PHY_INDEX_AUTO_NEG_ADVERT
);
615 if ((Flags
& AUTO_NEGOTIATE_ADVERTISE_ALL
) > 0) {
616 // Link speed capabilities
617 Features
|= (PHYANA_10BASET
| PHYANA_10BASETFD
| PHYANA_100BASETX
| PHYANA_100BASETXFD
);
619 // Pause frame capabilities
620 Features
&= ~(PHYANA_PAUSE_OP_MASK
);
624 // Write the features
625 IndirectPHYWrite32 (PHY_INDEX_AUTO_NEG_ADVERT
, Features
);
627 // Read control register
628 PhyControl
= IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL
);
630 // Enable Auto-Negotiation
631 if ((PhyControl
& PHYCR_AUTO_EN
) == 0) {
632 PhyControl
|= PHYCR_AUTO_EN
;
635 // Restart auto-negotiation
636 PhyControl
|= PHYCR_RST_AUTO
;
638 // Enable collision test if required to do so
639 if (Flags
& AUTO_NEGOTIATE_COLLISION_TEST
) {
640 PhyControl
|= PHYCR_COLL_TEST
;
642 PhyControl
&= ~ PHYCR_COLL_TEST
;
645 // Write this configuration
646 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL
, PhyControl
);
648 // Wait until process has completed
649 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
) & PHYSTS_AUTO_COMP
) == 0);
654 // Check the Link Status and take appropriate action
658 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
661 // Get the PHY Status
662 UINT32 PhyBStatus
= IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS
);
664 if (PhyBStatus
& PHYSTS_LINK_STS
) {
667 return EFI_DEVICE_ERROR
;
671 // Stop the transmitter
675 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
684 // Check if we want to clear tx
685 if (Flags
& STOP_TX_CLEAR
) {
686 TxCfg
= MmioRead32 (LAN9118_TX_CFG
);
687 TxCfg
|= TXCFG_TXS_DUMP
| TXCFG_TXD_DUMP
;
688 MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
689 gBS
->Stall (LAN9118_STALL
);
692 // Check if already stopped
693 if (Flags
& STOP_TX_MAC
) {
694 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
696 if (MacCsr
& MACCR_TX_EN
) {
697 MacCsr
&= ~MACCR_TX_EN
;
698 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
702 if (Flags
& STOP_TX_CFG
) {
703 TxCfg
= MmioRead32 (LAN9118_TX_CFG
);
705 if (TxCfg
& TXCFG_TX_ON
) {
706 TxCfg
|= TXCFG_STOP_TX
;
707 MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
708 gBS
->Stall (LAN9118_STALL
);
710 // Wait for Tx to finish transmitting
711 while (MmioRead32 (LAN9118_TX_CFG
) & TXCFG_STOP_TX
);
722 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
730 // Check if already stopped
731 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
733 if (MacCsr
& MACCR_RX_EN
) {
734 MacCsr
&= ~ MACCR_RX_EN
;
735 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
738 // Check if we want to clear receiver FIFOs
739 if (Flags
& STOP_RX_CLEAR
) {
740 RxCfg
= MmioRead32 (LAN9118_RX_CFG
);
741 RxCfg
|= RXCFG_RX_DUMP
;
742 MmioWrite32 (LAN9118_RX_CFG
, RxCfg
);
743 gBS
->Stall (LAN9118_STALL
);
745 while (MmioRead32 (LAN9118_RX_CFG
) & RXCFG_RX_DUMP
);
751 // Start the transmitter
755 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
764 // Check if we want to clear tx
765 if (Flags
& START_TX_CLEAR
) {
766 TxCfg
= MmioRead32 (LAN9118_TX_CFG
);
767 TxCfg
|= TXCFG_TXS_DUMP
| TXCFG_TXD_DUMP
;
768 MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
769 gBS
->Stall (LAN9118_STALL
);
772 // Check if tx was started from MAC and enable if not
773 if (Flags
& START_TX_MAC
) {
774 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
775 gBS
->Stall (LAN9118_STALL
);
776 if ((MacCsr
& MACCR_TX_EN
) == 0) {
777 MacCsr
|= MACCR_TX_EN
;
778 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
779 gBS
->Stall (LAN9118_STALL
);
783 // Check if tx was started from TX_CFG and enable if not
784 if (Flags
& START_TX_CFG
) {
785 TxCfg
= MmioRead32 (LAN9118_TX_CFG
);
786 gBS
->Stall (LAN9118_STALL
);
787 if ((TxCfg
& TXCFG_TX_ON
) == 0) {
788 TxCfg
|= TXCFG_TX_ON
;
789 MmioWrite32 (LAN9118_TX_CFG
, TxCfg
);
790 gBS
->Stall (LAN9118_STALL
);
794 // Set the tx data trigger level
799 // Start the receiver
803 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
811 // Check if already started
812 MacCsr
= IndirectMACRead32 (INDIRECT_MAC_INDEX_CR
);
814 if ((MacCsr
& MACCR_RX_EN
) == 0) {
815 // Check if we want to clear receiver FIFOs before starting
816 if (Flags
& START_RX_CLEAR
) {
817 RxCfg
= MmioRead32 (LAN9118_RX_CFG
);
818 RxCfg
|= RXCFG_RX_DUMP
;
819 MmioWrite32 (LAN9118_RX_CFG
, RxCfg
);
820 gBS
->Stall (LAN9118_STALL
);
822 while (MmioRead32 (LAN9118_RX_CFG
) & RXCFG_RX_DUMP
);
825 MacCsr
|= MACCR_RX_EN
;
826 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR
, MacCsr
);
827 gBS
->Stall (LAN9118_STALL
);
833 // Check Tx Data available space
837 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
843 // Get the amount of free space from information register
844 TxInf
= MmioRead32 (LAN9118_TX_FIFO_INF
);
845 FreeSpace
= (TxInf
& TXFIFOINF_TDFREE_MASK
);
847 return FreeSpace
; // Value in bytes
850 // Check Tx Status used space
854 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
860 // Get the amount of used space from information register
861 TxInf
= MmioRead32 (LAN9118_TX_FIFO_INF
);
862 UsedSpace
= (TxInf
& TXFIFOINF_TXSUSED_MASK
) >> 16;
864 return UsedSpace
<< 2; // Value in bytes
867 // Check Rx Data used space
871 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
877 // Get the amount of used space from information register
878 RxInf
= MmioRead32 (LAN9118_RX_FIFO_INF
);
879 UsedSpace
= (RxInf
& RXFIFOINF_RXDUSED_MASK
);
881 return UsedSpace
; // Value in bytes (rounded up to nearest DWORD)
884 // Check Rx Status used space
888 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
894 // Get the amount of used space from information register
895 RxInf
= MmioRead32 (LAN9118_RX_FIFO_INF
);
896 UsedSpace
= (RxInf
& RXFIFOINF_RXSUSED_MASK
) >> 16;
898 return UsedSpace
<< 2; // Value in bytes
902 // Change the allocation of FIFOs
904 ChangeFifoAllocation (
906 IN OUT UINTN
*TxDataSize OPTIONAL
,
907 IN OUT UINTN
*RxDataSize OPTIONAL
,
908 IN OUT UINT32
*TxStatusSize OPTIONAL
,
909 IN OUT UINT32
*RxStatusSize OPTIONAL
,
910 IN OUT EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
916 // Check that desired sizes don't exceed limits
917 if (*TxDataSize
> TX_FIFO_MAX_SIZE
)
918 return EFI_INVALID_PARAMETER
;
920 #if defined(RX_FIFO_MIN_SIZE) && defined(RX_FIFO_MAX_SIZE)
921 if (*RxDataSize
> RX_FIFO_MAX_SIZE
) {
922 return EFI_INVALID_PARAMETER
;
926 if (Flags
& ALLOC_USE_DEFAULT
) {
930 // If we use the FIFOs (always use this first)
931 if (Flags
& ALLOC_USE_FIFOS
) {
932 // Read the current value of allocation
933 HwConf
= MmioRead32 (LAN9118_HW_CFG
);
934 TxFifoOption
= (HwConf
>> 16) & 0xF;
936 // Choose the correct size (always use larger than requested if possible)
937 if (*TxDataSize
< TX_FIFO_MIN_SIZE
) {
938 *TxDataSize
= TX_FIFO_MIN_SIZE
;
942 } else if ((*TxDataSize
> TX_FIFO_MIN_SIZE
) && (*TxDataSize
<= 2560)) {
947 } else if ((*TxDataSize
> 2560) && (*TxDataSize
<= 3584)) {
952 } else if ((*TxDataSize
> 3584) && (*TxDataSize
<= 4608)) { // default option
957 } else if ((*TxDataSize
> 4608) && (*TxDataSize
<= 5632)) {
962 } else if ((*TxDataSize
> 5632) && (*TxDataSize
<= 6656)) {
967 } else if ((*TxDataSize
> 6656) && (*TxDataSize
<= 7680)) {
972 } else if ((*TxDataSize
> 7680) && (*TxDataSize
<= 8704)) {
977 } else if ((*TxDataSize
> 8704) && (*TxDataSize
<= 9728)) {
982 } else if ((*TxDataSize
> 9728) && (*TxDataSize
<= 10752)) {
987 } else if ((*TxDataSize
> 10752) && (*TxDataSize
<= 11776)) {
992 } else if ((*TxDataSize
> 11776) && (*TxDataSize
<= 12800)) {
997 } else if ((*TxDataSize
> 12800) && (*TxDataSize
<= 13824)) {
1000 *RxStatusSize
= 128;
1004 ASSERT(0); // Untested code path
1010 if (Flags
& ALLOC_USE_DMA
) {
1011 return EFI_UNSUPPORTED
; // Unsupported as of now
1013 // Clear and assign the new size option
1014 HwConf
&= ~(0xF0000);
1015 HwConf
|= ((TxFifoOption
& 0xF) << 16);
1016 MmioWrite32 (LAN9118_HW_CFG
, HwConf
);
1017 gBS
->Stall (LAN9118_STALL
);