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 ((MmioRead32 (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 MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); 110 111 // Wait until CSR busy bit is cleared 112 while ((MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); 113 114 // Now read from data register to get read value 115 return MmioRead32 (LAN9118_MAC_CSR_DATA); 116 } 117 118 // Function to write to MAC indirect registers 119 UINT32 120 IndirectMACWrite32 ( 121 UINT32 Index, 122 UINT32 Value 123 ) 124 { 125 UINT32 ValueWritten; 126 UINT32 MacCSR; 127 128 // Check index is in the range 129 ASSERT(Index <= 12); 130 131 // Wait until CSR busy bit is cleared 132 while ((MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); 133 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); 138 139 // Now write the value to the register before issuing the write command 140 ValueWritten = MmioWrite32 (LAN9118_MAC_CSR_DATA, Value); 141 142 // Write the config to the register 143 MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR); 144 145 // Wait until CSR busy bit is cleared 146 while ((MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY); 147 148 return ValueWritten; 149 } 150 151 // Function to read from MII register (PHY Access) 152 UINT32 153 IndirectPHYRead32 ( 154 UINT32 Index 155 ) 156 { 157 UINT32 ValueRead; 158 UINT32 MiiAcc; 159 160 // Check it is a valid index 161 ASSERT(Index < 31); 162 163 // Wait for busy bit to clear 164 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 165 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; 171 172 // Now write this config to register 173 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC, MiiAcc & 0xFFFF); 174 175 // Wait for busy bit to clear 176 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 177 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 180 181 return ValueRead; 182 } 183 184 185 // Function to write to the MII register (PHY Access) 186 UINT32 187 IndirectPHYWrite32 ( 188 UINT32 Index, 189 UINT32 Value 190 ) 191 { 192 UINT32 MiiAcc; 193 UINT32 ValueWritten; 194 195 // Check it is a valid index 196 ASSERT(Index < 31); 197 198 // Wait for busy bit to clear 199 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 200 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; 206 207 // Write the desired value to the register first 208 ValueWritten = IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_DATA, (Value & 0xFFFF)); 209 210 // Now write the config to register 211 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC, MiiAcc & 0xFFFF); 212 213 // Wait for operation to terminate 214 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY); 215 216 return ValueWritten; 217 } 218 219 220 /* ---------------- EEPROM Operations ------------------ */ 221 222 223 // Function to read from EEPROM memory 224 UINT32 225 IndirectEEPROMRead32 ( 226 UINT32 Index 227 ) 228 { 229 UINT32 EepromCmd; 230 231 // Set the busy bit to ensure read will occur 232 EepromCmd = E2P_EPC_BUSY | E2P_EPC_CMD_READ; 233 234 // Set the index to access desired EEPROM memory location 235 EepromCmd |= E2P_EPC_ADDRESS(Index); 236 237 // Write to Eeprom command register 238 MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); 239 gBS->Stall (LAN9118_STALL); 240 241 // Wait until operation has completed 242 while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 243 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)); 247 return 0; 248 } 249 250 // Wait until operation has completed 251 while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 252 253 // Finally read the value 254 return MmioRead32 (LAN9118_E2P_DATA); 255 } 256 257 // Function to write to EEPROM memory 258 UINT32 259 IndirectEEPROMWrite32 ( 260 UINT32 Index, 261 UINT32 Value 262 ) 263 { 264 UINT32 ValueWritten; 265 UINT32 EepromCmd; 266 267 ValueWritten = 0; 268 269 // Read the EEPROM Command register 270 EepromCmd = MmioRead32 (LAN9118_E2P_CMD); 271 272 // Set the busy bit to ensure read will occur 273 EepromCmd |= ((UINT32)1 << 31); 274 275 // Set the EEPROM command to write(0b011) 276 EepromCmd &= ~(7 << 28); // Clear the command first 277 EepromCmd |= (3 << 28); // Write 011 278 279 // Set the index to access desired EEPROM memory location 280 EepromCmd |= (Index & 0xF); 281 282 // Write the value to the data register first 283 ValueWritten = MmioWrite32 (LAN9118_E2P_DATA, Value); 284 285 // Write to Eeprom command register 286 MmioWrite32 (LAN9118_E2P_CMD, EepromCmd); 287 gBS->Stall (LAN9118_STALL); 288 289 // Wait until operation has completed 290 while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 291 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)); 295 return 0; 296 } 297 298 // Wait until operation has completed 299 while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 300 301 return ValueWritten; 302 } 303 304 /* ---------------- General Operations ----------------- */ 305 306 VOID 307 Lan9118SetMacAddress ( 308 EFI_MAC_ADDRESS *Mac, 309 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 310 ) 311 { 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) 317 ); 318 319 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRH, 320 (UINT32)(Mac->Addr[4] & 0xFF) | 321 ((Mac->Addr[5] & 0xFF) << 8) 322 ); 323 } 324 325 VOID 326 Lan9118ReadMacAddress ( 327 OUT EFI_MAC_ADDRESS *MacAddress 328 ) 329 { 330 UINT32 MacAddrHighValue; 331 UINT32 MacAddrLowValue; 332 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); 337 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; 345 } 346 347 /* 348 * Power up the 9118 and find its MAC address. 349 * 350 * This operation can be carried out when the LAN9118 is in any power state 351 * 352 */ 353 EFI_STATUS 354 Lan9118Initialize ( 355 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp 356 ) 357 { 358 UINTN Timeout; 359 UINT64 DefaultMacAddress; 360 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); 366 } 367 368 // Check that device is active 369 Timeout = 20; 370 while ((MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_READY) == 0 && --Timeout) { 371 gBS->Stall (LAN9118_STALL); 372 } 373 if (!Timeout) { 374 return EFI_TIMEOUT; 375 } 376 377 // Check that EEPROM isn't active 378 Timeout = 20; 379 while ((MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY) && --Timeout){ 380 gBS->Stall (LAN9118_STALL); 381 } 382 if (!Timeout) { 383 return EFI_TIMEOUT; 384 } 385 386 // Check if a MAC address was loaded from EEPROM, and if it was, set it as the 387 // current address. 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")); 390 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); 394 } else { 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); 400 } 401 } else { 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); 405 } 406 407 // Clear and acknowledge interrupts 408 MmioWrite32 (LAN9118_INT_EN, 0); 409 MmioWrite32 (LAN9118_IRQ_CFG, 0); 410 MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); 411 412 // Do self tests here? 413 414 return EFI_SUCCESS; 415 } 416 417 418 // Perform software reset on the LAN9118 419 // Return 0 on success, -1 on error 420 EFI_STATUS 421 SoftReset ( 422 UINT32 Flags, 423 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 424 ) 425 { 426 UINT32 HwConf; 427 UINT32 ResetTime; 428 429 // Initialize variable 430 ResetTime = 0; 431 432 // Stop Rx and Tx 433 StopTx (STOP_TX_MAC | STOP_TX_CFG | STOP_TX_CLEAR, Snp); 434 StopRx (STOP_RX_CLEAR, Snp); // Clear receiver FIFO 435 436 // Issue the reset 437 HwConf = MmioRead32 (LAN9118_HW_CFG); 438 HwConf |= 1; 439 440 // Set the Must Be One (MBO) bit 441 if (((HwConf & HWCFG_MBO) >> 20) == 0) { 442 HwConf |= HWCFG_MBO; 443 } 444 445 // Check that EEPROM isn't active 446 while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 447 448 // Write the configuration 449 MmioWrite32 (LAN9118_HW_CFG, HwConf); 450 gBS->Stall (LAN9118_STALL); 451 452 // Wait for reset to complete 453 while (MmioRead32 (LAN9118_HW_CFG) & HWCFG_SRST) { 454 455 gBS->Stall (LAN9118_STALL); 456 ResetTime += 1; 457 458 // If time taken exceeds 100us, then there was an error condition 459 if (ResetTime > 1000) { 460 Snp->Mode->State = EfiSimpleNetworkStopped; 461 return EFI_TIMEOUT; 462 } 463 } 464 465 // Check that EEPROM isn't active 466 while (MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY); 467 468 // TODO we probably need to re-set the mac address here. 469 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); 475 } 476 477 // Do self tests here? 478 if (Flags & SOFT_RESET_SELF_TEST) { 479 480 } 481 482 return EFI_SUCCESS; 483 } 484 485 486 // Perform PHY software reset 487 EFI_STATUS 488 PhySoftReset ( 489 UINT32 Flags, 490 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 491 ) 492 { 493 UINT32 PmtCtrl = 0; 494 495 // PMT PHY reset takes precedence over BCR 496 if (Flags & PHY_RESET_PMT) { 497 PmtCtrl = MmioRead32 (LAN9118_PMT_CTRL); 498 PmtCtrl |= MPTCTRL_PHY_RST; 499 MmioWrite32 (LAN9118_PMT_CTRL,PmtCtrl); 500 501 // Wait for completion 502 while (MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PHY_RST) { 503 gBS->Stall (LAN9118_STALL); 504 } 505 // PHY Basic Control Register reset 506 } else if (Flags & PHY_RESET_BCR) { 507 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL, PHYCR_RESET); 508 509 // Wait for completion 510 while (IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL) & PHYCR_RESET) { 511 gBS->Stall (LAN9118_STALL); 512 } 513 } 514 515 // Clear and acknowledge all interrupts 516 if (Flags & PHY_SOFT_RESET_CLEAR_INT) { 517 MmioWrite32 (LAN9118_INT_EN, 0); 518 MmioWrite32 (LAN9118_IRQ_CFG, 0); 519 MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF); 520 } 521 522 return EFI_SUCCESS; 523 } 524 525 526 // Configure hardware for LAN9118 527 EFI_STATUS 528 ConfigureHardware ( 529 UINT32 Flags, 530 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 531 ) 532 { 533 UINT32 GpioConf; 534 535 // Check if we want to use LEDs on GPIO 536 if (Flags & HW_CONF_USE_LEDS) { 537 GpioConf = MmioRead32 (LAN9118_GPIO_CFG); 538 539 // Enable GPIO as LEDs and Config as Push-Pull driver 540 GpioConf |= GPIO_GPIO0_PUSH_PULL | GPIO_GPIO1_PUSH_PULL | GPIO_GPIO2_PUSH_PULL | 541 GPIO_LED1_ENABLE | GPIO_LED2_ENABLE | GPIO_LED3_ENABLE; 542 543 // Write the configuration 544 MmioWrite32 (LAN9118_GPIO_CFG, GpioConf); 545 gBS->Stall (LAN9118_STALL); 546 } 547 548 return EFI_SUCCESS; 549 } 550 551 // Configure flow control 552 EFI_STATUS 553 ConfigureFlow ( 554 UINT32 Flags, 555 UINT32 HighTrig, 556 UINT32 LowTrig, 557 UINT32 BPDuration, 558 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 559 ) 560 { 561 return EFI_SUCCESS; 562 } 563 564 // Do auto-negotiation 565 EFI_STATUS 566 AutoNegotiate ( 567 UINT32 Flags, 568 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 569 ) 570 { 571 UINT32 PhyControl; 572 UINT32 PhyStatus; 573 UINT32 Features; 574 UINT32 TimeOut; 575 576 // First check that auto-negotiation is supported 577 PhyStatus = IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS); 578 if ((PhyStatus & PHYSTS_AUTO_CAP) == 0) { 579 DEBUG ((EFI_D_ERROR, "Auto-negotiation not supported.\n")); 580 return EFI_DEVICE_ERROR; 581 } 582 583 // Check that link is up first 584 if ((PhyStatus & PHYSTS_LINK_STS) == 0) { 585 // Wait until it is up or until Time Out 586 TimeOut = 2000; 587 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS) & PHYSTS_LINK_STS) == 0) { 588 gBS->Stall (LAN9118_STALL); 589 TimeOut--; 590 if (!TimeOut) { 591 DEBUG ((EFI_D_ERROR, "Link timeout in auto-negotiation.\n")); 592 return EFI_TIMEOUT; 593 } 594 } 595 } 596 597 // Configure features to advertise 598 Features = IndirectPHYRead32 (PHY_INDEX_AUTO_NEG_ADVERT); 599 600 if ((Flags & AUTO_NEGOTIATE_ADVERTISE_ALL) > 0) { 601 // Link speed capabilities 602 Features |= (PHYANA_10BASET | PHYANA_10BASETFD | PHYANA_100BASETX | PHYANA_100BASETXFD); 603 604 // Pause frame capabilities 605 Features &= ~(PHYANA_PAUSE_OP_MASK); 606 Features |= 3 << 10; 607 } 608 609 // Write the features 610 IndirectPHYWrite32 (PHY_INDEX_AUTO_NEG_ADVERT, Features); 611 612 // Read control register 613 PhyControl = IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL); 614 615 // Enable Auto-Negotiation 616 if ((PhyControl & PHYCR_AUTO_EN) == 0) { 617 PhyControl |= PHYCR_AUTO_EN; 618 } 619 620 // Restart auto-negotiation 621 PhyControl |= PHYCR_RST_AUTO; 622 623 // Enable collision test if required to do so 624 if (Flags & AUTO_NEGOTIATE_COLLISION_TEST) { 625 PhyControl |= PHYCR_COLL_TEST; 626 } else { 627 PhyControl &= ~ PHYCR_COLL_TEST; 628 } 629 630 // Write this configuration 631 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL, PhyControl); 632 633 // Wait until process has completed 634 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS) & PHYSTS_AUTO_COMP) == 0); 635 636 return EFI_SUCCESS; 637 } 638 639 // Check the Link Status and take appropriate action 640 EFI_STATUS 641 CheckLinkStatus ( 642 UINT32 Flags, 643 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 644 ) 645 { 646 // Get the PHY Status 647 UINT32 PhyBStatus = IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS); 648 649 if (PhyBStatus & PHYSTS_LINK_STS) { 650 return EFI_SUCCESS; 651 } else { 652 return EFI_DEVICE_ERROR; 653 } 654 } 655 656 // Stop the transmitter 657 EFI_STATUS 658 StopTx ( 659 UINT32 Flags, 660 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 661 ) 662 { 663 UINT32 MacCsr; 664 UINT32 TxCfg; 665 666 MacCsr = 0; 667 TxCfg = 0; 668 669 // Check if we want to clear tx 670 if (Flags & STOP_TX_CLEAR) { 671 TxCfg = MmioRead32 (LAN9118_TX_CFG); 672 TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP; 673 MmioWrite32 (LAN9118_TX_CFG, TxCfg); 674 gBS->Stall (LAN9118_STALL); 675 } 676 677 // Check if already stopped 678 if (Flags & STOP_TX_MAC) { 679 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 680 681 if (MacCsr & MACCR_TX_EN) { 682 MacCsr &= ~MACCR_TX_EN; 683 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 684 } 685 } 686 687 if (Flags & STOP_TX_CFG) { 688 TxCfg = MmioRead32 (LAN9118_TX_CFG); 689 690 if (TxCfg & TXCFG_TX_ON) { 691 TxCfg |= TXCFG_STOP_TX; 692 MmioWrite32 (LAN9118_TX_CFG, TxCfg); 693 gBS->Stall (LAN9118_STALL); 694 695 // Wait for Tx to finish transmitting 696 while (MmioRead32 (LAN9118_TX_CFG) & TXCFG_STOP_TX); 697 } 698 } 699 700 return EFI_SUCCESS; 701 } 702 703 // Stop the receiver 704 EFI_STATUS 705 StopRx ( 706 UINT32 Flags, 707 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 708 ) 709 { 710 UINT32 MacCsr; 711 UINT32 RxCfg; 712 713 RxCfg = 0; 714 715 // Check if already stopped 716 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 717 718 if (MacCsr & MACCR_RX_EN) { 719 MacCsr &= ~ MACCR_RX_EN; 720 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 721 } 722 723 // Check if we want to clear receiver FIFOs 724 if (Flags & STOP_RX_CLEAR) { 725 RxCfg = MmioRead32 (LAN9118_RX_CFG); 726 RxCfg |= RXCFG_RX_DUMP; 727 MmioWrite32 (LAN9118_RX_CFG, RxCfg); 728 gBS->Stall (LAN9118_STALL); 729 730 while (MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); 731 } 732 733 return EFI_SUCCESS; 734 } 735 736 // Start the transmitter 737 EFI_STATUS 738 StartTx ( 739 UINT32 Flags, 740 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 741 ) 742 { 743 UINT32 MacCsr; 744 UINT32 TxCfg; 745 746 MacCsr = 0; 747 TxCfg = 0; 748 749 // Check if we want to clear tx 750 if (Flags & START_TX_CLEAR) { 751 TxCfg = MmioRead32 (LAN9118_TX_CFG); 752 TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP; 753 MmioWrite32 (LAN9118_TX_CFG, TxCfg); 754 gBS->Stall (LAN9118_STALL); 755 } 756 757 // Check if tx was started from MAC and enable if not 758 if (Flags & START_TX_MAC) { 759 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 760 gBS->Stall (LAN9118_STALL); 761 if ((MacCsr & MACCR_TX_EN) == 0) { 762 MacCsr |= MACCR_TX_EN; 763 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 764 gBS->Stall (LAN9118_STALL); 765 } 766 } 767 768 // Check if tx was started from TX_CFG and enable if not 769 if (Flags & START_TX_CFG) { 770 TxCfg = MmioRead32 (LAN9118_TX_CFG); 771 gBS->Stall (LAN9118_STALL); 772 if ((TxCfg & TXCFG_TX_ON) == 0) { 773 TxCfg |= TXCFG_TX_ON; 774 MmioWrite32 (LAN9118_TX_CFG, TxCfg); 775 gBS->Stall (LAN9118_STALL); 776 } 777 } 778 779 // Set the tx data trigger level 780 781 return EFI_SUCCESS; 782 } 783 784 // Start the receiver 785 EFI_STATUS 786 StartRx ( 787 UINT32 Flags, 788 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 789 ) 790 { 791 UINT32 MacCsr; 792 UINT32 RxCfg; 793 794 RxCfg = 0; 795 796 // Check if already started 797 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 798 799 if ((MacCsr & MACCR_RX_EN) == 0) { 800 // Check if we want to clear receiver FIFOs before starting 801 if (Flags & START_RX_CLEAR) { 802 RxCfg = MmioRead32 (LAN9118_RX_CFG); 803 RxCfg |= RXCFG_RX_DUMP; 804 MmioWrite32 (LAN9118_RX_CFG, RxCfg); 805 gBS->Stall (LAN9118_STALL); 806 807 while (MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP); 808 } 809 810 MacCsr |= MACCR_RX_EN; 811 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr); 812 gBS->Stall (LAN9118_STALL); 813 } 814 815 return EFI_SUCCESS; 816 } 817 818 // Check Tx Data available space 819 UINT32 820 TxDataFreeSpace ( 821 UINT32 Flags, 822 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 823 ) 824 { 825 UINT32 TxInf; 826 UINT32 FreeSpace; 827 828 // Get the amount of free space from information register 829 TxInf = MmioRead32 (LAN9118_TX_FIFO_INF); 830 FreeSpace = (TxInf & TXFIFOINF_TDFREE_MASK); 831 832 return FreeSpace; // Value in bytes 833 } 834 835 // Check Tx Status used space 836 UINT32 837 TxStatusUsedSpace ( 838 UINT32 Flags, 839 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 840 ) 841 { 842 UINT32 TxInf; 843 UINT32 UsedSpace; 844 845 // Get the amount of used space from information register 846 TxInf = MmioRead32 (LAN9118_TX_FIFO_INF); 847 UsedSpace = (TxInf & TXFIFOINF_TXSUSED_MASK) >> 16; 848 849 return UsedSpace << 2; // Value in bytes 850 } 851 852 // Check Rx Data used space 853 UINT32 854 RxDataUsedSpace ( 855 UINT32 Flags, 856 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 857 ) 858 { 859 UINT32 RxInf; 860 UINT32 UsedSpace; 861 862 // Get the amount of used space from information register 863 RxInf = MmioRead32 (LAN9118_RX_FIFO_INF); 864 UsedSpace = (RxInf & RXFIFOINF_RXDUSED_MASK); 865 866 return UsedSpace; // Value in bytes (rounded up to nearest DWORD) 867 } 868 869 // Check Rx Status used space 870 UINT32 871 RxStatusUsedSpace ( 872 UINT32 Flags, 873 EFI_SIMPLE_NETWORK_PROTOCOL *Snp 874 ) 875 { 876 UINT32 RxInf; 877 UINT32 UsedSpace; 878 879 // Get the amount of used space from information register 880 RxInf = MmioRead32 (LAN9118_RX_FIFO_INF); 881 UsedSpace = (RxInf & RXFIFOINF_RXSUSED_MASK) >> 16; 882 883 return UsedSpace << 2; // Value in bytes 884 } 885 886 887 // Change the allocation of FIFOs 888 EFI_STATUS 889 ChangeFifoAllocation ( 890 IN UINT32 Flags, 891 IN OUT UINTN *TxDataSize OPTIONAL, 892 IN OUT UINTN *RxDataSize OPTIONAL, 893 IN OUT UINT32 *TxStatusSize OPTIONAL, 894 IN OUT UINT32 *RxStatusSize OPTIONAL, 895 IN OUT EFI_SIMPLE_NETWORK_PROTOCOL *Snp 896 ) 897 { 898 UINT32 HwConf; 899 UINT32 TxFifoOption; 900 901 // Check that desired sizes don't exceed limits 902 if (*TxDataSize > TX_FIFO_MAX_SIZE) 903 return EFI_INVALID_PARAMETER; 904 905 #if defined(RX_FIFO_MIN_SIZE) && defined(RX_FIFO_MAX_SIZE) 906 if (*RxDataSize > RX_FIFO_MAX_SIZE) { 907 return EFI_INVALID_PARAMETER; 908 } 909 #endif 910 911 if (Flags & ALLOC_USE_DEFAULT) { 912 return EFI_SUCCESS; 913 } 914 915 // If we use the FIFOs (always use this first) 916 if (Flags & ALLOC_USE_FIFOS) { 917 // Read the current value of allocation 918 HwConf = MmioRead32 (LAN9118_HW_CFG); 919 TxFifoOption = (HwConf >> 16) & 0xF; 920 921 // Choose the correct size (always use larger than requested if possible) 922 if (*TxDataSize < TX_FIFO_MIN_SIZE) { 923 *TxDataSize = TX_FIFO_MIN_SIZE; 924 *RxDataSize = 13440; 925 *RxStatusSize = 896; 926 TxFifoOption = 2; 927 } else if ((*TxDataSize > TX_FIFO_MIN_SIZE) && (*TxDataSize <= 2560)) { 928 *TxDataSize = 2560; 929 *RxDataSize = 12480; 930 *RxStatusSize = 832; 931 TxFifoOption = 3; 932 } else if ((*TxDataSize > 2560) && (*TxDataSize <= 3584)) { 933 *TxDataSize = 3584; 934 *RxDataSize = 11520; 935 *RxStatusSize = 768; 936 TxFifoOption = 4; 937 } else if ((*TxDataSize > 3584) && (*TxDataSize <= 4608)) { // default option 938 *TxDataSize = 4608; 939 *RxDataSize = 10560; 940 *RxStatusSize = 704; 941 TxFifoOption = 5; 942 } else if ((*TxDataSize > 4608) && (*TxDataSize <= 5632)) { 943 *TxDataSize = 5632; 944 *RxDataSize = 9600; 945 *RxStatusSize = 640; 946 TxFifoOption = 6; 947 } else if ((*TxDataSize > 5632) && (*TxDataSize <= 6656)) { 948 *TxDataSize = 6656; 949 *RxDataSize = 8640; 950 *RxStatusSize = 576; 951 TxFifoOption = 7; 952 } else if ((*TxDataSize > 6656) && (*TxDataSize <= 7680)) { 953 *TxDataSize = 7680; 954 *RxDataSize = 7680; 955 *RxStatusSize = 512; 956 TxFifoOption = 8; 957 } else if ((*TxDataSize > 7680) && (*TxDataSize <= 8704)) { 958 *TxDataSize = 8704; 959 *RxDataSize = 6720; 960 *RxStatusSize = 448; 961 TxFifoOption = 9; 962 } else if ((*TxDataSize > 8704) && (*TxDataSize <= 9728)) { 963 *TxDataSize = 9728; 964 *RxDataSize = 5760; 965 *RxStatusSize = 384; 966 TxFifoOption = 10; 967 } else if ((*TxDataSize > 9728) && (*TxDataSize <= 10752)) { 968 *TxDataSize = 10752; 969 *RxDataSize = 4800; 970 *RxStatusSize = 320; 971 TxFifoOption = 11; 972 } else if ((*TxDataSize > 10752) && (*TxDataSize <= 11776)) { 973 *TxDataSize = 11776; 974 *RxDataSize = 3840; 975 *RxStatusSize = 256; 976 TxFifoOption = 12; 977 } else if ((*TxDataSize > 11776) && (*TxDataSize <= 12800)) { 978 *TxDataSize = 12800; 979 *RxDataSize = 2880; 980 *RxStatusSize = 192; 981 TxFifoOption = 13; 982 } else if ((*TxDataSize > 12800) && (*TxDataSize <= 13824)) { 983 *TxDataSize = 13824; 984 *RxDataSize = 1920; 985 *RxStatusSize = 128; 986 TxFifoOption = 14; 987 } 988 } else { 989 ASSERT(0); // Untested code path 990 HwConf = 0; 991 TxFifoOption = 0; 992 } 993 994 // Do we need DMA? 995 if (Flags & ALLOC_USE_DMA) { 996 return EFI_UNSUPPORTED; // Unsupported as of now 997 } 998 // Clear and assign the new size option 999 HwConf &= ~(0xF0000); 1000 HwConf |= ((TxFifoOption & 0xF) << 16); 1001 MmioWrite32 (LAN9118_HW_CFG, HwConf); 1002 gBS->Stall (LAN9118_STALL); 1003 1004 return EFI_SUCCESS; 1005 } 1006