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
Ax88772Crc(IN UINT8 * pMacAddress)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
Ax88772MacAddressGet(IN NIC_DEVICE * pNicDevice,OUT UINT8 * pMacAddress)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
Ax88772MacAddressSet(IN NIC_DEVICE * pNicDevice,IN UINT8 * pMacAddress)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
Ax88772MulticastClear(IN NIC_DEVICE * pNicDevice)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
Ax88772MulticastSet(IN NIC_DEVICE * pNicDevice,IN UINT8 * pMacAddress)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
Ax88772NegotiateLinkStart(IN NIC_DEVICE * pNicDevice)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
Ax88772NegotiateLinkComplete(IN NIC_DEVICE * pNicDevice,IN OUT UINTN * pPollCount,OUT BOOLEAN * pbComplete,OUT BOOLEAN * pbLinkUp,OUT BOOLEAN * pbHiSpeed,OUT BOOLEAN * pbFullDuplex)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
Ax88772PhyRead(IN NIC_DEVICE * pNicDevice,IN UINT8 RegisterAddress,IN OUT UINT16 * pPhyData)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
Ax88772PhyWrite(IN NIC_DEVICE * pNicDevice,IN UINT8 RegisterAddress,IN UINT16 PhyData)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
Ax88772Reset(IN NIC_DEVICE * pNicDevice)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
FillPkt2Queue(IN NIC_DEVICE * pNicDevice,IN UINTN BufLength)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 EFI_STATUS Status;
671
672 for ( offset = 0; offset < BufLength; ){
673 pLength = (UINT16*) (pNicDevice->pBulkInBuff + offset);
674 pLengthBar = (UINT16*) (pNicDevice->pBulkInBuff + offset +2);
675
676 *pLength &= 0x7ff;
677 *pLengthBar &= 0x7ff;
678 *pLengthBar |= 0xf800;
679
680 if ((*pLength ^ *pLengthBar ) != 0xFFFF) {
681 DEBUG (( EFI_D_ERROR , "Pkt length error. BufLength = %d\n", BufLength));
682 return;
683 }
684
685 pRxPacket = pNicDevice->pRxFree;
686 if ( NULL == pRxPacket ) {
687 Status = gBS->AllocatePool ( EfiRuntimeServicesData,
688 sizeof( RX_TX_PACKET ),
689 (VOID **) &pRxPacket );
690 if ( !EFI_ERROR ( Status )) {
691 //
692 // Add this packet to the free packet list
693 //
694 pNicDevice->pRxFree = pRxPacket;
695 pRxPacket->pNext = NULL;
696 }
697 else {
698 //
699 // Use the discard packet buffer
700 //
701 //pRxPacket = &Packet;
702 }
703 }
704
705
706 pData = pNicDevice->pBulkInBuff + offset + 4;
707 pRxPacket->Length = *pLength;
708 pRxPacket->LengthBar = *(UINT16*) (pNicDevice->pBulkInBuff + offset +2);
709 CopyMem (&pRxPacket->Data[0], pData, *pLength);
710 //DEBUG((DEBUG_INFO, "Packet [%d]\n", *pLength));
711
712 pNicDevice->pRxFree = pRxPacket->pNext;
713 pRxPacket->pNext = NULL;
714
715 if ( NULL == pNicDevice->pRxTail ) {
716 pNicDevice->pRxHead = pRxPacket;
717 }
718 else {
719 pNicDevice->pRxTail->pNext = pRxPacket;
720 }
721 pNicDevice->pRxTail = pRxPacket;
722 offset += (*pLength + 4);
723
724 }
725 }
726
727
728
729 /**
730 Receive a frame from the network.
731
732 This routine polls the USB receive interface for a packet. If a packet
733 is available, this routine adds the receive packet to the list of
734 pending receive packets.
735
736 This routine calls ::Ax88772NegotiateLinkComplete to verify
737 that the link is up. This routine also calls ::SN_Reset to
738 reset the network adapter when necessary. Finally this
739 routine attempts to receive one or more packets from the
740 network adapter.
741
742 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
743 @param [in] bUpdateLink TRUE = Update link status
744
745 **/
746 VOID
Ax88772Rx(IN NIC_DEVICE * pNicDevice,IN BOOLEAN bUpdateLink)747 Ax88772Rx (
748 IN NIC_DEVICE * pNicDevice,
749 IN BOOLEAN bUpdateLink
750 )
751 {
752 BOOLEAN bFullDuplex;
753 BOOLEAN bLinkUp;
754 BOOLEAN bRxPacket;
755 BOOLEAN bSpeed100;
756 UINTN LengthInBytes;
757 RX_TX_PACKET Packet;
758 RX_TX_PACKET * pRxPacket;
759 EFI_USB_IO_PROTOCOL *pUsbIo;
760 EFI_STATUS Status;
761 EFI_TPL TplPrevious;
762 UINT32 TransferStatus;
763
764 //
765 // Synchronize with Ax88772Timer
766 //
767 VERIFY_TPL ( TPL_AX88772 );
768 TplPrevious = gBS->RaiseTPL ( TPL_AX88772 );
769 DEBUG (( DEBUG_TPL | DEBUG_INFO,
770 "%d: TPL\r\n",
771 TPL_AX88772 ));
772
773 //
774 // Get the link status
775 //
776 if ( bUpdateLink ) {
777 bLinkUp = pNicDevice->bLinkUp;
778 bSpeed100 = pNicDevice->b100Mbps;
779 bFullDuplex = pNicDevice->bFullDuplex;
780 Status = Ax88772NegotiateLinkComplete ( pNicDevice,
781 &pNicDevice->PollCount,
782 &pNicDevice->bComplete,
783 &pNicDevice->bLinkUp,
784 &pNicDevice->b100Mbps,
785 &pNicDevice->bFullDuplex );
786
787 //
788 // Determine if the autonegotiation is complete
789 //
790 if ( pNicDevice->bComplete ) {
791 if ( pNicDevice->bLinkUp ) {
792 if (( bSpeed100 && ( !pNicDevice->b100Mbps ))
793 || (( !bSpeed100 ) && pNicDevice->b100Mbps )
794 || ( bFullDuplex && ( !pNicDevice->bFullDuplex ))
795 || (( !bFullDuplex ) && pNicDevice->bFullDuplex )) {
796 pNicDevice->PollCount = 0;
797 DEBUG (( DEBUG_LINK | DEBUG_INFO,
798 "Reset to establish proper link setup: %d Mbps, %s duplex\r\n",
799 pNicDevice->b100Mbps ? 100 : 10,
800 pNicDevice->bFullDuplex ? L"Full" : L"Half" ));
801 Status = SN_Reset ( &pNicDevice->SimpleNetwork, FALSE );
802 }
803 if (( !bLinkUp ) && pNicDevice->bLinkUp ) {
804 //
805 // Display the autonegotiation status
806 //
807 DEBUG (( DEBUG_LINK | DEBUG_INFO,
808 "Link: Up, %d Mbps, %s duplex\r\n",
809 pNicDevice->b100Mbps ? 100 : 10,
810 pNicDevice->bFullDuplex ? L"Full" : L"Half" ));
811 }
812 }
813 }
814
815 //
816 // Update the link status
817 //
818 if ( bLinkUp && ( !pNicDevice->bLinkUp )) {
819 DEBUG (( DEBUG_LINK | DEBUG_INFO, "Link: Down\r\n" ));
820 }
821 }
822
823 //
824 // Loop until all the packets are emptied from the receiver
825 //
826 do {
827 bRxPacket = FALSE;
828
829 //
830 // Locate a packet for use
831 //
832 pRxPacket = pNicDevice->pRxFree;
833 LengthInBytes = MAX_BULKIN_SIZE;
834 if ( NULL == pRxPacket ) {
835 Status = gBS->AllocatePool ( EfiRuntimeServicesData,
836 sizeof ( *pRxPacket ),
837 (VOID **) &pRxPacket );
838 if ( !EFI_ERROR ( Status )) {
839 //
840 // Add this packet to the free packet list
841 //
842 pNicDevice->pRxFree = pRxPacket;
843 pRxPacket->pNext = NULL;
844 }
845 else {
846 //
847 // Use the discard packet buffer
848 //
849 pRxPacket = &Packet;
850 }
851 }
852
853 //
854 // Attempt to receive a packet
855 //
856 SetMem (&pNicDevice->pBulkInBuff[0], MAX_BULKIN_SIZE, 0);
857 pUsbIo = pNicDevice->pUsbIo;
858 Status = pUsbIo->UsbBulkTransfer ( pUsbIo,
859 USB_ENDPOINT_DIR_IN | BULK_IN_ENDPOINT,
860 &pNicDevice->pBulkInBuff[0],
861 &LengthInBytes,
862 2,
863 &TransferStatus );
864 if ( LengthInBytes > 0 ) {
865 FillPkt2Queue(pNicDevice, LengthInBytes);
866 }
867 pRxPacket = pNicDevice->pRxHead;
868 if (( !EFI_ERROR ( Status ))
869 && ( 0 < pRxPacket->Length )
870 && ( pRxPacket->Length <= sizeof ( pRxPacket->Data ))
871 && ( LengthInBytes > 0)) {
872
873 //
874 // Determine if the packet should be received
875 //
876 bRxPacket = TRUE;
877 LengthInBytes = pRxPacket->Length;
878 pNicDevice->bLinkIdle = FALSE;
879 if ( pNicDevice->pRxFree == pRxPacket ) {
880 //
881 // Display the received packet
882 //
883 if ( 0 != ( pRxPacket->Data[0] & 1 )) {
884 if (( 0xff == pRxPacket->Data[0])
885 && ( 0xff == pRxPacket->Data[1])
886 && ( 0xff == pRxPacket->Data[2])
887 && ( 0xff == pRxPacket->Data[3])
888 && ( 0xff == pRxPacket->Data[4])
889 && ( 0xff == pRxPacket->Data[5])) {
890 DEBUG (( DEBUG_RX_BROADCAST | DEBUG_INFO,
891 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
892 pRxPacket->Data[0],
893 pRxPacket->Data[1],
894 pRxPacket->Data[2],
895 pRxPacket->Data[3],
896 pRxPacket->Data[4],
897 pRxPacket->Data[5],
898 pRxPacket->Data[6],
899 pRxPacket->Data[7],
900 pRxPacket->Data[8],
901 pRxPacket->Data[9],
902 pRxPacket->Data[10],
903 pRxPacket->Data[11],
904 pRxPacket->Data[12],
905 pRxPacket->Data[13],
906 LengthInBytes ));
907 }
908 else {
909 DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,
910 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
911 pRxPacket->Data[0],
912 pRxPacket->Data[1],
913 pRxPacket->Data[2],
914 pRxPacket->Data[3],
915 pRxPacket->Data[4],
916 pRxPacket->Data[5],
917 pRxPacket->Data[6],
918 pRxPacket->Data[7],
919 pRxPacket->Data[8],
920 pRxPacket->Data[9],
921 pRxPacket->Data[10],
922 pRxPacket->Data[11],
923 pRxPacket->Data[12],
924 pRxPacket->Data[13],
925 LengthInBytes ));
926 }
927 }
928 else {
929 DEBUG (( DEBUG_RX_UNICAST | DEBUG_INFO,
930 "RX: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
931 pRxPacket->Data[0],
932 pRxPacket->Data[1],
933 pRxPacket->Data[2],
934 pRxPacket->Data[3],
935 pRxPacket->Data[4],
936 pRxPacket->Data[5],
937 pRxPacket->Data[6],
938 pRxPacket->Data[7],
939 pRxPacket->Data[8],
940 pRxPacket->Data[9],
941 pRxPacket->Data[10],
942 pRxPacket->Data[11],
943 pRxPacket->Data[12],
944 pRxPacket->Data[13],
945 LengthInBytes ));
946 }
947
948 }
949 else {
950 //
951 // Error, not enough buffers for this packet, discard packet
952 //
953 DEBUG (( DEBUG_WARN | DEBUG_INFO,
954 "WARNING - No buffer, discarding RX packet: %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x-%02x-%02x-%02x-%02x %02x-%02x %d bytes\r\n",
955 pRxPacket->Data[0],
956 pRxPacket->Data[1],
957 pRxPacket->Data[2],
958 pRxPacket->Data[3],
959 pRxPacket->Data[4],
960 pRxPacket->Data[5],
961 pRxPacket->Data[6],
962 pRxPacket->Data[7],
963 pRxPacket->Data[8],
964 pRxPacket->Data[9],
965 pRxPacket->Data[10],
966 pRxPacket->Data[11],
967 pRxPacket->Data[12],
968 pRxPacket->Data[13],
969 LengthInBytes ));
970 }
971 }
972 }while ( bRxPacket );
973
974 //
975 // Release the synchronization withhe Ax88772Timer
976 //
977 gBS->RestoreTPL ( TplPrevious );
978 DEBUG (( DEBUG_TPL | DEBUG_INFO,
979 "%d: TPL\r\n",
980 TplPrevious ));
981 }
982
983
984 /**
985 Enable or disable the receiver
986
987 This routine calls ::Ax88772UsbCommand to update the
988 receiver state. This routine also calls ::Ax88772MacAddressSet
989 to establish the MAC address for the network adapter.
990
991 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
992 @param [in] RxFilter Simple network RX filter mask value
993
994 @retval EFI_SUCCESS The MAC address was set.
995 @retval other The MAC address was not set.
996
997 **/
998 EFI_STATUS
Ax88772RxControl(IN NIC_DEVICE * pNicDevice,IN UINT32 RxFilter)999 Ax88772RxControl (
1000 IN NIC_DEVICE * pNicDevice,
1001 IN UINT32 RxFilter
1002 )
1003 {
1004 UINT16 MediumStatus;
1005 INT32 MulticastHash[2];
1006 UINT16 RxControl;
1007 USB_DEVICE_REQUEST SetupMsg;
1008 EFI_STATUS Status;
1009
1010 DBG_ENTER ( );
1011
1012 //
1013 // Disable all multicast
1014 //
1015 MulticastHash[0] = 0;
1016 MulticastHash[1] = 0;
1017
1018 //
1019 // Enable the receiver if something is to be received
1020 //
1021 Status = EFI_SUCCESS;
1022 RxControl = RXC_SO | RXC_MFB_16384;
1023 if ( 0 != RxFilter ) {
1024 //
1025 // Enable the receiver
1026 //
1027 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
1028 | USB_REQ_TYPE_VENDOR
1029 | USB_TARGET_DEVICE;
1030 SetupMsg.Request = CMD_MEDIUM_STATUS_READ;
1031 SetupMsg.Value = 0;
1032 SetupMsg.Index = 0;
1033 SetupMsg.Length = sizeof ( MediumStatus );
1034 Status = Ax88772UsbCommand ( pNicDevice,
1035 &SetupMsg,
1036 &MediumStatus );
1037 if ( !EFI_ERROR ( Status )) {
1038 if ( 0 == ( MediumStatus & MS_RE )) {
1039 MediumStatus |= MS_RE | MS_ONE;
1040 if ( pNicDevice->bFullDuplex ) {
1041 MediumStatus |= MS_TFC | MS_RFC;
1042 }
1043 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
1044 | USB_TARGET_DEVICE;
1045 SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;
1046 SetupMsg.Value = MediumStatus;
1047 SetupMsg.Index = 0;
1048 SetupMsg.Length = 0;
1049 Status = Ax88772UsbCommand ( pNicDevice,
1050 &SetupMsg,
1051 NULL );
1052 if ( EFI_ERROR ( Status )) {
1053 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1054 "ERROR - Failed to enable receiver, Status: %r\r\n",
1055 Status ));
1056 }
1057 }
1058 }
1059 else {
1060 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1061 "ERROR - Failed to read receiver status, Status: %r\r\n",
1062 Status ));
1063 }
1064
1065 //
1066 // Enable multicast if requested
1067 //
1068 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {
1069 RxControl |= RXC_AM;
1070 MulticastHash[0] = pNicDevice->MulticastHash[0];
1071 MulticastHash[1] = pNicDevice->MulticastHash[1];
1072 }
1073
1074 //
1075 // Enable all multicast if requested
1076 //
1077 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {
1078 RxControl |= RXC_AMALL;
1079 MulticastHash[0] = -1;
1080 MulticastHash[1] = -1;
1081 }
1082
1083 //
1084 // Enable broadcast if requested
1085 //
1086 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {
1087 RxControl |= RXC_AB;
1088 }
1089
1090 //
1091 // Enable promiscuous mode if requested
1092 //
1093 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {
1094 RxControl |= RXC_PRO;
1095 MulticastHash[0] = -1;
1096 MulticastHash[1] = -1;
1097 }
1098 }
1099
1100 //
1101 // Update the MAC address
1102 //
1103 if ( !EFI_ERROR ( Status )) {
1104 Status = Ax88772MacAddressSet ( pNicDevice, &pNicDevice->SimpleNetworkData.CurrentAddress.Addr[0]);
1105 }
1106
1107 //
1108 // Update the receiver control
1109 //
1110 if ( !EFI_ERROR ( Status )) {
1111 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
1112 | USB_TARGET_DEVICE;
1113 SetupMsg.Request = CMD_RX_CONTROL_WRITE;
1114 SetupMsg.Value = RxControl;
1115 SetupMsg.Index = 0;
1116 SetupMsg.Length = 0;
1117 Status = Ax88772UsbCommand ( pNicDevice,
1118 &SetupMsg,
1119 NULL );
1120 if ( !EFI_ERROR ( Status )) {
1121 DEBUG (( DEBUG_RX_BROADCAST | DEBUG_RX_MULTICAST | DEBUG_RX_UNICAST | DEBUG_INFO,
1122 "RxControl: 0x%04x\r\n",
1123 RxControl ));
1124
1125 //
1126 // Update the multicast hash table
1127 //
1128 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR
1129 | USB_TARGET_DEVICE;
1130 SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;
1131 SetupMsg.Value = 0;
1132 SetupMsg.Index = 0;
1133 SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );
1134 Status = Ax88772UsbCommand ( pNicDevice,
1135 &SetupMsg,
1136 &pNicDevice->MulticastHash );
1137 if ( !EFI_ERROR ( Status )) {
1138 DEBUG (( DEBUG_RX_MULTICAST | DEBUG_INFO,
1139 "Multicast Hash: 0x%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
1140 (UINT8) MulticastHash[0],
1141 (UINT8)( MulticastHash[0] >> 8 ),
1142 (UINT8)( MulticastHash[0] >> 16 ),
1143 (UINT8)( MulticastHash[0] >> 24 ),
1144 (UINT8) MulticastHash[1],
1145 (UINT8)( MulticastHash[1] >> 8 ),
1146 (UINT8)( MulticastHash[1] >> 16 ),
1147 (UINT8)( MulticastHash[1] >> 24 )));
1148 }
1149 else {
1150 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1151 "ERROR - Failed to update multicast hash table, Status: %r\r\n",
1152 Status ));
1153 }
1154 }
1155 else {
1156 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
1157 "ERROR - Failed to set receiver control, Status: %r\r\n",
1158 Status ));
1159 }
1160 }
1161
1162 //
1163 // Return the operation status
1164 //
1165 DBG_EXIT_STATUS ( Status );
1166 return Status;
1167 }
1168
1169
1170 /**
1171 Read an SROM location
1172
1173 This routine calls ::Ax88772UsbCommand to read data from the
1174 SROM.
1175
1176 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1177 @param [in] Address SROM address
1178 @param [out] pData Buffer to receive the data
1179
1180 @retval EFI_SUCCESS The read was successful
1181 @retval other The read failed
1182
1183 **/
1184 EFI_STATUS
Ax88772SromRead(IN NIC_DEVICE * pNicDevice,IN UINT32 Address,OUT UINT16 * pData)1185 Ax88772SromRead (
1186 IN NIC_DEVICE * pNicDevice,
1187 IN UINT32 Address,
1188 OUT UINT16 * pData
1189 )
1190 {
1191 USB_DEVICE_REQUEST SetupMsg;
1192 EFI_STATUS Status;
1193
1194 DBG_ENTER ( );
1195
1196 //
1197 // Read a value from the SROM
1198 //
1199 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN
1200 | USB_REQ_TYPE_VENDOR
1201 | USB_TARGET_DEVICE;
1202 SetupMsg.Request = CMD_SROM_READ;
1203 SetupMsg.Value = (UINT16) Address;
1204 SetupMsg.Index = 0;
1205 SetupMsg.Length = sizeof ( *pData );
1206 Status = Ax88772UsbCommand ( pNicDevice,
1207 &SetupMsg,
1208 pData );
1209
1210 //
1211 // Return the operation status
1212 //
1213 DBG_EXIT_STATUS ( Status );
1214 return Status;
1215 }
1216
1217
1218 /**
1219 This routine is called at a regular interval to poll for
1220 receive packets.
1221
1222 This routine polls the link state and gets any receive packets
1223 by calling ::Ax88772Rx.
1224
1225 @param [in] Event Timer event
1226 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1227
1228 **/
1229 VOID
Ax88772Timer(IN EFI_EVENT Event,IN NIC_DEVICE * pNicDevice)1230 Ax88772Timer (
1231 IN EFI_EVENT Event,
1232 IN NIC_DEVICE * pNicDevice
1233 )
1234 {
1235 //
1236 // Use explicit DEBUG messages since the output frequency is too
1237 // high for DEBUG_INFO to keep up and have spare cycles for the
1238 // shell
1239 //
1240 DEBUG (( DEBUG_TIMER, "Entering Ax88772Timer\r\n" ));
1241
1242 //
1243 // Poll the link state and get any receive packets
1244 //
1245 Ax88772Rx ( pNicDevice, FALSE );
1246
1247 DEBUG (( DEBUG_TIMER, "Exiting Ax88772Timer\r\n" ));
1248 }
1249
1250
1251 /**
1252 Send a command to the USB device.
1253
1254 @param [in] pNicDevice Pointer to the NIC_DEVICE structure
1255 @param [in] pRequest Pointer to the request structure
1256 @param [in, out] pBuffer Data buffer address
1257
1258 @retval EFI_SUCCESS The USB transfer was successful
1259 @retval other The USB transfer failed
1260
1261 **/
1262 EFI_STATUS
Ax88772UsbCommand(IN NIC_DEVICE * pNicDevice,IN USB_DEVICE_REQUEST * pRequest,IN OUT VOID * pBuffer)1263 Ax88772UsbCommand (
1264 IN NIC_DEVICE * pNicDevice,
1265 IN USB_DEVICE_REQUEST * pRequest,
1266 IN OUT VOID * pBuffer
1267 )
1268 {
1269 UINT32 CmdStatus;
1270 EFI_USB_DATA_DIRECTION Direction;
1271 EFI_USB_IO_PROTOCOL * pUsbIo;
1272 EFI_STATUS Status;
1273
1274 DBG_ENTER ( );
1275
1276 //
1277 // Determine the transfer direction
1278 //
1279 Direction = EfiUsbNoData;
1280 if ( 0 != pRequest->Length ) {
1281 Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))
1282 ? EfiUsbDataIn : EfiUsbDataOut;
1283 }
1284
1285 //
1286 // Issue the command
1287 //
1288 pUsbIo = pNicDevice->pUsbIo;
1289 Status = pUsbIo->UsbControlTransfer ( pUsbIo,
1290 pRequest,
1291 Direction,
1292 USB_BUS_TIMEOUT,
1293 pBuffer,
1294 pRequest->Length,
1295 &CmdStatus );
1296
1297 //
1298 // Determine the operation status
1299 //
1300 if ( !EFI_ERROR ( Status )) {
1301 Status = CmdStatus;
1302 }
1303 else {
1304 //
1305 // Display any errors
1306 //
1307 DEBUG (( DEBUG_INFO,
1308 "Ax88772UsbCommand - Status: %r\n",
1309 Status ));
1310
1311 //
1312 // Only use status values associated with the Simple Network protocol
1313 //
1314 if ( EFI_TIMEOUT == Status ) {
1315 Status = EFI_DEVICE_ERROR;
1316 }
1317 }
1318
1319 //
1320 // Return the operation status
1321 //
1322 DBG_EXIT_STATUS ( Status );
1323 return Status;
1324 }
1325