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
);
660 Receive a frame from the network.
662 This routine polls the USB receive interface for a packet. If a packet
663 is available, this routine adds the receive packet to the list of
664 pending receive packets.
666 This routine calls ::Ax88772NegotiateLinkComplete to verify
667 that the link is up. This routine also calls ::SN_Reset to
668 reset the network adapter when necessary. Finally this
669 routine attempts to receive one or more packets from the
672 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
673 @param [in] bUpdateLink TRUE = Update link status
678 IN NIC_DEVICE
* pNicDevice
,
679 IN BOOLEAN bUpdateLink
688 RX_TX_PACKET
* pRxPacket
;
689 EFI_USB_IO_PROTOCOL
*pUsbIo
;
692 UINT32 TransferStatus
;
695 // Synchronize with Ax88772Timer
697 VERIFY_TPL ( TPL_AX88772
);
698 TplPrevious
= gBS
->RaiseTPL ( TPL_AX88772
);
699 DEBUG (( DEBUG_TPL
| DEBUG_INFO
,
704 // Get the link status
707 bLinkUp
= pNicDevice
->bLinkUp
;
708 bSpeed100
= pNicDevice
->b100Mbps
;
709 bFullDuplex
= pNicDevice
->bFullDuplex
;
710 Status
= Ax88772NegotiateLinkComplete ( pNicDevice
,
711 &pNicDevice
->PollCount
,
712 &pNicDevice
->bComplete
,
713 &pNicDevice
->bLinkUp
,
714 &pNicDevice
->b100Mbps
,
715 &pNicDevice
->bFullDuplex
);
718 // Determine if the autonegotiation is complete
720 if ( pNicDevice
->bComplete
) {
721 if ( pNicDevice
->bLinkUp
) {
722 if (( bSpeed100
&& ( !pNicDevice
->b100Mbps
))
723 || (( !bSpeed100
) && pNicDevice
->b100Mbps
)
724 || ( bFullDuplex
&& ( !pNicDevice
->bFullDuplex
))
725 || (( !bFullDuplex
) && pNicDevice
->bFullDuplex
)) {
726 pNicDevice
->PollCount
= 0;
727 DEBUG (( DEBUG_LINK
| DEBUG_INFO
,
728 "Reset to establish proper link setup: %d Mbps, %s duplex\r\n",
729 pNicDevice
->b100Mbps
? 100 : 10,
730 pNicDevice
->bFullDuplex
? L
"Full" : L
"Half" ));
731 Status
= SN_Reset ( &pNicDevice
->SimpleNetwork
, FALSE
);
733 if (( !bLinkUp
) && pNicDevice
->bLinkUp
) {
735 // Display the autonegotiation status
737 DEBUG (( DEBUG_LINK
| DEBUG_INFO
,
738 "Link: Up, %d Mbps, %s duplex\r\n",
739 pNicDevice
->b100Mbps
? 100 : 10,
740 pNicDevice
->bFullDuplex
? L
"Full" : L
"Half" ));
746 // Update the link status
748 if ( bLinkUp
&& ( !pNicDevice
->bLinkUp
)) {
749 DEBUG (( DEBUG_LINK
| DEBUG_INFO
, "Link: Down\r\n" ));
754 // Loop until all the packets are emptied from the receiver
760 // Locate a packet for use
762 pRxPacket
= pNicDevice
->pRxFree
;
763 LengthInBytes
= sizeof ( *pRxPacket
) - sizeof ( pRxPacket
->pNext
);
764 if ( NULL
== pRxPacket
) {
765 Status
= gBS
->AllocatePool ( EfiRuntimeServicesData
,
767 (VOID
**) &pRxPacket
);
768 if ( !EFI_ERROR ( Status
)) {
770 // Add this packet to the free packet list
772 pNicDevice
->pRxFree
= pRxPacket
;
773 pRxPacket
->pNext
= NULL
;
777 // Use the discard packet buffer
784 // Attempt to receive a packet
786 pUsbIo
= pNicDevice
->pUsbIo
;
787 Status
= pUsbIo
->UsbBulkTransfer ( pUsbIo
,
788 USB_ENDPOINT_DIR_IN
| BULK_IN_ENDPOINT
,
793 if (( !EFI_ERROR ( Status
))
794 && ( 0 < pRxPacket
->Length
)
795 && ( pRxPacket
->Length
<= sizeof ( pRxPacket
->Data
))) {
798 // Determine if the packet should be received
801 LengthInBytes
= pRxPacket
->Length
;
802 pNicDevice
->bLinkIdle
= FALSE
;
803 if ( pNicDevice
->pRxFree
== pRxPacket
) {
805 // Display the received packet
807 if ( 0 != ( pRxPacket
->Data
[0] & 1 )) {
808 if (( 0xff == pRxPacket
->Data
[0])
809 && ( 0xff == pRxPacket
->Data
[1])
810 && ( 0xff == pRxPacket
->Data
[2])
811 && ( 0xff == pRxPacket
->Data
[3])
812 && ( 0xff == pRxPacket
->Data
[4])
813 && ( 0xff == pRxPacket
->Data
[5])) {
814 DEBUG (( DEBUG_RX_BROADCAST
| DEBUG_INFO
,
815 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
833 DEBUG (( DEBUG_RX_MULTICAST
| DEBUG_INFO
,
834 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
853 DEBUG (( DEBUG_RX_UNICAST
| DEBUG_INFO
,
854 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
873 // Remove this packet from the free packet list
875 pNicDevice
->pRxFree
= pRxPacket
->pNext
;
876 pRxPacket
->pNext
= NULL
;
879 // Append this packet to the receive list
881 if ( NULL
== pNicDevice
->pRxTail
) {
882 pNicDevice
->pRxHead
= pRxPacket
;
885 pNicDevice
->pRxTail
->pNext
= pRxPacket
;
887 pNicDevice
->pRxTail
= pRxPacket
;
891 // Error, not enough buffers for this packet, discard packet
893 DEBUG (( DEBUG_WARN
| DEBUG_INFO
,
894 "WARNING - No buffer, discarding RX packet: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
912 }while ( bRxPacket
);
915 // Release the synchronization withhe Ax88772Timer
917 gBS
->RestoreTPL ( TplPrevious
);
918 DEBUG (( DEBUG_TPL
| DEBUG_INFO
,
925 Enable or disable the receiver
927 This routine calls ::Ax88772UsbCommand to update the
928 receiver state. This routine also calls ::Ax88772MacAddressSet
929 to establish the MAC address for the network adapter.
931 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
932 @param [in] RxFilter Simple network RX filter mask value
934 @retval EFI_SUCCESS The MAC address was set.
935 @retval other The MAC address was not set.
940 IN NIC_DEVICE
* pNicDevice
,
945 INT32 MulticastHash
[2];
947 USB_DEVICE_REQUEST SetupMsg
;
953 // Disable all multicast
955 MulticastHash
[0] = 0;
956 MulticastHash
[1] = 0;
959 // Enable the receiver if something is to be received
961 Status
= EFI_SUCCESS
;
962 RxControl
= RXC_SO
| RXC_MFB_16384
;
963 if ( 0 != RxFilter
) {
965 // Enable the receiver
967 SetupMsg
.RequestType
= USB_ENDPOINT_DIR_IN
968 | USB_REQ_TYPE_VENDOR
970 SetupMsg
.Request
= CMD_MEDIUM_STATUS_READ
;
973 SetupMsg
.Length
= sizeof ( MediumStatus
);
974 Status
= Ax88772UsbCommand ( pNicDevice
,
977 if ( !EFI_ERROR ( Status
)) {
978 if ( 0 == ( MediumStatus
& MS_RE
)) {
979 MediumStatus
|= MS_RE
| MS_ONE
;
980 if ( pNicDevice
->bFullDuplex
) {
981 MediumStatus
|= MS_TFC
| MS_RFC
;
983 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
985 SetupMsg
.Request
= CMD_MEDIUM_STATUS_WRITE
;
986 SetupMsg
.Value
= MediumStatus
;
989 Status
= Ax88772UsbCommand ( pNicDevice
,
992 if ( EFI_ERROR ( Status
)) {
993 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
994 "ERROR - Failed to enable receiver, Status: %r\r\n",
1000 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1001 "ERROR - Failed to read receiver status, Status: %r\r\n",
1006 // Enable multicast if requested
1008 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
)) {
1009 RxControl
|= RXC_AM
;
1010 MulticastHash
[0] = pNicDevice
->MulticastHash
[0];
1011 MulticastHash
[1] = pNicDevice
->MulticastHash
[1];
1015 // Enable all multicast if requested
1017 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
)) {
1018 RxControl
|= RXC_AMALL
;
1019 MulticastHash
[0] = -1;
1020 MulticastHash
[1] = -1;
1024 // Enable broadcast if requested
1026 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
)) {
1027 RxControl
|= RXC_AB
;
1031 // Enable promiscuous mode if requested
1033 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
)) {
1034 RxControl
|= RXC_PRO
;
1035 MulticastHash
[0] = -1;
1036 MulticastHash
[1] = -1;
1041 // Update the MAC address
1043 if ( !EFI_ERROR ( Status
)) {
1044 Status
= Ax88772MacAddressSet ( pNicDevice
, &pNicDevice
->SimpleNetworkData
.CurrentAddress
.Addr
[0]);
1048 // Update the receiver control
1050 if ( !EFI_ERROR ( Status
)) {
1051 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
1052 | USB_TARGET_DEVICE
;
1053 SetupMsg
.Request
= CMD_RX_CONTROL_WRITE
;
1054 SetupMsg
.Value
= RxControl
;
1056 SetupMsg
.Length
= 0;
1057 Status
= Ax88772UsbCommand ( pNicDevice
,
1060 if ( !EFI_ERROR ( Status
)) {
1061 DEBUG (( DEBUG_RX_BROADCAST
| DEBUG_RX_MULTICAST
| DEBUG_RX_UNICAST
| DEBUG_INFO
,
1062 "RxControl: 0x%04x\r\n",
1066 // Update the multicast hash table
1068 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
1069 | USB_TARGET_DEVICE
;
1070 SetupMsg
.Request
= CMD_MULTICAST_HASH_WRITE
;
1073 SetupMsg
.Length
= sizeof ( pNicDevice
->MulticastHash
);
1074 Status
= Ax88772UsbCommand ( pNicDevice
,
1076 &pNicDevice
->MulticastHash
);
1077 if ( !EFI_ERROR ( Status
)) {
1078 DEBUG (( DEBUG_RX_MULTICAST
| DEBUG_INFO
,
1079 "Multicast Hash: 0x%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
1080 (UINT8
) MulticastHash
[0],
1081 (UINT8
)( MulticastHash
[0] >> 8 ),
1082 (UINT8
)( MulticastHash
[0] >> 16 ),
1083 (UINT8
)( MulticastHash
[0] >> 24 ),
1084 (UINT8
) MulticastHash
[1],
1085 (UINT8
)( MulticastHash
[1] >> 8 ),
1086 (UINT8
)( MulticastHash
[1] >> 16 ),
1087 (UINT8
)( MulticastHash
[1] >> 24 )));
1090 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1091 "ERROR - Failed to update multicast hash table, Status: %r\r\n",
1096 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1097 "ERROR - Failed to set receiver control, Status: %r\r\n",
1103 // Return the operation status
1105 DBG_EXIT_STATUS ( Status
);
1111 Read an SROM location
1113 This routine calls ::Ax88772UsbCommand to read data from the
1116 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1117 @param [in] Address SROM address
1118 @param [out] pData Buffer to receive the data
1120 @retval EFI_SUCCESS The read was successful
1121 @retval other The read failed
1126 IN NIC_DEVICE
* pNicDevice
,
1131 USB_DEVICE_REQUEST SetupMsg
;
1137 // Read a value from the SROM
1139 SetupMsg
.RequestType
= USB_ENDPOINT_DIR_IN
1140 | USB_REQ_TYPE_VENDOR
1141 | USB_TARGET_DEVICE
;
1142 SetupMsg
.Request
= CMD_SROM_READ
;
1143 SetupMsg
.Value
= (UINT16
) Address
;
1145 SetupMsg
.Length
= sizeof ( *pData
);
1146 Status
= Ax88772UsbCommand ( pNicDevice
,
1151 // Return the operation status
1153 DBG_EXIT_STATUS ( Status
);
1159 This routine is called at a regular interval to poll for
1162 This routine polls the link state and gets any receive packets
1163 by calling ::Ax88772Rx.
1165 @param [in] Event Timer event
1166 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1172 IN NIC_DEVICE
* pNicDevice
1176 // Use explicit DEBUG messages since the output frequency is too
1177 // high for DEBUG_INFO to keep up and have spare cycles for the
1180 DEBUG (( DEBUG_TIMER
, "Entering Ax88772Timer\r\n" ));
1183 // Poll the link state and get any receive packets
1185 Ax88772Rx ( pNicDevice
, FALSE
);
1187 DEBUG (( DEBUG_TIMER
, "Exiting Ax88772Timer\r\n" ));
1192 Send a command to the USB device.
1194 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1195 @param [in] pRequest Pointer to the request structure
1196 @param [in, out] pBuffer Data buffer address
1198 @retval EFI_SUCCESS The USB transfer was successful
1199 @retval other The USB transfer failed
1204 IN NIC_DEVICE
* pNicDevice
,
1205 IN USB_DEVICE_REQUEST
* pRequest
,
1206 IN OUT VOID
* pBuffer
1210 EFI_USB_DATA_DIRECTION Direction
;
1211 EFI_USB_IO_PROTOCOL
* pUsbIo
;
1217 // Determine the transfer direction
1219 Direction
= EfiUsbNoData
;
1220 if ( 0 != pRequest
->Length
) {
1221 Direction
= ( 0 != ( pRequest
->RequestType
& USB_ENDPOINT_DIR_IN
))
1222 ? EfiUsbDataIn
: EfiUsbDataOut
;
1226 // Issue the command
1228 pUsbIo
= pNicDevice
->pUsbIo
;
1229 Status
= pUsbIo
->UsbControlTransfer ( pUsbIo
,
1238 // Determine the operation status
1240 if ( !EFI_ERROR ( Status
)) {
1245 // Display any errors
1247 DEBUG (( DEBUG_INFO
,
1248 "Ax88772UsbCommand - Status: %r\n",
1252 // Only use status values associated with the Simple Network protocol
1254 if ( EFI_TIMEOUT
== Status
) {
1255 Status
= EFI_DEVICE_ERROR
;
1260 // Return the operation status
1262 DBG_EXIT_STATUS ( Status
);