]> git.proxmox.com Git - mirror_edk2.git/blame - OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/Ax88772.c
Omap35xxPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / OptionRomPkg / Bus / Usb / UsbNetworking / Ax88772b / Ax88772.c
CommitLineData
7f556e4d 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
8 Copyright (c) 2011, Intel Corporation\r
9 All rights reserved. This program and the accompanying materials\r
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 //\r
42 // Walk the MAC address\r
43 //\r
44 Crc = -1;\r
45 pEnd = &pMacAddress[ PXE_HWADDR_LEN_ETHER ];\r
46 while ( pEnd > pMacAddress ) {\r
47 Data = *pMacAddress++;\r
48 //\r
49 // CRC32: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1\r
50 //\r
51 // 1 0000 0100 1100 0001 0001 1101 1011 0111\r
52 //\r
53 for ( BitNumber = 0; 8 > BitNumber; BitNumber++ ) {\r
54 Carry = (( Crc >> 31 ) & 1 ) ^ ( Data & 1 );\r
55 Crc <<= 1;\r
56 if ( 0 != Carry ) {\r
57 Crc ^= 0x04c11db7;\r
58 }\r
59 Data >>= 1;\r
60 }\r
61 }\r
62 //\r
63 // Return the CRC value\r
64 //\r
65 return (UINT32) Crc;\r
66}\r
67\r
68\r
69/**\r
70 Get the MAC address\r
71\r
72 This routine calls ::Ax88772UsbCommand to request the MAC\r
73 address from the network adapter.\r
74\r
75 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
76 @param [out] pMacAddress Address of a six byte buffer to receive the MAC address.\r
77\r
78 @retval EFI_SUCCESS The MAC address is available.\r
79 @retval other The MAC address is not valid.\r
80\r
81**/\r
82EFI_STATUS\r
83Ax88772MacAddressGet (\r
84 IN NIC_DEVICE * pNicDevice,\r
85 OUT UINT8 * pMacAddress\r
86 )\r
87{\r
88 USB_DEVICE_REQUEST SetupMsg;\r
89 EFI_STATUS Status;\r
90\r
91 //\r
92 // Set the register address.\r
93 //\r
94 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN\r
95 | USB_REQ_TYPE_VENDOR\r
96 | USB_TARGET_DEVICE;\r
97 SetupMsg.Request = CMD_MAC_ADDRESS_READ;\r
98 SetupMsg.Value = 0;\r
99 SetupMsg.Index = 0;\r
100 SetupMsg.Length = PXE_HWADDR_LEN_ETHER;\r
101\r
102 //\r
103 // Read the PHY register\r
104 //\r
105 Status = Ax88772UsbCommand ( pNicDevice,\r
106 &SetupMsg,\r
107 pMacAddress );\r
108 return Status;\r
109}\r
110\r
111\r
112/**\r
113 Set the MAC address\r
114\r
115 This routine calls ::Ax88772UsbCommand to set the MAC address\r
116 in the network adapter.\r
117\r
118 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
119 @param [in] pMacAddress Address of a six byte buffer to containing the new MAC address.\r
120\r
121 @retval EFI_SUCCESS The MAC address was set.\r
122 @retval other The MAC address was not set.\r
123\r
124**/\r
125EFI_STATUS\r
126Ax88772MacAddressSet (\r
127 IN NIC_DEVICE * pNicDevice,\r
128 IN UINT8 * pMacAddress\r
129 )\r
130{\r
131 USB_DEVICE_REQUEST SetupMsg;\r
132 EFI_STATUS Status;\r
133\r
134 //\r
135 // Set the register address.\r
136 //\r
137 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
138 | USB_TARGET_DEVICE;\r
139 SetupMsg.Request = CMD_MAC_ADDRESS_WRITE;\r
140 SetupMsg.Value = 0;\r
141 SetupMsg.Index = 0;\r
142 SetupMsg.Length = PXE_HWADDR_LEN_ETHER;\r
143 \r
144 //\r
145 // Read the PHY register\r
146 //\r
147 Status = Ax88772UsbCommand ( pNicDevice,\r
148 &SetupMsg,\r
149 pMacAddress );\r
150 return Status;\r
151}\r
152\r
153/**\r
154 Clear the multicast hash table\r
155\r
156 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
157\r
158**/\r
159VOID\r
160Ax88772MulticastClear (\r
161 IN NIC_DEVICE * pNicDevice\r
162 )\r
163{\r
164 int i = 0;\r
165 //\r
166 // Clear the multicast hash table\r
167 //\r
168 for ( i = 0 ; i < 8 ; i ++ )\r
169 pNicDevice->MulticastHash[0] = 0;\r
170}\r
171\r
172/**\r
173 Enable a multicast address in the multicast hash table\r
174\r
175 This routine calls ::Ax88772Crc to compute the hash bit for\r
176 this MAC address.\r
177\r
178 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
179 @param [in] pMacAddress Address of a six byte buffer to containing the MAC address.\r
180\r
181**/\r
182VOID\r
183Ax88772MulticastSet (\r
184 IN NIC_DEVICE * pNicDevice,\r
185 IN UINT8 * pMacAddress\r
186 )\r
187{\r
188 UINT32 Crc;\r
189\r
190 //\r
191 // Compute the CRC on the destination address\r
192 //\r
193 Crc = Ax88772Crc ( pMacAddress ) >> 26;\r
194\r
195 //\r
196 // Set the bit corresponding to the destination address\r
197 //\r
198 pNicDevice->MulticastHash [ Crc >> 3 ] |= ( 1<< (Crc& 7));\r
199}\r
200\r
201/**\r
202 Start the link negotiation\r
203\r
204 This routine calls ::Ax88772PhyWrite to start the PHY's link\r
205 negotiation.\r
206\r
207 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
208\r
209 @retval EFI_SUCCESS The link negotiation was started.\r
210 @retval other Failed to start the link negotiation.\r
211\r
212**/\r
213EFI_STATUS\r
214Ax88772NegotiateLinkStart (\r
215 IN NIC_DEVICE * pNicDevice\r
216 )\r
217{\r
218 UINT16 Control;\r
219 EFI_STATUS Status;\r
220 int i; \r
221 //\r
222 // Set the supported capabilities.\r
223 //\r
224 Status = Ax88772PhyWrite ( pNicDevice,\r
225 PHY_ANAR,\r
226 AN_CSMA_CD\r
227 | AN_TX_FDX | AN_TX_HDX\r
228 | AN_10_FDX | AN_10_HDX );\r
229 if ( !EFI_ERROR ( Status )) {\r
230 //\r
231 // Set the link speed and duplex\r
232 //\r
233 Control = BMCR_AUTONEGOTIATION_ENABLE\r
234 | BMCR_RESTART_AUTONEGOTIATION;\r
235 if ( pNicDevice->b100Mbps ) {\r
236 Control |= BMCR_100MBPS;\r
237 }\r
238 if ( pNicDevice->bFullDuplex ) {\r
239 Control |= BMCR_FULL_DUPLEX;\r
240 }\r
241 Status = Ax88772PhyWrite ( pNicDevice, PHY_BMCR, Control );\r
242 }\r
243 \r
244 if (!EFI_ERROR(Status)) {\r
245 i = 0;\r
246 do {\r
247 \r
248 if (pNicDevice->bComplete && pNicDevice->bLinkUp) {\r
249 pNicDevice->SimpleNetwork.Mode->MediaPresent \r
250 = pNicDevice->bLinkUp & pNicDevice->bComplete;\r
251 break;\r
252 }\r
253 else {\r
254 gBS->Stall(AUTONEG_DELAY);\r
255 Status = Ax88772NegotiateLinkComplete ( pNicDevice,\r
256 &pNicDevice->PollCount,\r
257 &pNicDevice->bComplete,\r
258 &pNicDevice->bLinkUp,\r
259 &pNicDevice->b100Mbps,\r
260 &pNicDevice->bFullDuplex );\r
261 i++;\r
262 }\r
263 }while(!pNicDevice->bLinkUp && i < AUTONEG_POLLCNT);\r
264 }\r
265 return Status;\r
266}\r
267\r
268\r
269/**\r
270 Complete the negotiation of the PHY link\r
271\r
272 This routine calls ::Ax88772PhyRead to determine if the\r
273 link negotiation is complete.\r
274\r
275 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
276 @param [in, out] pPollCount Address of number of times this routine was polled\r
277 @param [out] pbComplete Address of boolean to receive complate status.\r
278 @param [out] pbLinkUp Address of boolean to receive link status, TRUE=up.\r
279 @param [out] pbHiSpeed Address of boolean to receive link speed, TRUE=100Mbps.\r
280 @param [out] pbFullDuplex Address of boolean to receive link duplex, TRUE=full.\r
281\r
282 @retval EFI_SUCCESS The MAC address is available.\r
283 @retval other The MAC address is not valid.\r
284\r
285**/\r
286EFI_STATUS\r
287Ax88772NegotiateLinkComplete (\r
288 IN NIC_DEVICE * pNicDevice,\r
289 IN OUT UINTN * pPollCount,\r
290 OUT BOOLEAN * pbComplete,\r
291 OUT BOOLEAN * pbLinkUp,\r
292 OUT BOOLEAN * pbHiSpeed,\r
293 OUT BOOLEAN * pbFullDuplex\r
294 )\r
295{\r
296 UINT16 Mask;\r
297 UINT16 PhyData;\r
298 EFI_STATUS Status;\r
299 \r
300 //\r
301 // Determine if the link is up.\r
302 //\r
303 *pbComplete = FALSE; \r
304\r
305 //\r
306 // Get the link status\r
307 //\r
308 Status = Ax88772PhyRead ( pNicDevice,\r
309 PHY_BMSR,\r
310 &PhyData );\r
311\r
312 if ( !EFI_ERROR ( Status )) {\r
313 *pbLinkUp = (BOOLEAN)( 0 != ( PhyData & BMSR_LINKST ));\r
314 if ( 0 == *pbLinkUp ) {\r
315 DEBUG (( EFI_D_INFO, "Link Down\n" ));\r
316 } \r
317 else {\r
318 *pbComplete = (BOOLEAN)( 0 != ( PhyData & 0x20 ));\r
319 if ( 0 == *pbComplete ) {\r
320 DEBUG (( EFI_D_INFO, "Autoneg is not yet Complete\n" ));\r
321 }\r
322 else {\r
323 Status = Ax88772PhyRead ( pNicDevice,\r
324 PHY_ANLPAR,\r
325 &PhyData );\r
326 if ( !EFI_ERROR ( Status )) {\r
327 //\r
328 // Autonegotiation is complete\r
329 // Determine the link speed.\r
330 //\r
331 *pbHiSpeed = (BOOLEAN)( 0 != ( PhyData & ( AN_TX_FDX | AN_TX_HDX )));\r
332\r
333 //\r
334 // Determine the link duplex.\r
335 //\r
336 Mask = ( *pbHiSpeed ) ? AN_TX_FDX : AN_10_FDX;\r
337 *pbFullDuplex = (BOOLEAN)( 0 != ( PhyData & Mask ));\r
338 }\r
339 } \r
340 }\r
341 } \r
342 else {\r
343 DEBUG (( EFI_D_ERROR, "Failed to read BMCR\n" ));\r
344 }\r
345 return Status;\r
346}\r
347\r
348\r
349/**\r
350 Read a register from the PHY\r
351\r
352 This routine calls ::Ax88772UsbCommand to read a PHY register.\r
353\r
354 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
355 @param [in] RegisterAddress Number of the register to read.\r
356 @param [in, out] pPhyData Address of a buffer to receive the PHY register value\r
357\r
358 @retval EFI_SUCCESS The PHY data is available.\r
359 @retval other The PHY data is not valid.\r
360\r
361**/\r
362EFI_STATUS\r
363Ax88772PhyRead (\r
364 IN NIC_DEVICE * pNicDevice,\r
365 IN UINT8 RegisterAddress,\r
366 IN OUT UINT16 * pPhyData\r
367 )\r
368{\r
369 USB_DEVICE_REQUEST SetupMsg;\r
370 EFI_STATUS Status;\r
371\r
372 //\r
373 // Request access to the PHY\r
374 //\r
375 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
376 | USB_TARGET_DEVICE;\r
377 SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE; \r
378 SetupMsg.Value = 0;\r
379 SetupMsg.Index = 0;\r
380 SetupMsg.Length = 0;\r
381 Status = Ax88772UsbCommand ( pNicDevice,\r
382 &SetupMsg,\r
383 NULL );\r
384 if ( !EFI_ERROR ( Status )) {\r
385 //\r
386 // Read the PHY register address.\r
387 //\r
388 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN\r
389 | USB_REQ_TYPE_VENDOR\r
390 | USB_TARGET_DEVICE;\r
391 SetupMsg.Request = CMD_PHY_REG_READ;\r
392 SetupMsg.Value = pNicDevice->PhyId;\r
393 SetupMsg.Index = RegisterAddress;\r
394 SetupMsg.Length = sizeof ( *pPhyData );\r
395 Status = Ax88772UsbCommand ( pNicDevice,\r
396 &SetupMsg,\r
397 pPhyData );\r
398 if ( !EFI_ERROR ( Status )) {\r
399\r
400 //\r
401 // Release the PHY to the hardware\r
402 //\r
403 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
404 | USB_TARGET_DEVICE;\r
405 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;\r
406 SetupMsg.Value = 0;\r
407 SetupMsg.Index = 0;\r
408 SetupMsg.Length = 0;\r
409 Status = Ax88772UsbCommand ( pNicDevice,\r
410 &SetupMsg,\r
411 NULL );\r
412 }\r
413 }\r
414 return Status;\r
415}\r
416\r
417\r
418/**\r
419 Write to a PHY register\r
420\r
421 This routine calls ::Ax88772UsbCommand to write a PHY register.\r
422\r
423 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
424 @param [in] RegisterAddress Number of the register to read.\r
425 @param [in] PhyData Address of a buffer to receive the PHY register value\r
426\r
427 @retval EFI_SUCCESS The PHY data was written.\r
428 @retval other Failed to wwrite the PHY register.\r
429\r
430**/\r
431EFI_STATUS\r
432Ax88772PhyWrite (\r
433 IN NIC_DEVICE * pNicDevice,\r
434 IN UINT8 RegisterAddress,\r
435 IN UINT16 PhyData\r
436 )\r
437{\r
438 USB_DEVICE_REQUEST SetupMsg;\r
439 EFI_STATUS Status;\r
440\r
441 //\r
442 // Request access to the PHY\r
443 //\r
444 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
445 | USB_TARGET_DEVICE;\r
446 SetupMsg.Request = CMD_PHY_ACCESS_SOFTWARE;\r
447 SetupMsg.Value = 0;\r
448 SetupMsg.Index = 0;\r
449 SetupMsg.Length = 0;\r
450 Status = Ax88772UsbCommand ( pNicDevice,\r
451 &SetupMsg,\r
452 NULL );\r
453 if ( !EFI_ERROR ( Status )) {\r
454 //\r
455 // Write the PHY register\r
456 //\r
457 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
458 | USB_TARGET_DEVICE;\r
459 SetupMsg.Request = CMD_PHY_REG_WRITE;\r
460 SetupMsg.Value = pNicDevice->PhyId;\r
461 SetupMsg.Index = RegisterAddress;\r
462 SetupMsg.Length = sizeof ( PhyData );\r
463 Status = Ax88772UsbCommand ( pNicDevice,\r
464 &SetupMsg,\r
465 &PhyData );\r
466 if ( !EFI_ERROR ( Status )) {\r
467\r
468 //\r
469 // Release the PHY to the hardware\r
470 //\r
471 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
472 | USB_TARGET_DEVICE;\r
473 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;\r
474 SetupMsg.Value = 0;\r
475 SetupMsg.Index = 0;\r
476 SetupMsg.Length = 0;\r
477 Status = Ax88772UsbCommand ( pNicDevice,\r
478 &SetupMsg,\r
479 NULL );\r
480 }\r
481 }\r
482\r
483 return Status;\r
484}\r
485\r
486\r
487/**\r
488 Reset the AX88772\r
489\r
490 This routine uses ::Ax88772UsbCommand to reset the network\r
491 adapter. This routine also uses ::Ax88772PhyWrite to reset\r
492 the PHY.\r
493\r
494 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
495\r
496 @retval EFI_SUCCESS The MAC address is available.\r
497 @retval other The MAC address is not valid.\r
498\r
499**/\r
500EFI_STATUS\r
501Ax88772Reset (\r
502 IN NIC_DEVICE * pNicDevice\r
503 )\r
504{\r
505 USB_DEVICE_REQUEST SetupMsg;\r
506 EFI_STATUS Status;\r
507 \r
508 EFI_USB_IO_PROTOCOL *pUsbIo;\r
509 EFI_USB_DEVICE_DESCRIPTOR Device;\r
510 \r
511 pUsbIo = pNicDevice->pUsbIo;\r
512 Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );\r
513\r
514 if (EFI_ERROR(Status)) goto err; \r
515\r
516 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
517 | USB_TARGET_DEVICE;\r
518 SetupMsg.Request = CMD_PHY_ACCESS_HARDWARE;\r
519 SetupMsg.Value = 0;\r
520 SetupMsg.Index = 0;\r
521 SetupMsg.Length = 0;\r
522 Status = Ax88772UsbCommand ( pNicDevice,\r
523 &SetupMsg,\r
524 NULL );\r
525 \r
526 if (EFI_ERROR(Status)) goto err; \r
527 \r
528 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
529 | USB_TARGET_DEVICE;\r
530 SetupMsg.Request = CMD_PHY_SELECT;\r
531 SetupMsg.Value = SPHY_PSEL;\r
532 SetupMsg.Index = 0;\r
533 SetupMsg.Length = 0;\r
534 Status = Ax88772UsbCommand ( pNicDevice,\r
535 &SetupMsg,\r
536 NULL );\r
537 \r
538 if (EFI_ERROR(Status)) goto err; \r
539 \r
540 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
541 | USB_TARGET_DEVICE; \r
542 SetupMsg.Request = CMD_RESET;\r
543 SetupMsg.Value = SRR_IPRL ;\r
544 SetupMsg.Index = 0;\r
545 SetupMsg.Length = 0;\r
546 Status = Ax88772UsbCommand ( pNicDevice,\r
547 &SetupMsg,\r
548 NULL ); \r
549 \r
550 if (EFI_ERROR(Status)) goto err; \r
551 \r
552 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
553 | USB_TARGET_DEVICE; \r
554 SetupMsg.Request = CMD_RESET;\r
555 SetupMsg.Value = SRR_IPPD | SRR_IPRL ;\r
556 SetupMsg.Index = 0;\r
557 SetupMsg.Length = 0;\r
558 Status = Ax88772UsbCommand ( pNicDevice,\r
559 &SetupMsg,\r
560 NULL );\r
561 \r
562 gBS->Stall ( 200000 );\r
563 \r
564 if (EFI_ERROR(Status)) goto err; \r
565 \r
566 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
567 | USB_TARGET_DEVICE;\r
568 SetupMsg.Request = CMD_RESET;\r
569 SetupMsg.Value = SRR_IPRL ;\r
570 SetupMsg.Index = 0;\r
571 SetupMsg.Length = 0;\r
572 Status = Ax88772UsbCommand ( pNicDevice,\r
573 &SetupMsg,\r
574 NULL ); \r
575 \r
576 gBS->Stall ( 200000 ); \r
577 \r
578 if (EFI_ERROR(Status)) goto err; \r
579 \r
580 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
581 | USB_TARGET_DEVICE;\r
582 SetupMsg.Request = CMD_RESET;\r
583 SetupMsg.Value = 0;\r
584 SetupMsg.Index = 0;\r
585 SetupMsg.Length = 0;\r
586 Status = Ax88772UsbCommand ( pNicDevice,\r
587 &SetupMsg,\r
588 NULL );\r
589 \r
590 if (EFI_ERROR(Status)) goto err; \r
591 \r
592 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
593 | USB_TARGET_DEVICE;\r
594 SetupMsg.Request = CMD_PHY_SELECT;\r
595 SetupMsg.Value = SPHY_PSEL;\r
596 SetupMsg.Index = 0;\r
597 SetupMsg.Length = 0;\r
598 Status = Ax88772UsbCommand ( pNicDevice,\r
599 &SetupMsg,\r
600 NULL ); \r
601 \r
602 if (EFI_ERROR(Status)) goto err; \r
603 \r
604 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
605 | USB_TARGET_DEVICE;\r
606 SetupMsg.Request = CMD_RESET;\r
607 SetupMsg.Value = SRR_IPRL | SRR_BZ | SRR_BZTYPE;\r
608 SetupMsg.Index = 0;\r
609 SetupMsg.Length = 0;\r
610 Status = Ax88772UsbCommand ( pNicDevice,\r
611 &SetupMsg,\r
612 NULL );\r
613 \r
614 if (EFI_ERROR(Status)) goto err; \r
615 \r
616 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
617 | USB_TARGET_DEVICE;\r
618 SetupMsg.Request = CMD_RX_CONTROL_WRITE;\r
619 SetupMsg.Value = 0;\r
620 SetupMsg.Index = 0;\r
621 SetupMsg.Length = 0;\r
622 Status = Ax88772UsbCommand ( pNicDevice,\r
623 &SetupMsg,\r
624 NULL );\r
625 \r
626 if (EFI_ERROR(Status)) goto err; \r
627\r
7361d3ff
SS
628 if (pNicDevice->Flags != FLAG_TYPE_AX88772) {\r
629 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
630 | USB_TARGET_DEVICE;\r
631 SetupMsg.Request = CMD_RXQTC;\r
632 SetupMsg.Value = 0x8000;\r
633 SetupMsg.Index = 0x8001;\r
634 SetupMsg.Length = 0;\r
635 Status = Ax88772UsbCommand ( pNicDevice,\r
7f556e4d 636 &SetupMsg,\r
7361d3ff
SS
637 NULL );\r
638 }\r
639\r
7f556e4d 640err:\r
641 return Status;\r
642}\r
643\r
644/**\r
645 Enable or disable the receiver\r
646\r
647 This routine calls ::Ax88772UsbCommand to update the\r
648 receiver state. This routine also calls ::Ax88772MacAddressSet\r
649 to establish the MAC address for the network adapter.\r
650\r
651 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
652 @param [in] RxFilter Simple network RX filter mask value\r
653\r
654 @retval EFI_SUCCESS The MAC address was set.\r
655 @retval other The MAC address was not set.\r
656\r
657**/\r
658EFI_STATUS\r
659Ax88772RxControl (\r
660 IN NIC_DEVICE * pNicDevice,\r
661 IN UINT32 RxFilter\r
662 )\r
663{\r
664 UINT16 MediumStatus;\r
665 UINT16 RxControl;\r
666 USB_DEVICE_REQUEST SetupMsg;\r
667 EFI_STATUS Status;\r
668 EFI_USB_IO_PROTOCOL *pUsbIo;\r
669 EFI_USB_DEVICE_DESCRIPTOR Device;\r
670 \r
671 pUsbIo = pNicDevice->pUsbIo;\r
672 Status = pUsbIo->UsbGetDeviceDescriptor ( pUsbIo, &Device );\r
673 \r
674 if (EFI_ERROR(Status)) {\r
675 DEBUG (( EFI_D_ERROR, "Failed to get device descriptor\n" ));\r
676 return Status;\r
677 }\r
678\r
679 //\r
680 // Enable the receiver if something is to be received\r
681 //\r
682 \r
683 if ( 0 != RxFilter ) {\r
684 //\r
685 // Enable the receiver\r
686 //\r
687 SetupMsg.RequestType = USB_ENDPOINT_DIR_IN\r
688 | USB_REQ_TYPE_VENDOR\r
689 | USB_TARGET_DEVICE;\r
690 SetupMsg.Request = CMD_MEDIUM_STATUS_READ; \r
691 SetupMsg.Value = 0;\r
692 SetupMsg.Index = 0;\r
693 SetupMsg.Length = sizeof ( MediumStatus );\r
694 Status = Ax88772UsbCommand ( pNicDevice,\r
695 &SetupMsg,\r
696 &MediumStatus );\r
697 if ( !EFI_ERROR ( Status )) {\r
698 if ( 0 == ( MediumStatus & MS_RE )) {\r
699 MediumStatus |= MS_RE | MS_ONE;\r
700 \r
701 if ( pNicDevice->bFullDuplex )\r
702 MediumStatus |= MS_TFC | MS_RFC | MS_FD;\r
703 else\r
704 MediumStatus &= ~(MS_TFC | MS_RFC | MS_FD);\r
705 \r
706 if ( pNicDevice->b100Mbps )\r
707 MediumStatus |= MS_PS;\r
708 else\r
709 MediumStatus &= ~MS_PS;\r
710 \r
711 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
712 | USB_TARGET_DEVICE;\r
713 SetupMsg.Request = CMD_MEDIUM_STATUS_WRITE;\r
714 SetupMsg.Value = MediumStatus;\r
715 SetupMsg.Index = 0;\r
716 SetupMsg.Length = 0;\r
717 Status = Ax88772UsbCommand ( pNicDevice,\r
718 &SetupMsg,\r
719 NULL );\r
720 if ( EFI_ERROR ( Status )) {\r
721 DEBUG (( EFI_D_ERROR, "Failed to enable receiver, Status: %r\r\n",\r
722 Status ));\r
723 }\r
724 }\r
725 }\r
726 else {\r
727 DEBUG (( EFI_D_ERROR, "Failed to read receiver status, Status: %r\r\n",\r
728 Status ));\r
729 }\r
730 }\r
731 \r
732 RxControl = RXC_SO | RXC_RH1M; \r
733 //\r
734 // Enable multicast if requested\r
735 //\r
736 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST )) {\r
737 RxControl |= RXC_AM;\r
738 //\r
739 // Update the multicast hash table\r
740 //\r
741 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
742 | USB_TARGET_DEVICE;\r
743 SetupMsg.Request = CMD_MULTICAST_HASH_WRITE;\r
744 SetupMsg.Value = 0;\r
745 SetupMsg.Index = 0;\r
746 SetupMsg.Length = sizeof ( pNicDevice ->MulticastHash );\r
747 Status = Ax88772UsbCommand ( pNicDevice,\r
748 &SetupMsg,\r
749 &pNicDevice->MulticastHash );\r
750 }\r
751 //\r
752 // Enable all multicast if requested\r
753 //\r
754 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST )) {\r
755 RxControl |= RXC_AMALL;\r
756 }\r
757\r
758 //\r
759 // Enable broadcast if requested\r
760 //\r
761 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST )) {\r
762 RxControl |= RXC_AB;\r
763 }\r
764\r
765 //\r
766 // Enable promiscuous mode if requested\r
767 //\r
768 if ( 0 != ( RxFilter & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS )) {\r
769 RxControl |= RXC_PRO;\r
770 }\r
771 \r
772 //\r
773 // Update the receiver control\r
774 //\r
775 if (pNicDevice->CurRxControl != RxControl) {\r
776 SetupMsg.RequestType = USB_REQ_TYPE_VENDOR\r
777 | USB_TARGET_DEVICE;\r
778 SetupMsg.Request = CMD_RX_CONTROL_WRITE;\r
779 SetupMsg.Value = RxControl;\r
780 SetupMsg.Index = 0;\r
781 SetupMsg.Length = 0;\r
782 Status = Ax88772UsbCommand ( pNicDevice,\r
783 &SetupMsg,\r
784 NULL );\r
785 if ( !EFI_ERROR ( Status )) {\r
786 pNicDevice->CurRxControl = RxControl;\r
787 \r
788 }\r
789 else {\r
790 DEBUG (( EFI_D_ERROR, "ERROR - Failed to set receiver control, Status: %r\r\n",\r
791 Status ));\r
792 }\r
793 }\r
794 return Status;\r
795}\r
796\r
797\r
798/**\r
799 Read an SROM location\r
800\r
801 This routine calls ::Ax88772UsbCommand to read data from the\r
802 SROM.\r
803\r
804 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
805 @param [in] Address SROM address\r
806 @param [out] pData Buffer to receive the data\r
807\r
808 @retval EFI_SUCCESS The read was successful\r
809 @retval other The read failed\r
810\r
811**/\r
812EFI_STATUS\r
813Ax88772SromRead (\r
814 IN NIC_DEVICE * pNicDevice,\r
815 IN UINT32 Address,\r
816 OUT UINT16 * pData\r
817 )\r
818{ \r
819 return EFI_UNSUPPORTED;\r
820}\r
821\r
822/**\r
823 Send a command to the USB device.\r
824\r
825 @param [in] pNicDevice Pointer to the NIC_DEVICE structure\r
826 @param [in] pRequest Pointer to the request structure\r
827 @param [in, out] pBuffer Data buffer address\r
828\r
829 @retval EFI_SUCCESS The USB transfer was successful\r
830 @retval other The USB transfer failed\r
831\r
832**/\r
833EFI_STATUS\r
834Ax88772UsbCommand (\r
835 IN NIC_DEVICE * pNicDevice,\r
836 IN USB_DEVICE_REQUEST * pRequest,\r
837 IN OUT VOID * pBuffer\r
838 )\r
839{\r
840 UINT32 CmdStatus;\r
841 EFI_USB_DATA_DIRECTION Direction;\r
842 EFI_USB_IO_PROTOCOL * pUsbIo;\r
843 EFI_STATUS Status;\r
844\r
845 //\r
846 // Determine the transfer direction\r
847 //\r
848 Direction = EfiUsbNoData;\r
849 if ( 0 != pRequest->Length ) {\r
850 Direction = ( 0 != ( pRequest->RequestType & USB_ENDPOINT_DIR_IN ))\r
851 ? EfiUsbDataIn : EfiUsbDataOut;\r
852 }\r
853\r
854 //\r
855 // Issue the command\r
856 //\r
857 pUsbIo = pNicDevice->pUsbIo;\r
858 Status = pUsbIo->UsbControlTransfer ( pUsbIo,\r
859 pRequest,\r
860 Direction,\r
861 USB_BUS_TIMEOUT,\r
862 pBuffer,\r
863 pRequest->Length,\r
864 &CmdStatus );\r
865 //\r
866 // Determine the operation status\r
867 //\r
868 if ( !EFI_ERROR ( Status )) {\r
869 Status = CmdStatus;\r
870 }\r
871 else {\r
872 //\r
873 // Only use status values associated with the Simple Network protocol\r
874 //\r
875 if ( EFI_TIMEOUT == Status ) {\r
876 Status = EFI_DEVICE_ERROR;\r
877 }\r
878 }\r
879 return Status;\r
880}\r
881\r