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