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 typedef struct { 18 MAC_ADDR_DEVICE_PATH Lan9118; 19 EFI_DEVICE_PATH_PROTOCOL End; 20 } LAN9118_DEVICE_PATH; 21 22 LAN9118_DEVICE_PATH Lan9118PathTemplate = { 23 { 24 { 25 MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, 26 { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) } 27 }, 28 { { 0 } }, 29 0 30 }, 31 { 32 END_DEVICE_PATH_TYPE, 33 END_ENTIRE_DEVICE_PATH_SUBTYPE, 34 { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 } 35 } 36 }; 37 38 /* 39 ** Entry point for the LAN9118 driver 40 ** 41 */ 42 EFI_STATUS 43 Lan9118DxeEntry ( 44 IN EFI_HANDLE Handle, 45 IN EFI_SYSTEM_TABLE *SystemTable 46 ) 47 { 48 EFI_STATUS Status; 49 LAN9118_DRIVER *LanDriver; 50 EFI_SIMPLE_NETWORK_PROTOCOL *Snp; 51 EFI_SIMPLE_NETWORK_MODE *SnpMode; 52 LAN9118_DEVICE_PATH *Lan9118Path; 53 EFI_HANDLE ControllerHandle; 54 55 // The PcdLan9118DxeBaseAddress PCD must be defined 56 ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress) != 0); 57 58 // Allocate Resources 59 LanDriver = AllocateZeroPool (sizeof (LAN9118_DRIVER)); 60 if (LanDriver == NULL) { 61 return EFI_OUT_OF_RESOURCES; 62 } 63 Lan9118Path = (LAN9118_DEVICE_PATH*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH), &Lan9118PathTemplate); 64 if (Lan9118Path == NULL) { 65 return EFI_OUT_OF_RESOURCES; 66 } 67 68 // Initialize pointers 69 Snp = &(LanDriver->Snp); 70 SnpMode = &(LanDriver->SnpMode); 71 Snp->Mode = SnpMode; 72 73 // Set the signature of the LAN Driver structure 74 LanDriver->Signature = LAN9118_SIGNATURE; 75 76 // Assign fields and func pointers 77 Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; 78 Snp->WaitForPacket = NULL; 79 Snp->Initialize = SnpInitialize; 80 Snp->Start = SnpStart; 81 Snp->Stop = SnpStop; 82 Snp->Reset = SnpReset; 83 Snp->Shutdown = SnpShutdown; 84 Snp->ReceiveFilters = SnpReceiveFilters; 85 Snp->StationAddress = SnpStationAddress; 86 Snp->Statistics = SnpStatistics; 87 Snp->MCastIpToMac = SnpMcastIptoMac; 88 Snp->NvData = SnpNvData; 89 Snp->GetStatus = SnpGetStatus; 90 Snp->Transmit = SnpTransmit; 91 Snp->Receive = SnpReceive; 92 93 // Start completing simple network mode structure 94 SnpMode->State = EfiSimpleNetworkStopped; 95 SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes 96 SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this 97 SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes) 98 SnpMode->NvRamSize = 0; // No NVRAM with this device 99 SnpMode->NvRamAccessSize = 0; // No NVRAM with this device 100 101 // 102 // Claim that all receive filter settings are supported, though the MULTICAST mode 103 // is not completely supported. The LAN9118 Ethernet controller is only able to 104 // do a "hash filtering" and not a perfect filtering on multicast addresses. The 105 // controller does not filter the multicast addresses directly but a hash value 106 // of them. The hash value of a multicast address is derived from its CRC and 107 // ranges from 0 to 63 included. 108 // We claim that the perfect MULTICAST filtering mode is supported because 109 // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode 110 // and thus not being able to take advantage of the hash filtering. 111 // 112 SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | 113 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | 114 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | 115 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | 116 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; 117 118 // We do not intend to receive anything for the time being. 119 SnpMode->ReceiveFilterSetting = 0; 120 121 // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses 122 SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT; 123 SnpMode->MCastFilterCount = 0; 124 ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS)); 125 126 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks) 127 SnpMode->IfType = NET_IFTYPE_ETHERNET; 128 129 // Mac address is changeable as it is loaded from erasable memory 130 SnpMode->MacAddressChangeable = TRUE; 131 132 // Can only transmit one packet at a time 133 SnpMode->MultipleTxSupported = FALSE; 134 135 // MediaPresent checks for cable connection and partner link 136 SnpMode->MediaPresentSupported = TRUE; 137 SnpMode->MediaPresent = FALSE; 138 139 // Set broadcast address 140 SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF); 141 142 // Power up the device so we can find the MAC address 143 Status = Lan9118Initialize (Snp); 144 if (EFI_ERROR (Status)) { 145 DEBUG ((EFI_D_ERROR, "Lan9118: Error initialising hardware\n")); 146 return EFI_DEVICE_ERROR; 147 } 148 149 // Assign fields for device path 150 CopyMem (&Lan9118Path->Lan9118.MacAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN); 151 Lan9118Path->Lan9118.IfType = Snp->Mode->IfType; 152 153 // Initialise the protocol 154 ControllerHandle = NULL; 155 Status = gBS->InstallMultipleProtocolInterfaces ( 156 &ControllerHandle, 157 &gEfiSimpleNetworkProtocolGuid, Snp, 158 &gEfiDevicePathProtocolGuid, Lan9118Path, 159 NULL 160 ); 161 // Say what the status of loading the protocol structure is 162 if (EFI_ERROR(Status)) { 163 FreePool (LanDriver); 164 } else { 165 LanDriver->ControllerHandle = ControllerHandle; 166 } 167 168 return Status; 169 } 170 171 /* 172 * UEFI Start() function 173 * 174 * Parameters: 175 * 176 * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance. 177 * 178 * Description: 179 * 180 * This function starts a network interface. If the network interface successfully starts, then 181 * EFI_SUCCESS will be returned. 182 */ 183 EFI_STATUS 184 EFIAPI 185 SnpStart ( 186 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp 187 ) 188 { 189 // Check Snp instance 190 if (Snp == NULL) { 191 return EFI_INVALID_PARAMETER; 192 } 193 194 // Check state 195 if ((Snp->Mode->State == EfiSimpleNetworkStarted) || 196 (Snp->Mode->State == EfiSimpleNetworkInitialized) ) { 197 return EFI_ALREADY_STARTED; 198 } 199 200 // Change state 201 Snp->Mode->State = EfiSimpleNetworkStarted; 202 return EFI_SUCCESS; 203 } 204 205 /* 206 * UEFI Stop() function 207 * 208 */ 209 EFI_STATUS 210 EFIAPI 211 SnpStop ( 212 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp 213 ) 214 { 215 // Check Snp Instance 216 if (Snp == NULL) { 217 return EFI_INVALID_PARAMETER; 218 } 219 220 // Check state of the driver 221 if (Snp->Mode->State == EfiSimpleNetworkStopped) { 222 return EFI_NOT_STARTED; 223 } 224 225 // Stop the Tx and Rx 226 StopTx (STOP_TX_CFG | STOP_TX_MAC, Snp); 227 StopRx (0, Snp); 228 229 // Change the state 230 switch (Snp->Mode->State) { 231 case EfiSimpleNetworkStarted: 232 case EfiSimpleNetworkInitialized: 233 Snp->Mode->State = EfiSimpleNetworkStopped; 234 break; 235 default: 236 return EFI_DEVICE_ERROR; 237 } 238 239 // Put the device into a power saving mode ? 240 return EFI_SUCCESS; 241 } 242 243 244 // Allocated receive and transmit buffers 245 STATIC UINT32 gTxBuffer = 0; 246 247 /* 248 * UEFI Initialize() function 249 * 250 */ 251 EFI_STATUS 252 EFIAPI 253 SnpInitialize ( 254 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp, 255 IN UINTN RxBufferSize OPTIONAL, 256 IN UINTN TxBufferSize OPTIONAL 257 ) 258 { 259 EFI_STATUS Status; 260 UINT32 PmConf; 261 INT32 AllocResult; 262 UINT32 RxStatusSize; 263 UINT32 TxStatusSize; 264 265 // Initialize variables 266 // Global variables to hold tx and rx FIFO allocation 267 gTxBuffer = 0; 268 269 // Check Snp Instance 270 if (Snp == NULL) { 271 return EFI_INVALID_PARAMETER; 272 } 273 274 // First check that driver has not already been initialized 275 if (Snp->Mode->State == EfiSimpleNetworkInitialized) { 276 DEBUG ((EFI_D_WARN, "LAN9118 Driver already initialized\n")); 277 return EFI_SUCCESS; 278 } else 279 if (Snp->Mode->State == EfiSimpleNetworkStopped) { 280 DEBUG ((EFI_D_WARN, "LAN9118 Driver not started\n")); 281 return EFI_NOT_STARTED; 282 } 283 284 // Initiate a PHY reset 285 Status = PhySoftReset (PHY_RESET_PMT, Snp); 286 if (EFI_ERROR (Status)) { 287 Snp->Mode->State = EfiSimpleNetworkStopped; 288 DEBUG ((EFI_D_WARN, "Warning: Link not ready after TimeOut. Check ethernet cable\n")); 289 return EFI_NOT_STARTED; 290 } 291 292 // Initiate a software reset 293 Status = SoftReset (0, Snp); 294 if (EFI_ERROR(Status)) { 295 DEBUG ((EFI_D_WARN, "Soft Reset Failed: Hardware Error\n")); 296 return EFI_DEVICE_ERROR; 297 } 298 299 // Read the PM register 300 PmConf = MmioRead32 (LAN9118_PMT_CTRL); 301 302 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets 303 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode 304 // MPTCTRL_PME_EN: Allow Power Management Events 305 PmConf = 0; 306 PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN); 307 308 // Write the current configuration to the register 309 MmioWrite32 (LAN9118_PMT_CTRL, PmConf); 310 gBS->Stall (LAN9118_STALL); 311 gBS->Stall (LAN9118_STALL); 312 313 // Configure GPIO and HW 314 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp); 315 if (EFI_ERROR(Status)) { 316 return Status; 317 } 318 319 // Assign the transmitter buffer size (default values) 320 TxStatusSize = LAN9118_TX_STATUS_SIZE; 321 RxStatusSize = LAN9118_RX_STATUS_SIZE; 322 323 // Check that a buff size was specified 324 if (TxBufferSize > 0) { 325 if (RxBufferSize == 0) { 326 RxBufferSize = LAN9118_RX_DATA_SIZE; 327 } 328 329 AllocResult = ChangeFifoAllocation ( 330 ALLOC_USE_FIFOS, 331 &TxBufferSize, 332 &RxBufferSize, 333 &TxStatusSize, 334 &RxStatusSize, 335 Snp 336 ); 337 338 if (AllocResult < 0) { 339 return EFI_OUT_OF_RESOURCES; 340 } 341 } 342 343 // Do auto-negotiation if supported 344 Status = AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL, Snp); 345 if (EFI_ERROR(Status)) { 346 DEBUG ((EFI_D_WARN, "Lan9118: Auto Negociation not supported.\n")); 347 } 348 349 // Configure flow control depending on speed capabilities 350 Status = ConfigureFlow (0, 0, 0, 0, Snp); 351 if (EFI_ERROR(Status)) { 352 return Status; 353 } 354 355 // Enable the transmitter 356 Status = StartTx (START_TX_MAC | START_TX_CFG, Snp); 357 if (EFI_ERROR(Status)) { 358 return Status; 359 } 360 361 // Now acknowledge all interrupts 362 MmioWrite32 (LAN9118_INT_STS, ~0); 363 364 // Declare the driver as initialized 365 Snp->Mode->State = EfiSimpleNetworkInitialized; 366 367 return Status; 368 } 369 370 /* 371 * UEFI Reset () function 372 * 373 */ 374 EFI_STATUS 375 EFIAPI 376 SnpReset ( 377 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp, 378 IN BOOLEAN Verification 379 ) 380 { 381 UINT32 PmConf; 382 UINT32 HwConf; 383 UINT32 ResetFlags; 384 EFI_STATUS Status; 385 386 PmConf = 0; 387 HwConf = 0; 388 ResetFlags = 0; 389 390 // Check Snp Instance 391 if (Snp == NULL) { 392 return EFI_INVALID_PARAMETER; 393 } 394 395 // First check that driver has not already been initialized 396 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 397 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not yet initialized\n")); 398 return EFI_DEVICE_ERROR; 399 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 400 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not started\n")); 401 return EFI_NOT_STARTED; 402 } 403 404 // Initiate a PHY reset 405 Status = PhySoftReset (PHY_RESET_PMT, Snp); 406 if (EFI_ERROR (Status)) { 407 Snp->Mode->State = EfiSimpleNetworkStopped; 408 return EFI_NOT_STARTED; 409 } 410 411 // Initiate a software reset 412 ResetFlags |= SOFT_RESET_CHECK_MAC_ADDR_LOAD | SOFT_RESET_CLEAR_INT; 413 414 if (Verification) { 415 ResetFlags |= SOFT_RESET_SELF_TEST; 416 } 417 418 Status = SoftReset (ResetFlags, Snp); 419 if (EFI_ERROR (Status)) { 420 DEBUG ((EFI_D_WARN, "Warning: Soft Reset Failed: Hardware Error\n")); 421 return EFI_DEVICE_ERROR; 422 } 423 424 // Read the PM register 425 PmConf = MmioRead32 (LAN9118_PMT_CTRL); 426 427 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets 428 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode 429 // MPTCTRL_PME_EN: Allow Power Management Events 430 PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN); 431 432 // Write the current configuration to the register 433 MmioWrite32 (LAN9118_PMT_CTRL, PmConf); 434 gBS->Stall (LAN9118_STALL); 435 436 // Reactivate the LEDs 437 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp); 438 if (EFI_ERROR (Status)) { 439 return Status; 440 } 441 442 // Check that a buffer size was specified in SnpInitialize 443 if (gTxBuffer != 0) { 444 HwConf = MmioRead32 (LAN9118_HW_CFG); // Read the HW register 445 HwConf &= ~HW_CFG_TX_FIFO_SIZE_MASK; // Clear buffer bits first 446 HwConf |= HW_CFG_TX_FIFO_SIZE(gTxBuffer); // assign size chosen in SnpInitialize 447 448 MmioWrite32 (LAN9118_HW_CFG, HwConf); // Write the conf 449 gBS->Stall (LAN9118_STALL); 450 } 451 452 // Enable the receiver and transmitter and clear their contents 453 StartRx (START_RX_CLEAR, Snp); 454 StartTx (START_TX_MAC | START_TX_CFG | START_TX_CLEAR, Snp); 455 456 // Now acknowledge all interrupts 457 MmioWrite32 (LAN9118_INT_STS, ~0); 458 459 return EFI_SUCCESS; 460 } 461 462 /* 463 * UEFI Shutdown () function 464 * 465 */ 466 EFI_STATUS 467 EFIAPI 468 SnpShutdown ( 469 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp 470 ) 471 { 472 EFI_STATUS Status; 473 474 // Check Snp Instance 475 if (Snp == NULL) { 476 return EFI_INVALID_PARAMETER; 477 } 478 479 // First check that driver has not already been initialized 480 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 481 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not yet initialized\n")); 482 return EFI_DEVICE_ERROR; 483 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 484 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not started\n")); 485 return EFI_NOT_STARTED; 486 } 487 488 // Initiate a PHY reset 489 Status = PhySoftReset (PHY_RESET_PMT, Snp); 490 if (EFI_ERROR (Status)) { 491 return Status; 492 } 493 494 // Initiate a software reset 495 Status = SoftReset (0, Snp); 496 if (EFI_ERROR (Status)) { 497 DEBUG ((EFI_D_WARN, "Warning: Soft Reset Failed: Hardware Error\n")); 498 return Status; 499 } 500 501 // Back to the started and thus not initialized state 502 Snp->Mode->State = EfiSimpleNetworkStarted; 503 504 return EFI_SUCCESS; 505 } 506 507 /** 508 Enable and/or disable the receive filters of the LAN9118 509 510 Please refer to the UEFI specification for the precedence rules among the 511 Enable, Disable and ResetMCastFilter parameters. 512 513 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL 514 instance. 515 @param[in] Enable A bit mask of receive filters to enable. 516 @param[in] Disable A bit mask of receive filters to disable. 517 @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast 518 receive filters on the network interface to 519 their default values. 520 @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new 521 MCastFilter list. This value must be less than or 522 equal to the MCastFilterCnt field of 523 EFI_SIMPLE_NETWORK_MODE. This field is optional if 524 ResetMCastFilter is TRUE. 525 @param[in] MCastFilter A pointer to a list of new multicast receive 526 filter HW MAC addresses. This list will replace 527 any existing multicast HW MAC address list. This 528 field is optional if ResetMCastFilter is TRUE. 529 530 @retval EFI_SUCCESS The receive filters of the LAN9118 were updated. 531 @retval EFI_NOT_STARTED The LAN9118 has not been started. 532 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE : 533 . This is NULL 534 . Multicast is being enabled (the 535 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in 536 Enable, it is not set in Disable, and ResetMCastFilter 537 is FALSE) and MCastFilterCount is zero. 538 . Multicast is being enabled and MCastFilterCount is 539 greater than Snp->Mode->MaxMCastFilterCount. 540 . Multicast is being enabled and MCastFilter is NULL 541 . Multicast is being enabled and one or more of the 542 addresses in the MCastFilter list are not valid 543 multicast MAC addresses. 544 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized. 545 546 **/ 547 EFI_STATUS 548 EFIAPI 549 SnpReceiveFilters ( 550 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp, 551 IN UINT32 Enable, 552 IN UINT32 Disable, 553 IN BOOLEAN ResetMCastFilter, 554 IN UINTN MCastFilterCnt OPTIONAL, 555 IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL 556 ) 557 { 558 EFI_SIMPLE_NETWORK_MODE *Mode; 559 UINT32 MultHashTableHigh; 560 UINT32 MultHashTableLow; 561 UINT32 Count; 562 UINT32 Crc; 563 UINT8 HashValue; 564 UINT32 MacCSRValue; 565 UINT32 ReceiveFilterSetting; 566 EFI_MAC_ADDRESS *Mac; 567 EFI_MAC_ADDRESS ZeroMac; 568 569 // Check Snp Instance 570 if (Snp == NULL) { 571 return EFI_INVALID_PARAMETER; 572 } 573 Mode = Snp->Mode; 574 575 // Check that driver was started and initialised 576 if (Mode->State == EfiSimpleNetworkStarted) { 577 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n")); 578 return EFI_DEVICE_ERROR; 579 } else if (Mode->State == EfiSimpleNetworkStopped) { 580 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n")); 581 return EFI_NOT_STARTED; 582 } 583 584 if ((Enable & (~Mode->ReceiveFilterMask)) || 585 (Disable & (~Mode->ReceiveFilterMask)) ) { 586 return EFI_INVALID_PARAMETER; 587 } 588 589 // 590 // Check the validity of the multicast setting and compute the 591 // hash values of the multicast mac addresses to listen to. 592 // 593 594 MultHashTableHigh = 0; 595 MultHashTableLow = 0; 596 if ((!ResetMCastFilter) && 597 ((Disable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) == 0) && 598 ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) ) { 599 if ((MCastFilterCnt == 0) || 600 (MCastFilterCnt > Mode->MaxMCastFilterCount) || 601 (MCastFilter == NULL) ) { 602 return EFI_INVALID_PARAMETER; 603 } 604 // 605 // Check the validity of all multicast addresses before to change 606 // anything. 607 // 608 for (Count = 0; Count < MCastFilterCnt; Count++) { 609 if ((MCastFilter[Count].Addr[0] & 1) == 0) { 610 return EFI_INVALID_PARAMETER; 611 } 612 } 613 614 // 615 // Go through each filter address and set appropriate bits on hash table 616 // 617 for (Count = 0; Count < MCastFilterCnt; Count++) { 618 Mac = &(MCastFilter[Count]); 619 CopyMem (&Mode->MCastFilter[Count], Mac, sizeof(EFI_MAC_ADDRESS)); 620 621 Crc = GenEtherCrc32 (Mac, NET_ETHER_ADDR_LEN); 622 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired 623 624 // 625 // The most significant 6 bits of the MAC address CRC constitute the hash 626 // value of the MAC address. 627 // 628 HashValue = (Crc >> 26) & 0x3F; 629 630 // Select hashlow register if MSB is not set 631 if ((HashValue & 0x20) == 0) { 632 MultHashTableLow |= (1 << HashValue); 633 } else { 634 MultHashTableHigh |= (1 << (HashValue & 0x1F)); 635 } 636 } 637 Mode->MCastFilterCount = MCastFilterCnt; 638 } else if (ResetMCastFilter) { 639 Mode->MCastFilterCount = 0; 640 } else { 641 MultHashTableLow = IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL); 642 MultHashTableHigh = IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH); 643 } 644 645 // 646 // Before to change anything, stop and reset the reception of 647 // packets. 648 // 649 StopRx (STOP_RX_CLEAR, Snp); 650 651 // 652 // Write the mask of the selected hash values for the multicast filtering. 653 // The two masks are set to zero if the multicast filtering is not enabled. 654 // 655 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL, MultHashTableLow); 656 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH, MultHashTableHigh); 657 658 ReceiveFilterSetting = (Mode->ReceiveFilterSetting | Enable) & (~Disable); 659 660 // 661 // Read MAC controller 662 // 663 MacCSRValue = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR); 664 MacCSRValue &= ~(MACCR_HPFILT | MACCR_BCAST | MACCR_PRMS | MACCR_MCPAS); 665 666 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) { 667 Lan9118SetMacAddress (&Mode->CurrentAddress, Snp); 668 DEBUG ((DEBUG_NET, "Allowing Unicast Frame Reception\n")); 669 } else { 670 // 671 // The Unicast packets do not have to be listen to, set the MAC 672 // address of the LAN9118 to be the "not configured" all zeroes 673 // ethernet MAC address. 674 // 675 ZeroMem (&ZeroMac, NET_ETHER_ADDR_LEN); 676 Lan9118SetMacAddress (&ZeroMac, Snp); 677 } 678 679 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) { 680 MacCSRValue |= MACCR_HPFILT; 681 DEBUG ((DEBUG_NET, "Allowing Multicast Frame Reception\n")); 682 } 683 684 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) { 685 MacCSRValue |= MACCR_MCPAS; 686 DEBUG ((DEBUG_NET, "Enabling Promiscuous Multicast Mode\n")); 687 } 688 689 if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) == 0) { 690 MacCSRValue |= MACCR_BCAST; 691 } else { 692 DEBUG ((DEBUG_NET, "Allowing Broadcast Frame Reception\n")); 693 } 694 695 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) { 696 MacCSRValue |= MACCR_PRMS; 697 DEBUG ((DEBUG_NET, "Enabling Promiscuous Mode\n")); 698 } 699 700 // 701 // Write the options to the MAC_CSR 702 // 703 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCSRValue); 704 gBS->Stall (LAN9118_STALL); 705 706 // 707 // If we have to retrieve something, start packet reception. 708 // 709 Mode->ReceiveFilterSetting = ReceiveFilterSetting; 710 if (ReceiveFilterSetting != 0) { 711 StartRx (0, Snp); 712 } 713 714 return EFI_SUCCESS; 715 } 716 717 /** 718 Modify of reset the current station address 719 720 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL 721 instance. 722 @param[in] Reset Flag used to reset the station address to the 723 LAN9118's permanent address. 724 @param[in] New New station address to be used for the network interface. 725 726 @retval EFI_SUCCESS The LAN9118's station address was updated. 727 @retval EFI_NOT_STARTED The LAN9118 has not been started. 728 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE : 729 . The "New" station address is invalid. 730 . "Reset" is FALSE and "New" is NULL. 731 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized. 732 733 **/ 734 EFI_STATUS 735 EFIAPI 736 SnpStationAddress ( 737 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp, 738 IN BOOLEAN Reset, 739 IN EFI_MAC_ADDRESS *New 740 ) 741 { 742 UINT32 Count; 743 UINT8 PermAddr[NET_ETHER_ADDR_LEN]; 744 745 DEBUG ((DEBUG_NET, "SnpStationAddress()\n")); 746 747 // Check Snp instance 748 if (Snp == NULL) { 749 return EFI_INVALID_PARAMETER; 750 } 751 752 // Check that driver was started and initialised 753 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 754 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n")); 755 return EFI_DEVICE_ERROR; 756 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 757 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n")); 758 return EFI_NOT_STARTED; 759 } 760 761 // Get the Permanent MAC address if need reset 762 if (Reset) { 763 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0 764 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM) { 765 for (Count = 0; Count < NET_ETHER_ADDR_LEN; Count++) { 766 PermAddr[Count] = IndirectEEPROMRead32 (Count + 1); 767 } 768 New = (EFI_MAC_ADDRESS *) PermAddr; 769 Lan9118SetMacAddress ((EFI_MAC_ADDRESS *) PermAddr, Snp); 770 } else { 771 DEBUG ((EFI_D_ERROR, "Lan9118: Warning: No valid MAC address in EEPROM, using fallback\n")); 772 New = (EFI_MAC_ADDRESS*) (FixedPcdGet64 (PcdLan9118DefaultMacAddress)); 773 } 774 } else { 775 // Otherwise use the specified new MAC address 776 if (New == NULL) { 777 return EFI_INVALID_PARAMETER; 778 } 779 // 780 // If it is a multicast address, it is not valid. 781 // 782 if (New->Addr[0] & 0x01) { 783 return EFI_INVALID_PARAMETER; 784 } 785 } 786 787 CopyMem (&Snp->Mode->CurrentAddress, New, NET_ETHER_ADDR_LEN); 788 789 // 790 // If packet reception is currently activated, stop and reset it, 791 // set the new ethernet address and restart the packet reception. 792 // Otherwise, nothing to do, the MAC address will be updated in 793 // SnpReceiveFilters() when the UNICAST packet reception will be 794 // activated. 795 // 796 if (Snp->Mode->ReceiveFilterSetting != 0) { 797 StopRx (STOP_RX_CLEAR, Snp); 798 Lan9118SetMacAddress (New, Snp); 799 StartRx (0, Snp); 800 } 801 802 return EFI_SUCCESS; 803 } 804 805 /* 806 * UEFI Statistics() function 807 * 808 */ 809 EFI_STATUS 810 EFIAPI 811 SnpStatistics ( 812 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp, 813 IN BOOLEAN Reset, 814 IN OUT UINTN *StatSize, 815 OUT EFI_NETWORK_STATISTICS *Statistics 816 ) 817 { 818 LAN9118_DRIVER *LanDriver; 819 EFI_STATUS Status; 820 821 LanDriver = INSTANCE_FROM_SNP_THIS (Snp); 822 823 DEBUG ((DEBUG_NET, "SnpStatistics()\n")); 824 825 // Check Snp instance 826 if (Snp == NULL) { 827 return EFI_INVALID_PARAMETER; 828 } 829 830 // Check that driver was started and initialised 831 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 832 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n")); 833 return EFI_DEVICE_ERROR; 834 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 835 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n")); 836 return EFI_NOT_STARTED; 837 } 838 839 // 840 // Do a reset if required. It is not clearly stated in the UEFI specification 841 // whether the reset has to be done before to copy the statistics in "Statictics" 842 // or after. It is a bit strange to do it before but that is what is expected by 843 // the SCT test on Statistics() with reset : "0x3de76704,0x4bf5,0x42cd,0x8c,0x89, 844 // 0x54,0x7e,0x4f,0xad,0x4f,0x24". 845 // 846 if (Reset) { 847 ZeroMem (&LanDriver->Stats, sizeof(EFI_NETWORK_STATISTICS)); 848 } 849 850 Status = EFI_SUCCESS; 851 if (StatSize == NULL) { 852 if (Statistics != NULL) { 853 return EFI_INVALID_PARAMETER; 854 } 855 } else { 856 if (Statistics == NULL) { 857 Status = EFI_BUFFER_TOO_SMALL; 858 } else { 859 // Fill in the statistics 860 CopyMem ( 861 Statistics, &LanDriver->Stats, 862 MIN (*StatSize, sizeof (EFI_NETWORK_STATISTICS)) 863 ); 864 if (*StatSize < sizeof (EFI_NETWORK_STATISTICS)) { 865 Status = EFI_BUFFER_TOO_SMALL; 866 } 867 } 868 *StatSize = sizeof (EFI_NETWORK_STATISTICS); 869 } 870 871 return Status; 872 } 873 874 /* 875 * UEFI MCastIPtoMAC() function 876 * 877 */ 878 EFI_STATUS 879 EFIAPI 880 SnpMcastIptoMac ( 881 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp, 882 IN BOOLEAN IsIpv6, 883 IN EFI_IP_ADDRESS *Ip, 884 OUT EFI_MAC_ADDRESS *McastMac 885 ) 886 { 887 DEBUG ((DEBUG_NET, "SnpMcastIptoMac()\n")); 888 889 // Check Snp instance 890 if (Snp == NULL) { 891 return EFI_INVALID_PARAMETER; 892 } 893 894 // Check that driver was started and initialised 895 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 896 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n")); 897 return EFI_DEVICE_ERROR; 898 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 899 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n")); 900 return EFI_NOT_STARTED; 901 } 902 903 // Check parameters 904 if ((McastMac == NULL) || (Ip == NULL)) { 905 return EFI_INVALID_PARAMETER; 906 } 907 908 // Make sure MAC address is empty 909 ZeroMem (McastMac, sizeof(EFI_MAC_ADDRESS)); 910 911 // If we need ipv4 address 912 if (!IsIpv6) { 913 // Most significant 25 bits of a multicast HW address are set. 914 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112) 915 McastMac->Addr[0] = 0x01; 916 McastMac->Addr[1] = 0x00; 917 McastMac->Addr[2] = 0x5E; 918 919 // Lower 23 bits from ipv4 address 920 McastMac->Addr[3] = (Ip->v4.Addr[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0) 921 McastMac->Addr[4] = Ip->v4.Addr[2]; 922 McastMac->Addr[5] = Ip->v4.Addr[3]; 923 } else { 924 // Most significant 16 bits of multicast v6 HW address are set 925 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464) 926 McastMac->Addr[0] = 0x33; 927 McastMac->Addr[1] = 0x33; 928 929 // lower four octets are taken from ipv6 address 930 McastMac->Addr[2] = Ip->v6.Addr[8]; 931 McastMac->Addr[3] = Ip->v6.Addr[9]; 932 McastMac->Addr[4] = Ip->v6.Addr[10]; 933 McastMac->Addr[5] = Ip->v6.Addr[11]; 934 } 935 936 return EFI_SUCCESS; 937 } 938 939 /* 940 * UEFI NvData() function 941 * 942 */ 943 EFI_STATUS 944 EFIAPI 945 SnpNvData ( 946 IN EFI_SIMPLE_NETWORK_PROTOCOL* pobj, 947 IN BOOLEAN read_write, 948 IN UINTN offset, 949 IN UINTN buff_size, 950 IN OUT VOID *data 951 ) 952 { 953 DEBUG ((DEBUG_NET, "SnpNvData()\n")); 954 955 return EFI_UNSUPPORTED; 956 } 957 958 959 /* 960 * UEFI GetStatus () function 961 * 962 */ 963 EFI_STATUS 964 EFIAPI 965 SnpGetStatus ( 966 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp, 967 OUT UINT32 *IrqStat OPTIONAL, 968 OUT VOID **TxBuff OPTIONAL 969 ) 970 { 971 UINT32 FifoInt; 972 EFI_STATUS Status; 973 UINTN NumTxStatusEntries; 974 UINT32 TxStatus; 975 UINT16 PacketTag; 976 UINT32 Interrupts; 977 LAN9118_DRIVER *LanDriver; 978 979 LanDriver = INSTANCE_FROM_SNP_THIS (Snp); 980 981 // Check preliminaries 982 if (Snp == NULL) { 983 return EFI_INVALID_PARAMETER; 984 } 985 986 // Check that driver was started and initialised 987 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 988 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n")); 989 return EFI_DEVICE_ERROR; 990 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 991 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n")); 992 return EFI_NOT_STARTED; 993 } 994 995 // Check and acknowledge TX Status interrupt (this will happen if the 996 // consumer of SNP does not call GetStatus.) 997 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we 998 // should check for it and dump the TX Status FIFO. 999 FifoInt = MmioRead32 (LAN9118_FIFO_INT); 1000 1001 // Clear the TX Status FIFO Overflow 1002 if ((FifoInt & INSTS_TXSO) == 0) { 1003 FifoInt |= INSTS_TXSO; 1004 MmioWrite32 (LAN9118_FIFO_INT, FifoInt); 1005 } 1006 1007 // Read interrupt status if IrqStat is not NULL 1008 if (IrqStat != NULL) { 1009 *IrqStat = 0; 1010 1011 // Check for receive interrupt 1012 if (MmioRead32 (LAN9118_INT_STS) & INSTS_RSFL) { // Data moved from rx FIFO 1013 *IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; 1014 MmioWrite32 (LAN9118_INT_STS,INSTS_RSFL); 1015 } 1016 1017 // Check for transmit interrupt 1018 if (MmioRead32 (LAN9118_INT_STS) & INSTS_TSFL) { 1019 *IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; 1020 MmioWrite32 (LAN9118_INT_STS,INSTS_TSFL); 1021 } 1022 1023 // Check for software interrupt 1024 if (MmioRead32 (LAN9118_INT_STS) & INSTS_SW_INT) { 1025 *IrqStat |= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT; 1026 MmioWrite32 (LAN9118_INT_STS,INSTS_SW_INT); 1027 } 1028 } 1029 1030 // Check Status of transmitted packets 1031 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex) 1032 1033 NumTxStatusEntries = MmioRead32(LAN9118_TX_FIFO_INF) & TXFIFOINF_TXSUSED_MASK; 1034 if (NumTxStatusEntries > 0) { 1035 TxStatus = MmioRead32 (LAN9118_TX_STATUS); 1036 PacketTag = TxStatus >> 16; 1037 TxStatus = TxStatus & 0xFFFF; 1038 if ((TxStatus & TXSTATUS_ES) && (TxStatus != (TXSTATUS_ES | TXSTATUS_NO_CA))) { 1039 DEBUG ((EFI_D_ERROR, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus)); 1040 if (TxStatus & TXSTATUS_NO_CA) { 1041 DEBUG ((EFI_D_ERROR, "- No carrier\n")); 1042 } 1043 if (TxStatus & TXSTATUS_DEF) { 1044 DEBUG ((EFI_D_ERROR, "- Packet tx was deferred\n")); 1045 } 1046 if (TxStatus & TXSTATUS_EDEF) { 1047 DEBUG ((EFI_D_ERROR, "- Tx ended because of excessive deferral\n")); 1048 } 1049 if (TxStatus & TXSTATUS_ECOLL) { 1050 DEBUG ((EFI_D_ERROR, "- Tx ended because of Excessive Collisions\n")); 1051 } 1052 if (TxStatus & TXSTATUS_LCOLL) { 1053 DEBUG ((EFI_D_ERROR, "- Packet Tx aborted after coll window of 64 bytes\n")); 1054 } 1055 if (TxStatus & TXSTATUS_LOST_CA) { 1056 DEBUG ((EFI_D_ERROR, "- Lost carrier during Tx\n")); 1057 } 1058 return EFI_DEVICE_ERROR; 1059 } else if (TxBuff != NULL) { 1060 LanDriver->Stats.TxTotalFrames += 1; 1061 *TxBuff = LanDriver->TxRing[PacketTag % LAN9118_TX_RING_NUM_ENTRIES]; 1062 } 1063 } 1064 1065 // Check for a TX Error interrupt 1066 Interrupts = MmioRead32 (LAN9118_INT_STS); 1067 if (Interrupts & INSTS_TXE) { 1068 DEBUG ((EFI_D_ERROR, "LAN9118: Transmitter error. Restarting...")); 1069 1070 // Software reset, the TXE interrupt is cleared by the reset. 1071 Status = SoftReset (0, Snp); 1072 if (EFI_ERROR (Status)) { 1073 DEBUG ((EFI_D_ERROR, "\n\tSoft Reset Failed: Hardware Error\n")); 1074 return EFI_DEVICE_ERROR; 1075 } 1076 1077 // Reactivate the LEDs 1078 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp); 1079 if (EFI_ERROR (Status)) { 1080 return Status; 1081 } 1082 1083 // 1084 // Restart the transmitter and if necessary the receiver. 1085 // Do not ask for FIFO reset as it has already been done 1086 // by SoftReset(). 1087 // 1088 StartTx (START_TX_MAC | START_TX_CFG, Snp); 1089 if (Snp->Mode->ReceiveFilterSetting != 0) { 1090 StartRx (0, Snp); 1091 } 1092 } 1093 1094 // Update the media status 1095 Status = CheckLinkStatus (0, Snp); 1096 if (EFI_ERROR(Status)) { 1097 Snp->Mode->MediaPresent = FALSE; 1098 } else { 1099 Snp->Mode->MediaPresent = TRUE; 1100 } 1101 1102 return EFI_SUCCESS; 1103 } 1104 1105 1106 /* 1107 * UEFI Transmit() function 1108 * 1109 */ 1110 EFI_STATUS 1111 EFIAPI 1112 SnpTransmit ( 1113 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp, 1114 IN UINTN HdrSize, 1115 IN UINTN BuffSize, 1116 IN VOID* Data, 1117 IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, 1118 IN EFI_MAC_ADDRESS *DstAddr OPTIONAL, 1119 IN UINT16 *Protocol OPTIONAL 1120 ) 1121 { 1122 LAN9118_DRIVER *LanDriver; 1123 UINT32 TxFreeSpace; 1124 UINT32 TxStatusSpace; 1125 INT32 Count; 1126 UINT32 CommandA; 1127 UINT32 CommandB; 1128 UINT16 LocalProtocol; 1129 UINT32 *LocalData; 1130 UINT16 PacketTag; 1131 1132 #if defined(EVAL_PERFORMANCE) 1133 UINT64 Perf; 1134 UINT64 StartClock; 1135 UINT64 EndClock; 1136 1137 Perf = GetPerformanceCounterProperties (NULL, NULL); 1138 StartClock = GetPerformanceCounter (); 1139 #endif 1140 1141 LanDriver = INSTANCE_FROM_SNP_THIS (Snp); 1142 1143 // Check preliminaries 1144 if ((Snp == NULL) || (Data == NULL)) { 1145 return EFI_INVALID_PARAMETER; 1146 } 1147 1148 // Check that driver was started and initialised 1149 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 1150 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n")); 1151 return EFI_DEVICE_ERROR; 1152 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 1153 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n")); 1154 return EFI_NOT_STARTED; 1155 } 1156 1157 // Ensure header is correct size if non-zero 1158 if (HdrSize) { 1159 if (HdrSize != Snp->Mode->MediaHeaderSize) { 1160 return EFI_INVALID_PARAMETER; 1161 } 1162 1163 if ((DstAddr == NULL) || (Protocol == NULL)) { 1164 return EFI_INVALID_PARAMETER; 1165 } 1166 } 1167 1168 // 1169 // Check validity of BufferSize 1170 // 1171 if (BuffSize < Snp->Mode->MediaHeaderSize) { 1172 return EFI_BUFFER_TOO_SMALL; 1173 } 1174 1175 // Before transmitting check the link status 1176 /*if (CheckLinkStatus (0, Snp) < 0) { 1177 return EFI_NOT_READY; 1178 }*/ 1179 1180 // Get DATA FIFO free space in bytes 1181 TxFreeSpace = TxDataFreeSpace (0, Snp); 1182 if (TxFreeSpace < BuffSize) { 1183 return EFI_NOT_READY; 1184 } 1185 1186 // Get STATUS FIFO used space in bytes 1187 TxStatusSpace = TxStatusUsedSpace (0, Snp); 1188 if (TxStatusSpace > 500) { 1189 return EFI_NOT_READY; 1190 } 1191 1192 // If DstAddr is not provided, get it from Buffer (we trust that the caller 1193 // has provided a well-formed frame). 1194 if (DstAddr == NULL) { 1195 DstAddr = (EFI_MAC_ADDRESS *) Data; 1196 } 1197 1198 // Check for the nature of the frame 1199 if ((DstAddr->Addr[0] & 0x1) == 1) { 1200 LanDriver->Stats.TxMulticastFrames += 1; 1201 } else { 1202 LanDriver->Stats.TxUnicastFrames += 1; 1203 } 1204 1205 // Check if broadcast 1206 if (DstAddr->Addr[0] == 0xFF) { 1207 LanDriver->Stats.TxBroadcastFrames += 1; 1208 } 1209 1210 PacketTag = LanDriver->NextPacketTag; 1211 LanDriver->NextPacketTag++; 1212 1213 if (HdrSize) { 1214 1215 // Format pointer 1216 LocalData = (UINT32*) Data; 1217 LocalProtocol = *Protocol; 1218 1219 // Create first buffer to pass to controller (for the header) 1220 CommandA = TX_CMD_A_FIRST_SEGMENT | TX_CMD_A_BUFF_SIZE (HdrSize); 1221 CommandB = TX_CMD_B_PACKET_TAG (PacketTag) | TX_CMD_B_PACKET_LENGTH (BuffSize); 1222 1223 // Write the commands first 1224 MmioWrite32 (LAN9118_TX_DATA, CommandA); 1225 MmioWrite32 (LAN9118_TX_DATA, CommandB); 1226 1227 // Write the destination address 1228 MmioWrite32 (LAN9118_TX_DATA, 1229 (DstAddr->Addr[0]) | 1230 (DstAddr->Addr[1] << 8) | 1231 (DstAddr->Addr[2] << 16) | 1232 (DstAddr->Addr[3] << 24) 1233 ); 1234 1235 MmioWrite32 (LAN9118_TX_DATA, 1236 (DstAddr->Addr[4]) | 1237 (DstAddr->Addr[5] << 8) | 1238 (SrcAddr->Addr[0] << 16) | // Write the Source Address 1239 (SrcAddr->Addr[1] << 24) 1240 ); 1241 1242 MmioWrite32 (LAN9118_TX_DATA, 1243 (SrcAddr->Addr[2]) | 1244 (SrcAddr->Addr[3] << 8) | 1245 (SrcAddr->Addr[4] << 16) | 1246 (SrcAddr->Addr[5] << 24) 1247 ); 1248 1249 // Write the Protocol 1250 MmioWrite32 (LAN9118_TX_DATA, (UINT32)(HTONS (LocalProtocol))); 1251 1252 // Next buffer is the payload 1253 CommandA = TX_CMD_A_LAST_SEGMENT | TX_CMD_A_BUFF_SIZE (BuffSize - HdrSize) | TX_CMD_A_COMPLETION_INT | TX_CMD_A_DATA_START_OFFSET (2); // 2 bytes beginning offset 1254 1255 // Write the commands 1256 MmioWrite32 (LAN9118_TX_DATA, CommandA); 1257 MmioWrite32 (LAN9118_TX_DATA, CommandB); 1258 1259 // Write the payload 1260 for (Count = 0; Count < ((BuffSize + 3) >> 2) - 3; Count++) { 1261 MmioWrite32 (LAN9118_TX_DATA, LocalData[Count + 3]); 1262 } 1263 } else { 1264 // Format pointer 1265 LocalData = (UINT32*) Data; 1266 1267 // Create a buffer to pass to controller 1268 CommandA = TX_CMD_A_FIRST_SEGMENT | TX_CMD_A_LAST_SEGMENT | TX_CMD_A_BUFF_SIZE (BuffSize) | TX_CMD_A_COMPLETION_INT; 1269 CommandB = TX_CMD_B_PACKET_TAG (PacketTag) | TX_CMD_B_PACKET_LENGTH (BuffSize); 1270 1271 // Write the commands first 1272 MmioWrite32 (LAN9118_TX_DATA, CommandA); 1273 MmioWrite32 (LAN9118_TX_DATA, CommandB); 1274 1275 // Write all the data 1276 for (Count = 0; Count < ((BuffSize + 3) >> 2); Count++) { 1277 MmioWrite32 (LAN9118_TX_DATA, LocalData[Count]); 1278 } 1279 } 1280 1281 // Save the address of the submitted packet so we can notify the consumer that 1282 // it has been sent in GetStatus. When the packet tag appears in the Tx Status 1283 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus. 1284 LanDriver->TxRing[PacketTag % LAN9118_TX_RING_NUM_ENTRIES] = Data; 1285 1286 #if defined(EVAL_PERFORMANCE) 1287 EndClock = GetPerformanceCounter (); 1288 DEBUG ((EFI_D_ERROR, "Time processing: %d counts @ %d Hz\n", StartClock - EndClock,Perf)); 1289 #endif 1290 1291 LanDriver->Stats.TxGoodFrames += 1; 1292 1293 return EFI_SUCCESS; 1294 } 1295 1296 1297 /* 1298 * UEFI Receive() function 1299 * 1300 */ 1301 EFI_STATUS 1302 EFIAPI 1303 SnpReceive ( 1304 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp, 1305 OUT UINTN *HdrSize OPTIONAL, 1306 IN OUT UINTN *BuffSize, 1307 OUT VOID *Data, 1308 OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, 1309 OUT EFI_MAC_ADDRESS *DstAddr OPTIONAL, 1310 OUT UINT16 *Protocol OPTIONAL 1311 ) 1312 { 1313 LAN9118_DRIVER *LanDriver; 1314 UINT32 IntSts; 1315 UINT32 RxFifoStatus; 1316 UINT32 NumPackets; 1317 UINT32 RxCfgValue; 1318 UINT32 PLength; // Packet length 1319 UINT32 ReadLimit; 1320 UINT32 Count; 1321 UINT32 Padding; 1322 UINT32 *RawData; 1323 EFI_MAC_ADDRESS Dst; 1324 EFI_MAC_ADDRESS Src; 1325 UINTN DroppedFrames; 1326 EFI_STATUS Status; 1327 1328 LanDriver = INSTANCE_FROM_SNP_THIS (Snp); 1329 1330 #if defined(EVAL_PERFORMANCE) 1331 UINT64 Perf = GetPerformanceCounterProperties (NULL, NULL); 1332 UINT64 StartClock = GetPerformanceCounter (); 1333 #endif 1334 1335 // Check preliminaries 1336 if ((Snp == NULL) || (Data == NULL) || (BuffSize == NULL)) { 1337 return EFI_INVALID_PARAMETER; 1338 } 1339 1340 // Check that driver was started and initialised 1341 if (Snp->Mode->State == EfiSimpleNetworkStarted) { 1342 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n")); 1343 return EFI_DEVICE_ERROR; 1344 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) { 1345 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n")); 1346 return EFI_NOT_STARTED; 1347 } 1348 1349 // 1350 // If the receiver raised the RXE error bit, check if the receiver status 1351 // FIFO is full and if not just acknowledge the error. The two other 1352 // conditions to get a RXE error are : 1353 // . the RX data FIFO is read whereas being empty. 1354 // . the RX status FIFO is read whereas being empty. 1355 // The RX data and status FIFO are read by this driver only in the following 1356 // code of this function. After the readings, the RXE error bit is checked 1357 // and if raised, the controller is reset. Thus, at this point, we consider 1358 // that the only valid reason to get an RXE error is the receiver status 1359 // FIFO being full. And if this is not the case, we consider that this is 1360 // a spurious error and we just get rid of it. We experienced such 'spurious' 1361 // errors when running the driver on an A57 on Juno. No valid reason to 1362 // explain those errors has been found so far and everything seems to 1363 // work perfectly when they are just ignored. 1364 // 1365 IntSts = MmioRead32 (LAN9118_INT_STS); 1366 if ((IntSts & INSTS_RXE) && (!(IntSts & INSTS_RSFF))) { 1367 MmioWrite32 (LAN9118_INT_STS, INSTS_RXE); 1368 } 1369 1370 // Count dropped frames 1371 DroppedFrames = MmioRead32 (LAN9118_RX_DROP); 1372 LanDriver->Stats.RxDroppedFrames += DroppedFrames; 1373 1374 NumPackets = RxStatusUsedSpace (0, Snp) / 4; 1375 if (!NumPackets) { 1376 return EFI_NOT_READY; 1377 } 1378 1379 // Read Rx Status (only if not empty) 1380 RxFifoStatus = MmioRead32 (LAN9118_RX_STATUS); 1381 LanDriver->Stats.RxTotalFrames += 1; 1382 1383 // First check for errors 1384 if ((RxFifoStatus & RXSTATUS_MII_ERROR) || 1385 (RxFifoStatus & RXSTATUS_RXW_TO) || 1386 (RxFifoStatus & RXSTATUS_FTL) || 1387 (RxFifoStatus & RXSTATUS_LCOLL) || 1388 (RxFifoStatus & RXSTATUS_LE) || 1389 (RxFifoStatus & RXSTATUS_DB)) 1390 { 1391 DEBUG ((EFI_D_WARN, "Warning: There was an error on frame reception.\n")); 1392 return EFI_DEVICE_ERROR; 1393 } 1394 1395 // Check if we got a CRC error 1396 if (RxFifoStatus & RXSTATUS_CRC_ERROR) { 1397 DEBUG ((EFI_D_WARN, "Warning: Crc Error\n")); 1398 LanDriver->Stats.RxCrcErrorFrames += 1; 1399 LanDriver->Stats.RxDroppedFrames += 1; 1400 return EFI_DEVICE_ERROR; 1401 } 1402 1403 // Check if we got a runt frame 1404 if (RxFifoStatus & RXSTATUS_RUNT) { 1405 DEBUG ((EFI_D_WARN, "Warning: Runt Frame\n")); 1406 LanDriver->Stats.RxUndersizeFrames += 1; 1407 LanDriver->Stats.RxDroppedFrames += 1; 1408 return EFI_DEVICE_ERROR; 1409 } 1410 1411 // Check filtering status for this packet 1412 if (RxFifoStatus & RXSTATUS_FILT_FAIL) { 1413 DEBUG ((EFI_D_WARN, "Warning: Frame Failed Filtering\n")); 1414 // fast forward? 1415 } 1416 1417 // Check if we got a broadcast frame 1418 if (RxFifoStatus & RXSTATUS_BCF) { 1419 LanDriver->Stats.RxBroadcastFrames += 1; 1420 } 1421 1422 // Check if we got a multicast frame 1423 if (RxFifoStatus & RXSTATUS_MCF) { 1424 LanDriver->Stats.RxMulticastFrames += 1; 1425 } 1426 1427 // Check if we got a unicast frame 1428 if ((RxFifoStatus & RXSTATUS_BCF) && ((RxFifoStatus & RXSTATUS_MCF) == 0)) { 1429 LanDriver->Stats.RxUnicastFrames += 1; 1430 } 1431 1432 // Get the received packet length 1433 PLength = GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus); 1434 LanDriver->Stats.RxTotalBytes += (PLength - 4); 1435 1436 // If padding is applied, read more DWORDs 1437 if (PLength % 4) { 1438 Padding = 4 - (PLength % 4); 1439 ReadLimit = (PLength + Padding)/4; 1440 } else { 1441 ReadLimit = PLength/4; 1442 Padding = 0; 1443 } 1444 1445 // Check buffer size 1446 if (*BuffSize < (PLength + Padding)) { 1447 *BuffSize = PLength + Padding; 1448 return EFI_BUFFER_TOO_SMALL; 1449 } 1450 1451 // Set the amount of data to be transfered out of FIFO for THIS packet 1452 // This can be used to trigger an interrupt, and status can be checked 1453 RxCfgValue = MmioRead32 (LAN9118_RX_CFG); 1454 RxCfgValue &= ~(RXCFG_RX_DMA_CNT_MASK); 1455 RxCfgValue |= RXCFG_RX_DMA_CNT (ReadLimit); 1456 1457 // Set end alignment to 4-bytes 1458 RxCfgValue &= ~(RXCFG_RX_END_ALIGN_MASK); 1459 MmioWrite32 (LAN9118_RX_CFG, RxCfgValue); 1460 1461 // Update buffer size 1462 *BuffSize = PLength; // -4 bytes may be needed: Received in buffer as 1463 // 4 bytes longer than packet actually is, unless 1464 // packet is < 64 bytes 1465 1466 if (HdrSize != NULL) 1467 *HdrSize = Snp->Mode->MediaHeaderSize; 1468 1469 // Format the pointer 1470 RawData = (UINT32*)Data; 1471 1472 // Read Rx Packet 1473 for (Count = 0; Count < ReadLimit; Count++) { 1474 RawData[Count] = MmioRead32 (LAN9118_RX_DATA); 1475 } 1476 1477 // Get the destination address 1478 if (DstAddr != NULL) { 1479 Dst.Addr[0] = (RawData[0] & 0xFF); 1480 Dst.Addr[1] = (RawData[0] & 0xFF00) >> 8; 1481 Dst.Addr[2] = (RawData[0] & 0xFF0000) >> 16; 1482 Dst.Addr[3] = (RawData[0] & 0xFF000000) >> 24; 1483 Dst.Addr[4] = (RawData[1] & 0xFF); 1484 Dst.Addr[5] = (RawData[1] & 0xFF00) >> 8; 1485 CopyMem (DstAddr, &Dst, NET_ETHER_ADDR_LEN); 1486 } 1487 1488 // Get the source address 1489 if (SrcAddr != NULL) { 1490 Src.Addr[0] = (RawData[1] & 0xFF0000) >> 16; 1491 Src.Addr[1] = (RawData[1] & 0xFF000000) >> 24; 1492 Src.Addr[2] = (RawData[2] & 0xFF); 1493 Src.Addr[3] = (RawData[2] & 0xFF00) >> 8; 1494 Src.Addr[4] = (RawData[2] & 0xFF0000) >> 16; 1495 Src.Addr[5] = (RawData[2] & 0xFF000000) >> 24; 1496 CopyMem (SrcAddr, &Src, NET_ETHER_ADDR_LEN); 1497 } 1498 1499 // Get the protocol 1500 if (Protocol != NULL) { 1501 *Protocol = NTOHS (RawData[3] & 0xFFFF); 1502 } 1503 1504 // Check for Rx errors (worst possible error) 1505 if (MmioRead32 (LAN9118_INT_STS) & INSTS_RXE) { 1506 DEBUG ((EFI_D_WARN, "Warning: Receiver Error. Restarting...\n")); 1507 1508 // Software reset, the RXE interrupt is cleared by the reset. 1509 Status = SoftReset (0, Snp); 1510 if (EFI_ERROR (Status)) { 1511 DEBUG ((EFI_D_ERROR, "Error: Soft Reset Failed: Hardware Error.\n")); 1512 return EFI_DEVICE_ERROR; 1513 } 1514 1515 // Reactivate the LEDs 1516 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp); 1517 if (EFI_ERROR (Status)) { 1518 return Status; 1519 } 1520 1521 // 1522 // Restart the receiver and the transmitter without reseting the FIFOs 1523 // as it has been done by SoftReset(). 1524 // 1525 StartRx (0, Snp); 1526 StartTx (START_TX_MAC | START_TX_CFG, Snp); 1527 1528 // Say that command could not be sent 1529 return EFI_DEVICE_ERROR; 1530 } 1531 1532 #if defined(EVAL_PERFORMANCE) 1533 UINT64 EndClock = GetPerformanceCounter (); 1534 DEBUG ((EFI_D_ERROR, "Receive Time processing: %d counts @ %d Hz\n", StartClock - EndClock,Perf)); 1535 #endif 1536 1537 LanDriver->Stats.RxGoodFrames += 1; 1538 1539 return EFI_SUCCESS; 1540 } 1541