1 /** @file 2 Implement the interface to the AX88772 Ethernet controller. 3 4 This module implements the interface to the ASIX AX88772 5 USB to Ethernet MAC with integrated 10/100 PHY. Note that this implementation 6 only supports the integrated PHY since no other test cases were available. 7 8 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR> 9 This program and the accompanying materials 10 are licensed and made available under the terms and conditions of the BSD License 11 which accompanies this distribution. The full text of the license may be found at 12 http://opensource.org/licenses/bsd-license.php 13 14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 16 17 **/ 18 19 #include "Ax88772.h" 20 21 22 /** 23 Compute the CRC 24 25 @param [in] pMacAddress Address of a six byte buffer to containing the MAC address. 26 27 @returns The CRC-32 value associated with this MAC address 28 29 **/ 30 UINT32 31 Ax88772Crc ( 32 IN UINT8 * pMacAddress 33 ) 34 { 35 UINT32 BitNumber; 36 INT32 Carry; 37 INT32 Crc; 38 UINT32 Data; 39 UINT8 * pEnd; 40 41 DBG_ENTER ( ); 42 43 // 44 // Walk the MAC address 45 // 46 Crc = -1; 47 pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ]; 48 while ( pEnd > pMacAddress ) { 49 Data = *pMacAddress++; 50 51 52 // 53 // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 54 // 55 // 1 0000 0100 1100 0001 0001 1101 1011 0111 56 // 57 for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) { 58 Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 ); 59 Crc <<= 1; 60 if ( 0 != Carry ) { 61 Crc ^= 0x04c11db7; 62 } 63 Data >>= 1; 64 } 65 } 66 67 // 68 // Return the CRC value 69 // 70 DBG_EXIT_HEX ( Crc ); 71 return (UINT32) Crc; 72 } 73 74 75 /** 76 Get the MAC address 77 78 This routine calls ::Ax88772UsbCommand to request the MAC 79 address from the network adapter. 80 81 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 82 @param [out] pMacAddress Address of a six byte buffer to receive the MAC address. 83 84 @retval EFI_SUCCESS The MAC address is available. 85 @retval other The MAC address is not valid. 86 87 **/ 88 EFI_STATUS 89 Ax88772MacAddressGet ( 90 IN NIC_DEVICE * pNicDevice, 91 OUT UINT8 * pMacAddress 92 ) 93 { 94 USB_DEVICE_REQUEST SetupMsg; 95 EFI_STATUS Status; 96 97 DBG_ENTER ( ); 98 99 // 100 // Set the register address. 101 // 102 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN 103 | USB_REQ_TYPE_VENDOR 104 | USB_TARGET_DEVICE; 105 SetupMsg.Request = CMD_MAC_ADDRESS_READ; 106 SetupMsg.Value = 0; 107 SetupMsg.Index = 0; 108 SetupMsg.Length = PXE_HWADDR_LEN_ETHER; 109 110 // 111 // Read the PHY register 112 // 113 Status = Ax88772UsbCommand ( pNicDevice, 114 &SetupMsg, 115 pMacAddress ); 116 117 // 118 // Return the operation status 119 // 120 DBG_EXIT_STATUS ( Status ); 121 return Status; 122 } 123 124 125 /** 126 Set the MAC address 127 128 This routine calls ::Ax88772UsbCommand to set the MAC address 129 in the network adapter. 130 131 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 132 @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address. 133 134 @retval EFI_SUCCESS The MAC address was set. 135 @retval other The MAC address was not set. 136 137 **/ 138 EFI_STATUS 139 Ax88772MacAddressSet ( 140 IN NIC_DEVICE * pNicDevice, 141 IN UINT8 * pMacAddress 142 ) 143 { 144 USB_DEVICE_REQUEST SetupMsg; 145 EFI_STATUS Status; 146 147 DBG_ENTER ( ); 148 149 // 150 // Set the register address. 151 // 152 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 153 | USB_TARGET_DEVICE; 154 SetupMsg.Request = CMD_MAC_ADDRESS_WRITE; 155 SetupMsg.Value = 0; 156 SetupMsg.Index = 0; 157 SetupMsg.Length = PXE_HWADDR_LEN_ETHER; 158 159 // 160 // Read the PHY register 161 // 162 Status = Ax88772UsbCommand ( pNicDevice, 163 &SetupMsg, 164 pMacAddress ); 165 166 // 167 // Return the operation status 168 // 169 DBG_EXIT_STATUS ( Status ); 170 return Status; 171 } 172 173 174 /** 175 Clear the multicast hash table 176 177 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 178 179 **/ 180 VOID 181 Ax88772MulticastClear ( 182 IN NIC_DEVICE * pNicDevice 183 ) 184 { 185 DBG_ENTER ( ); 186 187 // 188 // Clear the multicast hash table 189 // 190 pNicDevice->MulticastHash[0] = 0; 191 pNicDevice->MulticastHash[1] = 0; 192 193 DBG_EXIT ( ); 194 } 195 196 197 /** 198 Enable a multicast address in the multicast hash table 199 200 This routine calls ::Ax88772Crc to compute the hash bit for 201 this MAC address. 202 203 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 204 @param [in] pMacAddress Address of a six byte buffer to containing the MAC address. 205 206 **/ 207 VOID 208 Ax88772MulticastSet ( 209 IN NIC_DEVICE * pNicDevice, 210 IN UINT8 * pMacAddress 211 ) 212 { 213 UINT32 BitNumber; 214 UINT32 Crc; 215 UINT32 Mask; 216 217 DBG_ENTER ( ); 218 219 // 220 // Compute the CRC on the destination address 221 // 222 Crc = Ax88772Crc ( pMacAddress ); 223 224 // 225 // Set the bit corresponding to the destination address 226 // 227 BitNumber = Crc >> 26; 228 if ( 32 > BitNumber ) { 229 Mask = 1 << BitNumber; 230 pNicDevice->MulticastHash[0] |= Mask; 231 } 232 else { 233 Mask = 1 << ( BitNumber - 32 ); 234 pNicDevice->MulticastHash[1] |= Mask; 235 } 236 237 // 238 // Display the multicast address 239 // 240 DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO, 241 "Enable multicast: 0x%02x-%02x-%02x-%02x-%02x-%02x, CRC: 0x%08x, Bit number: 0x%02x\r\n", 242 pMacAddress[0], 243 pMacAddress[1], 244 pMacAddress[2], 245 pMacAddress[3], 246 pMacAddress[4], 247 pMacAddress[5], 248 Crc, 249 BitNumber )); 250 251 DBG_EXIT ( ); 252 } 253 254 255 /** 256 Start the link negotiation 257 258 This routine calls ::Ax88772PhyWrite to start the PHY's link 259 negotiation. 260 261 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 262 263 @retval EFI_SUCCESS The link negotiation was started. 264 @retval other Failed to start the link negotiation. 265 266 **/ 267 EFI_STATUS 268 Ax88772NegotiateLinkStart ( 269 IN NIC_DEVICE * pNicDevice 270 ) 271 { 272 UINT16 Control; 273 EFI_STATUS Status; 274 275 DBG_ENTER ( ); 276 277 // 278 // Set the supported capabilities. 279 // 280 Status = Ax88772PhyWrite ( pNicDevice, 281 PHY_ANAR, 282 AN_CSMA_CD 283 | AN_TX_FDX | AN_TX_HDX 284 | AN_10_FDX | AN_10_HDX ); 285 if ( !EFI_ERROR ( Status )) { 286 // 287 // Set the link speed and duplex 288 // 289 Control = BMCR_AUTONEGOTIATION_ENABLE 290 | BMCR_RESTART_AUTONEGOTIATION; 291 if ( pNicDevice->b100Mbps ) { 292 Control |= BMCR_100MBPS; 293 } 294 if ( pNicDevice->bFullDuplex ) { 295 Control |= BMCR_FULL_DUPLEX; 296 } 297 Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control ); 298 } 299 300 // 301 // Return the operation status 302 // 303 DBG_EXIT_STATUS ( Status ); 304 return Status; 305 } 306 307 308 /** 309 Complete the negotiation of the PHY link 310 311 This routine calls ::Ax88772PhyRead to determine if the 312 link negotiation is complete. 313 314 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 315 @param [in, out] pPollCount Address of number of times this routine was polled 316 @param [out] pbComplete Address of boolean to receive complate status. 317 @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up. 318 @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps. 319 @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full. 320 321 @retval EFI_SUCCESS The MAC address is available. 322 @retval other The MAC address is not valid. 323 324 **/ 325 EFI_STATUS 326 Ax88772NegotiateLinkComplete ( 327 IN NIC_DEVICE * pNicDevice, 328 IN OUT UINTN * pPollCount, 329 OUT BOOLEAN * pbComplete, 330 OUT BOOLEAN * pbLinkUp, 331 OUT BOOLEAN * pbHiSpeed, 332 OUT BOOLEAN * pbFullDuplex 333 ) 334 { 335 UINT16 Mask; 336 UINT16 PhyData; 337 EFI_STATUS Status; 338 339 DBG_ENTER ( ); 340 341 // 342 // Determine if the link is up. 343 // 344 *pbComplete = FALSE; 345 346 // 347 // Get the link status 348 // 349 Status = Ax88772PhyRead ( pNicDevice, 350 PHY_BMSR, 351 &PhyData ); 352 if ( !EFI_ERROR ( Status )) { 353 // 354 // Determine if the autonegotiation is complete. 355 // 356 *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST )); 357 *pbComplete = *pbLinkUp; 358 if ( 0 != *pbComplete ) { 359 // 360 // Get the partners capabilities. 361 // 362 Status = Ax88772PhyRead ( pNicDevice, 363 PHY_ANLPAR, 364 &PhyData ); 365 if ( !EFI_ERROR ( Status )) { 366 // 367 // Autonegotiation is complete 368 // Determine the link speed. 369 // 370 *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX ))); 371 372 // 373 // Determine the link duplex. 374 // 375 Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX; 376 *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask )); 377 } 378 } 379 } 380 381 // 382 // Return the operation status 383 // 384 DBG_EXIT_STATUS ( Status ); 385 return Status; 386 } 387 388 389 /** 390 Read a register from the PHY 391 392 This routine calls ::Ax88772UsbCommand to read a PHY register. 393 394 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 395 @param [in] RegisterAddress Number of the register to read. 396 @param [in, out] pPhyData Address of a buffer to receive the PHY register value 397 398 @retval EFI_SUCCESS The PHY data is available. 399 @retval other The PHY data is not valid. 400 401 **/ 402 EFI_STATUS 403 Ax88772PhyRead ( 404 IN NIC_DEVICE * pNicDevice, 405 IN UINT8 RegisterAddress, 406 IN OUT UINT16 * pPhyData 407 ) 408 { 409 USB_DEVICE_REQUEST SetupMsg; 410 EFI_STATUS Status; 411 412 DBG_ENTER ( ); 413 414 // 415 // Request access to the PHY 416 // 417 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 418 | USB_TARGET_DEVICE; 419 SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE; 420 SetupMsg.Value = 0; 421 SetupMsg.Index = 0; 422 SetupMsg.Length = 0; 423 Status = Ax88772UsbCommand ( pNicDevice, 424 &SetupMsg, 425 NULL ); 426 if ( !EFI_ERROR ( Status )) { 427 // 428 // Read the PHY register address. 429 // 430 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN 431 | USB_REQ_TYPE_VENDOR 432 | USB_TARGET_DEVICE; 433 SetupMsg.Request = CMD_PHY_REG_READ; 434 SetupMsg.Value = pNicDevice->PhyId; 435 SetupMsg.Index = RegisterAddress; 436 SetupMsg.Length = sizeof ( *pPhyData ); 437 Status = Ax88772UsbCommand ( pNicDevice, 438 &SetupMsg, 439 pPhyData ); 440 if ( !EFI_ERROR ( Status )) { 441 DEBUG (( DEBUG_PHY | DEBUG_INFO, 442 "PHY %d: 0x%02x --> 0x%04x\r\n", 443 pNicDevice->PhyId, 444 RegisterAddress, 445 *pPhyData )); 446 447 // 448 // Release the PHY to the hardware 449 // 450 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 451 | USB_TARGET_DEVICE; 452 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE; 453 SetupMsg.Value = 0; 454 SetupMsg.Index = 0; 455 SetupMsg.Length = 0; 456 Status = Ax88772UsbCommand ( pNicDevice, 457 &SetupMsg, 458 NULL ); 459 } 460 } 461 462 // 463 // Return the operation status. 464 // 465 DBG_EXIT_STATUS ( Status ); 466 return Status; 467 } 468 469 470 /** 471 Write to a PHY register 472 473 This routine calls ::Ax88772UsbCommand to write a PHY register. 474 475 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 476 @param [in] RegisterAddress Number of the register to read. 477 @param [in] PhyData Address of a buffer to receive the PHY register value 478 479 @retval EFI_SUCCESS The PHY data was written. 480 @retval other Failed to wwrite the PHY register. 481 482 **/ 483 EFI_STATUS 484 Ax88772PhyWrite ( 485 IN NIC_DEVICE * pNicDevice, 486 IN UINT8 RegisterAddress, 487 IN UINT16 PhyData 488 ) 489 { 490 USB_DEVICE_REQUEST SetupMsg; 491 EFI_STATUS Status; 492 493 DBG_ENTER ( ); 494 495 // 496 // Request access to the PHY 497 // 498 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 499 | USB_TARGET_DEVICE; 500 SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE; 501 SetupMsg.Value = 0; 502 SetupMsg.Index = 0; 503 SetupMsg.Length = 0; 504 Status = Ax88772UsbCommand ( pNicDevice, 505 &SetupMsg, 506 NULL ); 507 if ( !EFI_ERROR ( Status )) { 508 // 509 // Write the PHY register 510 // 511 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 512 | USB_TARGET_DEVICE; 513 SetupMsg.Request = CMD_PHY_REG_WRITE; 514 SetupMsg.Value = pNicDevice->PhyId; 515 SetupMsg.Index = RegisterAddress; 516 SetupMsg.Length = sizeof ( PhyData ); 517 Status = Ax88772UsbCommand ( pNicDevice, 518 &SetupMsg, 519 &PhyData ); 520 if ( !EFI_ERROR ( Status )) { 521 DEBUG (( DEBUG_PHY | DEBUG_INFO, 522 "PHY %d: 0x%02x <-- 0x%04x\r\n", 523 pNicDevice->PhyId, 524 RegisterAddress, 525 PhyData )); 526 527 // 528 // Release the PHY to the hardware 529 // 530 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 531 | USB_TARGET_DEVICE; 532 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE; 533 SetupMsg.Value = 0; 534 SetupMsg.Index = 0; 535 SetupMsg.Length = 0; 536 Status = Ax88772UsbCommand ( pNicDevice, 537 &SetupMsg, 538 NULL ); 539 } 540 } 541 542 // 543 // Return the operation status. 544 // 545 DBG_EXIT_STATUS ( Status ); 546 return Status; 547 } 548 549 550 /** 551 Reset the AX88772 552 553 This routine uses ::Ax88772UsbCommand to reset the network 554 adapter. This routine also uses ::Ax88772PhyWrite to reset 555 the PHY. 556 557 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 558 559 @retval EFI_SUCCESS The MAC address is available. 560 @retval other The MAC address is not valid. 561 562 **/ 563 EFI_STATUS 564 Ax88772Reset ( 565 IN NIC_DEVICE * pNicDevice 566 ) 567 { 568 USB_DEVICE_REQUEST SetupMsg; 569 EFI_STATUS Status; 570 571 DBG_ENTER ( ); 572 573 // 574 // Turn off the MAC 575 // 576 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 577 | USB_TARGET_DEVICE; 578 SetupMsg.Request = CMD_RX_CONTROL_WRITE; 579 SetupMsg.Value = 0; 580 SetupMsg.Index = 0; 581 SetupMsg.Length = 0; 582 Status = Ax88772UsbCommand ( pNicDevice, 583 &SetupMsg, 584 NULL ); 585 if ( !EFI_ERROR ( Status )) { 586 DEBUG (( DEBUG_PHY | DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST 587 | DEBUG_RX_UNICAST | DEBUG_TX | DEBUG_INFO, 588 "MAC reset\r\n" )); 589 590 // 591 // The link is now idle 592 // 593 pNicDevice->bLinkIdle = TRUE; 594 595 // 596 // Delay for a bit 597 // 598 gBS->Stall ( RESET_MSEC ); 599 600 // 601 // Select the internal PHY 602 // 603 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 604 | USB_TARGET_DEVICE; 605 SetupMsg.Request = CMD_PHY_SELECT; 606 SetupMsg.Value = SPHY_PSEL; 607 SetupMsg.Index = 0; 608 SetupMsg.Length = 0; 609 Status = Ax88772UsbCommand ( pNicDevice, 610 &SetupMsg, 611 NULL ); 612 if ( !EFI_ERROR ( Status )) { 613 // 614 // Delay for a bit 615 // 616 gBS->Stall ( PHY_RESET_MSEC ); 617 618 // 619 // Clear the internal PHY reset 620 // 621 SetupMsg.Request = CMD_RESET; 622 SetupMsg.Value = SRR_IPRL | SRR_PRL; 623 Status = Ax88772UsbCommand ( pNicDevice, 624 &SetupMsg, 625 NULL ); 626 if ( !EFI_ERROR ( Status )) { 627 // 628 // Reset the PHY 629 // 630 Status = Ax88772PhyWrite ( pNicDevice, 631 PHY_BMCR, 632 BMCR_RESET ); 633 if ( !EFI_ERROR ( Status )) { 634 // 635 // Set the gaps 636 // 637 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 638 | USB_TARGET_DEVICE; 639 SetupMsg.Request = CMD_GAPS_WRITE; 640 SetupMsg.Value = 0x0c15; 641 SetupMsg.Index = 0x0e; 642 SetupMsg.Length = 0; 643 Status = Ax88772UsbCommand ( pNicDevice, 644 &SetupMsg, 645 NULL ); 646 } 647 } 648 } 649 } 650 651 // 652 // Return the operation status. 653 // 654 DBG_EXIT_STATUS ( Status ); 655 return Status; 656 } 657 658 659 VOID 660 FillPkt2Queue ( 661 IN NIC_DEVICE * pNicDevice, 662 IN UINTN BufLength) 663 { 664 665 UINT16 * pLength; 666 UINT16 * pLengthBar; 667 UINT8* pData; 668 UINT32 offset; 669 RX_TX_PACKET * pRxPacket; 670 UINTN LengthInBytes; 671 EFI_STATUS Status; 672 673 for ( offset = 0; offset < BufLength; ){ 674 pLength = (UINT16*) (pNicDevice->pBulkInBuff + offset); 675 pLengthBar = (UINT16*) (pNicDevice->pBulkInBuff + offset +2); 676 677 *pLength &= 0x7ff; 678 *pLengthBar &= 0x7ff; 679 *pLengthBar |= 0xf800; 680 681 if ((*pLength ^ *pLengthBar ) != 0xFFFF) { 682 DEBUG (( EFI_D_ERROR , "Pkt length error. BufLength = %d\n", BufLength)); 683 return; 684 } 685 686 pRxPacket = pNicDevice->pRxFree; 687 LengthInBytes = sizeof ( *pRxPacket ) - sizeof ( pRxPacket->pNext ); 688 if ( NULL == pRxPacket ) { 689 Status = gBS->AllocatePool ( EfiRuntimeServicesData, 690 sizeof( RX_TX_PACKET ), 691 (VOID **) &pRxPacket ); 692 if ( !EFI_ERROR ( Status )) { 693 // 694 // Add this packet to the free packet list 695 // 696 pNicDevice->pRxFree = pRxPacket; 697 pRxPacket->pNext = NULL; 698 } 699 else { 700 // 701 // Use the discard packet buffer 702 // 703 //pRxPacket = &Packet; 704 } 705 } 706 707 708 pData = pNicDevice->pBulkInBuff + offset + 4; 709 pRxPacket->Length = *pLength; 710 pRxPacket->LengthBar = *(UINT16*) (pNicDevice->pBulkInBuff + offset +2); 711 CopyMem (&pRxPacket->Data[0], pData, *pLength); 712 //DEBUG((DEBUG_INFO, "Packet [%d]\n", *pLength)); 713 714 pNicDevice->pRxFree = pRxPacket->pNext; 715 pRxPacket->pNext = NULL; 716 717 if ( NULL == pNicDevice->pRxTail ) { 718 pNicDevice->pRxHead = pRxPacket; 719 } 720 else { 721 pNicDevice->pRxTail->pNext = pRxPacket; 722 } 723 pNicDevice->pRxTail = pRxPacket; 724 offset += (*pLength + 4); 725 726 } 727 } 728 729 730 731 /** 732 Receive a frame from the network. 733 734 This routine polls the USB receive interface for a packet. If a packet 735 is available, this routine adds the receive packet to the list of 736 pending receive packets. 737 738 This routine calls ::Ax88772NegotiateLinkComplete to verify 739 that the link is up. This routine also calls ::SN_Reset to 740 reset the network adapter when necessary. Finally this 741 routine attempts to receive one or more packets from the 742 network adapter. 743 744 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 745 @param [in] bUpdateLink TRUE = Update link status 746 747 **/ 748 VOID 749 Ax88772Rx ( 750 IN NIC_DEVICE * pNicDevice, 751 IN BOOLEAN bUpdateLink 752 ) 753 { 754 BOOLEAN bFullDuplex; 755 BOOLEAN bLinkUp; 756 BOOLEAN bRxPacket; 757 BOOLEAN bSpeed100; 758 UINTN LengthInBytes; 759 RX_TX_PACKET Packet; 760 RX_TX_PACKET * pRxPacket; 761 EFI_USB_IO_PROTOCOL *pUsbIo; 762 EFI_STATUS Status; 763 EFI_TPL TplPrevious; 764 UINT32 TransferStatus; 765 766 // 767 // Synchronize with Ax88772Timer 768 // 769 VERIFY_TPL ( TPL_AX88772 ); 770 TplPrevious = gBS->RaiseTPL ( TPL_AX88772 ); 771 DEBUG (( DEBUG_TPL | DEBUG_INFO, 772 "%d: TPL\r\n", 773 TPL_AX88772 )); 774 775 // 776 // Get the link status 777 // 778 if ( bUpdateLink ) { 779 bLinkUp = pNicDevice->bLinkUp; 780 bSpeed100 = pNicDevice->b100Mbps; 781 bFullDuplex = pNicDevice->bFullDuplex; 782 Status = Ax88772NegotiateLinkComplete ( pNicDevice, 783 &pNicDevice->PollCount, 784 &pNicDevice->bComplete, 785 &pNicDevice->bLinkUp, 786 &pNicDevice->b100Mbps, 787 &pNicDevice->bFullDuplex ); 788 789 // 790 // Determine if the autonegotiation is complete 791 // 792 if ( pNicDevice->bComplete ) { 793 if ( pNicDevice->bLinkUp ) { 794 if (( bSpeed100 && ( !pNicDevice->b100Mbps )) 795 || (( !bSpeed100 ) && pNicDevice->b100Mbps ) 796 || ( bFullDuplex && ( !pNicDevice->bFullDuplex )) 797 || (( !bFullDuplex ) && pNicDevice->bFullDuplex )) { 798 pNicDevice->PollCount = 0; 799 DEBUG (( DEBUG_LINK | DEBUG_INFO, 800 "Reset to establish proper link setup: %d Mbps, %s duplex\r\n", 801 pNicDevice->b100Mbps ? 100 : 10, 802 pNicDevice->bFullDuplex ? L"Full" : L"Half" )); 803 Status = SN_Reset ( &pNicDevice->SimpleNetwork, FALSE ); 804 } 805 if (( !bLinkUp ) && pNicDevice->bLinkUp ) { 806 // 807 // Display the autonegotiation status 808 // 809 DEBUG (( DEBUG_LINK | DEBUG_INFO, 810 "Link: Up, %d Mbps, %s duplex\r\n", 811 pNicDevice->b100Mbps ? 100 : 10, 812 pNicDevice->bFullDuplex ? L"Full" : L"Half" )); 813 } 814 } 815 } 816 817 // 818 // Update the link status 819 // 820 if ( bLinkUp && ( !pNicDevice->bLinkUp )) { 821 DEBUG (( DEBUG_LINK | DEBUG_INFO, "Link: Down\r\n" )); 822 } 823 } 824 825 // 826 // Loop until all the packets are emptied from the receiver 827 // 828 do { 829 bRxPacket = FALSE; 830 831 // 832 // Locate a packet for use 833 // 834 pRxPacket = pNicDevice->pRxFree; 835 LengthInBytes = MAX_BULKIN_SIZE; 836 if ( NULL == pRxPacket ) { 837 Status = gBS->AllocatePool ( EfiRuntimeServicesData, 838 sizeof ( *pRxPacket ), 839 (VOID **) &pRxPacket ); 840 if ( !EFI_ERROR ( Status )) { 841 // 842 // Add this packet to the free packet list 843 // 844 pNicDevice->pRxFree = pRxPacket; 845 pRxPacket->pNext = NULL; 846 } 847 else { 848 // 849 // Use the discard packet buffer 850 // 851 pRxPacket = &Packet; 852 } 853 } 854 855 // 856 // Attempt to receive a packet 857 // 858 SetMem (&pNicDevice->pBulkInBuff[0], MAX_BULKIN_SIZE, 0); 859 pUsbIo = pNicDevice->pUsbIo; 860 Status = pUsbIo->UsbBulkTransfer ( pUsbIo, 861 USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT, 862 &pNicDevice->pBulkInBuff[0], 863 &LengthInBytes, 864 2, 865 &TransferStatus ); 866 if ( LengthInBytes > 0 ) { 867 FillPkt2Queue(pNicDevice, LengthInBytes); 868 } 869 pRxPacket = pNicDevice->pRxHead; 870 if (( !EFI_ERROR ( Status )) 871 && ( 0 < pRxPacket->Length ) 872 && ( pRxPacket->Length <= sizeof ( pRxPacket->Data )) 873 && ( LengthInBytes > 0)) { 874 875 // 876 // Determine if the packet should be received 877 // 878 bRxPacket = TRUE; 879 LengthInBytes = pRxPacket->Length; 880 pNicDevice->bLinkIdle = FALSE; 881 if ( pNicDevice->pRxFree == pRxPacket ) { 882 // 883 // Display the received packet 884 // 885 if ( 0 != ( pRxPacket->Data[0] & 1 )) { 886 if (( 0xff == pRxPacket->Data[0]) 887 && ( 0xff == pRxPacket->Data[1]) 888 && ( 0xff == pRxPacket->Data[2]) 889 && ( 0xff == pRxPacket->Data[3]) 890 && ( 0xff == pRxPacket->Data[4]) 891 && ( 0xff == pRxPacket->Data[5])) { 892 DEBUG (( DEBUG_RX_BROADCAST | DEBUG_INFO, 893 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", 894 pRxPacket->Data[0], 895 pRxPacket->Data[1], 896 pRxPacket->Data[2], 897 pRxPacket->Data[3], 898 pRxPacket->Data[4], 899 pRxPacket->Data[5], 900 pRxPacket->Data[6], 901 pRxPacket->Data[7], 902 pRxPacket->Data[8], 903 pRxPacket->Data[9], 904 pRxPacket->Data[10], 905 pRxPacket->Data[11], 906 pRxPacket->Data[12], 907 pRxPacket->Data[13], 908 LengthInBytes )); 909 } 910 else { 911 DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO, 912 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", 913 pRxPacket->Data[0], 914 pRxPacket->Data[1], 915 pRxPacket->Data[2], 916 pRxPacket->Data[3], 917 pRxPacket->Data[4], 918 pRxPacket->Data[5], 919 pRxPacket->Data[6], 920 pRxPacket->Data[7], 921 pRxPacket->Data[8], 922 pRxPacket->Data[9], 923 pRxPacket->Data[10], 924 pRxPacket->Data[11], 925 pRxPacket->Data[12], 926 pRxPacket->Data[13], 927 LengthInBytes )); 928 } 929 } 930 else { 931 DEBUG (( DEBUG_RX_UNICAST | DEBUG_INFO, 932 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", 933 pRxPacket->Data[0], 934 pRxPacket->Data[1], 935 pRxPacket->Data[2], 936 pRxPacket->Data[3], 937 pRxPacket->Data[4], 938 pRxPacket->Data[5], 939 pRxPacket->Data[6], 940 pRxPacket->Data[7], 941 pRxPacket->Data[8], 942 pRxPacket->Data[9], 943 pRxPacket->Data[10], 944 pRxPacket->Data[11], 945 pRxPacket->Data[12], 946 pRxPacket->Data[13], 947 LengthInBytes )); 948 } 949 950 } 951 else { 952 // 953 // Error, not enough buffers for this packet, discard packet 954 // 955 DEBUG (( DEBUG_WARN | DEBUG_INFO, 956 "WARNING - No buffer, discarding RX packet: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n", 957 pRxPacket->Data[0], 958 pRxPacket->Data[1], 959 pRxPacket->Data[2], 960 pRxPacket->Data[3], 961 pRxPacket->Data[4], 962 pRxPacket->Data[5], 963 pRxPacket->Data[6], 964 pRxPacket->Data[7], 965 pRxPacket->Data[8], 966 pRxPacket->Data[9], 967 pRxPacket->Data[10], 968 pRxPacket->Data[11], 969 pRxPacket->Data[12], 970 pRxPacket->Data[13], 971 LengthInBytes )); 972 } 973 } 974 }while ( bRxPacket ); 975 976 // 977 // Release the synchronization withhe Ax88772Timer 978 // 979 gBS->RestoreTPL ( TplPrevious ); 980 DEBUG (( DEBUG_TPL | DEBUG_INFO, 981 "%d: TPL\r\n", 982 TplPrevious )); 983 } 984 985 986 /** 987 Enable or disable the receiver 988 989 This routine calls ::Ax88772UsbCommand to update the 990 receiver state. This routine also calls ::Ax88772MacAddressSet 991 to establish the MAC address for the network adapter. 992 993 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 994 @param [in] RxFilter Simple network RX filter mask value 995 996 @retval EFI_SUCCESS The MAC address was set. 997 @retval other The MAC address was not set. 998 999 **/ 1000 EFI_STATUS 1001 Ax88772RxControl ( 1002 IN NIC_DEVICE * pNicDevice, 1003 IN UINT32 RxFilter 1004 ) 1005 { 1006 UINT16 MediumStatus; 1007 INT32 MulticastHash[2]; 1008 UINT16 RxControl; 1009 USB_DEVICE_REQUEST SetupMsg; 1010 EFI_STATUS Status; 1011 1012 DBG_ENTER ( ); 1013 1014 // 1015 // Disable all multicast 1016 // 1017 MulticastHash[0] = 0; 1018 MulticastHash[1] = 0; 1019 1020 // 1021 // Enable the receiver if something is to be received 1022 // 1023 Status = EFI_SUCCESS; 1024 RxControl = RXC_SO | RXC_MFB_16384; 1025 if ( 0 != RxFilter ) { 1026 // 1027 // Enable the receiver 1028 // 1029 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN 1030 | USB_REQ_TYPE_VENDOR 1031 | USB_TARGET_DEVICE; 1032 SetupMsg.Request = CMD_MEDIUM_STATUS_READ; 1033 SetupMsg.Value = 0; 1034 SetupMsg.Index = 0; 1035 SetupMsg.Length = sizeof ( MediumStatus ); 1036 Status = Ax88772UsbCommand ( pNicDevice, 1037 &SetupMsg, 1038 &MediumStatus ); 1039 if ( !EFI_ERROR ( Status )) { 1040 if ( 0 == ( MediumStatus & MS_RE )) { 1041 MediumStatus |= MS_RE | MS_ONE; 1042 if ( pNicDevice->bFullDuplex ) { 1043 MediumStatus |= MS_TFC | MS_RFC; 1044 } 1045 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 1046 | USB_TARGET_DEVICE; 1047 SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE; 1048 SetupMsg.Value = MediumStatus; 1049 SetupMsg.Index = 0; 1050 SetupMsg.Length = 0; 1051 Status = Ax88772UsbCommand ( pNicDevice, 1052 &SetupMsg, 1053 NULL ); 1054 if ( EFI_ERROR ( Status )) { 1055 DEBUG (( DEBUG_ERROR | DEBUG_INFO, 1056 "ERROR - Failed to enable receiver, Status: %r\r\n", 1057 Status )); 1058 } 1059 } 1060 } 1061 else { 1062 DEBUG (( DEBUG_ERROR | DEBUG_INFO, 1063 "ERROR - Failed to read receiver status, Status: %r\r\n", 1064 Status )); 1065 } 1066 1067 // 1068 // Enable multicast if requested 1069 // 1070 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) { 1071 RxControl |= RXC_AM; 1072 MulticastHash[0] = pNicDevice->MulticastHash[0]; 1073 MulticastHash[1] = pNicDevice->MulticastHash[1]; 1074 } 1075 1076 // 1077 // Enable all multicast if requested 1078 // 1079 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) { 1080 RxControl |= RXC_AMALL; 1081 MulticastHash[0] = -1; 1082 MulticastHash[1] = -1; 1083 } 1084 1085 // 1086 // Enable broadcast if requested 1087 // 1088 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) { 1089 RxControl |= RXC_AB; 1090 } 1091 1092 // 1093 // Enable promiscuous mode if requested 1094 // 1095 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) { 1096 RxControl |= RXC_PRO; 1097 MulticastHash[0] = -1; 1098 MulticastHash[1] = -1; 1099 } 1100 } 1101 1102 // 1103 // Update the MAC address 1104 // 1105 if ( !EFI_ERROR ( Status )) { 1106 Status = Ax88772MacAddressSet ( pNicDevice, &pNicDevice->SimpleNetworkData.CurrentAddress.Addr[0]); 1107 } 1108 1109 // 1110 // Update the receiver control 1111 // 1112 if ( !EFI_ERROR ( Status )) { 1113 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 1114 | USB_TARGET_DEVICE; 1115 SetupMsg.Request = CMD_RX_CONTROL_WRITE; 1116 SetupMsg.Value = RxControl; 1117 SetupMsg.Index = 0; 1118 SetupMsg.Length = 0; 1119 Status = Ax88772UsbCommand ( pNicDevice, 1120 &SetupMsg, 1121 NULL ); 1122 if ( !EFI_ERROR ( Status )) { 1123 DEBUG (( DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST | DEBUG_RX_UNICAST | DEBUG_INFO, 1124 "RxControl: 0x%04x\r\n", 1125 RxControl )); 1126 1127 // 1128 // Update the multicast hash table 1129 // 1130 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 1131 | USB_TARGET_DEVICE; 1132 SetupMsg.Request = CMD_MULTICAST_HASH_WRITE; 1133 SetupMsg.Value = 0; 1134 SetupMsg.Index = 0; 1135 SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash ); 1136 Status = Ax88772UsbCommand ( pNicDevice, 1137 &SetupMsg, 1138 &pNicDevice->MulticastHash ); 1139 if ( !EFI_ERROR ( Status )) { 1140 DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO, 1141 "Multicast Hash: 0x%02x %02x %02x %02x %02x %02x %02x %02x\r\n", 1142 (UINT8) MulticastHash[0], 1143 (UINT8)( MulticastHash[0] >> 8 ), 1144 (UINT8)( MulticastHash[0] >> 16 ), 1145 (UINT8)( MulticastHash[0] >> 24 ), 1146 (UINT8) MulticastHash[1], 1147 (UINT8)( MulticastHash[1] >> 8 ), 1148 (UINT8)( MulticastHash[1] >> 16 ), 1149 (UINT8)( MulticastHash[1] >> 24 ))); 1150 } 1151 else { 1152 DEBUG (( DEBUG_ERROR | DEBUG_INFO, 1153 "ERROR - Failed to update multicast hash table, Status: %r\r\n", 1154 Status )); 1155 } 1156 } 1157 else { 1158 DEBUG (( DEBUG_ERROR | DEBUG_INFO, 1159 "ERROR - Failed to set receiver control, Status: %r\r\n", 1160 Status )); 1161 } 1162 } 1163 1164 // 1165 // Return the operation status 1166 // 1167 DBG_EXIT_STATUS ( Status ); 1168 return Status; 1169 } 1170 1171 1172 /** 1173 Read an SROM location 1174 1175 This routine calls ::Ax88772UsbCommand to read data from the 1176 SROM. 1177 1178 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 1179 @param [in] Address SROM address 1180 @param [out] pData Buffer to receive the data 1181 1182 @retval EFI_SUCCESS The read was successful 1183 @retval other The read failed 1184 1185 **/ 1186 EFI_STATUS 1187 Ax88772SromRead ( 1188 IN NIC_DEVICE * pNicDevice, 1189 IN UINT32 Address, 1190 OUT UINT16 * pData 1191 ) 1192 { 1193 USB_DEVICE_REQUEST SetupMsg; 1194 EFI_STATUS Status; 1195 1196 DBG_ENTER ( ); 1197 1198 // 1199 // Read a value from the SROM 1200 // 1201 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN 1202 | USB_REQ_TYPE_VENDOR 1203 | USB_TARGET_DEVICE; 1204 SetupMsg.Request = CMD_SROM_READ; 1205 SetupMsg.Value = (UINT16) Address; 1206 SetupMsg.Index = 0; 1207 SetupMsg.Length = sizeof ( *pData ); 1208 Status = Ax88772UsbCommand ( pNicDevice, 1209 &SetupMsg, 1210 pData ); 1211 1212 // 1213 // Return the operation status 1214 // 1215 DBG_EXIT_STATUS ( Status ); 1216 return Status; 1217 } 1218 1219 1220 /** 1221 This routine is called at a regular interval to poll for 1222 receive packets. 1223 1224 This routine polls the link state and gets any receive packets 1225 by calling ::Ax88772Rx. 1226 1227 @param [in] Event Timer event 1228 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 1229 1230 **/ 1231 VOID 1232 Ax88772Timer ( 1233 IN EFI_EVENT Event, 1234 IN NIC_DEVICE * pNicDevice 1235 ) 1236 { 1237 // 1238 // Use explicit DEBUG messages since the output frequency is too 1239 // high for DEBUG_INFO to keep up and have spare cycles for the 1240 // shell 1241 // 1242 DEBUG (( DEBUG_TIMER, "Entering Ax88772Timer\r\n" )); 1243 1244 // 1245 // Poll the link state and get any receive packets 1246 // 1247 Ax88772Rx ( pNicDevice, FALSE ); 1248 1249 DEBUG (( DEBUG_TIMER, "Exiting Ax88772Timer\r\n" )); 1250 } 1251 1252 1253 /** 1254 Send a command to the USB device. 1255 1256 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 1257 @param [in] pRequest Pointer to the request structure 1258 @param [in, out] pBuffer Data buffer address 1259 1260 @retval EFI_SUCCESS The USB transfer was successful 1261 @retval other The USB transfer failed 1262 1263 **/ 1264 EFI_STATUS 1265 Ax88772UsbCommand ( 1266 IN NIC_DEVICE * pNicDevice, 1267 IN USB_DEVICE_REQUEST * pRequest, 1268 IN OUT VOID * pBuffer 1269 ) 1270 { 1271 UINT32 CmdStatus; 1272 EFI_USB_DATA_DIRECTION Direction; 1273 EFI_USB_IO_PROTOCOL * pUsbIo; 1274 EFI_STATUS Status; 1275 1276 DBG_ENTER ( ); 1277 1278 // 1279 // Determine the transfer direction 1280 // 1281 Direction = EfiUsbNoData; 1282 if ( 0 != pRequest->Length ) { 1283 Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN )) 1284 ? EfiUsbDataIn : EfiUsbDataOut; 1285 } 1286 1287 // 1288 // Issue the command 1289 // 1290 pUsbIo = pNicDevice->pUsbIo; 1291 Status = pUsbIo->UsbControlTransfer ( pUsbIo, 1292 pRequest, 1293 Direction, 1294 USB_BUS_TIMEOUT, 1295 pBuffer, 1296 pRequest->Length, 1297 &CmdStatus ); 1298 1299 // 1300 // Determine the operation status 1301 // 1302 if ( !EFI_ERROR ( Status )) { 1303 Status = CmdStatus; 1304 } 1305 else { 1306 // 1307 // Display any errors 1308 // 1309 DEBUG (( DEBUG_INFO, 1310 "Ax88772UsbCommand - Status: %r\n", 1311 Status )); 1312 1313 // 1314 // Only use status values associated with the Simple Network protocol 1315 // 1316 if ( EFI_TIMEOUT == Status ) { 1317 Status = EFI_DEVICE_ERROR; 1318 } 1319 } 1320 1321 // 1322 // Return the operation status 1323 // 1324 DBG_EXIT_STATUS ( Status ); 1325 return Status; 1326 } 1327