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