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
;
673 for ( offset
= 0; offset
< BufLength
; ){
674 pLength
= (UINT16
*) (pNicDevice
->pBulkInBuff
+ offset
);
675 pLengthBar
= (UINT16
*) (pNicDevice
->pBulkInBuff
+ offset
+2);
678 *pLengthBar
&= 0x7ff;
679 *pLengthBar
|= 0xf800;
681 if ((*pLength
^ *pLengthBar
) != 0xFFFF) {
682 DEBUG (( EFI_D_ERROR
, "Pkt length error. BufLength = %d\n", BufLength
));
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
)) {
694 // Add this packet to the free packet list
696 pNicDevice
->pRxFree
= pRxPacket
;
697 pRxPacket
->pNext
= NULL
;
701 // Use the discard packet buffer
703 //pRxPacket = &Packet;
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));
714 pNicDevice
->pRxFree
= pRxPacket
->pNext
;
715 pRxPacket
->pNext
= NULL
;
717 if ( NULL
== pNicDevice
->pRxTail
) {
718 pNicDevice
->pRxHead
= pRxPacket
;
721 pNicDevice
->pRxTail
->pNext
= pRxPacket
;
723 pNicDevice
->pRxTail
= pRxPacket
;
724 offset
+= (*pLength
+ 4);
732 Receive a frame from the network.
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.
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
744 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
745 @param [in] bUpdateLink TRUE = Update link status
750 IN NIC_DEVICE
* pNicDevice
,
751 IN BOOLEAN bUpdateLink
760 RX_TX_PACKET
* pRxPacket
;
761 EFI_USB_IO_PROTOCOL
*pUsbIo
;
764 UINT32 TransferStatus
;
767 // Synchronize with Ax88772Timer
769 VERIFY_TPL ( TPL_AX88772
);
770 TplPrevious
= gBS
->RaiseTPL ( TPL_AX88772
);
771 DEBUG (( DEBUG_TPL
| DEBUG_INFO
,
776 // Get the link status
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
);
790 // Determine if the autonegotiation is complete
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
);
805 if (( !bLinkUp
) && pNicDevice
->bLinkUp
) {
807 // Display the autonegotiation status
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" ));
818 // Update the link status
820 if ( bLinkUp
&& ( !pNicDevice
->bLinkUp
)) {
821 DEBUG (( DEBUG_LINK
| DEBUG_INFO
, "Link: Down\r\n" ));
826 // Loop until all the packets are emptied from the receiver
832 // Locate a packet for use
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
)) {
842 // Add this packet to the free packet list
844 pNicDevice
->pRxFree
= pRxPacket
;
845 pRxPacket
->pNext
= NULL
;
849 // Use the discard packet buffer
856 // Attempt to receive a packet
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],
866 if ( LengthInBytes
> 0 ) {
867 FillPkt2Queue(pNicDevice
, LengthInBytes
);
869 pRxPacket
= pNicDevice
->pRxHead
;
870 if (( !EFI_ERROR ( Status
))
871 && ( 0 < pRxPacket
->Length
)
872 && ( pRxPacket
->Length
<= sizeof ( pRxPacket
->Data
))
873 && ( LengthInBytes
> 0)) {
876 // Determine if the packet should be received
879 LengthInBytes
= pRxPacket
->Length
;
880 pNicDevice
->bLinkIdle
= FALSE
;
881 if ( pNicDevice
->pRxFree
== pRxPacket
) {
883 // Display the received packet
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",
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",
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",
953 // Error, not enough buffers for this packet, discard packet
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",
974 }while ( bRxPacket
);
977 // Release the synchronization withhe Ax88772Timer
979 gBS
->RestoreTPL ( TplPrevious
);
980 DEBUG (( DEBUG_TPL
| DEBUG_INFO
,
987 Enable or disable the receiver
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.
993 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
994 @param [in] RxFilter Simple network RX filter mask value
996 @retval EFI_SUCCESS The MAC address was set.
997 @retval other The MAC address was not set.
1002 IN NIC_DEVICE
* pNicDevice
,
1006 UINT16 MediumStatus
;
1007 INT32 MulticastHash
[2];
1009 USB_DEVICE_REQUEST SetupMsg
;
1015 // Disable all multicast
1017 MulticastHash
[0] = 0;
1018 MulticastHash
[1] = 0;
1021 // Enable the receiver if something is to be received
1023 Status
= EFI_SUCCESS
;
1024 RxControl
= RXC_SO
| RXC_MFB_16384
;
1025 if ( 0 != RxFilter
) {
1027 // Enable the receiver
1029 SetupMsg
.RequestType
= USB_ENDPOINT_DIR_IN
1030 | USB_REQ_TYPE_VENDOR
1031 | USB_TARGET_DEVICE
;
1032 SetupMsg
.Request
= CMD_MEDIUM_STATUS_READ
;
1035 SetupMsg
.Length
= sizeof ( MediumStatus
);
1036 Status
= Ax88772UsbCommand ( pNicDevice
,
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
;
1045 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
1046 | USB_TARGET_DEVICE
;
1047 SetupMsg
.Request
= CMD_MEDIUM_STATUS_WRITE
;
1048 SetupMsg
.Value
= MediumStatus
;
1050 SetupMsg
.Length
= 0;
1051 Status
= Ax88772UsbCommand ( pNicDevice
,
1054 if ( EFI_ERROR ( Status
)) {
1055 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1056 "ERROR - Failed to enable receiver, Status: %r\r\n",
1062 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1063 "ERROR - Failed to read receiver status, Status: %r\r\n",
1068 // Enable multicast if requested
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];
1077 // Enable all multicast if requested
1079 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
)) {
1080 RxControl
|= RXC_AMALL
;
1081 MulticastHash
[0] = -1;
1082 MulticastHash
[1] = -1;
1086 // Enable broadcast if requested
1088 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
)) {
1089 RxControl
|= RXC_AB
;
1093 // Enable promiscuous mode if requested
1095 if ( 0 != ( RxFilter
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
)) {
1096 RxControl
|= RXC_PRO
;
1097 MulticastHash
[0] = -1;
1098 MulticastHash
[1] = -1;
1103 // Update the MAC address
1105 if ( !EFI_ERROR ( Status
)) {
1106 Status
= Ax88772MacAddressSet ( pNicDevice
, &pNicDevice
->SimpleNetworkData
.CurrentAddress
.Addr
[0]);
1110 // Update the receiver control
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
;
1118 SetupMsg
.Length
= 0;
1119 Status
= Ax88772UsbCommand ( pNicDevice
,
1122 if ( !EFI_ERROR ( Status
)) {
1123 DEBUG (( DEBUG_RX_BROADCAST
| DEBUG_RX_MULTICAST
| DEBUG_RX_UNICAST
| DEBUG_INFO
,
1124 "RxControl: 0x%04x\r\n",
1128 // Update the multicast hash table
1130 SetupMsg
.RequestType
= USB_REQ_TYPE_VENDOR
1131 | USB_TARGET_DEVICE
;
1132 SetupMsg
.Request
= CMD_MULTICAST_HASH_WRITE
;
1135 SetupMsg
.Length
= sizeof ( pNicDevice
->MulticastHash
);
1136 Status
= Ax88772UsbCommand ( pNicDevice
,
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 )));
1152 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1153 "ERROR - Failed to update multicast hash table, Status: %r\r\n",
1158 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1159 "ERROR - Failed to set receiver control, Status: %r\r\n",
1165 // Return the operation status
1167 DBG_EXIT_STATUS ( Status
);
1173 Read an SROM location
1175 This routine calls ::Ax88772UsbCommand to read data from the
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
1182 @retval EFI_SUCCESS The read was successful
1183 @retval other The read failed
1188 IN NIC_DEVICE
* pNicDevice
,
1193 USB_DEVICE_REQUEST SetupMsg
;
1199 // Read a value from the SROM
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
;
1207 SetupMsg
.Length
= sizeof ( *pData
);
1208 Status
= Ax88772UsbCommand ( pNicDevice
,
1213 // Return the operation status
1215 DBG_EXIT_STATUS ( Status
);
1221 This routine is called at a regular interval to poll for
1224 This routine polls the link state and gets any receive packets
1225 by calling ::Ax88772Rx.
1227 @param [in] Event Timer event
1228 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1234 IN NIC_DEVICE
* pNicDevice
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
1242 DEBUG (( DEBUG_TIMER
, "Entering Ax88772Timer\r\n" ));
1245 // Poll the link state and get any receive packets
1247 Ax88772Rx ( pNicDevice
, FALSE
);
1249 DEBUG (( DEBUG_TIMER
, "Exiting Ax88772Timer\r\n" ));
1254 Send a command to the USB device.
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
1260 @retval EFI_SUCCESS The USB transfer was successful
1261 @retval other The USB transfer failed
1266 IN NIC_DEVICE
* pNicDevice
,
1267 IN USB_DEVICE_REQUEST
* pRequest
,
1268 IN OUT VOID
* pBuffer
1272 EFI_USB_DATA_DIRECTION Direction
;
1273 EFI_USB_IO_PROTOCOL
* pUsbIo
;
1279 // Determine the transfer direction
1281 Direction
= EfiUsbNoData
;
1282 if ( 0 != pRequest
->Length
) {
1283 Direction
= ( 0 != ( pRequest
->RequestType
& USB_ENDPOINT_DIR_IN
))
1284 ? EfiUsbDataIn
: EfiUsbDataOut
;
1288 // Issue the command
1290 pUsbIo
= pNicDevice
->pUsbIo
;
1291 Status
= pUsbIo
->UsbControlTransfer ( pUsbIo
,
1300 // Determine the operation status
1302 if ( !EFI_ERROR ( Status
)) {
1307 // Display any errors
1309 DEBUG (( DEBUG_INFO
,
1310 "Ax88772UsbCommand - Status: %r\n",
1314 // Only use status values associated with the Simple Network protocol
1316 if ( EFI_TIMEOUT
== Status
) {
1317 Status
= EFI_DEVICE_ERROR
;
1322 // Return the operation status
1324 DBG_EXIT_STATUS ( Status
);