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 9 All rights reserved. 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**/ 30UINT32 31Ax88772Crc ( 32 IN UINT8 * pMacAddress 33 ) 34{ 35 UINT32 BitNumber; 36 INT32 Carry; 37 INT32 Crc; 38 UINT32 Data; 39 UINT8 * pEnd; 40 41 // 42 // Walk the MAC address 43 // 44 Crc = -1; 45 pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ]; 46 while ( pEnd > pMacAddress ) { 47 Data = *pMacAddress++; 48 // 49 // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 50 // 51 // 1 0000 0100 1100 0001 0001 1101 1011 0111 52 // 53 for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) { 54 Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 ); 55 Crc <<= 1; 56 if ( 0 != Carry ) { 57 Crc ^= 0x04c11db7; 58 } 59 Data >>= 1; 60 } 61 } 62 // 63 // Return the CRC value 64 // 65 return (UINT32) Crc; 66} 67 68 69/** 70 Get the MAC address 71 72 This routine calls ::Ax88772UsbCommand to request the MAC 73 address from the network adapter. 74 75 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 76 @param [out] pMacAddress Address of a six byte buffer to receive the MAC address. 77 78 @retval EFI_SUCCESS The MAC address is available. 79 @retval other The MAC address is not valid. 80 81**/ 82EFI_STATUS 83Ax88772MacAddressGet ( 84 IN NIC_DEVICE * pNicDevice, 85 OUT UINT8 * pMacAddress 86 ) 87{ 88 USB_DEVICE_REQUEST SetupMsg; 89 EFI_STATUS Status; 90 91 // 92 // Set the register address. 93 // 94 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN 95 | USB_REQ_TYPE_VENDOR 96 | USB_TARGET_DEVICE; 97 SetupMsg.Request = CMD_MAC_ADDRESS_READ; 98 SetupMsg.Value = 0; 99 SetupMsg.Index = 0; 100 SetupMsg.Length = PXE_HWADDR_LEN_ETHER; 101 102 // 103 // Read the PHY register 104 // 105 Status = Ax88772UsbCommand ( pNicDevice, 106 &SetupMsg, 107 pMacAddress ); 108 return Status; 109} 110 111 112/** 113 Set the MAC address 114 115 This routine calls ::Ax88772UsbCommand to set the MAC address 116 in the network adapter. 117 118 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 119 @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address. 120 121 @retval EFI_SUCCESS The MAC address was set. 122 @retval other The MAC address was not set. 123 124**/ 125EFI_STATUS 126Ax88772MacAddressSet ( 127 IN NIC_DEVICE * pNicDevice, 128 IN UINT8 * pMacAddress 129 ) 130{ 131 USB_DEVICE_REQUEST SetupMsg; 132 EFI_STATUS Status; 133 134 // 135 // Set the register address. 136 // 137 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 138 | USB_TARGET_DEVICE; 139 SetupMsg.Request = CMD_MAC_ADDRESS_WRITE; 140 SetupMsg.Value = 0; 141 SetupMsg.Index = 0; 142 SetupMsg.Length = PXE_HWADDR_LEN_ETHER; 143 144 // 145 // Read the PHY register 146 // 147 Status = Ax88772UsbCommand ( pNicDevice, 148 &SetupMsg, 149 pMacAddress ); 150 return Status; 151} 152 153/** 154 Clear the multicast hash table 155 156 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 157 158**/ 159VOID 160Ax88772MulticastClear ( 161 IN NIC_DEVICE * pNicDevice 162 ) 163{ 164 int i = 0; 165 // 166 // Clear the multicast hash table 167 // 168 for ( i = 0 ; i < 8 ; i ++ ) 169 pNicDevice->MulticastHash[0] = 0; 170} 171 172/** 173 Enable a multicast address in the multicast hash table 174 175 This routine calls ::Ax88772Crc to compute the hash bit for 176 this MAC address. 177 178 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 179 @param [in] pMacAddress Address of a six byte buffer to containing the MAC address. 180 181**/ 182VOID 183Ax88772MulticastSet ( 184 IN NIC_DEVICE * pNicDevice, 185 IN UINT8 * pMacAddress 186 ) 187{ 188 UINT32 Crc; 189 190 // 191 // Compute the CRC on the destination address 192 // 193 Crc = Ax88772Crc ( pMacAddress ) >> 26; 194 195 // 196 // Set the bit corresponding to the destination address 197 // 198 pNicDevice->MulticastHash [ Crc >> 3 ] |= ( 1<< (Crc& 7)); 199} 200 201/** 202 Start the link negotiation 203 204 This routine calls ::Ax88772PhyWrite to start the PHY's link 205 negotiation. 206 207 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 208 209 @retval EFI_SUCCESS The link negotiation was started. 210 @retval other Failed to start the link negotiation. 211 212**/ 213EFI_STATUS 214Ax88772NegotiateLinkStart ( 215 IN NIC_DEVICE * pNicDevice 216 ) 217{ 218 UINT16 Control; 219 EFI_STATUS Status; 220 int i; 221 // 222 // Set the supported capabilities. 223 // 224 Status = Ax88772PhyWrite ( pNicDevice, 225 PHY_ANAR, 226 AN_CSMA_CD 227 | AN_TX_FDX | AN_TX_HDX 228 | AN_10_FDX | AN_10_HDX ); 229 if ( !EFI_ERROR ( Status )) { 230 // 231 // Set the link speed and duplex 232 // 233 Control = BMCR_AUTONEGOTIATION_ENABLE 234 | BMCR_RESTART_AUTONEGOTIATION; 235 if ( pNicDevice->b100Mbps ) { 236 Control |= BMCR_100MBPS; 237 } 238 if ( pNicDevice->bFullDuplex ) { 239 Control |= BMCR_FULL_DUPLEX; 240 } 241 Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control ); 242 } 243 244 if (!EFI_ERROR(Status)) { 245 i = 0; 246 do { 247 248 if (pNicDevice->bComplete && pNicDevice->bLinkUp) { 249 pNicDevice->SimpleNetwork.Mode->MediaPresent 250 = pNicDevice->bLinkUp & pNicDevice->bComplete; 251 break; 252 } 253 else { 254 gBS->Stall(AUTONEG_DELAY); 255 Status = Ax88772NegotiateLinkComplete ( pNicDevice, 256 &pNicDevice->PollCount, 257 &pNicDevice->bComplete, 258 &pNicDevice->bLinkUp, 259 &pNicDevice->b100Mbps, 260 &pNicDevice->bFullDuplex ); 261 i++; 262 } 263 }while(!pNicDevice->bLinkUp && i < AUTONEG_POLLCNT); 264 } 265 return Status; 266} 267 268 269/** 270 Complete the negotiation of the PHY link 271 272 This routine calls ::Ax88772PhyRead to determine if the 273 link negotiation is complete. 274 275 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 276 @param [in, out] pPollCount Address of number of times this routine was polled 277 @param [out] pbComplete Address of boolean to receive complate status. 278 @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up. 279 @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps. 280 @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full. 281 282 @retval EFI_SUCCESS The MAC address is available. 283 @retval other The MAC address is not valid. 284 285**/ 286EFI_STATUS 287Ax88772NegotiateLinkComplete ( 288 IN NIC_DEVICE * pNicDevice, 289 IN OUT UINTN * pPollCount, 290 OUT BOOLEAN * pbComplete, 291 OUT BOOLEAN * pbLinkUp, 292 OUT BOOLEAN * pbHiSpeed, 293 OUT BOOLEAN * pbFullDuplex 294 ) 295{ 296 UINT16 Mask; 297 UINT16 PhyData; 298 EFI_STATUS Status; 299 300 // 301 // Determine if the link is up. 302 // 303 *pbComplete = FALSE; 304 305 // 306 // Get the link status 307 // 308 Status = Ax88772PhyRead ( pNicDevice, 309 PHY_BMSR, 310 &PhyData ); 311 312 if ( !EFI_ERROR ( Status )) { 313 *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST )); 314 if ( 0 == *pbLinkUp ) { 315 DEBUG (( EFI_D_INFO, "Link Down\n" )); 316 } 317 else { 318 *pbComplete = (BOOLEAN)( 0 != ( PhyData & 0x20 )); 319 if ( 0 == *pbComplete ) { 320 DEBUG (( EFI_D_INFO, "Autoneg is not yet Complete\n" )); 321 } 322 else { 323 Status = Ax88772PhyRead ( pNicDevice, 324 PHY_ANLPAR, 325 &PhyData ); 326 if ( !EFI_ERROR ( Status )) { 327 // 328 // Autonegotiation is complete 329 // Determine the link speed. 330 // 331 *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX ))); 332 333 // 334 // Determine the link duplex. 335 // 336 Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX; 337 *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask )); 338 } 339 } 340 } 341 } 342 else { 343 DEBUG (( EFI_D_ERROR, "Failed to read BMCR\n" )); 344 } 345 return Status; 346} 347 348 349/** 350 Read a register from the PHY 351 352 This routine calls ::Ax88772UsbCommand to read a PHY register. 353 354 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 355 @param [in] RegisterAddress Number of the register to read. 356 @param [in, out] pPhyData Address of a buffer to receive the PHY register value 357 358 @retval EFI_SUCCESS The PHY data is available. 359 @retval other The PHY data is not valid. 360 361**/ 362EFI_STATUS 363Ax88772PhyRead ( 364 IN NIC_DEVICE * pNicDevice, 365 IN UINT8 RegisterAddress, 366 IN OUT UINT16 * pPhyData 367 ) 368{ 369 USB_DEVICE_REQUEST SetupMsg; 370 EFI_STATUS Status; 371 372 // 373 // Request access to the PHY 374 // 375 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 376 | USB_TARGET_DEVICE; 377 SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE; 378 SetupMsg.Value = 0; 379 SetupMsg.Index = 0; 380 SetupMsg.Length = 0; 381 Status = Ax88772UsbCommand ( pNicDevice, 382 &SetupMsg, 383 NULL ); 384 if ( !EFI_ERROR ( Status )) { 385 // 386 // Read the PHY register address. 387 // 388 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN 389 | USB_REQ_TYPE_VENDOR 390 | USB_TARGET_DEVICE; 391 SetupMsg.Request = CMD_PHY_REG_READ; 392 SetupMsg.Value = pNicDevice->PhyId; 393 SetupMsg.Index = RegisterAddress; 394 SetupMsg.Length = sizeof ( *pPhyData ); 395 Status = Ax88772UsbCommand ( pNicDevice, 396 &SetupMsg, 397 pPhyData ); 398 if ( !EFI_ERROR ( Status )) { 399 400 // 401 // Release the PHY to the hardware 402 // 403 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 404 | USB_TARGET_DEVICE; 405 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE; 406 SetupMsg.Value = 0; 407 SetupMsg.Index = 0; 408 SetupMsg.Length = 0; 409 Status = Ax88772UsbCommand ( pNicDevice, 410 &SetupMsg, 411 NULL ); 412 } 413 } 414 return Status; 415} 416 417 418/** 419 Write to a PHY register 420 421 This routine calls ::Ax88772UsbCommand to write a PHY register. 422 423 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 424 @param [in] RegisterAddress Number of the register to read. 425 @param [in] PhyData Address of a buffer to receive the PHY register value 426 427 @retval EFI_SUCCESS The PHY data was written. 428 @retval other Failed to wwrite the PHY register. 429 430**/ 431EFI_STATUS 432Ax88772PhyWrite ( 433 IN NIC_DEVICE * pNicDevice, 434 IN UINT8 RegisterAddress, 435 IN UINT16 PhyData 436 ) 437{ 438 USB_DEVICE_REQUEST SetupMsg; 439 EFI_STATUS Status; 440 441 // 442 // Request access to the PHY 443 // 444 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 445 | USB_TARGET_DEVICE; 446 SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE; 447 SetupMsg.Value = 0; 448 SetupMsg.Index = 0; 449 SetupMsg.Length = 0; 450 Status = Ax88772UsbCommand ( pNicDevice, 451 &SetupMsg, 452 NULL ); 453 if ( !EFI_ERROR ( Status )) { 454 // 455 // Write the PHY register 456 // 457 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 458 | USB_TARGET_DEVICE; 459 SetupMsg.Request = CMD_PHY_REG_WRITE; 460 SetupMsg.Value = pNicDevice->PhyId; 461 SetupMsg.Index = RegisterAddress; 462 SetupMsg.Length = sizeof ( PhyData ); 463 Status = Ax88772UsbCommand ( pNicDevice, 464 &SetupMsg, 465 &PhyData ); 466 if ( !EFI_ERROR ( Status )) { 467 468 // 469 // Release the PHY to the hardware 470 // 471 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 472 | USB_TARGET_DEVICE; 473 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE; 474 SetupMsg.Value = 0; 475 SetupMsg.Index = 0; 476 SetupMsg.Length = 0; 477 Status = Ax88772UsbCommand ( pNicDevice, 478 &SetupMsg, 479 NULL ); 480 } 481 } 482 483 return Status; 484} 485 486 487/** 488 Reset the AX88772 489 490 This routine uses ::Ax88772UsbCommand to reset the network 491 adapter. This routine also uses ::Ax88772PhyWrite to reset 492 the PHY. 493 494 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 495 496 @retval EFI_SUCCESS The MAC address is available. 497 @retval other The MAC address is not valid. 498 499**/ 500EFI_STATUS 501Ax88772Reset ( 502 IN NIC_DEVICE * pNicDevice 503 ) 504{ 505 USB_DEVICE_REQUEST SetupMsg; 506 EFI_STATUS Status; 507 508 EFI_USB_IO_PROTOCOL *pUsbIo; 509 EFI_USB_DEVICE_DESCRIPTOR Device; 510 511 pUsbIo = pNicDevice->pUsbIo; 512 Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device ); 513 514 if (EFI_ERROR(Status)) goto err; 515 516 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 517 | USB_TARGET_DEVICE; 518 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE; 519 SetupMsg.Value = 0; 520 SetupMsg.Index = 0; 521 SetupMsg.Length = 0; 522 Status = Ax88772UsbCommand ( pNicDevice, 523 &SetupMsg, 524 NULL ); 525 526 if (EFI_ERROR(Status)) goto err; 527 528 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 529 | USB_TARGET_DEVICE; 530 SetupMsg.Request = CMD_PHY_SELECT; 531 SetupMsg.Value = SPHY_PSEL; 532 SetupMsg.Index = 0; 533 SetupMsg.Length = 0; 534 Status = Ax88772UsbCommand ( pNicDevice, 535 &SetupMsg, 536 NULL ); 537 538 if (EFI_ERROR(Status)) goto err; 539 540 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 541 | USB_TARGET_DEVICE; 542 SetupMsg.Request = CMD_RESET; 543 SetupMsg.Value = SRR_IPRL ; 544 SetupMsg.Index = 0; 545 SetupMsg.Length = 0; 546 Status = Ax88772UsbCommand ( pNicDevice, 547 &SetupMsg, 548 NULL ); 549 550 if (EFI_ERROR(Status)) goto err; 551 552 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 553 | USB_TARGET_DEVICE; 554 SetupMsg.Request = CMD_RESET; 555 SetupMsg.Value = SRR_IPPD | SRR_IPRL ; 556 SetupMsg.Index = 0; 557 SetupMsg.Length = 0; 558 Status = Ax88772UsbCommand ( pNicDevice, 559 &SetupMsg, 560 NULL ); 561 562 gBS->Stall ( 200000 ); 563 564 if (EFI_ERROR(Status)) goto err; 565 566 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 567 | USB_TARGET_DEVICE; 568 SetupMsg.Request = CMD_RESET; 569 SetupMsg.Value = SRR_IPRL ; 570 SetupMsg.Index = 0; 571 SetupMsg.Length = 0; 572 Status = Ax88772UsbCommand ( pNicDevice, 573 &SetupMsg, 574 NULL ); 575 576 gBS->Stall ( 200000 ); 577 578 if (EFI_ERROR(Status)) goto err; 579 580 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 581 | USB_TARGET_DEVICE; 582 SetupMsg.Request = CMD_RESET; 583 SetupMsg.Value = 0; 584 SetupMsg.Index = 0; 585 SetupMsg.Length = 0; 586 Status = Ax88772UsbCommand ( pNicDevice, 587 &SetupMsg, 588 NULL ); 589 590 if (EFI_ERROR(Status)) goto err; 591 592 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 593 | USB_TARGET_DEVICE; 594 SetupMsg.Request = CMD_PHY_SELECT; 595 SetupMsg.Value = SPHY_PSEL; 596 SetupMsg.Index = 0; 597 SetupMsg.Length = 0; 598 Status = Ax88772UsbCommand ( pNicDevice, 599 &SetupMsg, 600 NULL ); 601 602 if (EFI_ERROR(Status)) goto err; 603 604 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 605 | USB_TARGET_DEVICE; 606 SetupMsg.Request = CMD_RESET; 607 SetupMsg.Value = SRR_IPRL | SRR_BZ | SRR_BZTYPE; 608 SetupMsg.Index = 0; 609 SetupMsg.Length = 0; 610 Status = Ax88772UsbCommand ( pNicDevice, 611 &SetupMsg, 612 NULL ); 613 614 if (EFI_ERROR(Status)) goto err; 615 616 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 617 | USB_TARGET_DEVICE; 618 SetupMsg.Request = CMD_RX_CONTROL_WRITE; 619 SetupMsg.Value = 0; 620 SetupMsg.Index = 0; 621 SetupMsg.Length = 0; 622 Status = Ax88772UsbCommand ( pNicDevice, 623 &SetupMsg, 624 NULL ); 625 626 if (EFI_ERROR(Status)) goto err; 627 628 if (pNicDevice->Flags != FLAG_TYPE_AX88772) { 629 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 630 | USB_TARGET_DEVICE; 631 SetupMsg.Request = CMD_RXQTC; 632 SetupMsg.Value = 0x8000; 633 SetupMsg.Index = 0x8001; 634 SetupMsg.Length = 0; 635 Status = Ax88772UsbCommand ( pNicDevice, 636 &SetupMsg, 637 NULL ); 638 } 639 640err: 641 return Status; 642} 643 644/** 645 Enable or disable the receiver 646 647 This routine calls ::Ax88772UsbCommand to update the 648 receiver state. This routine also calls ::Ax88772MacAddressSet 649 to establish the MAC address for the network adapter. 650 651 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 652 @param [in] RxFilter Simple network RX filter mask value 653 654 @retval EFI_SUCCESS The MAC address was set. 655 @retval other The MAC address was not set. 656 657**/ 658EFI_STATUS 659Ax88772RxControl ( 660 IN NIC_DEVICE * pNicDevice, 661 IN UINT32 RxFilter 662 ) 663{ 664 UINT16 MediumStatus; 665 UINT16 RxControl; 666 USB_DEVICE_REQUEST SetupMsg; 667 EFI_STATUS Status; 668 EFI_USB_IO_PROTOCOL *pUsbIo; 669 EFI_USB_DEVICE_DESCRIPTOR Device; 670 671 pUsbIo = pNicDevice->pUsbIo; 672 Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device ); 673 674 if (EFI_ERROR(Status)) { 675 DEBUG (( EFI_D_ERROR, "Failed to get device descriptor\n" )); 676 return Status; 677 } 678 679 // 680 // Enable the receiver if something is to be received 681 // 682 683 if ( 0 != RxFilter ) { 684 // 685 // Enable the receiver 686 // 687 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN 688 | USB_REQ_TYPE_VENDOR 689 | USB_TARGET_DEVICE; 690 SetupMsg.Request = CMD_MEDIUM_STATUS_READ; 691 SetupMsg.Value = 0; 692 SetupMsg.Index = 0; 693 SetupMsg.Length = sizeof ( MediumStatus ); 694 Status = Ax88772UsbCommand ( pNicDevice, 695 &SetupMsg, 696 &MediumStatus ); 697 if ( !EFI_ERROR ( Status )) { 698 if ( 0 == ( MediumStatus & MS_RE )) { 699 MediumStatus |= MS_RE | MS_ONE; 700 701 if ( pNicDevice->bFullDuplex ) 702 MediumStatus |= MS_TFC | MS_RFC | MS_FD; 703 else 704 MediumStatus &= ~(MS_TFC | MS_RFC | MS_FD); 705 706 if ( pNicDevice->b100Mbps ) 707 MediumStatus |= MS_PS; 708 else 709 MediumStatus &= ~MS_PS; 710 711 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 712 | USB_TARGET_DEVICE; 713 SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE; 714 SetupMsg.Value = MediumStatus; 715 SetupMsg.Index = 0; 716 SetupMsg.Length = 0; 717 Status = Ax88772UsbCommand ( pNicDevice, 718 &SetupMsg, 719 NULL ); 720 if ( EFI_ERROR ( Status )) { 721 DEBUG (( EFI_D_ERROR, "Failed to enable receiver, Status: %r\r\n", 722 Status )); 723 } 724 } 725 } 726 else { 727 DEBUG (( EFI_D_ERROR, "Failed to read receiver status, Status: %r\r\n", 728 Status )); 729 } 730 } 731 732 RxControl = RXC_SO | RXC_RH1M; 733 // 734 // Enable multicast if requested 735 // 736 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) { 737 RxControl |= RXC_AM; 738 // 739 // Update the multicast hash table 740 // 741 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 742 | USB_TARGET_DEVICE; 743 SetupMsg.Request = CMD_MULTICAST_HASH_WRITE; 744 SetupMsg.Value = 0; 745 SetupMsg.Index = 0; 746 SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash ); 747 Status = Ax88772UsbCommand ( pNicDevice, 748 &SetupMsg, 749 &pNicDevice->MulticastHash ); 750 } 751 // 752 // Enable all multicast if requested 753 // 754 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) { 755 RxControl |= RXC_AMALL; 756 } 757 758 // 759 // Enable broadcast if requested 760 // 761 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) { 762 RxControl |= RXC_AB; 763 } 764 765 // 766 // Enable promiscuous mode if requested 767 // 768 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) { 769 RxControl |= RXC_PRO; 770 } 771 772 // 773 // Update the receiver control 774 // 775 if (pNicDevice->CurRxControl != RxControl) { 776 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR 777 | USB_TARGET_DEVICE; 778 SetupMsg.Request = CMD_RX_CONTROL_WRITE; 779 SetupMsg.Value = RxControl; 780 SetupMsg.Index = 0; 781 SetupMsg.Length = 0; 782 Status = Ax88772UsbCommand ( pNicDevice, 783 &SetupMsg, 784 NULL ); 785 if ( !EFI_ERROR ( Status )) { 786 pNicDevice->CurRxControl = RxControl; 787 788 } 789 else { 790 DEBUG (( EFI_D_ERROR, "ERROR - Failed to set receiver control, Status: %r\r\n", 791 Status )); 792 } 793 } 794 return Status; 795} 796 797 798/** 799 Read an SROM location 800 801 This routine calls ::Ax88772UsbCommand to read data from the 802 SROM. 803 804 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 805 @param [in] Address SROM address 806 @param [out] pData Buffer to receive the data 807 808 @retval EFI_SUCCESS The read was successful 809 @retval other The read failed 810 811**/ 812EFI_STATUS 813Ax88772SromRead ( 814 IN NIC_DEVICE * pNicDevice, 815 IN UINT32 Address, 816 OUT UINT16 * pData 817 ) 818{ 819 return EFI_UNSUPPORTED; 820} 821 822/** 823 Send a command to the USB device. 824 825 @param [in] pNicDevice Pointer to the NIC_DEVICE structure 826 @param [in] pRequest Pointer to the request structure 827 @param [in, out] pBuffer Data buffer address 828 829 @retval EFI_SUCCESS The USB transfer was successful 830 @retval other The USB transfer failed 831 832**/ 833EFI_STATUS 834Ax88772UsbCommand ( 835 IN NIC_DEVICE * pNicDevice, 836 IN USB_DEVICE_REQUEST * pRequest, 837 IN OUT VOID * pBuffer 838 ) 839{ 840 UINT32 CmdStatus; 841 EFI_USB_DATA_DIRECTION Direction; 842 EFI_USB_IO_PROTOCOL * pUsbIo; 843 EFI_STATUS Status; 844 845 // 846 // Determine the transfer direction 847 // 848 Direction = EfiUsbNoData; 849 if ( 0 != pRequest->Length ) { 850 Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN )) 851 ? EfiUsbDataIn : EfiUsbDataOut; 852 } 853 854 // 855 // Issue the command 856 // 857 pUsbIo = pNicDevice->pUsbIo; 858 Status = pUsbIo->UsbControlTransfer ( pUsbIo, 859 pRequest, 860 Direction, 861 USB_BUS_TIMEOUT, 862 pBuffer, 863 pRequest->Length, 864 &CmdStatus ); 865 // 866 // Determine the operation status 867 // 868 if ( !EFI_ERROR ( Status )) { 869 Status = CmdStatus; 870 } 871 else { 872 // 873 // Only use status values associated with the Simple Network protocol 874 // 875 if ( EFI_TIMEOUT == Status ) { 876 Status = EFI_DEVICE_ERROR; 877 } 878 } 879 return Status; 880} 881 882