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