2 Implement the interface to the AX88772 Ethernet controller.
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.
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
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.
25 @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.
27 @returns The CRC-32 value associated with this MAC address
32 IN UINT8
* pMacAddress
44 // Walk the MAC address
47 pEnd
= &pMacAddress
[ PXE_HWADDR_LEN_ETHER
];
48 while ( pEnd
> pMacAddress
) {
49 Data
= *pMacAddress
++;
53 // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
55 // 1 0000 0100 1100 0001 0001 1101 1011 0111
57 for ( BitNumber
= 0; 8 > BitNumber
; BitNumber
++ ) {
58 Carry
= (( Crc
>> 31 ) & 1 ) ^ ( Data
& 1 );
68 // Return the CRC value
78 This routine calls ::Ax88772UsbCommand to request the MAC
79 address from the network adapter.
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.
84 @retval EFI_SUCCESS The MAC address is available.
85 @retval other The MAC address is not valid.
89 Ax88772MacAddressGet (
90 IN NIC_DEVICE
* pNicDevice
,
91 OUT UINT8
* pMacAddress
94 USB_DEVICE_REQUEST SetupMsg
;
100 // Set the register address.
102 SetupMsg
.RequestType
= USB_ENDPOINT_DIR_IN
103 | USB_REQ_TYPE_VENDOR
105 SetupMsg
.Request
= CMD_MAC_ADDRESS_READ
;
108 SetupMsg
.Length
= PXE_HWADDR_LEN_ETHER
;
111 // Read the PHY register
113 Status
= Ax88772UsbCommand ( pNicDevice
,
118 // Return the operation status
120 DBG_EXIT_STATUS ( Status
);
128 This routine calls ::Ax88772UsbCommand to set the MAC address
129 in the network adapter.
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.
134 @retval EFI_SUCCESS The MAC address was set.
135 @retval other The MAC address was not set.
139 Ax88772MacAddressSet (
140 IN NIC_DEVICE
* pNicDevice
,
141 IN UINT8
* pMacAddress
144 USB_DEVICE_REQUEST SetupMsg
;
150 // Set the register address.
152 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
154 SetupMsg
.Request
= CMD_MAC_ADDRESS_WRITE
;
157 SetupMsg
.Length
= PXE_HWADDR_LEN_ETHER
;
160 // Read the PHY register
162 Status
= Ax88772UsbCommand ( pNicDevice
,
167 // Return the operation status
169 DBG_EXIT_STATUS ( Status
);
175 Clear the multicast hash table
177 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
181 Ax88772MulticastClear (
182 IN NIC_DEVICE
* pNicDevice
188 // Clear the multicast hash table
190 pNicDevice
->MulticastHash
[0] = 0;
191 pNicDevice
->MulticastHash
[1] = 0;
198 Enable a multicast address in the multicast hash table
200 This routine calls ::Ax88772Crc to compute the hash bit for
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.
208 Ax88772MulticastSet (
209 IN NIC_DEVICE
* pNicDevice
,
210 IN UINT8
* pMacAddress
220 // Compute the CRC on the destination address
222 Crc
= Ax88772Crc ( pMacAddress
);
225 // Set the bit corresponding to the destination address
227 BitNumber
= Crc
>> 26;
228 if ( 32 > BitNumber
) {
229 Mask
= 1 << BitNumber
;
230 pNicDevice
->MulticastHash
[0] |= Mask
;
233 Mask
= 1 << ( BitNumber
- 32 );
234 pNicDevice
->MulticastHash
[1] |= Mask
;
238 // Display the multicast address
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",
256 Start the link negotiation
258 This routine calls ::Ax88772PhyWrite to start the PHY's link
261 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
263 @retval EFI_SUCCESS The link negotiation was started.
264 @retval other Failed to start the link negotiation.
268 Ax88772NegotiateLinkStart (
269 IN NIC_DEVICE
* pNicDevice
278 // Set the supported capabilities.
280 Status
= Ax88772PhyWrite ( pNicDevice
,
283 | AN_TX_FDX
| AN_TX_HDX
284 | AN_10_FDX
| AN_10_HDX
);
285 if ( !EFI_ERROR ( Status
)) {
287 // Set the link speed and duplex
289 Control
= BMCR_AUTONEGOTIATION_ENABLE
290 | BMCR_RESTART_AUTONEGOTIATION
;
291 if ( pNicDevice
->b100Mbps
) {
292 Control
|= BMCR_100MBPS
;
294 if ( pNicDevice
->bFullDuplex
) {
295 Control
|= BMCR_FULL_DUPLEX
;
297 Status
= Ax88772PhyWrite ( pNicDevice
, PHY_BMCR
, Control
);
301 // Return the operation status
303 DBG_EXIT_STATUS ( Status
);
309 Complete the negotiation of the PHY link
311 This routine calls ::Ax88772PhyRead to determine if the
312 link negotiation is complete.
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.
321 @retval EFI_SUCCESS The MAC address is available.
322 @retval other The MAC address is not valid.
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
342 // Determine if the link is up.
347 // Get the link status
349 Status
= Ax88772PhyRead ( pNicDevice
,
352 if ( !EFI_ERROR ( Status
)) {
354 // Determine if the autonegotiation is complete.
356 *pbLinkUp
= (BOOLEAN
)( 0 != ( PhyData
& BMSR_LINKST
));
357 *pbComplete
= *pbLinkUp
;
358 if ( 0 != *pbComplete
) {
360 // Get the partners capabilities.
362 Status
= Ax88772PhyRead ( pNicDevice
,
365 if ( !EFI_ERROR ( Status
)) {
367 // Autonegotiation is complete
368 // Determine the link speed.
370 *pbHiSpeed
= (BOOLEAN
)( 0 != ( PhyData
& ( AN_TX_FDX
| AN_TX_HDX
)));
373 // Determine the link duplex.
375 Mask
= ( *pbHiSpeed
) ? AN_TX_FDX
: AN_10_FDX
;
376 *pbFullDuplex
= (BOOLEAN
)( 0 != ( PhyData
& Mask
));
382 // Return the operation status
384 DBG_EXIT_STATUS ( Status
);
390 Read a register from the PHY
392 This routine calls ::Ax88772UsbCommand to read a PHY register.
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
398 @retval EFI_SUCCESS The PHY data is available.
399 @retval other The PHY data is not valid.
404 IN NIC_DEVICE
* pNicDevice
,
405 IN UINT8 RegisterAddress
,
406 IN OUT UINT16
* pPhyData
409 USB_DEVICE_REQUEST SetupMsg
;
415 // Request access to the PHY
417 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
419 SetupMsg
.Request
= CMD_PHY_ACCESS_SOFTWARE
;
423 Status
= Ax88772UsbCommand ( pNicDevice
,
426 if ( !EFI_ERROR ( Status
)) {
428 // Read the PHY register address.
430 SetupMsg
.RequestType
= USB_ENDPOINT_DIR_IN
431 | USB_REQ_TYPE_VENDOR
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
,
440 if ( !EFI_ERROR ( Status
)) {
441 DEBUG (( DEBUG_PHY
| DEBUG_INFO
,
442 "PHY %d: 0x%02x --> 0x%04x\r\n",
448 // Release the PHY to the hardware
450 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
452 SetupMsg
.Request
= CMD_PHY_ACCESS_HARDWARE
;
456 Status
= Ax88772UsbCommand ( pNicDevice
,
463 // Return the operation status.
465 DBG_EXIT_STATUS ( Status
);
471 Write to a PHY register
473 This routine calls ::Ax88772UsbCommand to write a PHY register.
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
479 @retval EFI_SUCCESS The PHY data was written.
480 @retval other Failed to wwrite the PHY register.
485 IN NIC_DEVICE
* pNicDevice
,
486 IN UINT8 RegisterAddress
,
490 USB_DEVICE_REQUEST SetupMsg
;
496 // Request access to the PHY
498 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
500 SetupMsg
.Request
= CMD_PHY_ACCESS_SOFTWARE
;
504 Status
= Ax88772UsbCommand ( pNicDevice
,
507 if ( !EFI_ERROR ( Status
)) {
509 // Write the PHY register
511 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
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
,
520 if ( !EFI_ERROR ( Status
)) {
521 DEBUG (( DEBUG_PHY
| DEBUG_INFO
,
522 "PHY %d: 0x%02x <-- 0x%04x\r\n",
528 // Release the PHY to the hardware
530 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
532 SetupMsg
.Request
= CMD_PHY_ACCESS_HARDWARE
;
536 Status
= Ax88772UsbCommand ( pNicDevice
,
543 // Return the operation status.
545 DBG_EXIT_STATUS ( Status
);
553 This routine uses ::Ax88772UsbCommand to reset the network
554 adapter. This routine also uses ::Ax88772PhyWrite to reset
557 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
559 @retval EFI_SUCCESS The MAC address is available.
560 @retval other The MAC address is not valid.
565 IN NIC_DEVICE
* pNicDevice
568 USB_DEVICE_REQUEST SetupMsg
;
576 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
578 SetupMsg
.Request
= CMD_RX_CONTROL_WRITE
;
582 Status
= Ax88772UsbCommand ( pNicDevice
,
585 if ( !EFI_ERROR ( Status
)) {
586 DEBUG (( DEBUG_PHY
| DEBUG_RX_BROADCAST
| DEBUG_RX_MULTICAST
587 | DEBUG_RX_UNICAST
| DEBUG_TX
| DEBUG_INFO
,
591 // The link is now idle
593 pNicDevice
->bLinkIdle
= TRUE
;
598 gBS
->Stall ( RESET_MSEC
);
601 // Select the internal PHY
603 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
605 SetupMsg
.Request
= CMD_PHY_SELECT
;
606 SetupMsg
.Value
= SPHY_PSEL
;
609 Status
= Ax88772UsbCommand ( pNicDevice
,
612 if ( !EFI_ERROR ( Status
)) {
616 gBS
->Stall ( PHY_RESET_MSEC
);
619 // Clear the internal PHY reset
621 SetupMsg
.Request
= CMD_RESET
;
622 SetupMsg
.Value
= SRR_IPRL
| SRR_PRL
;
623 Status
= Ax88772UsbCommand ( pNicDevice
,
626 if ( !EFI_ERROR ( Status
)) {
630 Status
= Ax88772PhyWrite ( pNicDevice
,
633 if ( !EFI_ERROR ( Status
)) {
637 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
639 SetupMsg
.Request
= CMD_GAPS_WRITE
;
640 SetupMsg
.Value
= 0x0c15;
641 SetupMsg
.Index
= 0x0e;
643 Status
= Ax88772UsbCommand ( pNicDevice
,
652 // Return the operation status.
654 DBG_EXIT_STATUS ( Status
);
661 IN NIC_DEVICE
* pNicDevice
,
669 RX_TX_PACKET
* pRxPacket
;
672 for ( offset
= 0; offset
< BufLength
; ){
673 pLength
= (UINT16
*) (pNicDevice
->pBulkInBuff
+ offset
);
674 pLengthBar
= (UINT16
*) (pNicDevice
->pBulkInBuff
+ offset
+2);
677 *pLengthBar
&= 0x7ff;
678 *pLengthBar
|= 0xf800;
680 if ((*pLength
^ *pLengthBar
) != 0xFFFF) {
681 DEBUG (( EFI_D_ERROR
, "Pkt length error. BufLength = %d\n", BufLength
));
685 pRxPacket
= pNicDevice
->pRxFree
;
686 if ( NULL
== pRxPacket
) {
687 Status
= gBS
->AllocatePool ( EfiRuntimeServicesData
,
688 sizeof( RX_TX_PACKET
),
689 (VOID
**) &pRxPacket
);
690 if ( !EFI_ERROR ( Status
)) {
692 // Add this packet to the free packet list
694 pNicDevice
->pRxFree
= pRxPacket
;
695 pRxPacket
->pNext
= NULL
;
699 // Use the discard packet buffer
701 //pRxPacket = &Packet;
706 pData
= pNicDevice
->pBulkInBuff
+ offset
+ 4;
707 pRxPacket
->Length
= *pLength
;
708 pRxPacket
->LengthBar
= *(UINT16
*) (pNicDevice
->pBulkInBuff
+ offset
+2);
709 CopyMem (&pRxPacket
->Data
[0], pData
, *pLength
);
710 //DEBUG((DEBUG_INFO, "Packet [%d]\n", *pLength));
712 pNicDevice
->pRxFree
= pRxPacket
->pNext
;
713 pRxPacket
->pNext
= NULL
;
715 if ( NULL
== pNicDevice
->pRxTail
) {
716 pNicDevice
->pRxHead
= pRxPacket
;
719 pNicDevice
->pRxTail
->pNext
= pRxPacket
;
721 pNicDevice
->pRxTail
= pRxPacket
;
722 offset
+= (*pLength
+ 4);
730 Receive a frame from the network.
732 This routine polls the USB receive interface for a packet. If a packet
733 is available, this routine adds the receive packet to the list of
734 pending receive packets.
736 This routine calls ::Ax88772NegotiateLinkComplete to verify
737 that the link is up. This routine also calls ::SN_Reset to
738 reset the network adapter when necessary. Finally this
739 routine attempts to receive one or more packets from the
742 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
743 @param [in] bUpdateLink TRUE = Update link status
748 IN NIC_DEVICE
* pNicDevice
,
749 IN BOOLEAN bUpdateLink
758 RX_TX_PACKET
* pRxPacket
;
759 EFI_USB_IO_PROTOCOL
*pUsbIo
;
762 UINT32 TransferStatus
;
765 // Synchronize with Ax88772Timer
767 VERIFY_TPL ( TPL_AX88772
);
768 TplPrevious
= gBS
->RaiseTPL ( TPL_AX88772
);
769 DEBUG (( DEBUG_TPL
| DEBUG_INFO
,
774 // Get the link status
777 bLinkUp
= pNicDevice
->bLinkUp
;
778 bSpeed100
= pNicDevice
->b100Mbps
;
779 bFullDuplex
= pNicDevice
->bFullDuplex
;
780 Status
= Ax88772NegotiateLinkComplete ( pNicDevice
,
781 &pNicDevice
->PollCount
,
782 &pNicDevice
->bComplete
,
783 &pNicDevice
->bLinkUp
,
784 &pNicDevice
->b100Mbps
,
785 &pNicDevice
->bFullDuplex
);
788 // Determine if the autonegotiation is complete
790 if ( pNicDevice
->bComplete
) {
791 if ( pNicDevice
->bLinkUp
) {
792 if (( bSpeed100
&& ( !pNicDevice
->b100Mbps
))
793 || (( !bSpeed100
) && pNicDevice
->b100Mbps
)
794 || ( bFullDuplex
&& ( !pNicDevice
->bFullDuplex
))
795 || (( !bFullDuplex
) && pNicDevice
->bFullDuplex
)) {
796 pNicDevice
->PollCount
= 0;
797 DEBUG (( DEBUG_LINK
| DEBUG_INFO
,
798 "Reset to establish proper link setup: %d Mbps, %s duplex\r\n",
799 pNicDevice
->b100Mbps
? 100 : 10,
800 pNicDevice
->bFullDuplex
? L
"Full" : L
"Half" ));
801 Status
= SN_Reset ( &pNicDevice
->SimpleNetwork
, FALSE
);
803 if (( !bLinkUp
) && pNicDevice
->bLinkUp
) {
805 // Display the autonegotiation status
807 DEBUG (( DEBUG_LINK
| DEBUG_INFO
,
808 "Link: Up, %d Mbps, %s duplex\r\n",
809 pNicDevice
->b100Mbps
? 100 : 10,
810 pNicDevice
->bFullDuplex
? L
"Full" : L
"Half" ));
816 // Update the link status
818 if ( bLinkUp
&& ( !pNicDevice
->bLinkUp
)) {
819 DEBUG (( DEBUG_LINK
| DEBUG_INFO
, "Link: Down\r\n" ));
824 // Loop until all the packets are emptied from the receiver
830 // Locate a packet for use
832 pRxPacket
= pNicDevice
->pRxFree
;
833 LengthInBytes
= MAX_BULKIN_SIZE
;
834 if ( NULL
== pRxPacket
) {
835 Status
= gBS
->AllocatePool ( EfiRuntimeServicesData
,
836 sizeof ( *pRxPacket
),
837 (VOID
**) &pRxPacket
);
838 if ( !EFI_ERROR ( Status
)) {
840 // Add this packet to the free packet list
842 pNicDevice
->pRxFree
= pRxPacket
;
843 pRxPacket
->pNext
= NULL
;
847 // Use the discard packet buffer
854 // Attempt to receive a packet
856 SetMem (&pNicDevice
->pBulkInBuff
[0], MAX_BULKIN_SIZE
, 0);
857 pUsbIo
= pNicDevice
->pUsbIo
;
858 Status
= pUsbIo
->UsbBulkTransfer ( pUsbIo
,
859 USB_ENDPOINT_DIR_IN
| BULK_IN_ENDPOINT
,
860 &pNicDevice
->pBulkInBuff
[0],
864 if ( LengthInBytes
> 0 ) {
865 FillPkt2Queue(pNicDevice
, LengthInBytes
);
867 pRxPacket
= pNicDevice
->pRxHead
;
868 if (( !EFI_ERROR ( Status
))
869 && ( 0 < pRxPacket
->Length
)
870 && ( pRxPacket
->Length
<= sizeof ( pRxPacket
->Data
))
871 && ( LengthInBytes
> 0)) {
874 // Determine if the packet should be received
877 LengthInBytes
= pRxPacket
->Length
;
878 pNicDevice
->bLinkIdle
= FALSE
;
879 if ( pNicDevice
->pRxFree
== pRxPacket
) {
881 // Display the received packet
883 if ( 0 != ( pRxPacket
->Data
[0] & 1 )) {
884 if (( 0xff == pRxPacket
->Data
[0])
885 && ( 0xff == pRxPacket
->Data
[1])
886 && ( 0xff == pRxPacket
->Data
[2])
887 && ( 0xff == pRxPacket
->Data
[3])
888 && ( 0xff == pRxPacket
->Data
[4])
889 && ( 0xff == pRxPacket
->Data
[5])) {
890 DEBUG (( DEBUG_RX_BROADCAST
| DEBUG_INFO
,
891 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
909 DEBUG (( DEBUG_RX_MULTICAST
| DEBUG_INFO
,
910 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
929 DEBUG (( DEBUG_RX_UNICAST
| DEBUG_INFO
,
930 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
951 // Error, not enough buffers for this packet, discard packet
953 DEBUG (( DEBUG_WARN
| DEBUG_INFO
,
954 "WARNING - No buffer, discarding RX packet: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
972 }while ( bRxPacket
);
975 // Release the synchronization withhe Ax88772Timer
977 gBS
->RestoreTPL ( TplPrevious
);
978 DEBUG (( DEBUG_TPL
| DEBUG_INFO
,
985 Enable or disable the receiver
987 This routine calls ::Ax88772UsbCommand to update the
988 receiver state. This routine also calls ::Ax88772MacAddressSet
989 to establish the MAC address for the network adapter.
991 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
992 @param [in] RxFilter Simple network RX filter mask value
994 @retval EFI_SUCCESS The MAC address was set.
995 @retval other The MAC address was not set.
1000 IN NIC_DEVICE
* pNicDevice
,
1004 UINT16 MediumStatus
;
1005 INT32 MulticastHash
[2];
1007 USB_DEVICE_REQUEST SetupMsg
;
1013 // Disable all multicast
1015 MulticastHash
[0] = 0;
1016 MulticastHash
[1] = 0;
1019 // Enable the receiver if something is to be received
1021 Status
= EFI_SUCCESS
;
1022 RxControl
= RXC_SO
| RXC_MFB_16384
;
1023 if ( 0 != RxFilter
) {
1025 // Enable the receiver
1027 SetupMsg
.RequestType
= USB_ENDPOINT_DIR_IN
1028 | USB_REQ_TYPE_VENDOR
1029 | USB_TARGET_DEVICE
;
1030 SetupMsg
.Request
= CMD_MEDIUM_STATUS_READ
;
1033 SetupMsg
.Length
= sizeof ( MediumStatus
);
1034 Status
= Ax88772UsbCommand ( pNicDevice
,
1037 if ( !EFI_ERROR ( Status
)) {
1038 if ( 0 == ( MediumStatus
& MS_RE
)) {
1039 MediumStatus
|= MS_RE
| MS_ONE
;
1040 if ( pNicDevice
->bFullDuplex
) {
1041 MediumStatus
|= MS_TFC
| MS_RFC
;
1043 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
1044 | USB_TARGET_DEVICE
;
1045 SetupMsg
.Request
= CMD_MEDIUM_STATUS_WRITE
;
1046 SetupMsg
.Value
= MediumStatus
;
1048 SetupMsg
.Length
= 0;
1049 Status
= Ax88772UsbCommand ( pNicDevice
,
1052 if ( EFI_ERROR ( Status
)) {
1053 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1054 "ERROR - Failed to enable receiver, Status: %r\r\n",
1060 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1061 "ERROR - Failed to read receiver status, Status: %r\r\n",
1066 // Enable multicast if requested
1068 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
)) {
1069 RxControl
|= RXC_AM
;
1070 MulticastHash
[0] = pNicDevice
->MulticastHash
[0];
1071 MulticastHash
[1] = pNicDevice
->MulticastHash
[1];
1075 // Enable all multicast if requested
1077 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
)) {
1078 RxControl
|= RXC_AMALL
;
1079 MulticastHash
[0] = -1;
1080 MulticastHash
[1] = -1;
1084 // Enable broadcast if requested
1086 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
)) {
1087 RxControl
|= RXC_AB
;
1091 // Enable promiscuous mode if requested
1093 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
)) {
1094 RxControl
|= RXC_PRO
;
1095 MulticastHash
[0] = -1;
1096 MulticastHash
[1] = -1;
1101 // Update the MAC address
1103 if ( !EFI_ERROR ( Status
)) {
1104 Status
= Ax88772MacAddressSet ( pNicDevice
, &pNicDevice
->SimpleNetworkData
.CurrentAddress
.Addr
[0]);
1108 // Update the receiver control
1110 if ( !EFI_ERROR ( Status
)) {
1111 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
1112 | USB_TARGET_DEVICE
;
1113 SetupMsg
.Request
= CMD_RX_CONTROL_WRITE
;
1114 SetupMsg
.Value
= RxControl
;
1116 SetupMsg
.Length
= 0;
1117 Status
= Ax88772UsbCommand ( pNicDevice
,
1120 if ( !EFI_ERROR ( Status
)) {
1121 DEBUG (( DEBUG_RX_BROADCAST
| DEBUG_RX_MULTICAST
| DEBUG_RX_UNICAST
| DEBUG_INFO
,
1122 "RxControl: 0x%04x\r\n",
1126 // Update the multicast hash table
1128 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
1129 | USB_TARGET_DEVICE
;
1130 SetupMsg
.Request
= CMD_MULTICAST_HASH_WRITE
;
1133 SetupMsg
.Length
= sizeof ( pNicDevice
->MulticastHash
);
1134 Status
= Ax88772UsbCommand ( pNicDevice
,
1136 &pNicDevice
->MulticastHash
);
1137 if ( !EFI_ERROR ( Status
)) {
1138 DEBUG (( DEBUG_RX_MULTICAST
| DEBUG_INFO
,
1139 "Multicast Hash: 0x%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
1140 (UINT8
) MulticastHash
[0],
1141 (UINT8
)( MulticastHash
[0] >> 8 ),
1142 (UINT8
)( MulticastHash
[0] >> 16 ),
1143 (UINT8
)( MulticastHash
[0] >> 24 ),
1144 (UINT8
) MulticastHash
[1],
1145 (UINT8
)( MulticastHash
[1] >> 8 ),
1146 (UINT8
)( MulticastHash
[1] >> 16 ),
1147 (UINT8
)( MulticastHash
[1] >> 24 )));
1150 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1151 "ERROR - Failed to update multicast hash table, Status: %r\r\n",
1156 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1157 "ERROR - Failed to set receiver control, Status: %r\r\n",
1163 // Return the operation status
1165 DBG_EXIT_STATUS ( Status
);
1171 Read an SROM location
1173 This routine calls ::Ax88772UsbCommand to read data from the
1176 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1177 @param [in] Address SROM address
1178 @param [out] pData Buffer to receive the data
1180 @retval EFI_SUCCESS The read was successful
1181 @retval other The read failed
1186 IN NIC_DEVICE
* pNicDevice
,
1191 USB_DEVICE_REQUEST SetupMsg
;
1197 // Read a value from the SROM
1199 SetupMsg
.RequestType
= USB_ENDPOINT_DIR_IN
1200 | USB_REQ_TYPE_VENDOR
1201 | USB_TARGET_DEVICE
;
1202 SetupMsg
.Request
= CMD_SROM_READ
;
1203 SetupMsg
.Value
= (UINT16
) Address
;
1205 SetupMsg
.Length
= sizeof ( *pData
);
1206 Status
= Ax88772UsbCommand ( pNicDevice
,
1211 // Return the operation status
1213 DBG_EXIT_STATUS ( Status
);
1219 This routine is called at a regular interval to poll for
1222 This routine polls the link state and gets any receive packets
1223 by calling ::Ax88772Rx.
1225 @param [in] Event Timer event
1226 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1232 IN NIC_DEVICE
* pNicDevice
1236 // Use explicit DEBUG messages since the output frequency is too
1237 // high for DEBUG_INFO to keep up and have spare cycles for the
1240 DEBUG (( DEBUG_TIMER
, "Entering Ax88772Timer\r\n" ));
1243 // Poll the link state and get any receive packets
1245 Ax88772Rx ( pNicDevice
, FALSE
);
1247 DEBUG (( DEBUG_TIMER
, "Exiting Ax88772Timer\r\n" ));
1252 Send a command to the USB device.
1254 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1255 @param [in] pRequest Pointer to the request structure
1256 @param [in, out] pBuffer Data buffer address
1258 @retval EFI_SUCCESS The USB transfer was successful
1259 @retval other The USB transfer failed
1264 IN NIC_DEVICE
* pNicDevice
,
1265 IN USB_DEVICE_REQUEST
* pRequest
,
1266 IN OUT VOID
* pBuffer
1270 EFI_USB_DATA_DIRECTION Direction
;
1271 EFI_USB_IO_PROTOCOL
* pUsbIo
;
1277 // Determine the transfer direction
1279 Direction
= EfiUsbNoData
;
1280 if ( 0 != pRequest
->Length
) {
1281 Direction
= ( 0 != ( pRequest
->RequestType
& USB_ENDPOINT_DIR_IN
))
1282 ? EfiUsbDataIn
: EfiUsbDataOut
;
1286 // Issue the command
1288 pUsbIo
= pNicDevice
->pUsbIo
;
1289 Status
= pUsbIo
->UsbControlTransfer ( pUsbIo
,
1298 // Determine the operation status
1300 if ( !EFI_ERROR ( Status
)) {
1305 // Display any errors
1307 DEBUG (( DEBUG_INFO
,
1308 "Ax88772UsbCommand - Status: %r\n",
1312 // Only use status values associated with the Simple Network protocol
1314 if ( EFI_TIMEOUT
== Status
) {
1315 Status
= EFI_DEVICE_ERROR
;
1320 // Return the operation status
1322 DBG_EXIT_STATUS ( Status
);