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