2 * SMSC LAN91x series Network Controller Driver.
4 * Copyright (c) 2013-2017 Linaro.org
6 * Derived from the LAN9118 driver. Original sources
7 * Copyright (c) 2012-2013, ARM Limited. All rights reserved.
9 * SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <Uefi/UefiSpec.h>
17 // Protocols used by this driver
18 #include <Protocol/SimpleNetwork.h>
19 #include <Protocol/ComponentName2.h>
20 #include <Protocol/PxeBaseCode.h>
21 #include <Protocol/DevicePath.h>
23 // Libraries used by this driver
24 #include <Library/UefiLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include <Library/MemoryAllocationLib.h>
28 #include <Library/IoLib.h>
29 #include <Library/PcdLib.h>
30 #include <Library/NetLib.h>
31 #include <Library/DevicePathLib.h>
33 // Hardware register definitions
34 #include "Lan91xDxeHw.h"
36 // Debugging output options
37 //#define LAN91X_PRINT_REGISTERS 1
38 //#define LAN91X_PRINT_PACKET_HEADERS 1
39 //#define LAN91X_PRINT_RECEIVE_FILTERS 1
41 // Chip power-down option -- UNTESTED
42 //#define LAN91X_POWER_DOWN 1
44 /*---------------------------------------------------------------------------------------------------------------------
46 LAN91x Information Structure
48 ---------------------------------------------------------------------------------------------------------------------*/
49 typedef struct _LAN91X_DRIVER
{
52 EFI_HANDLE ControllerHandle
;
54 // EFI SNP protocol instances
55 EFI_SIMPLE_NETWORK_PROTOCOL Snp
;
56 EFI_SIMPLE_NETWORK_MODE SnpMode
;
58 // EFI Snp statistics instance
59 EFI_NETWORK_STATISTICS Stats
;
61 // Transmit Buffer recycle queue
63 LIST_ENTRY TransmitQueueHead
;
65 // Register access variables
66 UINTN IoBase
; // I/O Base Address
67 UINT8 Revision
; // Chip Revision Number
68 INT8 PhyAd
; // Phy Address
69 UINT8 BankSel
; // Currently selected register bank
73 #define LAN91X_NO_PHY (-1) // PhyAd value if PHY not detected
75 #define LAN91X_SIGNATURE SIGNATURE_32('S', 'M', '9', '1')
76 #define INSTANCE_FROM_SNP_THIS(a) CR(a, LAN91X_DRIVER, Snp, LAN91X_SIGNATURE)
78 #define LAN91X_STALL 2
79 #define LAN91X_MEMORY_ALLOC_POLLS 100 // Max times to poll for memory allocation
80 #define LAN91X_PKT_OVERHEAD 6 // Overhead bytes in packet buffer
82 // Synchronization TPLs
83 #define LAN91X_TPL TPL_CALLBACK
85 // Most common CRC32 Polynomial for little endian machines
86 #define CRC_POLYNOMIAL 0xEDB88320
90 MAC_ADDR_DEVICE_PATH Lan91x
;
91 EFI_DEVICE_PATH_PROTOCOL End
;
94 LAN91X_DEVICE_PATH Lan91xPathTemplate
= {
97 MESSAGING_DEVICE_PATH
, MSG_MAC_ADDR_DP
,
98 { (UINT8
) (sizeof(MAC_ADDR_DEVICE_PATH
)), (UINT8
) ((sizeof(MAC_ADDR_DEVICE_PATH
)) >> 8) }
104 END_DEVICE_PATH_TYPE
,
105 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
106 { sizeof(EFI_DEVICE_PATH_PROTOCOL
), 0 }
110 // Chip ID numbers and name strings
116 #define CHIP_91100FD 8
117 #define CHIP_91111FD 9
119 STATIC CHAR16 CONST
* CONST ChipIds
[ 16 ] = {
121 /* 3 */ L
"SMC91C90/91C92",
125 /* 7 */ L
"SMC91C100",
126 /* 8 */ L
"SMC91C100FD",
127 /* 9 */ L
"SMC91C11xFD",
132 /* ------------------ TxBuffer Queue structures ------------------- */
142 MSK_SYSTEM_BUF SystemBuf
;
143 } MSK_LINKED_SYSTEM_BUF
;
145 #define TX_MBUF_SIGNATURE SIGNATURE_32 ('t','x','m','b')
147 /* ------------------ MAC Address Hash Calculations ------------------- */
150 ** Generate a hash value from a multicast address
152 ** This uses the Ethernet standard CRC32 algorithm
155 ** 1: http://en.wikipedia.org/wiki/Cyclic_redundancy_check
157 ** 2: http://www.erg.abdn.ac.uk/~gorry/eg3567/dl-pages/crc.html
159 ** 3: http://en.wikipedia.org/wiki/Computation_of_CRC
164 IN EFI_MAC_ADDRESS
*Mac
,
173 // 0xFFFFFFFF is standard seed for Ethernet
174 Remainder
= 0xFFFFFFFF;
176 // Generate the remainder byte-by-byte (LSB first)
177 Addr
= &Mac
->Addr
[0];
178 while (AddrLen
-- > 0) {
179 Remainder
^= *Addr
++;
180 for (Iter
= 0; Iter
< 8; ++Iter
) {
181 // Check if exponent is set
182 if ((Remainder
& 1) != 0) {
183 Remainder
= (Remainder
>> 1) ^ CRC_POLYNOMIAL
;
185 Remainder
= (Remainder
>> 1) ^ 0;
190 // Reverse the bits of the remainder
192 for (Iter
= 0; Iter
< 32; ++Iter
) {
194 Crc32
|= Remainder
& 1;
201 /* ---------------- Banked Register Operations ------------------ */
203 // Select the proper I/O bank
207 LAN91X_DRIVER
*LanDriver
,
213 Bank
= RegisterToBank (Register
);
215 // Select the proper I/O bank
216 if (LanDriver
->BankSel
!= Bank
) {
217 MmioWrite16 (LanDriver
->IoBase
+ LAN91X_BANK_OFFSET
, Bank
);
218 LanDriver
->BankSel
= Bank
;
222 // Read a 16-bit I/O-space register
226 LAN91X_DRIVER
*LanDriver
,
232 // Select the proper I/O bank
233 SelectIoBank (LanDriver
, Register
);
235 // Read the requested register
236 Offset
= RegisterToOffset (Register
);
237 return MmioRead16 (LanDriver
->IoBase
+ Offset
);
240 // Write a 16-bit I/O-space register
244 LAN91X_DRIVER
*LanDriver
,
251 // Select the proper I/O bank
252 SelectIoBank (LanDriver
, Register
);
254 // Write the requested register
255 Offset
= RegisterToOffset (Register
);
256 return MmioWrite16 (LanDriver
->IoBase
+ Offset
, Value
);
259 // Read an 8-bit I/O-space register
263 LAN91X_DRIVER
*LanDriver
,
269 // Select the proper I/O bank
270 SelectIoBank (LanDriver
, Register
);
272 // Read the requested register
273 Offset
= RegisterToOffset (Register
);
274 return MmioRead8 (LanDriver
->IoBase
+ Offset
);
277 // Write an 8-bit I/O-space register
281 LAN91X_DRIVER
*LanDriver
,
288 // Select the proper I/O bank
289 SelectIoBank (LanDriver
, Register
);
291 // Write the requested register
292 Offset
= RegisterToOffset (Register
);
293 return MmioWrite8 (LanDriver
->IoBase
+ Offset
, Value
);
297 /* ---------------- MII/PHY Access Operations ------------------ */
299 #define LAN91X_MDIO_STALL 1
304 LAN91X_DRIVER
*LanDriver
,
312 MgmtReg
= ReadIoReg16 (LanDriver
, LAN91X_MGMT
);
313 MgmtReg
&= ~MGMT_MCLK
;
314 MgmtReg
|= MGMT_MDOE
;
316 for (Mask
= (1 << (Bits
- 1)); Mask
!= 0; Mask
>>= 1) {
317 if ((Value
& Mask
) != 0) {
320 MgmtReg
&= ~MGMT_MDO
;
323 WriteIoReg16 (LanDriver
, LAN91X_MGMT
, MgmtReg
);
324 gBS
->Stall (LAN91X_MDIO_STALL
);
325 WriteIoReg16 (LanDriver
, LAN91X_MGMT
, MgmtReg
| MGMT_MCLK
);
326 gBS
->Stall (LAN91X_MDIO_STALL
);
329 #define PHY_OUTPUT_TIME (2 * LAN91X_MDIO_STALL)
334 LAN91X_DRIVER
*LanDriver
,
342 MgmtReg
= ReadIoReg16 (LanDriver
, LAN91X_MGMT
);
343 MgmtReg
&= ~(MGMT_MDOE
| MGMT_MCLK
| MGMT_MDO
);
344 WriteIoReg16 (LanDriver
, LAN91X_MGMT
, MgmtReg
);
347 for (Mask
= (1 << (Bits
- 1)); Mask
!= 0; Mask
>>= 1) {
348 if ((ReadIoReg16 (LanDriver
, LAN91X_MGMT
) & MGMT_MDI
) != 0) {
352 WriteIoReg16 (LanDriver
, LAN91X_MGMT
, MgmtReg
);
353 gBS
->Stall (LAN91X_MDIO_STALL
);
354 WriteIoReg16 (LanDriver
, LAN91X_MGMT
, MgmtReg
| MGMT_MCLK
);
355 gBS
->Stall (LAN91X_MDIO_STALL
);
360 #define PHY_INPUT_TIME (2 * LAN91X_MDIO_STALL)
365 LAN91X_DRIVER
*LanDriver
370 MgmtReg
= ReadIoReg16 (LanDriver
, LAN91X_MGMT
);
371 MgmtReg
&= ~(MGMT_MDOE
| MGMT_MCLK
| MGMT_MDO
);
372 WriteIoReg16 (LanDriver
, LAN91X_MGMT
, MgmtReg
);
375 // Write to a PHY register
379 LAN91X_DRIVER
*LanDriver
,
384 // Bit-bang the MII Serial Frame write operation
385 MdioOutput (LanDriver
, 32, 0xffffffff); // Send 32 Ones as a preamble
386 MdioOutput (LanDriver
, 2, 0x01); // Send Start (01)
387 MdioOutput (LanDriver
, 2, 0x01); // Send Write (01)
388 MdioOutput (LanDriver
, 5, LanDriver
->PhyAd
); // Send PHYAD[4:0]
389 MdioOutput (LanDriver
, 5, RegAd
); // Send REGAD[4:0]
390 MdioOutput (LanDriver
, 2, 0x02); // Send TurnAround (10)
391 MdioOutput (LanDriver
, 16, Value
); // Write 16 data bits
394 MdioIdle (LanDriver
);
396 // Calculate approximate time to write a PHY register in microseconds
397 #define PHY_WRITE_TIME ((32 + 2 + 2 + 5 + 5 + 2 + 16) * PHY_OUTPUT_TIME)
399 // Read from a PHY register
403 LAN91X_DRIVER
*LanDriver
,
409 // Bit-bang the MII Serial Frame read operation
410 MdioOutput (LanDriver
, 32, 0xffffffff); // Send 32 Ones as a preamble
411 MdioOutput (LanDriver
, 2, 0x01); // Send Start (01)
412 MdioOutput (LanDriver
, 2, 0x02); // Send Read (10)
413 MdioOutput (LanDriver
, 5, LanDriver
->PhyAd
); // Send PHYAD[4:0]
414 MdioOutput (LanDriver
, 5, RegAd
); // Send REGAD[4:0]
416 (VOID
) MdioInput (LanDriver
, 2); // Discard TurnAround bits
417 Value
= MdioInput (LanDriver
, 16); // Read 16 data bits
420 MdioIdle (LanDriver
);
422 return (Value
& 0xffff);
424 // Calculate approximate time to read a PHY register in microseconds
425 #define PHY_READ_TIME (((32 + 2 + 2 + 5 + 5) * PHY_OUTPUT_TIME) + \
426 ((2 + 16) * PHY_INPUT_TIME))
429 /* ---------------- Debug Functions ------------------ */
431 #ifdef LAN91X_PRINT_REGISTERS
435 IN LAN91X_DRIVER
*LanDriver
442 DEBUG ((DEBUG_ERROR
, "\nLAN91x I/O Register Dump:\n"));
444 // Print currrent bank select register
445 Value
= MmioRead16 (LanDriver
->IoBase
+ LAN91X_BANK_OFFSET
);
446 DEBUG ((DEBUG_ERROR
, " BankSel: %d Bank Register %04x (%d)\n",
447 LanDriver
->BankSel
, Value
, Value
& 0x0007));
449 // Print all I/O registers
450 for (Offset
= 0; Offset
< 0x0e; Offset
+= 2) {
451 DEBUG ((DEBUG_ERROR
, " %02x:", Offset
));
452 for (Bank
= 0; Bank
<= 3; ++Bank
) {
453 DEBUG ((DEBUG_ERROR
, " %04x", ReadIoReg16 (LanDriver
, MakeRegister (Bank
, Offset
))));
455 DEBUG ((DEBUG_ERROR
, "\n"));
462 IN LAN91X_DRIVER
*LanDriver
467 DEBUG ((DEBUG_ERROR
, "\nLAN91x Phy %d Register Dump:\n", LanDriver
->PhyAd
));
469 // Print all Phy registers
470 for (RegNum
= 0; RegNum
<= 5; ++RegNum
) {
471 DEBUG ((DEBUG_ERROR
, " %2d: %04x\n",
473 ReadPhyReg16 (LanDriver
, RegNum
)
476 for (RegNum
= 16; RegNum
<= 20; ++RegNum
) {
477 DEBUG ((DEBUG_ERROR
, " %2d: %04x\n",
479 ReadPhyReg16 (LanDriver
, RegNum
)
485 #if LAN91X_PRINT_PACKET_HEADERS
489 IN CONST VOID
*DstMac
,
490 IN CONST VOID
*SrcMac
,
491 IN CONST VOID
*Proto
,
492 IN CONST VOID
*IpDgram
500 DEBUG ((DEBUG_ERROR
, " Dst: %02x-%02x-%02x",
501 Ptr
[0], Ptr
[1], Ptr
[2]));
502 DEBUG ((DEBUG_ERROR
, "-%02x-%02x-%02x",
503 Ptr
[3], Ptr
[4], Ptr
[5]));
506 DEBUG ((DEBUG_ERROR
, " Src: %02x-%02x-%02x",
507 Ptr
[0], Ptr
[1], Ptr
[2]));
508 DEBUG ((DEBUG_ERROR
, "-%02x-%02x-%02x",
509 Ptr
[3], Ptr
[4], Ptr
[5]));
512 DEBUG ((DEBUG_ERROR
, " Proto: %02x%02x\n",
517 case EFI_IP_PROTO_ICMP
:
518 DEBUG ((DEBUG_ERROR
, " ICMP"));
520 case EFI_IP_PROTO_TCP
:
521 DEBUG ((DEBUG_ERROR
, " TCP"));
523 case EFI_IP_PROTO_UDP
:
524 DEBUG ((DEBUG_ERROR
, " UDP"));
527 DEBUG ((DEBUG_ERROR
, " IpProto %d\n", Ptr
[9]));
531 DEBUG ((DEBUG_ERROR
, " SrcIp: %d.%d.%d.%d",
532 Ptr
[12], Ptr
[13], Ptr
[14], Ptr
[15]));
533 DEBUG ((DEBUG_ERROR
, " DstIp: %d.%d.%d.%d",
534 Ptr
[16], Ptr
[17], Ptr
[18], Ptr
[19]));
536 SrcPort
= (Ptr
[20] << 8) | Ptr
[21];
537 DstPort
= (Ptr
[22] << 8) | Ptr
[23];
538 DEBUG ((DEBUG_ERROR
, " SrcPort: %d DstPort: %d\n", SrcPort
, DstPort
));
543 /* ---------------- PHY Management Operations ----------------- */
548 IN LAN91X_DRIVER
*LanDriver
554 for (LanDriver
->PhyAd
= 0x1f; LanDriver
->PhyAd
>= 0 ; --LanDriver
->PhyAd
) {
555 PhyId1
= ReadPhyReg16 (LanDriver
, PHY_INDEX_ID1
);
556 PhyId2
= ReadPhyReg16 (LanDriver
, PHY_INDEX_ID2
);
558 if ((PhyId1
!= 0x0000) && (PhyId1
!= 0xffff) &&
559 (PhyId2
!= 0x0000) && (PhyId2
!= 0xffff)) {
560 if ((PhyId1
== 0x0016) && ((PhyId2
& 0xfff0) == 0xf840)) {
561 DEBUG ((DEBUG_ERROR
, "LAN91x: PHY type LAN83C183 (LAN91C111 Internal)\n"));
562 } else if ((PhyId1
== 0x0282) && ((PhyId2
& 0xfff0) == 0x1c50)) {
563 DEBUG ((DEBUG_ERROR
, "LAN91x: PHY type LAN83C180\n"));
565 DEBUG ((DEBUG_ERROR
, "LAN91x: PHY id %04x:%04x\n", PhyId1
, PhyId2
));
571 DEBUG ((DEBUG_ERROR
, "LAN91x: PHY detection failed\n"));
576 // Check the Link Status and take appropriate action
580 IN LAN91X_DRIVER
*LanDriver
585 // Get the PHY Status
586 PhyStatus
= ReadPhyReg16 (LanDriver
, PHY_INDEX_BASIC_STATUS
);
588 return (PhyStatus
& PHYSTS_LINK_STS
) != 0;
592 // Do auto-negotiation
596 IN LAN91X_DRIVER
*LanDriver
604 // If there isn't a PHY, don't try to reset it
605 if (LanDriver
->PhyAd
== LAN91X_NO_PHY
) {
609 // Next check that auto-negotiation is supported
610 PhyStatus
= ReadPhyReg16 (LanDriver
, PHY_INDEX_BASIC_STATUS
);
611 if ((PhyStatus
& PHYSTS_AUTO_CAP
) == 0) {
615 // Translate capabilities to advertise
616 PhyAdvert
= PHYANA_CSMA
;
618 if ((PhyStatus
& PHYSTS_10BASET_HDPLX
) != 0) {
619 PhyAdvert
|= PHYANA_10BASET
;
621 if ((PhyStatus
& PHYSTS_10BASET_FDPLX
) != 0) {
622 PhyAdvert
|= PHYANA_10BASETFD
;
624 if ((PhyStatus
& PHYSTS_100BASETX_HDPLX
) != 0) {
625 PhyAdvert
|= PHYANA_100BASETX
;
627 if ((PhyStatus
& PHYSTS_100BASETX_FDPLX
) != 0) {
628 PhyAdvert
|= PHYANA_100BASETXFD
;
630 if ((PhyStatus
& PHYSTS_100BASE_T4
) != 0) {
631 PhyAdvert
|= PHYANA_100BASET4
;
634 // Set the capabilities to advertise
635 WritePhyReg16 (LanDriver
, PHY_INDEX_AUTO_NEG_ADVERT
, PhyAdvert
);
636 (VOID
) ReadPhyReg16 (LanDriver
, PHY_INDEX_AUTO_NEG_ADVERT
);
638 // Restart Auto-Negotiation
639 PhyControl
= ReadPhyReg16 (LanDriver
, PHY_INDEX_BASIC_CTRL
);
640 PhyControl
&= ~(PHYCR_SPEED_SEL
| PHYCR_DUPLEX_MODE
);
641 PhyControl
|= PHYCR_AUTO_EN
| PHYCR_RST_AUTO
;
642 WritePhyReg16 (LanDriver
, PHY_INDEX_BASIC_CTRL
, PhyControl
);
644 // Wait up to 2 seconds for the process to complete
645 Retries
= 2000000 / (PHY_READ_TIME
+ 100);
646 while ((ReadPhyReg16 (LanDriver
, PHY_INDEX_BASIC_STATUS
) & PHYSTS_AUTO_COMP
) == 0) {
647 if (--Retries
== 0) {
648 DEBUG ((DEBUG_ERROR
, "LAN91x: PHY auto-negotiation timed-out\n"));
658 // Perform PHY software reset
662 IN LAN91X_DRIVER
*LanDriver
667 // If there isn't a PHY, don't try to reset it
668 if (LanDriver
->PhyAd
== LAN91X_NO_PHY
) {
672 // Request a PHY reset
673 WritePhyReg16 (LanDriver
, PHY_INDEX_BASIC_CTRL
, PHYCR_RESET
);
675 // The internal PHY will reset within 50ms. Allow 100ms.
676 Retries
= 100000 / (PHY_READ_TIME
+ 100);
677 while (ReadPhyReg16 (LanDriver
, PHY_INDEX_BASIC_CTRL
) & PHYCR_RESET
) {
678 if (--Retries
== 0) {
679 DEBUG ((DEBUG_ERROR
, "LAN91x: PHY reset timed-out\n"));
689 /* ---------------- General Operations ----------------- */
693 GetCurrentMacAddress (
694 IN LAN91X_DRIVER
*LanDriver
699 EFI_MAC_ADDRESS MacAddress
;
701 SetMem (&MacAddress
, sizeof(MacAddress
), 0);
703 Addr
= &MacAddress
.Addr
[0];
704 for (RegNum
= LAN91X_IAR0
; RegNum
<= LAN91X_IAR5
; ++RegNum
) {
705 *Addr
= ReadIoReg8 (LanDriver
, RegNum
);
714 SetCurrentMacAddress (
715 IN LAN91X_DRIVER
*LanDriver
,
716 IN EFI_MAC_ADDRESS
*MacAddress
722 Addr
= &MacAddress
->Addr
[0];
723 for (RegNum
= LAN91X_IAR0
; RegNum
<= LAN91X_IAR5
; ++RegNum
) {
724 WriteIoReg8 (LanDriver
, RegNum
, *Addr
);
734 IN LAN91X_DRIVER
*LanDriver
,
740 WriteIoReg16 (LanDriver
, LAN91X_MMUCR
, MmuOp
);
742 while ((ReadIoReg16 (LanDriver
, LAN91X_MMUCR
) & MMUCR_BUSY
) != 0) {
744 DEBUG ((DEBUG_ERROR
, "LAN91x: MMU operation %04x timed-out\n", MmuOp
));
747 gBS
->Stall (LAN91X_STALL
);
753 // Read bytes from the DATA register
757 IN LAN91X_DRIVER
*LanDriver
,
765 for (; BufLen
> 0; --BufLen
) {
766 *Ptr
= ReadIoReg8 (LanDriver
, LAN91X_DATA0
);
773 // Write bytes to the DATA register
777 IN LAN91X_DRIVER
*LanDriver
,
785 for (; BufLen
> 0; --BufLen
) {
786 WriteIoReg8 (LanDriver
, LAN91X_DATA0
, *Ptr
);
793 // Disable the interface
797 IN LAN91X_DRIVER
*LanDriver
800 #ifdef LAN91X_POWER_DOWN
804 // Stop Rx and Tx operations
805 WriteIoReg16 (LanDriver
, LAN91X_RCR
, RCR_CLEAR
);
806 WriteIoReg16 (LanDriver
, LAN91X_TCR
, TCR_CLEAR
);
808 #ifdef LAN91X_POWER_DOWN
809 // Power-down the chip
810 Val16
= ReadIoReg16 (LanDriver
, LAN91X_CR
);
811 Val16
&= ~CR_EPH_POWER_EN
;
812 WriteIoReg16 (LanDriver
, LAN91X_CR
, Val16
);
818 // Enable the interface
822 IN LAN91X_DRIVER
*LanDriver
825 #ifdef LAN91X_POWER_DOWN
829 Val16
= ReadIoReg16 (LanDriver
, LAN91X_CR
);
830 Val16
|= CR_EPH_POWER_EN
;
831 WriteIoReg16 (LanDriver
, LAN91X_CR
, Val16
);
832 gBS
->Stall (LAN91X_STALL
);
835 // Start Rx and Tx operations
836 WriteIoReg16 (LanDriver
, LAN91X_TCR
, TCR_DEFAULT
);
837 WriteIoReg16 (LanDriver
, LAN91X_RCR
, RCR_DEFAULT
);
843 // Perform software reset on the LAN91x
847 IN LAN91X_DRIVER
*LanDriver
853 WriteIoReg16 (LanDriver
, LAN91X_RCR
, RCR_SOFT_RST
);
854 gBS
->Stall (LAN91X_STALL
);
855 WriteIoReg16 (LanDriver
, LAN91X_RCR
, RCR_CLEAR
);
857 // Set the configuration register
858 WriteIoReg16 (LanDriver
, LAN91X_CR
, CR_DEFAULT
);
859 gBS
->Stall (LAN91X_STALL
);
862 WriteIoReg16 (LanDriver
, LAN91X_RCR
, RCR_CLEAR
);
863 WriteIoReg16 (LanDriver
, LAN91X_TCR
, TCR_CLEAR
);
865 // Initialize the Control Register
866 Val16
= ReadIoReg16 (LanDriver
, LAN91X_CTR
);
867 Val16
|= CTR_AUTO_REL
;
868 WriteIoReg16 (LanDriver
, LAN91X_CTR
, Val16
);
871 MmuOperation (LanDriver
, MMUCR_OP_RESET_MMU
);
879 ** Validate that there is a LAN91x device.
885 IN LAN91X_DRIVER
*LanDriver
890 CHAR16 CONST
*ChipId
;
893 // First check that the Bank Select register is valid
894 Bank
= MmioRead16 (LanDriver
->IoBase
+ LAN91X_BANK_OFFSET
);
895 if ((Bank
& 0xff00) != 0x3300) {
896 DEBUG ((DEBUG_ERROR
, "LAN91x: signature error: expecting 33xx, read %04x\n", Bank
));
897 return EFI_DEVICE_ERROR
;
900 // Try reading the revision register next
901 LanDriver
->BankSel
= 0xff;
902 Val16
= ReadIoReg16 (LanDriver
, LAN91X_REV
);
904 Bank
= MmioRead16 (LanDriver
->IoBase
+ LAN91X_BANK_OFFSET
);
905 if ((Bank
& 0xff03) != 0x3303) {
906 DEBUG ((DEBUG_ERROR
, "LAN91x: signature error: expecting 33x3, read %04x\n", Bank
));
907 return EFI_DEVICE_ERROR
;
910 // Validate the revision register
911 if ((Val16
& 0xff00) != 0x3300) {
912 DEBUG ((DEBUG_ERROR
, "LAN91x: revision error: expecting 33xx, read %04x\n", Val16
));
913 return EFI_DEVICE_ERROR
;
916 ChipId
= ChipIds
[(Val16
>> 4) & 0x0f];
917 if (ChipId
== NULL
) {
918 DEBUG ((DEBUG_ERROR
, "LAN91x: unrecognized revision: %04x\n", Val16
));
919 return EFI_DEVICE_ERROR
;
921 DEBUG ((DEBUG_ERROR
, "LAN91x: detected chip %s rev %d\n", ChipId
, Val16
& 0xf));
922 LanDriver
->Revision
= Val16
& 0xff;
924 // Reload from EEPROM to get the hardware MAC address
925 WriteIoReg16 (LanDriver
, LAN91X_CTR
, CTR_RESERVED
| CTR_RELOAD
);
927 while ((ReadIoReg16 (LanDriver
, LAN91X_CTR
) & CTR_RELOAD
) != 0) {
928 if (--ResetTime
== 0) {
929 DEBUG ((DEBUG_ERROR
, "LAN91x: reload from EEPROM timed-out\n"));
930 WriteIoReg16 (LanDriver
, LAN91X_CTR
, CTR_RESERVED
);
931 return EFI_DEVICE_ERROR
;
933 gBS
->Stall (LAN91X_STALL
);
936 // Read and save the Permanent MAC Address
937 LanDriver
->SnpMode
.PermanentAddress
= GetCurrentMacAddress (LanDriver
);
938 LanDriver
->SnpMode
.CurrentAddress
= LanDriver
->SnpMode
.PermanentAddress
;
939 DEBUG ((DEBUG_ERROR
, //DEBUG_NET | DEBUG_INFO,
940 "LAN91x: HW MAC Address: %02x-%02x-%02x-%02x-%02x-%02x\n",
941 LanDriver
->SnpMode
.PermanentAddress
.Addr
[0],
942 LanDriver
->SnpMode
.PermanentAddress
.Addr
[1],
943 LanDriver
->SnpMode
.PermanentAddress
.Addr
[2],
944 LanDriver
->SnpMode
.PermanentAddress
.Addr
[3],
945 LanDriver
->SnpMode
.PermanentAddress
.Addr
[4],
946 LanDriver
->SnpMode
.PermanentAddress
.Addr
[5]
950 SoftReset (LanDriver
);
952 // Try to detect a PHY
953 if (LanDriver
->Revision
> (CHIP_91100
<< 4)) {
954 PhyDetect (LanDriver
);
956 LanDriver
->PhyAd
= LAN91X_NO_PHY
;
965 /*------------------ Simple Network Driver entry point functions ------------------*/
967 // Refer to the Simple Network Protocol section (21.1)
968 // in the UEFI 2.3.1 Specification for documentation.
970 #define ReturnUnlock(s) do { Status = (s); goto exit_unlock; } while(0)
974 ** UEFI Start() function
980 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
983 EFI_SIMPLE_NETWORK_MODE
*Mode
;
987 // Check Snp instance
989 return EFI_INVALID_PARAMETER
;
992 // Serialize access to data and registers
993 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
996 // Check state of the driver
997 switch (Mode
->State
) {
998 case EfiSimpleNetworkStopped
:
1000 case EfiSimpleNetworkStarted
:
1001 case EfiSimpleNetworkInitialized
:
1002 DEBUG ((DEBUG_WARN
, "LAN91x: Driver already started\n"));
1003 ReturnUnlock (EFI_ALREADY_STARTED
);
1005 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1006 (UINTN
)Snp
->Mode
->State
));
1007 ReturnUnlock (EFI_DEVICE_ERROR
);
1012 Mode
->State
= EfiSimpleNetworkStarted
;
1013 Status
= EFI_SUCCESS
;
1015 // Restore TPL and return
1017 gBS
->RestoreTPL (SavedTpl
);
1022 ** UEFI Stop() function
1028 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
1031 LAN91X_DRIVER
*LanDriver
;
1035 // Check Snp Instance
1037 return EFI_INVALID_PARAMETER
;
1040 // Serialize access to data and registers
1041 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1043 // Check state of the driver
1044 switch (Snp
->Mode
->State
) {
1045 case EfiSimpleNetworkStarted
:
1046 case EfiSimpleNetworkInitialized
:
1048 case EfiSimpleNetworkStopped
:
1049 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1050 ReturnUnlock (EFI_NOT_STARTED
);
1052 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1053 (UINTN
)Snp
->Mode
->State
));
1054 ReturnUnlock (EFI_DEVICE_ERROR
);
1057 // Find the LanDriver structure
1058 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1060 // Stop the Tx and Rx
1061 ChipDisable (LanDriver
);
1064 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
1065 Status
= EFI_SUCCESS
;
1067 // Restore TPL and return
1069 gBS
->RestoreTPL (SavedTpl
);
1074 ** UEFI Initialize() function
1080 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1081 IN UINTN RxBufferSize OPTIONAL
,
1082 IN UINTN TxBufferSize OPTIONAL
1085 LAN91X_DRIVER
*LanDriver
;
1089 // Check Snp Instance
1091 return EFI_INVALID_PARAMETER
;
1094 // Serialize access to data and registers
1095 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1097 // Check that driver was started but not initialised
1098 switch (Snp
->Mode
->State
) {
1099 case EfiSimpleNetworkStarted
:
1101 case EfiSimpleNetworkInitialized
:
1102 DEBUG ((DEBUG_WARN
, "LAN91x: Driver already initialized\n"));
1103 ReturnUnlock (EFI_SUCCESS
);
1104 case EfiSimpleNetworkStopped
:
1105 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1106 ReturnUnlock (EFI_NOT_STARTED
);
1108 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1109 (UINTN
)Snp
->Mode
->State
));
1110 ReturnUnlock (EFI_DEVICE_ERROR
);
1113 // Find the LanDriver structure
1114 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1116 // Initiate a software reset
1117 Status
= SoftReset (LanDriver
);
1118 if (EFI_ERROR(Status
)) {
1119 DEBUG ((DEBUG_WARN
, "LAN91x: Soft reset failed\n"));
1120 ReturnUnlock (EFI_DEVICE_ERROR
);
1123 // Initiate a PHY reset
1124 if (PhySoftReset (LanDriver
) < 0) {
1125 Snp
->Mode
->State
= EfiSimpleNetworkStopped
;
1126 DEBUG ((DEBUG_WARN
, "LAN91x: PHY soft reset timeout\n"));
1127 ReturnUnlock (EFI_NOT_STARTED
);
1130 // Do auto-negotiation
1131 Status
= PhyAutoNegotiate (LanDriver
);
1132 if (EFI_ERROR(Status
)) {
1133 DEBUG ((DEBUG_WARN
, "LAN91x: PHY auto-negotiation failed\n"));
1136 // Enable the receiver and transmitter
1137 ChipEnable (LanDriver
);
1139 // Now acknowledge all interrupts
1140 WriteIoReg8 (LanDriver
, LAN91X_IST
, 0xFF);
1142 // Declare the driver as initialized
1143 Snp
->Mode
->State
= EfiSimpleNetworkInitialized
;
1144 Status
= EFI_SUCCESS
;
1146 // Restore TPL and return
1148 gBS
->RestoreTPL (SavedTpl
);
1153 ** UEFI Reset () function
1159 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1160 IN BOOLEAN Verification
1163 LAN91X_DRIVER
*LanDriver
;
1167 // Check Snp Instance
1169 return EFI_INVALID_PARAMETER
;
1172 // Serialize access to data and registers
1173 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1175 // Check that driver was started and initialised
1176 switch (Snp
->Mode
->State
) {
1177 case EfiSimpleNetworkInitialized
:
1179 case EfiSimpleNetworkStarted
:
1180 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1181 ReturnUnlock (EFI_DEVICE_ERROR
);
1182 case EfiSimpleNetworkStopped
:
1183 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1184 ReturnUnlock (EFI_NOT_STARTED
);
1186 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1187 (UINTN
)Snp
->Mode
->State
));
1188 ReturnUnlock (EFI_DEVICE_ERROR
);
1191 // Find the LanDriver structure
1192 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1194 // Initiate a software reset
1195 if (EFI_ERROR (SoftReset (LanDriver
))) {
1196 DEBUG ((DEBUG_WARN
, "LAN91x: Soft reset failed\n"));
1197 ReturnUnlock (EFI_DEVICE_ERROR
);
1200 // Initiate a PHY reset
1201 if (EFI_ERROR (PhySoftReset (LanDriver
))) {
1202 DEBUG ((DEBUG_WARN
, "LAN91x: PHY soft reset failed\n"));
1203 ReturnUnlock (EFI_DEVICE_ERROR
);
1206 // Enable the receiver and transmitter
1207 Status
= ChipEnable (LanDriver
);
1209 // Restore TPL and return
1211 gBS
->RestoreTPL (SavedTpl
);
1216 ** UEFI Shutdown () function
1222 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
1225 LAN91X_DRIVER
*LanDriver
;
1229 // Check Snp Instance
1231 return EFI_INVALID_PARAMETER
;
1234 // Serialize access to data and registers
1235 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1237 // First check that driver has already been initialized
1238 switch (Snp
->Mode
->State
) {
1239 case EfiSimpleNetworkInitialized
:
1241 case EfiSimpleNetworkStarted
:
1242 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1243 ReturnUnlock (EFI_DEVICE_ERROR
);
1244 case EfiSimpleNetworkStopped
:
1245 DEBUG ((DEBUG_WARN
, "LAN91x: Driver in stopped state\n"));
1246 ReturnUnlock (EFI_NOT_STARTED
);
1248 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1249 (UINTN
)Snp
->Mode
->State
));
1250 ReturnUnlock (EFI_DEVICE_ERROR
);
1253 // Find the LanDriver structure
1254 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1256 // Disable the interface
1257 Status
= ChipDisable (LanDriver
);
1259 // Restore TPL and return
1261 gBS
->RestoreTPL (SavedTpl
);
1267 ** UEFI ReceiveFilters() function
1273 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1277 IN UINTN NumMfilter OPTIONAL
,
1278 IN EFI_MAC_ADDRESS
*Mfilter OPTIONAL
1281 #define MCAST_HASH_BYTES 8
1283 LAN91X_DRIVER
*LanDriver
;
1284 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1290 UINT8 McastHash
[MCAST_HASH_BYTES
];
1292 // Check Snp Instance
1294 return EFI_INVALID_PARAMETER
;
1297 // Serialize access to data and registers
1298 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1300 // First check that driver has already been initialized
1301 switch (Snp
->Mode
->State
) {
1302 case EfiSimpleNetworkInitialized
:
1304 case EfiSimpleNetworkStarted
:
1305 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1306 ReturnUnlock (EFI_DEVICE_ERROR
);
1307 case EfiSimpleNetworkStopped
:
1308 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1309 ReturnUnlock (EFI_NOT_STARTED
);
1311 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1312 (UINTN
)Snp
->Mode
->State
));
1313 ReturnUnlock (EFI_DEVICE_ERROR
);
1316 // Find the LanDriver structure
1317 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1318 SnpMode
= Snp
->Mode
;
1320 #ifdef LAN91X_PRINT_RECEIVE_FILTERS
1321 DEBUG ((DEBUG_ERROR
, "LAN91x:SnpReceiveFilters()\n"));
1322 DEBUG ((DEBUG_ERROR
, " Enable = %08x\n", Enable
));
1323 DEBUG ((DEBUG_ERROR
, " Disable = %08x\n", Disable
));
1324 DEBUG ((DEBUG_ERROR
, " Reset = %d\n", Reset
));
1325 DEBUG ((DEBUG_ERROR
, " NumMfilter = %d\n", NumMfilter
));
1326 for (i
= 0; i
< NumMfilter
; ++i
) {
1327 DEBUG ((DEBUG_ERROR
,
1328 " [%2d] = %02x-%02x-%02x-%02x-%02x-%02x\n",
1335 Mfilter
[i
].Addr
[5]));
1339 // Update the Multicast Hash registers
1341 // Clear the hash table
1342 SetMem (McastHash
, MCAST_HASH_BYTES
, 0);
1343 SnpMode
->MCastFilterCount
= 0;
1345 // Read the current hash table
1346 for (i
= 0; i
< MCAST_HASH_BYTES
; ++i
) {
1347 McastHash
[i
] = ReadIoReg8 (LanDriver
, LAN91X_MT0
+ i
);
1349 // Set the new additions
1350 for (i
= 0; i
< NumMfilter
; ++i
) {
1351 Crc
= MulticastHash (&Mfilter
[i
], NET_ETHER_ADDR_LEN
);
1352 McastHash
[(Crc
>> 29) & 0x3] |= 1 << ((Crc
>> 26) & 0x3);
1354 SnpMode
->MCastFilterCount
= NumMfilter
;
1356 // If the hash registers need updating, write them
1357 if (Reset
|| NumMfilter
> 0) {
1358 for (i
= 0; i
< MCAST_HASH_BYTES
; ++i
) {
1359 WriteIoReg8 (LanDriver
, LAN91X_MT0
+ i
, McastHash
[i
]);
1363 RcvCtrl
= ReadIoReg16 (LanDriver
, LAN91X_RCR
);
1364 if ((Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) != 0) {
1365 RcvCtrl
|= RCR_PRMS
;
1366 SnpMode
->ReceiveFilterSetting
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1368 if ((Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
) != 0) {
1369 RcvCtrl
&= ~RCR_PRMS
;
1370 SnpMode
->ReceiveFilterSetting
&= ~EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1373 if ((Enable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) != 0) {
1374 RcvCtrl
|= RCR_ALMUL
;
1375 SnpMode
->ReceiveFilterSetting
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1377 if ((Disable
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) != 0) {
1378 RcvCtrl
&= ~RCR_ALMUL
;
1379 SnpMode
->ReceiveFilterSetting
&= ~EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1381 WriteIoReg16 (LanDriver
, LAN91X_RCR
, RcvCtrl
);
1383 Status
= SetCurrentMacAddress (LanDriver
, &SnpMode
->CurrentAddress
);
1385 // Restore TPL and return
1387 gBS
->RestoreTPL (SavedTpl
);
1392 ** UEFI StationAddress() function
1398 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1400 IN EFI_MAC_ADDRESS
*NewMac
1403 LAN91X_DRIVER
*LanDriver
;
1407 // Check Snp instance
1409 return EFI_INVALID_PARAMETER
;
1412 // Serialize access to data and registers
1413 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1415 // Check that driver was started and initialised
1416 switch (Snp
->Mode
->State
) {
1417 case EfiSimpleNetworkInitialized
:
1419 case EfiSimpleNetworkStarted
:
1420 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1421 ReturnUnlock (EFI_DEVICE_ERROR
);
1422 case EfiSimpleNetworkStopped
:
1423 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1424 ReturnUnlock (EFI_NOT_STARTED
);
1426 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1427 (UINTN
)Snp
->Mode
->State
));
1428 ReturnUnlock (EFI_DEVICE_ERROR
);
1431 // Find the LanDriver structure
1432 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1435 Snp
->Mode
->CurrentAddress
= Snp
->Mode
->PermanentAddress
;
1437 if (NewMac
== NULL
) {
1438 ReturnUnlock (EFI_INVALID_PARAMETER
);
1440 Snp
->Mode
->CurrentAddress
= *NewMac
;
1443 Status
= SetCurrentMacAddress (LanDriver
, &Snp
->Mode
->CurrentAddress
);
1445 // Restore TPL and return
1447 gBS
->RestoreTPL (SavedTpl
);
1452 ** UEFI Statistics() function
1458 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1460 IN OUT UINTN
*StatSize
,
1461 OUT EFI_NETWORK_STATISTICS
*Statistics
1464 LAN91X_DRIVER
*LanDriver
;
1468 // Check Snp instance
1470 return EFI_INVALID_PARAMETER
;
1473 // Check pointless condition
1474 if ((!Reset
) && (StatSize
== NULL
) && (Statistics
== NULL
)) {
1478 // Check the parameters
1479 if ((StatSize
== NULL
) && (Statistics
!= NULL
)) {
1480 return EFI_INVALID_PARAMETER
;
1483 // Serialize access to data and registers
1484 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1486 // Check that driver was started and initialised
1487 switch (Snp
->Mode
->State
) {
1488 case EfiSimpleNetworkInitialized
:
1490 case EfiSimpleNetworkStarted
:
1491 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1492 ReturnUnlock (EFI_DEVICE_ERROR
);
1493 case EfiSimpleNetworkStopped
:
1494 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1495 ReturnUnlock (EFI_NOT_STARTED
);
1497 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1498 (UINTN
)Snp
->Mode
->State
));
1499 ReturnUnlock (EFI_DEVICE_ERROR
);
1502 // Find the LanDriver structure
1503 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1505 // Do a reset if required
1507 ZeroMem (&LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
1510 // Check buffer size
1511 if (*StatSize
< sizeof(EFI_NETWORK_STATISTICS
)) {
1512 *StatSize
= sizeof(EFI_NETWORK_STATISTICS
);
1513 ReturnUnlock (EFI_BUFFER_TOO_SMALL
);
1517 // Fill in the statistics
1518 CopyMem(&Statistics
, &LanDriver
->Stats
, sizeof(EFI_NETWORK_STATISTICS
));
1519 Status
= EFI_SUCCESS
;
1521 // Restore TPL and return
1523 gBS
->RestoreTPL (SavedTpl
);
1528 ** UEFI MCastIPtoMAC() function
1534 IN EFI_SIMPLE_NETWORK_PROTOCOL
* Snp
,
1536 IN EFI_IP_ADDRESS
*Ip
,
1537 OUT EFI_MAC_ADDRESS
*McastMac
1540 // Check Snp instance
1542 return EFI_INVALID_PARAMETER
;
1546 if ((McastMac
== NULL
) || (Ip
== NULL
)) {
1547 return EFI_INVALID_PARAMETER
;
1550 // Make sure MAC address is empty
1551 ZeroMem (McastMac
, sizeof(EFI_MAC_ADDRESS
));
1553 // If we need ipv4 address
1555 // Most significant 25 bits of a multicast HW address are set
1556 McastMac
->Addr
[0] = 0x01;
1557 McastMac
->Addr
[1] = 0x00;
1558 McastMac
->Addr
[2] = 0x5E;
1560 // Lower 23 bits from ipv4 address
1561 McastMac
->Addr
[3] = (Ip
->v4
.Addr
[1] & 0x7F); // Clear the ms bit (25th bit of MAC must be 0)
1562 McastMac
->Addr
[4] = Ip
->v4
.Addr
[2];
1563 McastMac
->Addr
[5] = Ip
->v4
.Addr
[3];
1565 // Most significant 16 bits of multicast v6 HW address are set
1566 McastMac
->Addr
[0] = 0x33;
1567 McastMac
->Addr
[1] = 0x33;
1569 // lower four octets are taken from ipv6 address
1570 McastMac
->Addr
[2] = Ip
->v6
.Addr
[8];
1571 McastMac
->Addr
[3] = Ip
->v6
.Addr
[9];
1572 McastMac
->Addr
[4] = Ip
->v6
.Addr
[10];
1573 McastMac
->Addr
[5] = Ip
->v6
.Addr
[11];
1580 ** UEFI NvData() function
1586 IN EFI_SIMPLE_NETWORK_PROTOCOL
* pobj
,
1587 IN BOOLEAN read_write
,
1593 DEBUG ((DEBUG_ERROR
, "LAN91x: Non-volatile storage not supported\n"));
1595 return EFI_UNSUPPORTED
;
1600 ** UEFI GetStatus () function
1606 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1607 OUT UINT32
*IrqStat OPTIONAL
,
1608 OUT VOID
**TxBuff OPTIONAL
1611 LAN91X_DRIVER
*LanDriver
;
1614 BOOLEAN MediaPresent
;
1616 MSK_LINKED_SYSTEM_BUF
*LinkedTXRecycleBuff
;
1618 // Check preliminaries
1620 return EFI_INVALID_PARAMETER
;
1623 // Serialize access to data and registers
1624 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1626 // Check that driver was started and initialised
1627 switch (Snp
->Mode
->State
) {
1628 case EfiSimpleNetworkInitialized
:
1630 case EfiSimpleNetworkStarted
:
1631 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1632 ReturnUnlock (EFI_DEVICE_ERROR
);
1633 case EfiSimpleNetworkStopped
:
1634 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1635 ReturnUnlock (EFI_NOT_STARTED
);
1637 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1638 (UINTN
)Snp
->Mode
->State
));
1639 ReturnUnlock (EFI_DEVICE_ERROR
);
1642 // Find the LanDriver structure
1643 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1645 // Arbitrarily set the interrupt status to 0
1646 if (IrqStat
!= NULL
) {
1648 IstReg
= ReadIoReg8 (LanDriver
, LAN91X_IST
);
1649 if ((IstReg
& IST_RCV
) != 0) {
1650 *IrqStat
|= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT
;
1652 if ((IstReg
& IST_TX
) != 0) {
1653 *IrqStat
|= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
;
1657 // Pass back the completed buffer address
1658 // The transmit buffer status is not read when TxBuf is NULL
1659 if (TxBuff
!= NULL
) {
1660 *((UINT8
**) TxBuff
) = (UINT8
*) 0;
1661 if( !IsListEmpty (&LanDriver
->TransmitQueueHead
))
1663 LinkedTXRecycleBuff
= CR (GetFirstNode (&LanDriver
->TransmitQueueHead
), MSK_LINKED_SYSTEM_BUF
, Link
, TX_MBUF_SIGNATURE
);
1664 if(LinkedTXRecycleBuff
!= NULL
) {
1665 *TxBuff
= LinkedTXRecycleBuff
->SystemBuf
.Buf
;
1666 RemoveEntryList (&LinkedTXRecycleBuff
->Link
);
1667 FreePool (LinkedTXRecycleBuff
);
1672 // Update the media status
1673 MediaPresent
= CheckLinkStatus (LanDriver
);
1674 if (MediaPresent
!= Snp
->Mode
->MediaPresent
) {
1675 DEBUG ((DEBUG_WARN
, "LAN91x: Link %s\n", MediaPresent
? L
"up" : L
"down"));
1677 Snp
->Mode
->MediaPresent
= MediaPresent
;
1678 Status
= EFI_SUCCESS
;
1680 // Restore TPL and return
1682 gBS
->RestoreTPL (SavedTpl
);
1688 ** UEFI Transmit() function
1694 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1698 IN EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1699 IN EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1700 IN UINT16
*Protocol OPTIONAL
1703 LAN91X_DRIVER
*LanDriver
;
1712 MSK_LINKED_SYSTEM_BUF
*LinkedTXRecycleBuff
;
1715 // Check preliminaries
1716 if ((Snp
== NULL
) || (BufAddr
== NULL
)) {
1717 DEBUG ((DEBUG_ERROR
, "LAN91x: SnpTransmit(): NULL Snp (%p) or BufAddr (%p)\n",
1719 return EFI_INVALID_PARAMETER
;
1722 // Serialize access to data and registers
1723 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1725 // Check that driver was started and initialised
1726 switch (Snp
->Mode
->State
) {
1727 case EfiSimpleNetworkInitialized
:
1729 case EfiSimpleNetworkStarted
:
1730 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1731 ReturnUnlock (EFI_DEVICE_ERROR
);
1732 case EfiSimpleNetworkStopped
:
1733 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1734 ReturnUnlock (EFI_NOT_STARTED
);
1736 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1737 (UINTN
)Snp
->Mode
->State
));
1738 ReturnUnlock (EFI_DEVICE_ERROR
);
1741 // Find the LanDriver structure
1742 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1744 // Ensure header is correct size if non-zero
1746 if (HdrSize
!= Snp
->Mode
->MediaHeaderSize
) {
1747 DEBUG ((DEBUG_ERROR
, "LAN91x: SnpTransmit(): Invalid HdrSize %d\n", HdrSize
));
1748 ReturnUnlock (EFI_INVALID_PARAMETER
);
1751 if ((DstAddr
== NULL
) || (Protocol
== NULL
)) {
1752 DEBUG ((DEBUG_ERROR
, "LAN91x: SnpTransmit(): NULL DstAddr %p or Protocol %p\n",
1753 DstAddr
, Protocol
));
1754 ReturnUnlock (EFI_INVALID_PARAMETER
);
1758 // Before transmitting check the link status
1759 if (!Snp
->Mode
->MediaPresent
) {
1760 DEBUG ((DEBUG_WARN
, "LAN91x: SnpTransmit(): Link not ready\n"));
1761 ReturnUnlock (EFI_NOT_READY
);
1764 // Calculate the request size in 256-byte "pages" minus 1
1765 // The 91C111 ignores this, but some older devices need it.
1766 MmuPages
= ((BufSize
& ~1) + LAN91X_PKT_OVERHEAD
- 1) >> 8;
1768 DEBUG ((DEBUG_WARN
, "LAN91x: Tx buffer too large (%d bytes)\n", BufSize
));
1769 LanDriver
->Stats
.TxOversizeFrames
+= 1;
1770 LanDriver
->Stats
.TxDroppedFrames
+= 1;
1771 ReturnUnlock (EFI_BAD_BUFFER_SIZE
);
1774 // Request allocation of a transmit buffer
1775 Status
= MmuOperation (LanDriver
, MMUCR_OP_TX_ALLOC
| MmuPages
);
1776 if (EFI_ERROR (Status
)) {
1777 DEBUG ((DEBUG_ERROR
, "LAN91x: Tx buffer request failure: %d\n", Status
));
1778 ReturnUnlock (EFI_DEVICE_ERROR
);
1781 // Wait for allocation request completion
1782 Retries
= LAN91X_MEMORY_ALLOC_POLLS
;
1783 while ((ReadIoReg8 (LanDriver
, LAN91X_IST
) & IST_ALLOC
) == 0) {
1784 if (--Retries
== 0) {
1785 DEBUG ((DEBUG_ERROR
, "LAN91x: Tx buffer allocation timeout\n"));
1786 ReturnUnlock (EFI_TIMEOUT
);
1790 // Check for successful allocation
1791 PktNum
= ReadIoReg8 (LanDriver
, LAN91X_ARR
);
1792 if ((PktNum
& ARR_FAILED
) != 0) {
1793 DEBUG ((DEBUG_ERROR
, "LAN91x: Tx buffer allocation failure: %02x\n", PktNum
));
1794 ReturnUnlock (EFI_NOT_READY
);
1796 PktNum
&= ARR_PACKET
;
1798 // Check for the nature of the frame
1799 // If no destination address, it's ARP broadcast
1802 if (DstAddr
->Addr
[0] == 0xFF) {
1803 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1804 } else if ((DstAddr
->Addr
[0] & 0x1) == 1) {
1805 LanDriver
->Stats
.TxMulticastFrames
+= 1;
1807 LanDriver
->Stats
.TxUnicastFrames
+= 1;
1810 LanDriver
->Stats
.TxBroadcastFrames
+= 1;
1813 // Set the Packet Number and Pointer registers
1814 WriteIoReg8 (LanDriver
, LAN91X_PNR
, PktNum
);
1815 WriteIoReg16 (LanDriver
, LAN91X_PTR
, PTR_AUTO_INCR
);
1817 // Set up mutable buffer information variables
1821 // Write Status and Byte Count first
1822 WriteIoReg16 (LanDriver
, LAN91X_DATA0
, 0);
1823 WriteIoReg16 (LanDriver
, LAN91X_DATA0
, (Len
+ LAN91X_PKT_OVERHEAD
) & BCW_COUNT
);
1825 // This packet may come with a preconfigured Ethernet header.
1826 // If not, we need to construct one from optional parameters.
1829 // Write the destination address
1830 WriteIoData (LanDriver
, DstAddr
, NET_ETHER_ADDR_LEN
);
1832 // Write the Source Address
1833 if (SrcAddr
!= NULL
) {
1834 WriteIoData (LanDriver
, SrcAddr
, NET_ETHER_ADDR_LEN
);
1836 WriteIoData (LanDriver
, &LanDriver
->SnpMode
.CurrentAddress
, NET_ETHER_ADDR_LEN
);
1839 // Write the Protocol word
1840 Proto
= HTONS (*Protocol
);
1841 WriteIoReg16 (LanDriver
, LAN91X_DATA0
, Proto
);
1843 // Adjust the data start and length
1844 Ptr
+= sizeof(ETHER_HEAD
);
1845 Len
-= sizeof(ETHER_HEAD
);
1848 // Copy the remainder data buffer, except the odd byte
1849 WriteIoData (LanDriver
, Ptr
, Len
& ~1);
1853 // Write the Packet Control Word and odd byte
1854 WriteIoReg16 (LanDriver
, LAN91X_DATA0
,
1855 (Len
!= 0) ? (PCW_ODD
| PCW_CRC
| *Ptr
) : PCW_CRC
);
1857 // Release the packet for transmission
1858 Status
= MmuOperation (LanDriver
, MMUCR_OP_TX_PUSH
);
1859 if (EFI_ERROR (Status
)) {
1860 DEBUG ((DEBUG_ERROR
, "LAN91x: Tx buffer release failure: %d\n", Status
));
1861 ReturnUnlock (EFI_DEVICE_ERROR
);
1864 // Update the Tx statistics
1865 LanDriver
->Stats
.TxTotalBytes
+= BufSize
;
1866 LanDriver
->Stats
.TxGoodFrames
+= 1;
1868 // Update the Tx Buffer cache
1869 LinkedTXRecycleBuff
= AllocateZeroPool (sizeof (MSK_LINKED_SYSTEM_BUF
));
1870 if (LinkedTXRecycleBuff
== NULL
) {
1871 return EFI_OUT_OF_RESOURCES
;
1873 LinkedTXRecycleBuff
->Signature
= TX_MBUF_SIGNATURE
;
1875 // Add the passed Buffer to the transmit queue. Don't copy.
1877 LinkedTXRecycleBuff
->SystemBuf
.Buf
= BufAddr
;
1878 LinkedTXRecycleBuff
->SystemBuf
.Length
= BufSize
;
1879 InsertTailList (&LanDriver
->TransmitQueueHead
, &LinkedTXRecycleBuff
->Link
);
1881 Status
= EFI_SUCCESS
;
1883 // Dump the packet header
1884 #if LAN91X_PRINT_PACKET_HEADERS
1886 DEBUG ((DEBUG_ERROR
, "LAN91X:SnpTransmit()\n"));
1887 DEBUG ((DEBUG_ERROR
, " HdrSize: %d, SrcAddr: %p, Length: %d, Last byte: %02x\n",
1888 HdrSize
, SrcAddr
, BufSize
, Ptr
[BufSize
- 1]));
1890 (HdrSize
== 0) ? (EFI_MAC_ADDRESS
*)&Ptr
[0] : DstAddr
,
1891 (HdrSize
== 0) ? (EFI_MAC_ADDRESS
*)&Ptr
[6] : (SrcAddr
!= NULL
) ? SrcAddr
: &LanDriver
->SnpMode
.CurrentAddress
,
1892 (HdrSize
== 0) ? (UINT16
*)&Ptr
[12] : &Proto
,
1897 // Restore TPL and return
1899 gBS
->RestoreTPL (SavedTpl
);
1905 ** UEFI Receive() function
1911 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
,
1912 OUT UINTN
*HdrSize OPTIONAL
,
1913 IN OUT UINTN
*BuffSize
,
1915 OUT EFI_MAC_ADDRESS
*SrcAddr OPTIONAL
,
1916 OUT EFI_MAC_ADDRESS
*DstAddr OPTIONAL
,
1917 OUT UINT16
*Protocol OPTIONAL
1922 LAN91X_DRIVER
*LanDriver
;
1929 // Check preliminaries
1930 if ((Snp
== NULL
) || (Data
== NULL
)) {
1931 return EFI_INVALID_PARAMETER
;
1934 // Serialize access to data and registers
1935 SavedTpl
= gBS
->RaiseTPL (LAN91X_TPL
);
1937 // Check that driver was started and initialised
1938 switch (Snp
->Mode
->State
) {
1939 case EfiSimpleNetworkInitialized
:
1941 case EfiSimpleNetworkStarted
:
1942 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not yet initialized\n"));
1943 ReturnUnlock (EFI_DEVICE_ERROR
);
1944 case EfiSimpleNetworkStopped
:
1945 DEBUG ((DEBUG_WARN
, "LAN91x: Driver not started\n"));
1946 ReturnUnlock (EFI_NOT_STARTED
);
1948 DEBUG ((DEBUG_ERROR
, "LAN91x: Driver in an invalid state: %u\n",
1949 (UINTN
)Snp
->Mode
->State
));
1950 ReturnUnlock (EFI_DEVICE_ERROR
);
1953 // Find the LanDriver structure
1954 LanDriver
= INSTANCE_FROM_SNP_THIS(Snp
);
1956 // Check for Rx Overrun
1957 IstReg
= ReadIoReg8 (LanDriver
, LAN91X_IST
);
1958 if ((IstReg
& IST_RX_OVRN
) != 0) {
1959 LanDriver
->Stats
.RxTotalFrames
+= 1;
1960 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1961 WriteIoReg8 (LanDriver
, LAN91X_IST
, IST_RX_OVRN
);
1962 DEBUG ((DEBUG_WARN
, "LAN91x: Receiver overrun\n"));
1965 // Check for Rx data available
1966 if ((IstReg
& IST_RCV
) == 0) {
1967 ReturnUnlock (EFI_NOT_READY
);
1970 // Configure the PTR register for reading
1971 WriteIoReg16 (LanDriver
, LAN91X_PTR
, PTR_RCV
| PTR_AUTO_INCR
| PTR_READ
);
1973 // Read the Packet Status and Packet Length words
1974 PktStatus
= ReadIoReg16 (LanDriver
, LAN91X_DATA0
);
1975 PktLength
= ReadIoReg16 (LanDriver
, LAN91X_DATA0
) & BCW_COUNT
;
1977 // Check for valid received packet
1978 if ((PktStatus
== 0) && (PktLength
== 0)) {
1979 DEBUG ((DEBUG_WARN
, "LAN91x: Received zero-length packet. IST=%04x\n", IstReg
));
1980 ReturnUnlock (EFI_NOT_READY
);
1982 LanDriver
->Stats
.RxTotalFrames
+= 1;
1984 // Check if we got a CRC error
1985 if ((PktStatus
& RX_BAD_CRC
) != 0) {
1986 DEBUG ((DEBUG_WARN
, "LAN91x: Received frame CRC error\n"));
1987 LanDriver
->Stats
.RxCrcErrorFrames
+= 1;
1988 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1989 Status
= EFI_DEVICE_ERROR
;
1993 // Check if we got a too-short frame
1994 if ((PktStatus
& RX_TOO_SHORT
) != 0) {
1995 DEBUG ((DEBUG_WARN
, "LAN91x: Received frame too short (%d bytes)\n", PktLength
));
1996 LanDriver
->Stats
.RxUndersizeFrames
+= 1;
1997 LanDriver
->Stats
.RxDroppedFrames
+= 1;
1998 Status
= EFI_DEVICE_ERROR
;
2002 // Check if we got a too-long frame
2003 if ((PktStatus
& RX_TOO_LONG
) != 0) {
2004 DEBUG ((DEBUG_WARN
, "LAN91x: Received frame too long (%d bytes)\n", PktLength
));
2005 LanDriver
->Stats
.RxOversizeFrames
+= 1;
2006 LanDriver
->Stats
.RxDroppedFrames
+= 1;
2007 Status
= EFI_DEVICE_ERROR
;
2011 // Check if we got an alignment error
2012 if ((PktStatus
& RX_ALGN_ERR
) != 0) {
2013 DEBUG ((DEBUG_WARN
, "LAN91x: Received frame alignment error\n"));
2014 // Don't seem to keep track of these specifically
2015 LanDriver
->Stats
.RxDroppedFrames
+= 1;
2016 Status
= EFI_DEVICE_ERROR
;
2020 // Classify the received fram
2021 if ((PktStatus
& RX_MULTICAST
) != 0) {
2022 LanDriver
->Stats
.RxMulticastFrames
+= 1;
2023 } else if ((PktStatus
& RX_BROADCAST
) != 0) {
2024 LanDriver
->Stats
.RxBroadcastFrames
+= 1;
2026 LanDriver
->Stats
.RxUnicastFrames
+= 1;
2029 // Calculate the received packet data length
2030 PktLength
-= LAN91X_PKT_OVERHEAD
;
2031 if ((PktStatus
& RX_ODD_FRAME
) != 0) {
2035 // Check buffer size
2036 if (*BuffSize
< PktLength
) {
2037 DEBUG ((DEBUG_WARN
, "LAN91x: Receive buffer too small for packet (%d < %d)\n",
2038 *BuffSize
, PktLength
));
2039 *BuffSize
= PktLength
;
2040 Status
= EFI_BUFFER_TOO_SMALL
;
2044 // Transfer the data bytes
2046 ReadIoData (LanDriver
, DataPtr
, PktLength
& ~0x0001);
2048 // Read the PktControl and Odd Byte from the FIFO
2049 PktControl
= ReadIoReg16 (LanDriver
, LAN91X_DATA0
);
2050 if ((PktControl
& PCW_ODD
) != 0) {
2051 DataPtr
[PktLength
- 1] = PktControl
& PCW_ODD_BYTE
;
2054 // Update buffer size
2055 *BuffSize
= PktLength
;
2057 if (HdrSize
!= NULL
) {
2058 *HdrSize
= LanDriver
->SnpMode
.MediaHeaderSize
;
2061 // Extract the destination address
2062 if (DstAddr
!= NULL
) {
2063 CopyMem (DstAddr
, &DataPtr
[0], NET_ETHER_ADDR_LEN
);
2066 // Get the source address
2067 if (SrcAddr
!= NULL
) {
2068 CopyMem (SrcAddr
, &DataPtr
[6], NET_ETHER_ADDR_LEN
);
2072 if (Protocol
!= NULL
) {
2073 *Protocol
= NTOHS (*(UINT16
*)(&DataPtr
[12]));
2076 // Update the Rx statistics
2077 LanDriver
->Stats
.RxTotalBytes
+= PktLength
;
2078 LanDriver
->Stats
.RxGoodFrames
+= 1;
2079 Status
= EFI_SUCCESS
;
2081 #if LAN91X_PRINT_PACKET_HEADERS
2082 // Dump the packet header
2083 DEBUG ((DEBUG_ERROR
, "LAN91X:SnpReceive()\n"));
2084 DEBUG ((DEBUG_ERROR
, " HdrSize: %p, SrcAddr: %p, DstAddr: %p, Protocol: %p\n",
2085 HdrSize
, SrcAddr
, DstAddr
, Protocol
));
2086 DEBUG ((DEBUG_ERROR
, " Length: %d, Last byte: %02x\n", PktLength
, DataPtr
[PktLength
- 1]));
2087 PrintIpDgram (&DataPtr
[0], &DataPtr
[6], &DataPtr
[12], &DataPtr
[14]);
2090 // Release the FIFO buffer
2092 MmuOperation (LanDriver
, MMUCR_OP_RX_POP_REL
);
2094 // Restore TPL and return
2096 gBS
->RestoreTPL (SavedTpl
);
2101 /*------------------ Driver Execution Environment main entry point ------------------*/
2104 ** Entry point for the LAN91x driver
2109 IN EFI_HANDLE Handle
,
2110 IN EFI_SYSTEM_TABLE
*SystemTable
2114 LAN91X_DRIVER
*LanDriver
;
2115 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
2116 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
2117 LAN91X_DEVICE_PATH
*Lan91xPath
;
2119 // The PcdLan91xDxeBaseAddress PCD must be defined
2120 ASSERT(PcdGet32 (PcdLan91xDxeBaseAddress
) != 0);
2122 // Allocate Resources
2123 LanDriver
= AllocateZeroPool (sizeof(LAN91X_DRIVER
));
2124 Lan91xPath
= AllocateCopyPool (sizeof(LAN91X_DEVICE_PATH
), &Lan91xPathTemplate
);
2126 // Initialize I/O Space access info
2127 LanDriver
->IoBase
= PcdGet32 (PcdLan91xDxeBaseAddress
);
2128 LanDriver
->PhyAd
= LAN91X_NO_PHY
;
2129 LanDriver
->BankSel
= 0xff;
2131 // Initialize pointers
2132 Snp
= &(LanDriver
->Snp
);
2133 SnpMode
= &(LanDriver
->SnpMode
);
2134 Snp
->Mode
= SnpMode
;
2136 // Set the signature of the LAN Driver structure
2137 LanDriver
->Signature
= LAN91X_SIGNATURE
;
2140 Status
= Probe (LanDriver
);
2141 if (EFI_ERROR(Status
)) {
2142 DEBUG ((DEBUG_ERROR
, "LAN91x:Lan91xDxeEntry(): Probe failed with status %d\n", Status
));
2146 #ifdef LAN91X_PRINT_REGISTERS
2147 PrintIoRegisters (LanDriver
);
2148 PrintPhyRegisters (LanDriver
);
2151 // Initialize transmit queue
2152 InitializeListHead (&LanDriver
->TransmitQueueHead
);
2154 // Assign fields and func pointers
2155 Snp
->Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
2156 Snp
->WaitForPacket
= NULL
;
2157 Snp
->Initialize
= SnpInitialize
;
2158 Snp
->Start
= SnpStart
;
2159 Snp
->Stop
= SnpStop
;
2160 Snp
->Reset
= SnpReset
;
2161 Snp
->Shutdown
= SnpShutdown
;
2162 Snp
->ReceiveFilters
= SnpReceiveFilters
;
2163 Snp
->StationAddress
= SnpStationAddress
;
2164 Snp
->Statistics
= SnpStatistics
;
2165 Snp
->MCastIpToMac
= SnpMcastIptoMac
;
2166 Snp
->NvData
= SnpNvData
;
2167 Snp
->GetStatus
= SnpGetStatus
;
2168 Snp
->Transmit
= SnpTransmit
;
2169 Snp
->Receive
= SnpReceive
;
2171 // Fill in simple network mode structure
2172 SnpMode
->State
= EfiSimpleNetworkStopped
;
2173 SnpMode
->HwAddressSize
= NET_ETHER_ADDR_LEN
; // HW address is 6 bytes
2174 SnpMode
->MediaHeaderSize
= sizeof(ETHER_HEAD
); // Size of an Ethernet header
2175 SnpMode
->MaxPacketSize
= EFI_PAGE_SIZE
; // Ethernet Frame (with VLAN tag +4 bytes)
2177 // Supported receive filters
2178 SnpMode
->ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
2179 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
2180 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
|
2181 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
|
2182 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
2184 // Initially-enabled receive filters
2185 SnpMode
->ReceiveFilterSetting
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
|
2186 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
|
2187 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
2189 // LAN91x has 64bit hash table. We can filter an infinite MACs, but
2190 // higher-level software must filter out any hash collisions.
2191 SnpMode
->MaxMCastFilterCount
= MAX_MCAST_FILTER_CNT
;
2192 SnpMode
->MCastFilterCount
= 0;
2193 ZeroMem (&SnpMode
->MCastFilter
, MAX_MCAST_FILTER_CNT
* sizeof(EFI_MAC_ADDRESS
));
2195 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
2196 SnpMode
->IfType
= NET_IFTYPE_ETHERNET
;
2198 // Mac address is changeable
2199 SnpMode
->MacAddressChangeable
= TRUE
;
2201 // We can only transmit one packet at a time
2202 SnpMode
->MultipleTxSupported
= FALSE
;
2204 // MediaPresent checks for cable connection and partner link
2205 SnpMode
->MediaPresentSupported
= TRUE
;
2206 SnpMode
->MediaPresent
= FALSE
;
2208 // Set broadcast address
2209 SetMem (&SnpMode
->BroadcastAddress
, sizeof (EFI_MAC_ADDRESS
), 0xFF);
2211 // Assign fields for device path
2212 Lan91xPath
->Lan91x
.MacAddress
= SnpMode
->PermanentAddress
;
2213 Lan91xPath
->Lan91x
.IfType
= SnpMode
->IfType
;
2215 // Initialise the protocol
2216 Status
= gBS
->InstallMultipleProtocolInterfaces (
2217 &LanDriver
->ControllerHandle
,
2218 &gEfiSimpleNetworkProtocolGuid
, Snp
,
2219 &gEfiDevicePathProtocolGuid
, Lan91xPath
,
2223 // Say what the status of loading the protocol structure is
2224 if (EFI_ERROR(Status
)) {
2225 FreePool (LanDriver
);