]> git.proxmox.com Git - mirror_edk2.git/blob - OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772/Ax88772.c
Ax88772: Add logic to separate packet, fix MTU issue. Ax88772b: Fix driver model...
[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 VOID
660 FillPkt2Queue (
661 IN NIC_DEVICE * pNicDevice,
662 IN UINTN BufLength)
663 {
664
665 UINT16 * pLength;
666 UINT16 * pLengthBar;
667 UINT8* pData;
668 UINT32 offset;
669 RX_TX_PACKET * pRxPacket;
670 UINTN LengthInBytes;
671 EFI_STATUS Status;
672
673 for ( offset = 0; offset < BufLength; ){
674 pLength = (UINT16*) (pNicDevice->pBulkInBuff + offset);
675 pLengthBar = (UINT16*) (pNicDevice->pBulkInBuff + offset +2);
676
677 *pLength &= 0x7ff;
678 *pLengthBar &= 0x7ff;
679 *pLengthBar |= 0xf800;
680
681 if ((*pLength ^ *pLengthBar ) != 0xFFFF) {
682 DEBUG (( EFI_D_ERROR , "Pkt length error. BufLength = %d\n", BufLength));
683 return;
684 }
685
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 )) {
693 //
694 // Add this packet to the free packet list
695 //
696 pNicDevice->pRxFree = pRxPacket;
697 pRxPacket->pNext = NULL;
698 }
699 else {
700 //
701 // Use the discard packet buffer
702 //
703 //pRxPacket = &Packet;
704 }
705 }
706
707
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));
713
714 pNicDevice->pRxFree = pRxPacket->pNext;
715 pRxPacket->pNext = NULL;
716
717 if ( NULL == pNicDevice->pRxTail ) {
718 pNicDevice->pRxHead = pRxPacket;
719 }
720 else {
721 pNicDevice->pRxTail->pNext = pRxPacket;
722 }
723 pNicDevice->pRxTail = pRxPacket;
724 offset += (*pLength + 4);
725
726 }
727 }
728
729
730
731 /**
732 Receive a frame from the network.
733
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.
737
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
742 network adapter.
743
744 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
745 @param [in] bUpdateLink TRUE = Update link status
746
747 **/
748 VOID
749 Ax88772Rx (
750 IN NIC_DEVICE * pNicDevice,
751 IN BOOLEAN bUpdateLink
752 )
753 {
754 BOOLEAN bFullDuplex;
755 BOOLEAN bLinkUp;
756 BOOLEAN bRxPacket;
757 BOOLEAN bSpeed100;
758 UINTN LengthInBytes;
759 RX_TX_PACKET Packet;
760 RX_TX_PACKET * pRxPacket;
761 EFI_USB_IO_PROTOCOL *pUsbIo;
762 EFI_STATUS Status;
763 EFI_TPL TplPrevious;
764 UINT32 TransferStatus;
765
766 //
767 // Synchronize with Ax88772Timer
768 //
769 VERIFY_TPL ( TPL_AX88772 );
770 TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );
771 DEBUG (( DEBUG_TPL | DEBUG_INFO,
772 "%d: TPL\r\n",
773 TPL_AX88772 ));
774
775 //
776 // Get the link status
777 //
778 if ( bUpdateLink ) {
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 );
788
789 //
790 // Determine if the autonegotiation is complete
791 //
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 );
804 }
805 if (( !bLinkUp ) && pNicDevice->bLinkUp ) {
806 //
807 // Display the autonegotiation status
808 //
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" ));
813 }
814 }
815 }
816
817 //
818 // Update the link status
819 //
820 if ( bLinkUp && ( !pNicDevice->bLinkUp )) {
821 DEBUG (( DEBUG_LINK | DEBUG_INFO, "Link: Down\r\n" ));
822 }
823 }
824
825 //
826 // Loop until all the packets are emptied from the receiver
827 //
828 do {
829 bRxPacket = FALSE;
830
831 //
832 // Locate a packet for use
833 //
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 )) {
841 //
842 // Add this packet to the free packet list
843 //
844 pNicDevice->pRxFree = pRxPacket;
845 pRxPacket->pNext = NULL;
846 }
847 else {
848 //
849 // Use the discard packet buffer
850 //
851 pRxPacket = &Packet;
852 }
853 }
854
855 //
856 // Attempt to receive a packet
857 //
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],
863 &LengthInBytes,
864 2,
865 &TransferStatus );
866 if ( LengthInBytes > 0 ) {
867 FillPkt2Queue(pNicDevice, LengthInBytes);
868 }
869 pRxPacket = pNicDevice->pRxHead;
870 if (( !EFI_ERROR ( Status ))
871 && ( 0 < pRxPacket->Length )
872 && ( pRxPacket->Length <= sizeof ( pRxPacket->Data ))
873 && ( LengthInBytes > 0)) {
874
875 //
876 // Determine if the packet should be received
877 //
878 bRxPacket = TRUE;
879 LengthInBytes = pRxPacket->Length;
880 pNicDevice->bLinkIdle = FALSE;
881 if ( pNicDevice->pRxFree == pRxPacket ) {
882 //
883 // Display the received packet
884 //
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",
894 pRxPacket->Data[0],
895 pRxPacket->Data[1],
896 pRxPacket->Data[2],
897 pRxPacket->Data[3],
898 pRxPacket->Data[4],
899 pRxPacket->Data[5],
900 pRxPacket->Data[6],
901 pRxPacket->Data[7],
902 pRxPacket->Data[8],
903 pRxPacket->Data[9],
904 pRxPacket->Data[10],
905 pRxPacket->Data[11],
906 pRxPacket->Data[12],
907 pRxPacket->Data[13],
908 LengthInBytes ));
909 }
910 else {
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",
913 pRxPacket->Data[0],
914 pRxPacket->Data[1],
915 pRxPacket->Data[2],
916 pRxPacket->Data[3],
917 pRxPacket->Data[4],
918 pRxPacket->Data[5],
919 pRxPacket->Data[6],
920 pRxPacket->Data[7],
921 pRxPacket->Data[8],
922 pRxPacket->Data[9],
923 pRxPacket->Data[10],
924 pRxPacket->Data[11],
925 pRxPacket->Data[12],
926 pRxPacket->Data[13],
927 LengthInBytes ));
928 }
929 }
930 else {
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",
933 pRxPacket->Data[0],
934 pRxPacket->Data[1],
935 pRxPacket->Data[2],
936 pRxPacket->Data[3],
937 pRxPacket->Data[4],
938 pRxPacket->Data[5],
939 pRxPacket->Data[6],
940 pRxPacket->Data[7],
941 pRxPacket->Data[8],
942 pRxPacket->Data[9],
943 pRxPacket->Data[10],
944 pRxPacket->Data[11],
945 pRxPacket->Data[12],
946 pRxPacket->Data[13],
947 LengthInBytes ));
948 }
949
950 }
951 else {
952 //
953 // Error, not enough buffers for this packet, discard packet
954 //
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",
957 pRxPacket->Data[0],
958 pRxPacket->Data[1],
959 pRxPacket->Data[2],
960 pRxPacket->Data[3],
961 pRxPacket->Data[4],
962 pRxPacket->Data[5],
963 pRxPacket->Data[6],
964 pRxPacket->Data[7],
965 pRxPacket->Data[8],
966 pRxPacket->Data[9],
967 pRxPacket->Data[10],
968 pRxPacket->Data[11],
969 pRxPacket->Data[12],
970 pRxPacket->Data[13],
971 LengthInBytes ));
972 }
973 }
974 }while ( bRxPacket );
975
976 //
977 // Release the synchronization withhe Ax88772Timer
978 //
979 gBS->RestoreTPL ( TplPrevious );
980 DEBUG (( DEBUG_TPL | DEBUG_INFO,
981 "%d: TPL\r\n",
982 TplPrevious ));
983 }
984
985
986 /**
987 Enable or disable the receiver
988
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.
992
993 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
994 @param [in] RxFilter Simple network RX filter mask value
995
996 @retval EFI_SUCCESS The MAC address was set.
997 @retval other The MAC address was not set.
998
999 **/
1000 EFI_STATUS
1001 Ax88772RxControl (
1002 IN NIC_DEVICE * pNicDevice,
1003 IN UINT32 RxFilter
1004 )
1005 {
1006 UINT16 MediumStatus;
1007 INT32 MulticastHash[2];
1008 UINT16 RxControl;
1009 USB_DEVICE_REQUEST SetupMsg;
1010 EFI_STATUS Status;
1011
1012 DBG_ENTER ( );
1013
1014 //
1015 // Disable all multicast
1016 //
1017 MulticastHash[0] = 0;
1018 MulticastHash[1] = 0;
1019
1020 //
1021 // Enable the receiver if something is to be received
1022 //
1023 Status = EFI_SUCCESS;
1024 RxControl = RXC_SO | RXC_MFB_16384;
1025 if ( 0 != RxFilter ) {
1026 //
1027 // Enable the receiver
1028 //
1029 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
1030 | USB_REQ_TYPE_VENDOR
1031 | USB_TARGET_DEVICE;
1032 SetupMsg.Request = CMD_MEDIUM_STATUS_READ;
1033 SetupMsg.Value = 0;
1034 SetupMsg.Index = 0;
1035 SetupMsg.Length = sizeof ( MediumStatus );
1036 Status = Ax88772UsbCommand ( pNicDevice,
1037 &SetupMsg,
1038 &MediumStatus );
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;
1044 }
1045 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
1046 | USB_TARGET_DEVICE;
1047 SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;
1048 SetupMsg.Value = MediumStatus;
1049 SetupMsg.Index = 0;
1050 SetupMsg.Length = 0;
1051 Status = Ax88772UsbCommand ( pNicDevice,
1052 &SetupMsg,
1053 NULL );
1054 if ( EFI_ERROR ( Status )) {
1055 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1056 "ERROR - Failed to enable receiver, Status: %r\r\n",
1057 Status ));
1058 }
1059 }
1060 }
1061 else {
1062 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1063 "ERROR - Failed to read receiver status, Status: %r\r\n",
1064 Status ));
1065 }
1066
1067 //
1068 // Enable multicast if requested
1069 //
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];
1074 }
1075
1076 //
1077 // Enable all multicast if requested
1078 //
1079 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {
1080 RxControl |= RXC_AMALL;
1081 MulticastHash[0] = -1;
1082 MulticastHash[1] = -1;
1083 }
1084
1085 //
1086 // Enable broadcast if requested
1087 //
1088 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {
1089 RxControl |= RXC_AB;
1090 }
1091
1092 //
1093 // Enable promiscuous mode if requested
1094 //
1095 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {
1096 RxControl |= RXC_PRO;
1097 MulticastHash[0] = -1;
1098 MulticastHash[1] = -1;
1099 }
1100 }
1101
1102 //
1103 // Update the MAC address
1104 //
1105 if ( !EFI_ERROR ( Status )) {
1106 Status = Ax88772MacAddressSet ( pNicDevice, &pNicDevice->SimpleNetworkData.CurrentAddress.Addr[0]);
1107 }
1108
1109 //
1110 // Update the receiver control
1111 //
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;
1117 SetupMsg.Index = 0;
1118 SetupMsg.Length = 0;
1119 Status = Ax88772UsbCommand ( pNicDevice,
1120 &SetupMsg,
1121 NULL );
1122 if ( !EFI_ERROR ( Status )) {
1123 DEBUG (( DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST | DEBUG_RX_UNICAST | DEBUG_INFO,
1124 "RxControl: 0x%04x\r\n",
1125 RxControl ));
1126
1127 //
1128 // Update the multicast hash table
1129 //
1130 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
1131 | USB_TARGET_DEVICE;
1132 SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;
1133 SetupMsg.Value = 0;
1134 SetupMsg.Index = 0;
1135 SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );
1136 Status = Ax88772UsbCommand ( pNicDevice,
1137 &SetupMsg,
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 )));
1150 }
1151 else {
1152 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1153 "ERROR - Failed to update multicast hash table, Status: %r\r\n",
1154 Status ));
1155 }
1156 }
1157 else {
1158 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1159 "ERROR - Failed to set receiver control, Status: %r\r\n",
1160 Status ));
1161 }
1162 }
1163
1164 //
1165 // Return the operation status
1166 //
1167 DBG_EXIT_STATUS ( Status );
1168 return Status;
1169 }
1170
1171
1172 /**
1173 Read an SROM location
1174
1175 This routine calls ::Ax88772UsbCommand to read data from the
1176 SROM.
1177
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
1181
1182 @retval EFI_SUCCESS The read was successful
1183 @retval other The read failed
1184
1185 **/
1186 EFI_STATUS
1187 Ax88772SromRead (
1188 IN NIC_DEVICE * pNicDevice,
1189 IN UINT32 Address,
1190 OUT UINT16 * pData
1191 )
1192 {
1193 USB_DEVICE_REQUEST SetupMsg;
1194 EFI_STATUS Status;
1195
1196 DBG_ENTER ( );
1197
1198 //
1199 // Read a value from the SROM
1200 //
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;
1206 SetupMsg.Index = 0;
1207 SetupMsg.Length = sizeof ( *pData );
1208 Status = Ax88772UsbCommand ( pNicDevice,
1209 &SetupMsg,
1210 pData );
1211
1212 //
1213 // Return the operation status
1214 //
1215 DBG_EXIT_STATUS ( Status );
1216 return Status;
1217 }
1218
1219
1220 /**
1221 This routine is called at a regular interval to poll for
1222 receive packets.
1223
1224 This routine polls the link state and gets any receive packets
1225 by calling ::Ax88772Rx.
1226
1227 @param [in] Event Timer event
1228 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1229
1230 **/
1231 VOID
1232 Ax88772Timer (
1233 IN EFI_EVENT Event,
1234 IN NIC_DEVICE * pNicDevice
1235 )
1236 {
1237 //
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
1240 // shell
1241 //
1242 DEBUG (( DEBUG_TIMER, "Entering Ax88772Timer\r\n" ));
1243
1244 //
1245 // Poll the link state and get any receive packets
1246 //
1247 Ax88772Rx ( pNicDevice, FALSE );
1248
1249 DEBUG (( DEBUG_TIMER, "Exiting Ax88772Timer\r\n" ));
1250 }
1251
1252
1253 /**
1254 Send a command to the USB device.
1255
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
1259
1260 @retval EFI_SUCCESS The USB transfer was successful
1261 @retval other The USB transfer failed
1262
1263 **/
1264 EFI_STATUS
1265 Ax88772UsbCommand (
1266 IN NIC_DEVICE * pNicDevice,
1267 IN USB_DEVICE_REQUEST * pRequest,
1268 IN OUT VOID * pBuffer
1269 )
1270 {
1271 UINT32 CmdStatus;
1272 EFI_USB_DATA_DIRECTION Direction;
1273 EFI_USB_IO_PROTOCOL * pUsbIo;
1274 EFI_STATUS Status;
1275
1276 DBG_ENTER ( );
1277
1278 //
1279 // Determine the transfer direction
1280 //
1281 Direction = EfiUsbNoData;
1282 if ( 0 != pRequest->Length ) {
1283 Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))
1284 ? EfiUsbDataIn : EfiUsbDataOut;
1285 }
1286
1287 //
1288 // Issue the command
1289 //
1290 pUsbIo = pNicDevice->pUsbIo;
1291 Status = pUsbIo->UsbControlTransfer ( pUsbIo,
1292 pRequest,
1293 Direction,
1294 USB_BUS_TIMEOUT,
1295 pBuffer,
1296 pRequest->Length,
1297 &CmdStatus );
1298
1299 //
1300 // Determine the operation status
1301 //
1302 if ( !EFI_ERROR ( Status )) {
1303 Status = CmdStatus;
1304 }
1305 else {
1306 //
1307 // Display any errors
1308 //
1309 DEBUG (( DEBUG_INFO,
1310 "Ax88772UsbCommand - Status: %r\n",
1311 Status ));
1312
1313 //
1314 // Only use status values associated with the Simple Network protocol
1315 //
1316 if ( EFI_TIMEOUT == Status ) {
1317 Status = EFI_DEVICE_ERROR;
1318 }
1319 }
1320
1321 //
1322 // Return the operation status
1323 //
1324 DBG_EXIT_STATUS ( Status );
1325 return Status;
1326 }