1 /** @file 2 * 3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved. 4 * 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 9 * 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. 12 * 13 **/ 14 15 #include "Lan9118Dxe.h" 16 17 STATIC EFI_MAC_ADDRESS mZeroMac = { { 0 } }; 18 19 /** 20 This internal function reverses bits for 32bit data. 21 22 @param Value The data to be reversed. 23 24 @return Data reversed. 25 26 **/ 27 UINT32 28 ReverseBits ( 29 UINT32 Value 30 ) 31 { 32 UINTN Index; 33 UINT32 NewValue; 34 35 NewValue = 0; 36 for (Index = 0; Index < 32; Index++) { 37 if ((Value & (1 << Index)) != 0) { 38 NewValue = NewValue | (1 << (31 - Index)); 39 } 40 } 41 42 return NewValue; 43 } 44 45 /* 46 ** Create Ethernet CRC 47 ** 48 ** INFO USED: 49 ** 1: http://en.wikipedia.org/wiki/Cyclic_redundancy_check 50 ** 51 ** 2: http://www.erg.abdn.ac.uk/~gorry/eg3567/dl-pages/crc.html 52 ** 53 ** 3: http://en.wikipedia.org/wiki/Computation_of_CRC 54 */ 55 UINT32 56 GenEtherCrc32 ( 57 IN EFI_MAC_ADDRESS *Mac, 58 IN UINT32 AddrLen 59 ) 60 { 61 INT32 Iter; 62 UINT32 Remainder; 63 UINT8 *Ptr; 64 65 Iter = 0; 66 Remainder = 0xFFFFFFFF; // 0xFFFFFFFF is standard seed for Ethernet 67 68 // Convert Mac Address to array of bytes 69 Ptr = (UINT8*)Mac; 70 71 // Generate the Crc bit-by-bit (LSB first) 72 while (AddrLen--) { 73 Remainder ^= *Ptr++; 74 for (Iter = 0;Iter < 8;Iter++) { 75 // Check if exponent is set 76 if (Remainder & 1) { 77 Remainder = (Remainder >> 1) ^ CRC_POLYNOMIAL; 78 } else { 79 Remainder = (Remainder >> 1) ^ 0; 80 } 81 } 82 } 83 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); 87 } 88 89 // Function to read from MAC indirect registers 90 UINT32 91 IndirectMACRead32 ( 92 UINT32 Index 93 ) 94 { 95 UINT32 MacCSR; 96 97 // Check index is in the range 98 ASSERT(Index <= 12); 99 100 // Wait until CSR busy bit is cleared 101 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); 102 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); 107 108 // Write to the register 109 Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); 110 111 // Wait until CSR busy bit is cleared 112 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); 113 114 // Now read from data register to get read value 115 return Lan9118MmioRead32 (LAN9118_MAC_CSR_DATA); 116 } 117 118 /* 119 * LAN9118 chips have special restrictions on some back-to-back Write/Read or 120 * Read/Read pairs of accesses. After a read or write that changes the state of 121 * the device, there is a period in which stale values may be returned in 122 * response to a read. This period is dependent on the registers accessed. 123 * 124 * We must delay prior reads by this period. This can either be achieved by 125 * timer-based delays, or by performing dummy reads of the BYTE_TEST register, 126 * for which the recommended number of reads is described in the LAN9118 data 127 * sheet. This is required in addition to any memory barriers. 128 * 129 * This function performs a number of dummy reads of the BYTE_TEST register, as 130 * a building block for the above. 131 */ 132 VOID 133 WaitDummyReads ( 134 UINTN Count 135 ) 136 { 137 while (Count--) 138 MmioRead32(LAN9118_BYTE_TEST); 139 } 140 141 UINT32 142 Lan9118RawMmioRead32( 143 UINTN Address, 144 UINTN Delay 145 ) 146 { 147 UINT32 Value; 148 149 Value = MmioRead32(Address); 150 WaitDummyReads(Delay); 151 return Value; 152 } 153 154 UINT32 155 Lan9118RawMmioWrite32( 156 UINTN Address, 157 UINT32 Value, 158 UINTN Delay 159 ) 160 { 161 MmioWrite32(Address, Value); 162 WaitDummyReads(Delay); 163 return Value; 164 } 165 166 // Function to write to MAC indirect registers 167 UINT32 168 IndirectMACWrite32 ( 169 UINT32 Index, 170 UINT32 Value 171 ) 172 { 173 UINT32 ValueWritten; 174 UINT32 MacCSR; 175 176 // Check index is in the range 177 ASSERT(Index <= 12); 178 179 // Wait until CSR busy bit is cleared 180 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); 181 182 // Set CSR busy bit to ensure read will occur 183 // Set the R/W bit to indicate we are writing 184 // Set the index of CSR Address to access desired register 185 MacCSR = MAC_CSR_BUSY | MAC_CSR_WRITE | MAC_CSR_ADDR(Index); 186 187 // Now write the value to the register before issuing the write command 188 ValueWritten = Lan9118MmioWrite32 (LAN9118_MAC_CSR_DATA, Value); 189 190 // Write the config to the register 191 Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); 192 193 // Wait until CSR busy bit is cleared 194 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); 195 196 return ValueWritten; 197 } 198 199 // Function to read from MII register (PHY Access) 200 UINT32 201 IndirectPHYRead32 ( 202 UINT32 Index 203 ) 204 { 205 UINT32 ValueRead; 206 UINT32 MiiAcc; 207 208 // Check it is a valid index 209 ASSERT(Index < 31); 210 211 // Wait for busy bit to clear 212 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 213 214 // Clear the R/W bit to indicate we are reading 215 // Set the index of the MII register 216 // Set the PHY Address 217 // Set the MII busy bit to allow read 218 MiiAcc = MII_ACC_MII_READ | MII_ACC_MII_REG_INDEX(Index) | MII_ACC_PHY_VALUE | MII_ACC_MII_BUSY; 219 220 // Now write this config to register 221 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC, MiiAcc & 0xFFFF); 222 223 // Wait for busy bit to clear 224 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 225 226 // Now read the value of the register 227 ValueRead = (IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_DATA) & 0xFFFF); // only lower 16 bits are valid for any PHY register 228 229 return ValueRead; 230 } 231 232 233 // Function to write to the MII register (PHY Access) 234 UINT32 235 IndirectPHYWrite32 ( 236 UINT32 Index, 237 UINT32 Value 238 ) 239 { 240 UINT32 MiiAcc; 241 UINT32 ValueWritten; 242 243 // Check it is a valid index 244 ASSERT(Index < 31); 245 246 // Wait for busy bit to clear 247 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 248 249 // Clear the R/W bit to indicate we are reading 250 // Set the index of the MII register 251 // Set the PHY Address 252 // Set the MII busy bit to allow read 253 MiiAcc = MII_ACC_MII_WRITE | MII_ACC_MII_REG_INDEX(Index) | MII_ACC_PHY_VALUE | MII_ACC_MII_BUSY; 254 255 // Write the desired value to the register first 256 ValueWritten = IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_DATA, (Value & 0xFFFF)); 257 258 // Now write the config to register 259 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC, MiiAcc & 0xFFFF); 260 261 // Wait for operation to terminate 262 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 263 264 return ValueWritten; 265 } 266 267 268 /* ---------------- EEPROM Operations ------------------ */ 269 270 271 // Function to read from EEPROM memory 272 UINT32 273 IndirectEEPROMRead32 ( 274 UINT32 Index 275 ) 276 { 277 UINT32 EepromCmd; 278 279 // Set the busy bit to ensure read will occur 280 EepromCmd = E2P_EPC_BUSY | E2P_EPC_CMD_READ; 281 282 // Set the index to access desired EEPROM memory location 283 EepromCmd |= E2P_EPC_ADDRESS(Index); 284 285 // Write to Eeprom command register 286 Lan9118MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); 287 288 // Wait until operation has completed 289 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 290 291 // Check that operation didn't time out 292 if (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) { 293 DEBUG ((EFI_D_ERROR, "EEPROM Operation Timed out: Read command on index %x\n",Index)); 294 return 0; 295 } 296 297 // Wait until operation has completed 298 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 299 300 // Finally read the value 301 return Lan9118MmioRead32 (LAN9118_E2P_DATA); 302 } 303 304 // Function to write to EEPROM memory 305 UINT32 306 IndirectEEPROMWrite32 ( 307 UINT32 Index, 308 UINT32 Value 309 ) 310 { 311 UINT32 ValueWritten; 312 UINT32 EepromCmd; 313 314 ValueWritten = 0; 315 316 // Read the EEPROM Command register 317 EepromCmd = Lan9118MmioRead32 (LAN9118_E2P_CMD); 318 319 // Set the busy bit to ensure read will occur 320 EepromCmd |= ((UINT32)1 << 31); 321 322 // Set the EEPROM command to write(0b011) 323 EepromCmd &= ~(7 << 28); // Clear the command first 324 EepromCmd |= (3 << 28); // Write 011 325 326 // Set the index to access desired EEPROM memory location 327 EepromCmd |= (Index & 0xF); 328 329 // Write the value to the data register first 330 ValueWritten = Lan9118MmioWrite32 (LAN9118_E2P_DATA, Value); 331 332 // Write to Eeprom command register 333 Lan9118MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); 334 335 // Wait until operation has completed 336 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 337 338 // Check that operation didn't time out 339 if (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) { 340 DEBUG ((EFI_D_ERROR, "EEPROM Operation Timed out: Write command at memloc 0x%x, with value 0x%x\n",Index, Value)); 341 return 0; 342 } 343 344 // Wait until operation has completed 345 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 346 347 return ValueWritten; 348 } 349 350 /* ---------------- General Operations ----------------- */ 351 352 VOID 353 Lan9118SetMacAddress ( 354 EFI_MAC_ADDRESS *Mac, 355 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 356 ) 357 { 358 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRL, 359 (Mac->Addr[0] & 0xFF) | 360 ((Mac->Addr[1] & 0xFF) << 8) | 361 ((Mac->Addr[2] & 0xFF) << 16) | 362 ((Mac->Addr[3] & 0xFF) << 24) 363 ); 364 365 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRH, 366 (UINT32)(Mac->Addr[4] & 0xFF) | 367 ((Mac->Addr[5] & 0xFF) << 8) 368 ); 369 } 370 371 VOID 372 Lan9118ReadMacAddress ( 373 OUT EFI_MAC_ADDRESS *MacAddress 374 ) 375 { 376 UINT32 MacAddrHighValue; 377 UINT32 MacAddrLowValue; 378 379 // Read the Mac Addr high register 380 MacAddrHighValue = (IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRH) & 0xFFFF); 381 // Read the Mac Addr low register 382 MacAddrLowValue = IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRL); 383 384 SetMem (MacAddress, sizeof(*MacAddress), 0); 385 MacAddress->Addr[0] = (MacAddrLowValue & 0xFF); 386 MacAddress->Addr[1] = (MacAddrLowValue & 0xFF00) >> 8; 387 MacAddress->Addr[2] = (MacAddrLowValue & 0xFF0000) >> 16; 388 MacAddress->Addr[3] = (MacAddrLowValue & 0xFF000000) >> 24; 389 MacAddress->Addr[4] = (MacAddrHighValue & 0xFF); 390 MacAddress->Addr[5] = (MacAddrHighValue & 0xFF00) >> 8; 391 } 392 393 /* 394 * Power up the 9118 and find its MAC address. 395 * 396 * This operation can be carried out when the LAN9118 is in any power state 397 * 398 */ 399 EFI_STATUS 400 Lan9118Initialize ( 401 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp 402 ) 403 { 404 UINTN Retries; 405 UINT64 DefaultMacAddress; 406 407 // Attempt to wake-up the device if it is in a lower power state 408 if (((Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PM_MODE_MASK) >> 12) != 0) { 409 DEBUG ((DEBUG_NET, "Waking from reduced power state.\n")); 410 Lan9118MmioWrite32 (LAN9118_BYTE_TEST, 0xFFFFFFFF); 411 } 412 413 // Check that device is active 414 Retries = 20; 415 while ((Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_READY) == 0 && --Retries) { 416 gBS->Stall (LAN9118_STALL); 417 } 418 if (!Retries) { 419 return EFI_TIMEOUT; 420 } 421 422 // Check that EEPROM isn't active 423 Retries = 20; 424 while ((Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY) && --Retries){ 425 gBS->Stall (LAN9118_STALL); 426 } 427 if (!Retries) { 428 return EFI_TIMEOUT; 429 } 430 431 // Check if a MAC address was loaded from EEPROM, and if it was, set it as the 432 // current address. 433 if ((Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_MAC_ADDRESS_LOADED) == 0) { 434 DEBUG ((EFI_D_ERROR, "Warning: There was an error detecting EEPROM or loading the MAC Address.\n")); 435 436 // If we had an address before (set by StationAddess), continue to use it 437 if (CompareMem (&Snp->Mode->CurrentAddress, &mZeroMac, NET_ETHER_ADDR_LEN)) { 438 Lan9118SetMacAddress (&Snp->Mode->CurrentAddress, Snp); 439 } else { 440 // If there are no cached addresses, then fall back to a default 441 DEBUG ((EFI_D_WARN, "Warning: using driver-default MAC address\n")); 442 DefaultMacAddress = FixedPcdGet64 (PcdLan9118DefaultMacAddress); 443 Lan9118SetMacAddress((EFI_MAC_ADDRESS *) &DefaultMacAddress, Snp); 444 CopyMem (&Snp->Mode->CurrentAddress, &DefaultMacAddress, NET_ETHER_ADDR_LEN); 445 } 446 } else { 447 // Store the MAC address that was loaded from EEPROM 448 Lan9118ReadMacAddress (&Snp->Mode->CurrentAddress); 449 CopyMem (&Snp->Mode->PermanentAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN); 450 } 451 452 // Clear and acknowledge interrupts 453 Lan9118MmioWrite32 (LAN9118_INT_EN, 0); 454 Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0); 455 Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); 456 457 // Do self tests here? 458 459 return EFI_SUCCESS; 460 } 461 462 463 // Perform software reset on the LAN9118 464 // Return 0 on success, -1 on error 465 EFI_STATUS 466 SoftReset ( 467 UINT32 Flags, 468 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 469 ) 470 { 471 UINT32 HwConf; 472 UINT32 ResetTime; 473 474 // Initialize variable 475 ResetTime = 0; 476 477 // Stop Rx and Tx 478 StopTx (STOP_TX_MAC | STOP_TX_CFG | STOP_TX_CLEAR, Snp); 479 StopRx (STOP_RX_CLEAR, Snp); // Clear receiver FIFO 480 481 // Issue the reset 482 HwConf = Lan9118MmioRead32 (LAN9118_HW_CFG); 483 HwConf |= 1; 484 485 // Set the Must Be One (MBO) bit 486 if (((HwConf & HWCFG_MBO) >> 20) == 0) { 487 HwConf |= HWCFG_MBO; 488 } 489 490 // Check that EEPROM isn't active 491 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 492 493 // Write the configuration 494 Lan9118MmioWrite32 (LAN9118_HW_CFG, HwConf); 495 496 // Wait for reset to complete 497 while (Lan9118MmioRead32 (LAN9118_HW_CFG) & HWCFG_SRST) { 498 499 gBS->Stall (LAN9118_STALL); 500 ResetTime += 1; 501 502 // If time taken exceeds 100us, then there was an error condition 503 if (ResetTime > 1000) { 504 Snp->Mode->State = EfiSimpleNetworkStopped; 505 return EFI_TIMEOUT; 506 } 507 } 508 509 // Check that EEPROM isn't active 510 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 511 512 // TODO we probably need to re-set the mac address here. 513 514 // Clear and acknowledge all interrupts 515 if (Flags & SOFT_RESET_CLEAR_INT) { 516 Lan9118MmioWrite32 (LAN9118_INT_EN, 0); 517 Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0); 518 Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); 519 } 520 521 // Do self tests here? 522 if (Flags & SOFT_RESET_SELF_TEST) { 523 524 } 525 526 return EFI_SUCCESS; 527 } 528 529 530 // Perform PHY software reset 531 EFI_STATUS 532 PhySoftReset ( 533 UINT32 Flags, 534 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 535 ) 536 { 537 UINT32 PmtCtrl = 0; 538 539 // PMT PHY reset takes precedence over BCR 540 if (Flags & PHY_RESET_PMT) { 541 PmtCtrl = Lan9118MmioRead32 (LAN9118_PMT_CTRL); 542 PmtCtrl |= MPTCTRL_PHY_RST; 543 Lan9118MmioWrite32 (LAN9118_PMT_CTRL,PmtCtrl); 544 545 // Wait for completion 546 while (Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PHY_RST) { 547 gBS->Stall (LAN9118_STALL); 548 } 549 // PHY Basic Control Register reset 550 } else if (Flags & PHY_RESET_BCR) { 551 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL, PHYCR_RESET); 552 553 // Wait for completion 554 while (IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL) & PHYCR_RESET) { 555 gBS->Stall (LAN9118_STALL); 556 } 557 } 558 559 // Clear and acknowledge all interrupts 560 if (Flags & PHY_SOFT_RESET_CLEAR_INT) { 561 Lan9118MmioWrite32 (LAN9118_INT_EN, 0); 562 Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0); 563 Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); 564 } 565 566 return EFI_SUCCESS; 567 } 568 569 570 // Configure hardware for LAN9118 571 EFI_STATUS 572 ConfigureHardware ( 573 UINT32 Flags, 574 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 575 ) 576 { 577 UINT32 GpioConf; 578 579 // Check if we want to use LEDs on GPIO 580 if (Flags & HW_CONF_USE_LEDS) { 581 GpioConf = Lan9118MmioRead32 (LAN9118_GPIO_CFG); 582 583 // Enable GPIO as LEDs and Config as Push-Pull driver 584 GpioConf |= GPIO_GPIO0_PUSH_PULL | GPIO_GPIO1_PUSH_PULL | GPIO_GPIO2_PUSH_PULL | 585 GPIO_LED1_ENABLE | GPIO_LED2_ENABLE | GPIO_LED3_ENABLE; 586 587 // Write the configuration 588 Lan9118MmioWrite32 (LAN9118_GPIO_CFG, GpioConf); 589 } 590 591 return EFI_SUCCESS; 592 } 593 594 // Configure flow control 595 EFI_STATUS 596 ConfigureFlow ( 597 UINT32 Flags, 598 UINT32 HighTrig, 599 UINT32 LowTrig, 600 UINT32 BPDuration, 601 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 602 ) 603 { 604 return EFI_SUCCESS; 605 } 606 607 // Do auto-negotiation 608 EFI_STATUS 609 AutoNegotiate ( 610 UINT32 Flags, 611 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 612 ) 613 { 614 UINT32 PhyControl; 615 UINT32 PhyStatus; 616 UINT32 Features; 617 UINT32 Retries; 618 619 // First check that auto-negotiation is supported 620 PhyStatus = IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS); 621 if ((PhyStatus & PHYSTS_AUTO_CAP) == 0) { 622 DEBUG ((EFI_D_ERROR, "Auto-negotiation not supported.\n")); 623 return EFI_DEVICE_ERROR; 624 } 625 626 // Check that link is up first 627 if ((PhyStatus & PHYSTS_LINK_STS) == 0) { 628 // Wait until it is up or until Time Out 629 Retries = FixedPcdGet32 (PcdLan9118DefaultNegotiationTimeout) / LAN9118_STALL; 630 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS) & PHYSTS_LINK_STS) == 0) { 631 gBS->Stall (LAN9118_STALL); 632 Retries--; 633 if (!Retries) { 634 DEBUG ((EFI_D_ERROR, "Link timeout in auto-negotiation.\n")); 635 return EFI_TIMEOUT; 636 } 637 } 638 } 639 640 // Configure features to advertise 641 Features = IndirectPHYRead32 (PHY_INDEX_AUTO_NEG_ADVERT); 642 643 if ((Flags & AUTO_NEGOTIATE_ADVERTISE_ALL) > 0) { 644 // Link speed capabilities 645 Features |= (PHYANA_10BASET | PHYANA_10BASETFD | PHYANA_100BASETX | PHYANA_100BASETXFD); 646 647 // Pause frame capabilities 648 Features &= ~(PHYANA_PAUSE_OP_MASK); 649 Features |= 3 << 10; 650 } 651 Features &= FixedPcdGet32 (PcdLan9118NegotiationFeatureMask); 652 653 // Write the features 654 IndirectPHYWrite32 (PHY_INDEX_AUTO_NEG_ADVERT, Features); 655 656 // Read control register 657 PhyControl = IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL); 658 659 // Enable Auto-Negotiation 660 if ((PhyControl & PHYCR_AUTO_EN) == 0) { 661 PhyControl |= PHYCR_AUTO_EN; 662 } 663 664 // Restart auto-negotiation 665 PhyControl |= PHYCR_RST_AUTO; 666 667 // Enable collision test if required to do so 668 if (Flags & AUTO_NEGOTIATE_COLLISION_TEST) { 669 PhyControl |= PHYCR_COLL_TEST; 670 } else { 671 PhyControl &= ~ PHYCR_COLL_TEST; 672 } 673 674 // Write this configuration 675 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL, PhyControl); 676 677 // Wait until process has completed 678 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS) & PHYSTS_AUTO_COMP) == 0); 679 680 return EFI_SUCCESS; 681 } 682 683 // Check the Link Status and take appropriate action 684 EFI_STATUS 685 CheckLinkStatus ( 686 UINT32 Flags, 687 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 688 ) 689 { 690 // Get the PHY Status 691 UINT32 PhyBStatus = IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS); 692 693 if (PhyBStatus & PHYSTS_LINK_STS) { 694 return EFI_SUCCESS; 695 } else { 696 return EFI_DEVICE_ERROR; 697 } 698 } 699 700 // Stop the transmitter 701 EFI_STATUS 702 StopTx ( 703 UINT32 Flags, 704 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 705 ) 706 { 707 UINT32 MacCsr; 708 UINT32 TxCfg; 709 710 MacCsr = 0; 711 TxCfg = 0; 712 713 // Check if we want to clear tx 714 if (Flags & STOP_TX_CLEAR) { 715 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); 716 TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP; 717 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); 718 } 719 720 // Check if already stopped 721 if (Flags & STOP_TX_MAC) { 722 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 723 724 if (MacCsr & MACCR_TX_EN) { 725 MacCsr &= ~MACCR_TX_EN; 726 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 727 } 728 } 729 730 if (Flags & STOP_TX_CFG) { 731 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); 732 733 if (TxCfg & TXCFG_TX_ON) { 734 TxCfg |= TXCFG_STOP_TX; 735 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); 736 737 // Wait for Tx to finish transmitting 738 while (Lan9118MmioRead32 (LAN9118_TX_CFG) & TXCFG_STOP_TX); 739 } 740 } 741 742 return EFI_SUCCESS; 743 } 744 745 // Stop the receiver 746 EFI_STATUS 747 StopRx ( 748 UINT32 Flags, 749 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 750 ) 751 { 752 UINT32 MacCsr; 753 UINT32 RxCfg; 754 755 RxCfg = 0; 756 757 // Check if already stopped 758 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 759 760 if (MacCsr & MACCR_RX_EN) { 761 MacCsr &= ~ MACCR_RX_EN; 762 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 763 } 764 765 // Check if we want to clear receiver FIFOs 766 if (Flags & STOP_RX_CLEAR) { 767 RxCfg = Lan9118MmioRead32 (LAN9118_RX_CFG); 768 RxCfg |= RXCFG_RX_DUMP; 769 Lan9118MmioWrite32 (LAN9118_RX_CFG, RxCfg); 770 771 while (Lan9118MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); 772 } 773 774 return EFI_SUCCESS; 775 } 776 777 // Start the transmitter 778 EFI_STATUS 779 StartTx ( 780 UINT32 Flags, 781 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 782 ) 783 { 784 UINT32 MacCsr; 785 UINT32 TxCfg; 786 787 MacCsr = 0; 788 TxCfg = 0; 789 790 // Check if we want to clear tx 791 if (Flags & START_TX_CLEAR) { 792 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); 793 TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP; 794 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); 795 } 796 797 // Check if tx was started from MAC and enable if not 798 if (Flags & START_TX_MAC) { 799 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 800 if ((MacCsr & MACCR_TX_EN) == 0) { 801 MacCsr |= MACCR_TX_EN; 802 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 803 } 804 } 805 806 // Check if tx was started from TX_CFG and enable if not 807 if (Flags & START_TX_CFG) { 808 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG); 809 if ((TxCfg & TXCFG_TX_ON) == 0) { 810 TxCfg |= TXCFG_TX_ON; 811 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg); 812 } 813 } 814 815 // Set the tx data trigger level 816 817 return EFI_SUCCESS; 818 } 819 820 // Start the receiver 821 EFI_STATUS 822 StartRx ( 823 UINT32 Flags, 824 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 825 ) 826 { 827 UINT32 MacCsr; 828 UINT32 RxCfg; 829 830 RxCfg = 0; 831 832 // Check if already started 833 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 834 835 if ((MacCsr & MACCR_RX_EN) == 0) { 836 // Check if we want to clear receiver FIFOs before starting 837 if (Flags & START_RX_CLEAR) { 838 RxCfg = Lan9118MmioRead32 (LAN9118_RX_CFG); 839 RxCfg |= RXCFG_RX_DUMP; 840 Lan9118MmioWrite32 (LAN9118_RX_CFG, RxCfg); 841 842 while (Lan9118MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); 843 } 844 845 MacCsr |= MACCR_RX_EN; 846 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 847 } 848 849 return EFI_SUCCESS; 850 } 851 852 // Check Tx Data available space 853 UINT32 854 TxDataFreeSpace ( 855 UINT32 Flags, 856 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 857 ) 858 { 859 UINT32 TxInf; 860 UINT32 FreeSpace; 861 862 // Get the amount of free space from information register 863 TxInf = Lan9118MmioRead32 (LAN9118_TX_FIFO_INF); 864 FreeSpace = (TxInf & TXFIFOINF_TDFREE_MASK); 865 866 return FreeSpace; // Value in bytes 867 } 868 869 // Check Tx Status used space 870 UINT32 871 TxStatusUsedSpace ( 872 UINT32 Flags, 873 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 874 ) 875 { 876 UINT32 TxInf; 877 UINT32 UsedSpace; 878 879 // Get the amount of used space from information register 880 TxInf = Lan9118MmioRead32 (LAN9118_TX_FIFO_INF); 881 UsedSpace = (TxInf & TXFIFOINF_TXSUSED_MASK) >> 16; 882 883 return UsedSpace << 2; // Value in bytes 884 } 885 886 // Check Rx Data used space 887 UINT32 888 RxDataUsedSpace ( 889 UINT32 Flags, 890 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 891 ) 892 { 893 UINT32 RxInf; 894 UINT32 UsedSpace; 895 896 // Get the amount of used space from information register 897 RxInf = Lan9118MmioRead32 (LAN9118_RX_FIFO_INF); 898 UsedSpace = (RxInf & RXFIFOINF_RXDUSED_MASK); 899 900 return UsedSpace; // Value in bytes (rounded up to nearest DWORD) 901 } 902 903 // Check Rx Status used space 904 UINT32 905 RxStatusUsedSpace ( 906 UINT32 Flags, 907 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 908 ) 909 { 910 UINT32 RxInf; 911 UINT32 UsedSpace; 912 913 // Get the amount of used space from information register 914 RxInf = Lan9118MmioRead32 (LAN9118_RX_FIFO_INF); 915 UsedSpace = (RxInf & RXFIFOINF_RXSUSED_MASK) >> 16; 916 917 return UsedSpace << 2; // Value in bytes 918 } 919 920 921 // Change the allocation of FIFOs 922 EFI_STATUS 923 ChangeFifoAllocation ( 924 IN UINT32 Flags, 925 IN OUT UINTN *TxDataSize OPTIONAL, 926 IN OUT UINTN *RxDataSize OPTIONAL, 927 IN OUT UINT32 *TxStatusSize OPTIONAL, 928 IN OUT UINT32 *RxStatusSize OPTIONAL, 929 IN OUT EFI_SIMPLE_NETWORK_PROTOCOL *Snp 930 ) 931 { 932 UINT32 HwConf; 933 UINT32 TxFifoOption; 934 935 // Check that desired sizes don't exceed limits 936 if (*TxDataSize > TX_FIFO_MAX_SIZE) 937 return EFI_INVALID_PARAMETER; 938 939 #if defined(RX_FIFO_MIN_SIZE) && defined(RX_FIFO_MAX_SIZE) 940 if (*RxDataSize > RX_FIFO_MAX_SIZE) { 941 return EFI_INVALID_PARAMETER; 942 } 943 #endif 944 945 if (Flags & ALLOC_USE_DEFAULT) { 946 return EFI_SUCCESS; 947 } 948 949 // If we use the FIFOs (always use this first) 950 if (Flags & ALLOC_USE_FIFOS) { 951 // Read the current value of allocation 952 HwConf = Lan9118MmioRead32 (LAN9118_HW_CFG); 953 TxFifoOption = (HwConf >> 16) & 0xF; 954 955 // Choose the correct size (always use larger than requested if possible) 956 if (*TxDataSize < TX_FIFO_MIN_SIZE) { 957 *TxDataSize = TX_FIFO_MIN_SIZE; 958 *RxDataSize = 13440; 959 *RxStatusSize = 896; 960 TxFifoOption = 2; 961 } else if ((*TxDataSize > TX_FIFO_MIN_SIZE) && (*TxDataSize <= 2560)) { 962 *TxDataSize = 2560; 963 *RxDataSize = 12480; 964 *RxStatusSize = 832; 965 TxFifoOption = 3; 966 } else if ((*TxDataSize > 2560) && (*TxDataSize <= 3584)) { 967 *TxDataSize = 3584; 968 *RxDataSize = 11520; 969 *RxStatusSize = 768; 970 TxFifoOption = 4; 971 } else if ((*TxDataSize > 3584) && (*TxDataSize <= 4608)) { // default option 972 *TxDataSize = 4608; 973 *RxDataSize = 10560; 974 *RxStatusSize = 704; 975 TxFifoOption = 5; 976 } else if ((*TxDataSize > 4608) && (*TxDataSize <= 5632)) { 977 *TxDataSize = 5632; 978 *RxDataSize = 9600; 979 *RxStatusSize = 640; 980 TxFifoOption = 6; 981 } else if ((*TxDataSize > 5632) && (*TxDataSize <= 6656)) { 982 *TxDataSize = 6656; 983 *RxDataSize = 8640; 984 *RxStatusSize = 576; 985 TxFifoOption = 7; 986 } else if ((*TxDataSize > 6656) && (*TxDataSize <= 7680)) { 987 *TxDataSize = 7680; 988 *RxDataSize = 7680; 989 *RxStatusSize = 512; 990 TxFifoOption = 8; 991 } else if ((*TxDataSize > 7680) && (*TxDataSize <= 8704)) { 992 *TxDataSize = 8704; 993 *RxDataSize = 6720; 994 *RxStatusSize = 448; 995 TxFifoOption = 9; 996 } else if ((*TxDataSize > 8704) && (*TxDataSize <= 9728)) { 997 *TxDataSize = 9728; 998 *RxDataSize = 5760; 999 *RxStatusSize = 384; 1000 TxFifoOption = 10; 1001 } else if ((*TxDataSize > 9728) && (*TxDataSize <= 10752)) { 1002 *TxDataSize = 10752; 1003 *RxDataSize = 4800; 1004 *RxStatusSize = 320; 1005 TxFifoOption = 11; 1006 } else if ((*TxDataSize > 10752) && (*TxDataSize <= 11776)) { 1007 *TxDataSize = 11776; 1008 *RxDataSize = 3840; 1009 *RxStatusSize = 256; 1010 TxFifoOption = 12; 1011 } else if ((*TxDataSize > 11776) && (*TxDataSize <= 12800)) { 1012 *TxDataSize = 12800; 1013 *RxDataSize = 2880; 1014 *RxStatusSize = 192; 1015 TxFifoOption = 13; 1016 } else if ((*TxDataSize > 12800) && (*TxDataSize <= 13824)) { 1017 *TxDataSize = 13824; 1018 *RxDataSize = 1920; 1019 *RxStatusSize = 128; 1020 TxFifoOption = 14; 1021 } 1022 } else { 1023 ASSERT(0); // Untested code path 1024 HwConf = 0; 1025 TxFifoOption = 0; 1026 } 1027 1028 // Do we need DMA? 1029 if (Flags & ALLOC_USE_DMA) { 1030 return EFI_UNSUPPORTED; // Unsupported as of now 1031 } 1032 // Clear and assign the new size option 1033 HwConf &= ~(0xF0000); 1034 HwConf |= ((TxFifoOption & 0xF) << 16); 1035 Lan9118MmioWrite32 (LAN9118_HW_CFG, HwConf); 1036 1037 return EFI_SUCCESS; 1038 } 1039