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