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