Home | History | Annotate | Download | only in Lan91xDxe
      1 /** @file
      2 *  SMSC LAN91x series Network Controller Driver.
      3 *
      4 *  Copyright (c) 2013 Linaro.org
      5 *
      6 *  Derived from the LAN9118 driver. Original sources
      7 *  Copyright (c) 2012-2013, ARM Limited. All rights reserved.
      8 *
      9 *  This program and the accompanying materials are licensed and
     10 *  made available under the terms and conditions of the BSD License
     11 *  which accompanies this distribution.  The full text of the license
     12 *  may be found at: 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 <Uefi.h>
     20 #include <Uefi/UefiSpec.h>
     21 #include <Base.h>
     22 
     23 // Protocols used by this driver
     24 #include <Protocol/SimpleNetwork.h>
     25 #include <Protocol/ComponentName2.h>
     26 #include <Protocol/PxeBaseCode.h>
     27 #include <Protocol/DevicePath.h>
     28 
     29 // Libraries used by this driver
     30 #include <Library/UefiLib.h>
     31 #include <Library/DebugLib.h>
     32 #include <Library/UefiBootServicesTableLib.h>
     33 #include <Library/MemoryAllocationLib.h>
     34 #include <Library/IoLib.h>
     35 #include <Library/PcdLib.h>
     36 #include <Library/NetLib.h>
     37 #include <Library/DevicePathLib.h>
     38 
     39 // Hardware register definitions
     40 #include "Lan91xDxeHw.h"
     41 
     42 // Debugging output options
     43 //#define LAN91X_PRINT_REGISTERS 1
     44 //#define LAN91X_PRINT_PACKET_HEADERS 1
     45 //#define LAN91X_PRINT_RECEIVE_FILTERS 1
     46 
     47 // Chip power-down option -- UNTESTED
     48 //#define LAN91X_POWER_DOWN 1
     49 
     50 /*---------------------------------------------------------------------------------------------------------------------
     51 
     52   LAN91x Information Structure
     53 
     54 ---------------------------------------------------------------------------------------------------------------------*/
     55 typedef struct _LAN91X_DRIVER {
     56   // Driver signature
     57   UINT32            Signature;
     58   EFI_HANDLE        ControllerHandle;
     59 
     60   // EFI SNP protocol instances
     61   EFI_SIMPLE_NETWORK_PROTOCOL Snp;
     62   EFI_SIMPLE_NETWORK_MODE SnpMode;
     63 
     64   // EFI Snp statistics instance
     65   EFI_NETWORK_STATISTICS Stats;
     66 
     67   // Transmit Buffer recycle queue
     68 
     69   LIST_ENTRY TransmitQueueHead;
     70 
     71   // Register access variables
     72   UINTN             IoBase;             // I/O Base Address
     73   UINT8             Revision;           // Chip Revision Number
     74   INT8              PhyAd;              // Phy Address
     75   UINT8             BankSel;            // Currently selected register bank
     76 
     77 } LAN91X_DRIVER;
     78 
     79 #define LAN91X_NO_PHY (-1)              // PhyAd value if PHY not detected
     80 
     81 #define LAN91X_SIGNATURE                        SIGNATURE_32('S', 'M', '9', '1')
     82 #define INSTANCE_FROM_SNP_THIS(a)               CR(a, LAN91X_DRIVER, Snp, LAN91X_SIGNATURE)
     83 
     84 #define LAN91X_STALL              2
     85 #define LAN91X_MEMORY_ALLOC_POLLS 100   // Max times to poll for memory allocation
     86 #define LAN91X_PKT_OVERHEAD       6     // Overhead bytes in packet buffer
     87 
     88 // Synchronization TPLs
     89 #define LAN91X_TPL  TPL_CALLBACK
     90 
     91 // Most common CRC32 Polynomial for little endian machines
     92 #define CRC_POLYNOMIAL               0xEDB88320
     93 
     94 
     95 typedef struct {
     96   MAC_ADDR_DEVICE_PATH      Lan91x;
     97   EFI_DEVICE_PATH_PROTOCOL  End;
     98 } LAN91X_DEVICE_PATH;
     99 
    100 LAN91X_DEVICE_PATH Lan91xPathTemplate =  {
    101   {
    102     {
    103       MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,
    104       { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) }
    105     },
    106     { { 0 } },
    107     0
    108   },
    109   {
    110     END_DEVICE_PATH_TYPE,
    111     END_ENTIRE_DEVICE_PATH_SUBTYPE,
    112     { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }
    113   }
    114 };
    115 
    116 // Chip ID numbers and name strings
    117 #define CHIP_9192       3
    118 #define CHIP_9194       4
    119 #define CHIP_9195       5
    120 #define CHIP_9196       6
    121 #define CHIP_91100      7
    122 #define CHIP_91100FD    8
    123 #define CHIP_91111FD    9
    124 
    125 STATIC CHAR16 CONST * CONST ChipIds[ 16 ] =  {
    126   NULL, NULL, NULL,
    127   /* 3 */ L"SMC91C90/91C92",
    128   /* 4 */ L"SMC91C94",
    129   /* 5 */ L"SMC91C95",
    130   /* 6 */ L"SMC91C96",
    131   /* 7 */ L"SMC91C100",
    132   /* 8 */ L"SMC91C100FD",
    133   /* 9 */ L"SMC91C11xFD",
    134   NULL, NULL, NULL,
    135   NULL, NULL, NULL
    136 };
    137 
    138 /* ------------------ TxBuffer Queue structures ------------------- */
    139 
    140 typedef struct {
    141   VOID            *Buf;
    142   UINTN           Length;
    143 } MSK_SYSTEM_BUF;
    144 
    145 typedef struct {
    146   UINTN           Signature;
    147   LIST_ENTRY      Link;
    148   MSK_SYSTEM_BUF  SystemBuf;
    149 } MSK_LINKED_SYSTEM_BUF;
    150 
    151 #define TX_MBUF_SIGNATURE  SIGNATURE_32 ('t','x','m','b')
    152 
    153 /* ------------------ MAC Address Hash Calculations ------------------- */
    154 
    155 /*
    156 **  Generate a hash value from a multicast address
    157 **
    158 **  This uses the Ethernet standard CRC32 algorithm
    159 **
    160 **  INFO USED:
    161 **    1: http://en.wikipedia.org/wiki/Cyclic_redundancy_check
    162 **
    163 **    2: http://www.erg.abdn.ac.uk/~gorry/eg3567/dl-pages/crc.html
    164 **
    165 **    3: http://en.wikipedia.org/wiki/Computation_of_CRC
    166 */
    167 STATIC
    168 UINT32
    169 MulticastHash (
    170   IN    EFI_MAC_ADDRESS *Mac,
    171   IN    UINT32 AddrLen
    172   )
    173 {
    174   UINT32 Iter;
    175   UINT32 Remainder;
    176   UINT32 Crc32;
    177   UINT8 *Addr;
    178 
    179   // 0xFFFFFFFF is standard seed for Ethernet
    180   Remainder = 0xFFFFFFFF;
    181 
    182   // Generate the remainder byte-by-byte (LSB first)
    183   Addr = &Mac->Addr[0];
    184   while (AddrLen-- > 0) {
    185     Remainder ^= *Addr++;
    186     for (Iter = 0; Iter < 8; ++Iter) {
    187       // Check if exponent is set
    188       if ((Remainder & 1) != 0) {
    189         Remainder = (Remainder >> 1) ^ CRC_POLYNOMIAL;
    190       } else {
    191         Remainder = (Remainder >> 1) ^ 0;
    192       }
    193     }
    194   }
    195 
    196   // Reverse the bits of the remainder
    197   Crc32 = 0;
    198   for (Iter = 0; Iter < 32; ++Iter) {
    199     Crc32 <<= 1;
    200     Crc32 |= Remainder & 1;
    201     Remainder >>= 1;
    202   }
    203   return Crc32;
    204 }
    205 
    206 
    207 /* ---------------- Banked Register Operations ------------------ */
    208 
    209 // Select the proper I/O bank
    210 STATIC
    211 VOID
    212 SelectIoBank (
    213   LAN91X_DRIVER   *LanDriver,
    214   UINTN            Register
    215   )
    216 {
    217   UINT8   Bank;
    218 
    219   Bank = RegisterToBank (Register);
    220 
    221   // Select the proper I/O bank
    222   if (LanDriver->BankSel != Bank) {
    223     MmioWrite16 (LanDriver->IoBase + LAN91X_BANK_OFFSET, Bank);
    224     LanDriver->BankSel = Bank;
    225   }
    226 }
    227 
    228 // Read a 16-bit I/O-space register
    229 STATIC
    230 UINT16
    231 ReadIoReg16 (
    232   LAN91X_DRIVER   *LanDriver,
    233   UINTN            Register
    234   )
    235 {
    236   UINT8   Offset;
    237 
    238   // Select the proper I/O bank
    239   SelectIoBank (LanDriver, Register);
    240 
    241   // Read the requested register
    242   Offset = RegisterToOffset (Register);
    243   return MmioRead16 (LanDriver->IoBase + Offset);
    244 }
    245 
    246 // Write a 16-bit I/O-space register
    247 STATIC
    248 UINT16
    249 WriteIoReg16 (
    250   LAN91X_DRIVER   *LanDriver,
    251   UINTN            Register,
    252   UINT16           Value
    253   )
    254 {
    255   UINT8   Offset;
    256 
    257   // Select the proper I/O bank
    258   SelectIoBank (LanDriver, Register);
    259 
    260   // Write the requested register
    261   Offset = RegisterToOffset (Register);
    262   return MmioWrite16 (LanDriver->IoBase + Offset, Value);
    263 }
    264 
    265 // Read an 8-bit I/O-space register
    266 STATIC
    267 UINT8
    268 ReadIoReg8 (
    269   LAN91X_DRIVER   *LanDriver,
    270   UINTN            Register
    271   )
    272 {
    273   UINT8   Offset;
    274 
    275   // Select the proper I/O bank
    276   SelectIoBank (LanDriver, Register);
    277 
    278   // Read the requested register
    279   Offset = RegisterToOffset (Register);
    280   return MmioRead8 (LanDriver->IoBase + Offset);
    281 }
    282 
    283 // Write an 8-bit I/O-space register
    284 STATIC
    285 UINT8
    286 WriteIoReg8 (
    287   LAN91X_DRIVER   *LanDriver,
    288   UINTN            Register,
    289   UINT8            Value
    290   )
    291 {
    292   UINT8   Offset;
    293 
    294   // Select the proper I/O bank
    295   SelectIoBank (LanDriver, Register);
    296 
    297   // Write the requested register
    298   Offset = RegisterToOffset (Register);
    299   return MmioWrite8 (LanDriver->IoBase + Offset, Value);
    300 }
    301 
    302 
    303 /* ---------------- MII/PHY Access Operations ------------------ */
    304 
    305 #define LAN91X_MDIO_STALL   1
    306 
    307 STATIC
    308 VOID
    309 MdioOutput (
    310   LAN91X_DRIVER   *LanDriver,
    311   UINTN            Bits,
    312   UINT32           Value
    313   )
    314 {
    315   UINT16          MgmtReg;
    316   UINT32          Mask;
    317 
    318   MgmtReg = ReadIoReg16 (LanDriver, LAN91X_MGMT);
    319   MgmtReg &= ~MGMT_MCLK;
    320   MgmtReg |= MGMT_MDOE;
    321 
    322   for (Mask = (1 << (Bits - 1)); Mask != 0; Mask >>= 1) {
    323     if ((Value & Mask) != 0) {
    324       MgmtReg |= MGMT_MDO;
    325     } else {
    326       MgmtReg &= ~MGMT_MDO;
    327     }
    328 
    329     WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
    330     gBS->Stall (LAN91X_MDIO_STALL);
    331     WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg | MGMT_MCLK);
    332     gBS->Stall (LAN91X_MDIO_STALL);
    333   }
    334 }
    335 #define PHY_OUTPUT_TIME (2 * LAN91X_MDIO_STALL)
    336 
    337 STATIC
    338 UINT32
    339 MdioInput (
    340   LAN91X_DRIVER   *LanDriver,
    341   UINTN            Bits
    342   )
    343 {
    344   UINT16          MgmtReg;
    345   UINT32          Mask;
    346   UINT32          Value;
    347 
    348   MgmtReg = ReadIoReg16 (LanDriver, LAN91X_MGMT);
    349   MgmtReg &= ~(MGMT_MDOE | MGMT_MCLK | MGMT_MDO);
    350   WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
    351 
    352   Value = 0;
    353   for (Mask = (1 << (Bits - 1)); Mask != 0; Mask >>= 1) {
    354     if ((ReadIoReg16 (LanDriver, LAN91X_MGMT) & MGMT_MDI) != 0) {
    355        Value |= Mask;
    356     }
    357 
    358     WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
    359     gBS->Stall (LAN91X_MDIO_STALL);
    360     WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg | MGMT_MCLK);
    361     gBS->Stall (LAN91X_MDIO_STALL);
    362   }
    363 
    364   return Value;
    365 }
    366 #define PHY_INPUT_TIME (2 * LAN91X_MDIO_STALL)
    367 
    368 STATIC
    369 VOID
    370 MdioIdle (
    371   LAN91X_DRIVER   *LanDriver
    372   )
    373 {
    374   UINT16          MgmtReg;
    375 
    376   MgmtReg = ReadIoReg16 (LanDriver, LAN91X_MGMT);
    377   MgmtReg &= ~(MGMT_MDOE | MGMT_MCLK | MGMT_MDO);
    378   WriteIoReg16 (LanDriver, LAN91X_MGMT, MgmtReg);
    379 }
    380 
    381 // Write to a PHY register
    382 STATIC
    383 VOID
    384 WritePhyReg16 (
    385   LAN91X_DRIVER   *LanDriver,
    386   UINTN            RegAd,
    387   UINT16           Value
    388   )
    389 {
    390   // Bit-bang the MII Serial Frame write operation
    391   MdioOutput (LanDriver, 32, 0xffffffff);       // Send 32 Ones as a preamble
    392   MdioOutput (LanDriver,  2, 0x01);             // Send Start (01)
    393   MdioOutput (LanDriver,  2, 0x01);             // Send Write (01)
    394   MdioOutput (LanDriver,  5, LanDriver->PhyAd); // Send PHYAD[4:0]
    395   MdioOutput (LanDriver,  5, RegAd);            // Send REGAD[4:0]
    396   MdioOutput (LanDriver,  2, 0x02);             // Send TurnAround (10)
    397   MdioOutput (LanDriver, 16, Value);            // Write 16 data bits
    398 
    399   // Idle the MDIO bus
    400   MdioIdle (LanDriver);
    401 }
    402 // Calculate approximate time to write a PHY register in microseconds
    403 #define PHY_WRITE_TIME  ((32 + 2 + 2 + 5 + 5 + 2 + 16) * PHY_OUTPUT_TIME)
    404 
    405 // Read from a PHY register
    406 STATIC
    407 UINT16
    408 ReadPhyReg16 (
    409   LAN91X_DRIVER   *LanDriver,
    410   UINTN            RegAd
    411   )
    412 {
    413   UINT32 Value;
    414 
    415   // Bit-bang the MII Serial Frame read operation
    416   MdioOutput (LanDriver, 32, 0xffffffff);       // Send 32 Ones as a preamble
    417   MdioOutput (LanDriver,  2, 0x01);             // Send Start (01)
    418   MdioOutput (LanDriver,  2, 0x02);             // Send Read (10)
    419   MdioOutput (LanDriver,  5, LanDriver->PhyAd); // Send PHYAD[4:0]
    420   MdioOutput (LanDriver,  5, RegAd);            // Send REGAD[4:0]
    421 
    422   (VOID)  MdioInput (LanDriver, 2);             // Discard TurnAround bits
    423   Value = MdioInput (LanDriver, 16);            // Read 16 data bits
    424 
    425   // Idle the MDIO bus
    426   MdioIdle (LanDriver);
    427 
    428   return (Value & 0xffff);
    429 }
    430 // Calculate approximate time to read a PHY register in microseconds
    431 #define PHY_READ_TIME  (((32 + 2 + 2 + 5 + 5) * PHY_OUTPUT_TIME) + \
    432                         ((2 + 16) * PHY_INPUT_TIME))
    433 
    434 
    435 /* ---------------- Debug Functions ------------------ */
    436 
    437 #ifdef LAN91X_PRINT_REGISTERS
    438 STATIC
    439 VOID
    440 PrintIoRegisters (
    441   IN  LAN91X_DRIVER   *LanDriver
    442   )
    443 {
    444   UINTN   Bank;
    445   UINTN   Offset;
    446   UINT16  Value;
    447 
    448   DEBUG((EFI_D_ERROR, "\nLAN91x I/O Register Dump:\n"));
    449 
    450   // Print currrent bank select register
    451   Value = MmioRead16 (LanDriver->IoBase + LAN91X_BANK_OFFSET);
    452   DEBUG((EFI_D_ERROR, "  BankSel: %d  Bank Register %04x (%d)\n",
    453       LanDriver->BankSel, Value, Value & 0x0007));
    454 
    455   // Print all I/O registers
    456   for (Offset = 0; Offset < 0x0e; Offset += 2) {
    457     DEBUG((EFI_D_ERROR, "  %02x:", Offset));
    458     for (Bank = 0; Bank <= 3; ++Bank) {
    459       DEBUG((EFI_D_ERROR, "  %04x", ReadIoReg16 (LanDriver, MakeRegister (Bank, Offset))));
    460     }
    461     DEBUG((EFI_D_ERROR, "\n"));
    462   }
    463 }
    464 
    465 STATIC
    466 VOID
    467 PrintPhyRegisters (
    468   IN  LAN91X_DRIVER   *LanDriver
    469   )
    470 {
    471   UINTN   RegNum;
    472 
    473   DEBUG((EFI_D_ERROR, "\nLAN91x Phy %d Register Dump:\n", LanDriver->PhyAd));
    474 
    475   // Print all Phy registers
    476   for (RegNum = 0; RegNum <= 5; ++RegNum) {
    477     DEBUG((EFI_D_ERROR, "  %2d:  %04x\n",
    478            RegNum,
    479            ReadPhyReg16 (LanDriver, RegNum)
    480     ));
    481   }
    482   for (RegNum = 16; RegNum <= 20; ++RegNum) {
    483     DEBUG((EFI_D_ERROR, "  %2d:  %04x\n",
    484            RegNum,
    485            ReadPhyReg16 (LanDriver, RegNum)
    486     ));
    487   }
    488 }
    489 #endif
    490 
    491 #if LAN91X_PRINT_PACKET_HEADERS
    492 STATIC
    493 VOID
    494 PrintIpDgram (
    495   IN  CONST VOID  *DstMac,
    496   IN  CONST VOID  *SrcMac,
    497   IN  CONST VOID  *Proto,
    498   IN  CONST VOID  *IpDgram
    499   )
    500 {
    501   CONST UINT8   *Ptr;
    502   UINT16         SrcPort;
    503   UINT16         DstPort;
    504 
    505   Ptr = DstMac;
    506   DEBUG((EFI_D_ERROR, "  Dst: %02x-%02x-%02x",
    507          Ptr[0], Ptr[1], Ptr[2]));
    508   DEBUG((EFI_D_ERROR, "-%02x-%02x-%02x",
    509          Ptr[3], Ptr[4], Ptr[5]));
    510 
    511   Ptr = SrcMac;
    512   DEBUG((EFI_D_ERROR, "  Src: %02x-%02x-%02x",
    513          Ptr[0], Ptr[1], Ptr[2]));
    514   DEBUG((EFI_D_ERROR, "-%02x-%02x-%02x",
    515          Ptr[3], Ptr[4], Ptr[5]));
    516 
    517   Ptr = Proto;
    518   DEBUG((EFI_D_ERROR, "  Proto: %02x%02x\n",
    519          Ptr[0], Ptr[1]));
    520 
    521   Ptr = IpDgram;
    522   switch (Ptr[9]) {
    523   case EFI_IP_PROTO_ICMP:
    524     DEBUG((EFI_D_ERROR, "  ICMP"));
    525     break;
    526   case EFI_IP_PROTO_TCP:
    527     DEBUG((EFI_D_ERROR, "  TCP"));
    528     break;
    529   case EFI_IP_PROTO_UDP:
    530     DEBUG((EFI_D_ERROR, "  UDP"));
    531     break;
    532   default:
    533     DEBUG((EFI_D_ERROR, "  IpProto %d\n", Ptr[9]));
    534     return;
    535   }
    536 
    537   DEBUG((EFI_D_ERROR, "  SrcIp: %d.%d.%d.%d",
    538          Ptr[12], Ptr[13], Ptr[14], Ptr[15]));
    539   DEBUG((EFI_D_ERROR, "  DstIp: %d.%d.%d.%d",
    540          Ptr[16], Ptr[17], Ptr[18], Ptr[19]));
    541 
    542   SrcPort = (Ptr[20] << 8) | Ptr[21];
    543   DstPort = (Ptr[22] << 8) | Ptr[23];
    544   DEBUG((EFI_D_ERROR, "  SrcPort: %d  DstPort: %d\n", SrcPort, DstPort));
    545 }
    546 #endif
    547 
    548 
    549 /* ---------------- PHY Management Operations ----------------- */
    550 
    551 STATIC
    552 EFI_STATUS
    553 PhyDetect (
    554   IN  LAN91X_DRIVER *LanDriver
    555   )
    556 {
    557   UINT16  PhyId1;
    558   UINT16  PhyId2;
    559 
    560   for (LanDriver->PhyAd = 0x1f; LanDriver->PhyAd >= 0 ; --LanDriver->PhyAd) {
    561     PhyId1 = ReadPhyReg16 (LanDriver, PHY_INDEX_ID1);
    562     PhyId2 = ReadPhyReg16 (LanDriver, PHY_INDEX_ID2);
    563 
    564     if ((PhyId1 != 0x0000) && (PhyId1 != 0xffff) &&
    565         (PhyId2 != 0x0000) && (PhyId2 != 0xffff)) {
    566       if ((PhyId1 == 0x0016) && ((PhyId2 & 0xfff0) == 0xf840)) {
    567         DEBUG((EFI_D_ERROR, "LAN91x: PHY type LAN83C183 (LAN91C111 Internal)\n"));
    568       } else if ((PhyId1 == 0x0282) && ((PhyId2 & 0xfff0) == 0x1c50)) {
    569         DEBUG((EFI_D_ERROR, "LAN91x: PHY type LAN83C180\n"));
    570       } else {
    571         DEBUG((EFI_D_ERROR, "LAN91x: PHY id %04x:%04x\n", PhyId1, PhyId2));
    572       }
    573       return EFI_SUCCESS;
    574     }
    575   }
    576 
    577   DEBUG((EFI_D_ERROR, "LAN91x: PHY detection failed\n"));
    578   return EFI_NO_MEDIA;
    579 }
    580 
    581 
    582 // Check the Link Status and take appropriate action
    583 STATIC
    584 BOOLEAN
    585 CheckLinkStatus (
    586   IN  LAN91X_DRIVER *LanDriver
    587   )
    588 {
    589   UINT16  PhyStatus;
    590 
    591   // Get the PHY Status
    592   PhyStatus = ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_STATUS);
    593 
    594   return (PhyStatus & PHYSTS_LINK_STS) != 0;
    595 }
    596 
    597 
    598 // Do auto-negotiation
    599 STATIC
    600 EFI_STATUS
    601 PhyAutoNegotiate (
    602   IN  LAN91X_DRIVER *LanDriver
    603   )
    604 {
    605   UINTN  Retries;
    606   UINT16 PhyControl;
    607   UINT16 PhyStatus;
    608   UINT16 PhyAdvert;
    609 
    610   // If there isn't a PHY, don't try to reset it
    611   if (LanDriver->PhyAd == LAN91X_NO_PHY) {
    612     return EFI_SUCCESS;
    613   }
    614 
    615   // Next check that auto-negotiation is supported
    616   PhyStatus = ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_STATUS);
    617   if ((PhyStatus & PHYSTS_AUTO_CAP) == 0) {
    618     return EFI_SUCCESS;
    619   }
    620 
    621   // Translate capabilities to advertise
    622   PhyAdvert = PHYANA_CSMA;
    623 
    624   if ((PhyStatus & PHYSTS_10BASET_HDPLX) != 0) {
    625     PhyAdvert |= PHYANA_10BASET;
    626   }
    627   if ((PhyStatus & PHYSTS_10BASET_FDPLX) != 0) {
    628     PhyAdvert |= PHYANA_10BASETFD;
    629   }
    630   if ((PhyStatus & PHYSTS_100BASETX_HDPLX) != 0) {
    631     PhyAdvert |= PHYANA_100BASETX;
    632   }
    633   if ((PhyStatus & PHYSTS_100BASETX_FDPLX) != 0) {
    634     PhyAdvert |= PHYANA_100BASETXFD;
    635   }
    636   if ((PhyStatus & PHYSTS_100BASE_T4) != 0) {
    637     PhyAdvert |= PHYANA_100BASET4;
    638   }
    639 
    640   // Set the capabilities to advertise
    641   WritePhyReg16 (LanDriver, PHY_INDEX_AUTO_NEG_ADVERT, PhyAdvert);
    642   (VOID) ReadPhyReg16 (LanDriver, PHY_INDEX_AUTO_NEG_ADVERT);
    643 
    644   // Restart Auto-Negotiation
    645   PhyControl = ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL);
    646   PhyControl &= ~(PHYCR_SPEED_SEL | PHYCR_DUPLEX_MODE);
    647   PhyControl |= PHYCR_AUTO_EN | PHYCR_RST_AUTO;
    648   WritePhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL, PhyControl);
    649 
    650   // Wait up to 2 seconds for the process to complete
    651   Retries = 2000000 / (PHY_READ_TIME + 100);
    652   while ((ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_STATUS) & PHYSTS_AUTO_COMP) == 0) {
    653     if (--Retries == 0) {
    654       DEBUG((EFI_D_ERROR, "LAN91x: PHY auto-negotiation timed-out\n"));
    655       return EFI_TIMEOUT;
    656     }
    657     gBS->Stall (100);
    658   }
    659 
    660   return EFI_SUCCESS;
    661 }
    662 
    663 
    664 // Perform PHY software reset
    665 STATIC
    666 EFI_STATUS
    667 PhySoftReset (
    668   IN  LAN91X_DRIVER *LanDriver
    669   )
    670 {
    671   UINTN     Retries;
    672 
    673   // If there isn't a PHY, don't try to reset it
    674   if (LanDriver->PhyAd == LAN91X_NO_PHY) {
    675     return EFI_SUCCESS;
    676   }
    677 
    678   // Request a PHY reset
    679   WritePhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL, PHYCR_RESET);
    680 
    681   // The internal PHY will reset within 50ms. Allow 100ms.
    682   Retries = 100000 / (PHY_READ_TIME + 100);
    683   while (ReadPhyReg16 (LanDriver, PHY_INDEX_BASIC_CTRL) & PHYCR_RESET) {
    684     if (--Retries == 0) {
    685       DEBUG((EFI_D_ERROR, "LAN91x: PHY reset timed-out\n"));
    686       return EFI_TIMEOUT;
    687     }
    688     gBS->Stall (100);
    689   }
    690 
    691   return EFI_SUCCESS;
    692 }
    693 
    694 
    695 /* ---------------- General Operations ----------------- */
    696 
    697 STATIC
    698 EFI_MAC_ADDRESS
    699 GetCurrentMacAddress (
    700   IN  LAN91X_DRIVER *LanDriver
    701   )
    702 {
    703   UINTN            RegNum;
    704   UINT8           *Addr;
    705   EFI_MAC_ADDRESS  MacAddress;
    706 
    707   SetMem (&MacAddress, sizeof(MacAddress), 0);
    708 
    709   Addr = &MacAddress.Addr[0];
    710   for (RegNum = LAN91X_IAR0; RegNum <= LAN91X_IAR5; ++RegNum) {
    711     *Addr = ReadIoReg8 (LanDriver, RegNum);
    712     ++Addr;
    713   }
    714 
    715   return MacAddress;
    716 }
    717 
    718 STATIC
    719 EFI_STATUS
    720 SetCurrentMacAddress (
    721   IN  LAN91X_DRIVER   *LanDriver,
    722   IN  EFI_MAC_ADDRESS *MacAddress
    723   )
    724 {
    725   UINTN            RegNum;
    726   UINT8           *Addr;
    727 
    728   Addr = &MacAddress->Addr[0];
    729   for (RegNum = LAN91X_IAR0; RegNum <= LAN91X_IAR5; ++RegNum) {
    730     WriteIoReg8 (LanDriver, RegNum, *Addr);
    731     ++Addr;
    732   }
    733 
    734   return EFI_SUCCESS;
    735 }
    736 
    737 STATIC
    738 EFI_STATUS
    739 MmuOperation (
    740   IN  LAN91X_DRIVER *LanDriver,
    741   IN  UINTN          MmuOp
    742   )
    743 {
    744   UINTN   Polls;
    745 
    746   WriteIoReg16 (LanDriver, LAN91X_MMUCR, MmuOp);
    747   Polls = 100;
    748   while ((ReadIoReg16 (LanDriver, LAN91X_MMUCR) & MMUCR_BUSY) != 0) {
    749     if (--Polls == 0) {
    750       DEBUG((EFI_D_ERROR, "LAN91x: MMU operation %04x timed-out\n", MmuOp));
    751       return EFI_TIMEOUT;
    752     }
    753     gBS->Stall (LAN91X_STALL);
    754   }
    755 
    756   return EFI_SUCCESS;
    757 }
    758 
    759 // Read bytes from the DATA register
    760 STATIC
    761 EFI_STATUS
    762 ReadIoData (
    763   IN  LAN91X_DRIVER *LanDriver,
    764   IN  VOID          *Buffer,
    765   IN  UINTN          BufLen
    766   )
    767 {
    768   UINT8     *Ptr;
    769 
    770   Ptr = Buffer;
    771   for (; BufLen > 0; --BufLen) {
    772     *Ptr = ReadIoReg8 (LanDriver, LAN91X_DATA0);
    773     ++Ptr;
    774   }
    775 
    776   return EFI_SUCCESS;
    777 }
    778 
    779 // Write bytes to the DATA register
    780 STATIC
    781 EFI_STATUS
    782 WriteIoData (
    783   IN  LAN91X_DRIVER *LanDriver,
    784   IN  VOID          *Buffer,
    785   IN  UINTN          BufLen
    786   )
    787 {
    788   UINT8     *Ptr;
    789 
    790   Ptr = Buffer;
    791   for (; BufLen > 0; --BufLen) {
    792     WriteIoReg8 (LanDriver, LAN91X_DATA0, *Ptr);
    793     ++Ptr;
    794   }
    795 
    796   return EFI_SUCCESS;
    797 }
    798 
    799 // Disable the interface
    800 STATIC
    801 EFI_STATUS
    802 ChipDisable (
    803   IN  LAN91X_DRIVER *LanDriver
    804   )
    805 {
    806 #ifdef LAN91X_POWER_DOWN
    807   UINT16  Val16;
    808 #endif
    809 
    810   // Stop Rx and Tx operations
    811   WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_CLEAR);
    812   WriteIoReg16 (LanDriver, LAN91X_TCR, TCR_CLEAR);
    813 
    814 #ifdef LAN91X_POWER_DOWN
    815   // Power-down the chip
    816   Val16 = ReadIoReg16 (LanDriver, LAN91X_CR);
    817   Val16 &= ~CR_EPH_POWER_EN;
    818   WriteIoReg16 (LanDriver, LAN91X_CR, Val16);
    819 #endif
    820 
    821   return EFI_SUCCESS;
    822 }
    823 
    824 // Enable the interface
    825 STATIC
    826 EFI_STATUS
    827 ChipEnable (
    828   IN  LAN91X_DRIVER *LanDriver
    829   )
    830 {
    831 #ifdef LAN91X_POWER_DOWN
    832   UINT16  Val16;
    833 
    834   // Power-up the chip
    835   Val16 = ReadIoReg16 (LanDriver, LAN91X_CR);
    836   Val16 |= CR_EPH_POWER_EN;
    837   WriteIoReg16 (LanDriver, LAN91X_CR, Val16);
    838   gBS->Stall (LAN91X_STALL);
    839 #endif
    840 
    841   // Start Rx and Tx operations
    842   WriteIoReg16 (LanDriver, LAN91X_TCR, TCR_DEFAULT);
    843   WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_DEFAULT);
    844 
    845   return EFI_SUCCESS;
    846 }
    847 
    848 
    849 // Perform software reset on the LAN91x
    850 STATIC
    851 EFI_STATUS
    852 SoftReset (
    853   IN  LAN91X_DRIVER   *LanDriver
    854   )
    855 {
    856   UINT16  Val16;
    857 
    858   // Issue the reset
    859   WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_SOFT_RST);
    860   gBS->Stall (LAN91X_STALL);
    861   WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_CLEAR);
    862 
    863   // Set the configuration register
    864   WriteIoReg16 (LanDriver, LAN91X_CR, CR_DEFAULT);
    865   gBS->Stall (LAN91X_STALL);
    866 
    867   // Stop Rx and Tx
    868   WriteIoReg16 (LanDriver, LAN91X_RCR, RCR_CLEAR);
    869   WriteIoReg16 (LanDriver, LAN91X_TCR, TCR_CLEAR);
    870 
    871   // Initialize the Control Register
    872   Val16 = ReadIoReg16 (LanDriver, LAN91X_CTR);
    873   Val16 |= CTR_AUTO_REL;
    874   WriteIoReg16 (LanDriver, LAN91X_CTR, Val16);
    875 
    876   // Reset the MMU
    877   MmuOperation (LanDriver, MMUCR_OP_RESET_MMU);
    878 
    879   return EFI_SUCCESS;
    880 }
    881 
    882 /*
    883 **  Probe()
    884 **
    885 **  Validate that there is a LAN91x device.
    886 **
    887 */
    888 STATIC
    889 EFI_STATUS
    890 Probe (
    891   IN  LAN91X_DRIVER   *LanDriver
    892   )
    893 {
    894   UINT16        Bank;
    895   UINT16        Val16;
    896   CHAR16 CONST *ChipId;
    897   UINTN         ResetTime;
    898 
    899   // First check that the Bank Select register is valid
    900   Bank = MmioRead16 (LanDriver->IoBase + LAN91X_BANK_OFFSET);
    901   if ((Bank & 0xff00) != 0x3300) {
    902     DEBUG((EFI_D_ERROR, "LAN91x: signature error: expecting 33xx, read %04x\n", Bank));
    903     return EFI_DEVICE_ERROR;
    904   }
    905 
    906   // Try reading the revision register next
    907   LanDriver->BankSel = 0xff;
    908   Val16 = ReadIoReg16 (LanDriver, LAN91X_REV);
    909 
    910   Bank = MmioRead16 (LanDriver->IoBase + LAN91X_BANK_OFFSET);
    911   if ((Bank & 0xff03) != 0x3303) {
    912     DEBUG((EFI_D_ERROR, "LAN91x: signature error: expecting 33x3, read %04x\n", Bank));
    913     return EFI_DEVICE_ERROR;
    914   }
    915 
    916   // Validate the revision register
    917   if ((Val16 & 0xff00) != 0x3300) {
    918     DEBUG((EFI_D_ERROR, "LAN91x: revision error: expecting 33xx, read %04x\n", Val16));
    919     return EFI_DEVICE_ERROR;
    920   }
    921 
    922   ChipId = ChipIds[(Val16 >> 4) & 0x0f];
    923   if (ChipId == NULL) {
    924     DEBUG((EFI_D_ERROR, "LAN91x: unrecognized revision: %04x\n", Val16));
    925     return EFI_DEVICE_ERROR;
    926   }
    927   DEBUG((EFI_D_ERROR, "LAN91x: detected chip %s rev %d\n", ChipId, Val16 & 0xf));
    928   LanDriver->Revision = Val16 & 0xff;
    929 
    930   // Reload from EEPROM to get the hardware MAC address
    931   WriteIoReg16 (LanDriver, LAN91X_CTR, CTR_RESERVED | CTR_RELOAD);
    932   ResetTime = 1000;
    933   while ((ReadIoReg16 (LanDriver, LAN91X_CTR) & CTR_RELOAD) != 0) {
    934     if (--ResetTime == 0) {
    935       DEBUG((EFI_D_ERROR, "LAN91x: reload from EEPROM timed-out\n"));
    936       WriteIoReg16 (LanDriver, LAN91X_CTR, CTR_RESERVED);
    937       return EFI_DEVICE_ERROR;
    938     }
    939     gBS->Stall (LAN91X_STALL);
    940   }
    941 
    942   // Read and save the Permanent MAC Address
    943   LanDriver->SnpMode.PermanentAddress = GetCurrentMacAddress (LanDriver);
    944   LanDriver->SnpMode.CurrentAddress = LanDriver->SnpMode.PermanentAddress;
    945   DEBUG((EFI_D_ERROR, //EFI_D_NET | EFI_D_INFO,
    946          "LAN91x: HW MAC Address: %02x-%02x-%02x-%02x-%02x-%02x\n",
    947          LanDriver->SnpMode.PermanentAddress.Addr[0],
    948          LanDriver->SnpMode.PermanentAddress.Addr[1],
    949          LanDriver->SnpMode.PermanentAddress.Addr[2],
    950          LanDriver->SnpMode.PermanentAddress.Addr[3],
    951          LanDriver->SnpMode.PermanentAddress.Addr[4],
    952          LanDriver->SnpMode.PermanentAddress.Addr[5]
    953          ));
    954 
    955   // Reset the device
    956   SoftReset (LanDriver);
    957 
    958   // Try to detect a PHY
    959   if (LanDriver->Revision > (CHIP_91100 << 4)) {
    960     PhyDetect (LanDriver);
    961   } else {
    962     LanDriver->PhyAd = LAN91X_NO_PHY;
    963   }
    964 
    965   return EFI_SUCCESS;
    966 }
    967 
    968 
    969 
    970 
    971 /*------------------ Simple Network Driver entry point functions ------------------*/
    972 
    973 // Refer to the Simple Network Protocol section (21.1)
    974 // in the UEFI 2.3.1 Specification for documentation.
    975 
    976 #define ReturnUnlock(s) do { Status = (s); goto exit_unlock; } while(0)
    977 
    978 
    979 /*
    980 **  UEFI Start() function
    981 **
    982 */
    983 EFI_STATUS
    984 EFIAPI
    985 SnpStart (
    986   IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
    987  )
    988 {
    989   EFI_SIMPLE_NETWORK_MODE *Mode;
    990   EFI_TPL                  SavedTpl;
    991   EFI_STATUS               Status;
    992 
    993   // Check Snp instance
    994   if (Snp == NULL) {
    995     return EFI_INVALID_PARAMETER;
    996   }
    997 
    998   // Serialize access to data and registers
    999   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1000   Mode = Snp->Mode;
   1001 
   1002   // Check state of the driver
   1003   switch (Mode->State) {
   1004   case EfiSimpleNetworkStopped:
   1005     break;
   1006   case EfiSimpleNetworkStarted:
   1007   case EfiSimpleNetworkInitialized:
   1008     DEBUG((EFI_D_WARN, "LAN91x: Driver already started\n"));
   1009     ReturnUnlock (EFI_ALREADY_STARTED);
   1010   default:
   1011     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1012           (UINTN)Snp->Mode->State));
   1013     ReturnUnlock (EFI_DEVICE_ERROR);
   1014   }
   1015 
   1016 
   1017   // Change state
   1018   Mode->State = EfiSimpleNetworkStarted;
   1019   Status = EFI_SUCCESS;
   1020 
   1021   // Restore TPL and return
   1022 exit_unlock:
   1023   gBS->RestoreTPL (SavedTpl);
   1024   return Status;
   1025 }
   1026 
   1027 /*
   1028 **  UEFI Stop() function
   1029 **
   1030 */
   1031 EFI_STATUS
   1032 EFIAPI
   1033 SnpStop (
   1034   IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
   1035   )
   1036 {
   1037   LAN91X_DRIVER *LanDriver;
   1038   EFI_TPL        SavedTpl;
   1039   EFI_STATUS     Status;
   1040 
   1041   // Check Snp Instance
   1042   if (Snp == NULL) {
   1043     return EFI_INVALID_PARAMETER;
   1044   }
   1045 
   1046   // Serialize access to data and registers
   1047   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1048 
   1049   // Check state of the driver
   1050   switch (Snp->Mode->State) {
   1051   case EfiSimpleNetworkStarted:
   1052   case EfiSimpleNetworkInitialized:
   1053     break;
   1054   case EfiSimpleNetworkStopped:
   1055     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1056     ReturnUnlock (EFI_NOT_STARTED);
   1057   default:
   1058     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1059           (UINTN)Snp->Mode->State));
   1060     ReturnUnlock (EFI_DEVICE_ERROR);
   1061   }
   1062 
   1063   // Find the LanDriver structure
   1064   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1065 
   1066   // Stop the Tx and Rx
   1067   ChipDisable (LanDriver);
   1068 
   1069   // Change the state
   1070   Snp->Mode->State = EfiSimpleNetworkStopped;
   1071   Status = EFI_SUCCESS;
   1072 
   1073   // Restore TPL and return
   1074 exit_unlock:
   1075   gBS->RestoreTPL (SavedTpl);
   1076   return Status;
   1077 }
   1078 
   1079 /*
   1080 **  UEFI Initialize() function
   1081 **
   1082 */
   1083 EFI_STATUS
   1084 EFIAPI
   1085 SnpInitialize (
   1086   IN  EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
   1087   IN  UINTN                        RxBufferSize    OPTIONAL,
   1088   IN  UINTN                        TxBufferSize    OPTIONAL
   1089   )
   1090 {
   1091   LAN91X_DRIVER *LanDriver;
   1092   EFI_TPL        SavedTpl;
   1093   EFI_STATUS     Status;
   1094 
   1095   // Check Snp Instance
   1096   if (Snp == NULL) {
   1097     return EFI_INVALID_PARAMETER;
   1098   }
   1099 
   1100   // Serialize access to data and registers
   1101   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1102 
   1103   // Check that driver was started but not initialised
   1104   switch (Snp->Mode->State) {
   1105   case EfiSimpleNetworkStarted:
   1106     break;
   1107   case EfiSimpleNetworkInitialized:
   1108     DEBUG((EFI_D_WARN, "LAN91x: Driver already initialized\n"));
   1109     ReturnUnlock (EFI_SUCCESS);
   1110   case EfiSimpleNetworkStopped:
   1111     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1112     ReturnUnlock (EFI_NOT_STARTED);
   1113   default:
   1114     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1115           (UINTN)Snp->Mode->State));
   1116     ReturnUnlock (EFI_DEVICE_ERROR);
   1117   }
   1118 
   1119   // Find the LanDriver structure
   1120   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1121 
   1122   // Initiate a software reset
   1123   Status = SoftReset (LanDriver);
   1124   if (EFI_ERROR(Status)) {
   1125     DEBUG((EFI_D_WARN, "LAN91x: Soft reset failed\n"));
   1126     ReturnUnlock (EFI_DEVICE_ERROR);
   1127   }
   1128 
   1129   // Initiate a PHY reset
   1130   if (PhySoftReset (LanDriver) < 0) {
   1131     Snp->Mode->State = EfiSimpleNetworkStopped;
   1132     DEBUG((EFI_D_WARN, "LAN91x: PHY soft reset timeout\n"));
   1133     ReturnUnlock (EFI_NOT_STARTED);
   1134   }
   1135 
   1136   // Do auto-negotiation
   1137   Status = PhyAutoNegotiate (LanDriver);
   1138   if (EFI_ERROR(Status)) {
   1139     DEBUG((EFI_D_WARN, "LAN91x: PHY auto-negotiation failed\n"));
   1140   }
   1141 
   1142   // Enable the receiver and transmitter
   1143   ChipEnable (LanDriver);
   1144 
   1145   // Now acknowledge all interrupts
   1146   WriteIoReg8 (LanDriver, LAN91X_IST, 0xFF);
   1147 
   1148   // Declare the driver as initialized
   1149   Snp->Mode->State = EfiSimpleNetworkInitialized;
   1150   Status = EFI_SUCCESS;
   1151 
   1152   // Restore TPL and return
   1153 exit_unlock:
   1154   gBS->RestoreTPL (SavedTpl);
   1155   return Status;
   1156 }
   1157 
   1158 /*
   1159 **  UEFI Reset () function
   1160 **
   1161 */
   1162 EFI_STATUS
   1163 EFIAPI
   1164 SnpReset (
   1165   IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
   1166   IN        BOOLEAN Verification
   1167   )
   1168 {
   1169   LAN91X_DRIVER *LanDriver;
   1170   EFI_TPL        SavedTpl;
   1171   EFI_STATUS     Status;
   1172 
   1173   // Check Snp Instance
   1174   if (Snp == NULL) {
   1175     return EFI_INVALID_PARAMETER;
   1176   }
   1177 
   1178   // Serialize access to data and registers
   1179   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1180 
   1181   // Check that driver was started and initialised
   1182   switch (Snp->Mode->State) {
   1183   case EfiSimpleNetworkInitialized:
   1184     break;
   1185   case EfiSimpleNetworkStarted:
   1186     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1187     ReturnUnlock (EFI_DEVICE_ERROR);
   1188   case EfiSimpleNetworkStopped:
   1189     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1190     ReturnUnlock (EFI_NOT_STARTED);
   1191   default:
   1192     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1193           (UINTN)Snp->Mode->State));
   1194     ReturnUnlock (EFI_DEVICE_ERROR);
   1195   }
   1196 
   1197   // Find the LanDriver structure
   1198   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1199 
   1200   // Initiate a software reset
   1201   if (EFI_ERROR (SoftReset (LanDriver))) {
   1202     DEBUG((EFI_D_WARN, "LAN91x: Soft reset failed\n"));
   1203     ReturnUnlock (EFI_DEVICE_ERROR);
   1204   }
   1205 
   1206   // Initiate a PHY reset
   1207   if (EFI_ERROR (PhySoftReset (LanDriver))) {
   1208     DEBUG((EFI_D_WARN, "LAN91x: PHY soft reset failed\n"));
   1209     ReturnUnlock (EFI_DEVICE_ERROR);
   1210   }
   1211 
   1212   // Enable the receiver and transmitter
   1213   Status = ChipEnable (LanDriver);
   1214 
   1215   // Restore TPL and return
   1216 exit_unlock:
   1217   gBS->RestoreTPL (SavedTpl);
   1218   return Status;
   1219 }
   1220 
   1221 /*
   1222 **  UEFI Shutdown () function
   1223 **
   1224 */
   1225 EFI_STATUS
   1226 EFIAPI
   1227 SnpShutdown (
   1228   IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp
   1229   )
   1230 {
   1231   LAN91X_DRIVER *LanDriver;
   1232   EFI_TPL        SavedTpl;
   1233   EFI_STATUS     Status;
   1234 
   1235   // Check Snp Instance
   1236   if (Snp == NULL) {
   1237     return EFI_INVALID_PARAMETER;
   1238   }
   1239 
   1240   // Serialize access to data and registers
   1241   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1242 
   1243   // First check that driver has already been initialized
   1244   switch (Snp->Mode->State) {
   1245   case EfiSimpleNetworkInitialized:
   1246     break;
   1247   case EfiSimpleNetworkStarted:
   1248     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1249     ReturnUnlock (EFI_DEVICE_ERROR);
   1250   case EfiSimpleNetworkStopped:
   1251     DEBUG((EFI_D_WARN, "LAN91x: Driver in stopped state\n"));
   1252     ReturnUnlock (EFI_NOT_STARTED);
   1253   default:
   1254     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1255           (UINTN)Snp->Mode->State));
   1256     ReturnUnlock (EFI_DEVICE_ERROR);
   1257   }
   1258 
   1259   // Find the LanDriver structure
   1260   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1261 
   1262   // Disable the interface
   1263   Status = ChipDisable (LanDriver);
   1264 
   1265   // Restore TPL and return
   1266 exit_unlock:
   1267   gBS->RestoreTPL (SavedTpl);
   1268   return Status;
   1269 }
   1270 
   1271 
   1272 /*
   1273 **  UEFI ReceiveFilters() function
   1274 **
   1275 */
   1276 EFI_STATUS
   1277 EFIAPI
   1278 SnpReceiveFilters (
   1279   IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
   1280   IN        UINT32 Enable,
   1281   IN        UINT32 Disable,
   1282   IN        BOOLEAN Reset,
   1283   IN        UINTN NumMfilter          OPTIONAL,
   1284   IN        EFI_MAC_ADDRESS *Mfilter  OPTIONAL
   1285   )
   1286 {
   1287 #define MCAST_HASH_BYTES  8
   1288 
   1289   LAN91X_DRIVER           *LanDriver;
   1290   EFI_SIMPLE_NETWORK_MODE *SnpMode;
   1291   EFI_TPL        SavedTpl;
   1292   EFI_STATUS     Status;
   1293   UINTN          i;
   1294   UINT32         Crc;
   1295   UINT16         RcvCtrl;
   1296   UINT8          McastHash[MCAST_HASH_BYTES];
   1297 
   1298   // Check Snp Instance
   1299   if (Snp == NULL) {
   1300     return EFI_INVALID_PARAMETER;
   1301   }
   1302 
   1303   // Serialize access to data and registers
   1304   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1305 
   1306   // First check that driver has already been initialized
   1307   switch (Snp->Mode->State) {
   1308   case EfiSimpleNetworkInitialized:
   1309     break;
   1310   case EfiSimpleNetworkStarted:
   1311     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1312     ReturnUnlock (EFI_DEVICE_ERROR);
   1313   case EfiSimpleNetworkStopped:
   1314     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1315     ReturnUnlock (EFI_NOT_STARTED);
   1316   default:
   1317     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1318           (UINTN)Snp->Mode->State));
   1319     ReturnUnlock (EFI_DEVICE_ERROR);
   1320   }
   1321 
   1322   // Find the LanDriver structure
   1323   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1324   SnpMode = Snp->Mode;
   1325 
   1326 #ifdef LAN91X_PRINT_RECEIVE_FILTERS
   1327   DEBUG((EFI_D_ERROR, "LAN91x:SnpReceiveFilters()\n"));
   1328   DEBUG((EFI_D_ERROR, "  Enable     = %08x\n", Enable));
   1329   DEBUG((EFI_D_ERROR, "  Disable    = %08x\n", Disable));
   1330   DEBUG((EFI_D_ERROR, "  Reset      = %d\n",  Reset));
   1331   DEBUG((EFI_D_ERROR, "  NumMfilter = %d\n",  NumMfilter));
   1332   for (i = 0; i < NumMfilter; ++i) {
   1333     DEBUG((EFI_D_ERROR,
   1334            "    [%2d] = %02x-%02x-%02x-%02x-%02x-%02x\n",
   1335            i,
   1336            Mfilter[i].Addr[0],
   1337            Mfilter[i].Addr[1],
   1338            Mfilter[i].Addr[2],
   1339            Mfilter[i].Addr[3],
   1340            Mfilter[i].Addr[4],
   1341            Mfilter[i].Addr[5]));
   1342   }
   1343 #endif
   1344 
   1345   // Update the Multicast Hash registers
   1346   if (Reset) {
   1347     // Clear the hash table
   1348     SetMem (McastHash, MCAST_HASH_BYTES, 0);
   1349     SnpMode->MCastFilterCount = 0;
   1350   } else {
   1351     // Read the current hash table
   1352     for (i = 0; i < MCAST_HASH_BYTES; ++i) {
   1353       McastHash[i] = ReadIoReg8 (LanDriver, LAN91X_MT0 + i);
   1354     }
   1355     // Set the new additions
   1356     for (i = 0; i < NumMfilter; ++i) {
   1357       Crc = MulticastHash (&Mfilter[i], NET_ETHER_ADDR_LEN);
   1358       McastHash[(Crc >> 29) & 0x3] |= 1 << ((Crc >> 26) & 0x3);
   1359     }
   1360     SnpMode->MCastFilterCount = NumMfilter;
   1361   }
   1362   // If the hash registers need updating, write them
   1363   if (Reset || NumMfilter > 0) {
   1364     for (i = 0; i < MCAST_HASH_BYTES; ++i) {
   1365       WriteIoReg8 (LanDriver, LAN91X_MT0 + i, McastHash[i]);
   1366     }
   1367   }
   1368 
   1369   RcvCtrl = ReadIoReg16 (LanDriver, LAN91X_RCR);
   1370   if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
   1371     RcvCtrl |= RCR_PRMS;
   1372     SnpMode->ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
   1373   }
   1374   if ((Disable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
   1375     RcvCtrl &= ~RCR_PRMS;
   1376     SnpMode->ReceiveFilterSetting &= ~EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
   1377   }
   1378 
   1379   if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
   1380     RcvCtrl |= RCR_ALMUL;
   1381     SnpMode->ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
   1382   }
   1383   if ((Disable & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
   1384     RcvCtrl &= ~RCR_ALMUL;
   1385     SnpMode->ReceiveFilterSetting &= ~EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
   1386   }
   1387   WriteIoReg16 (LanDriver, LAN91X_RCR, RcvCtrl);
   1388 
   1389   Status = SetCurrentMacAddress (LanDriver, &SnpMode->CurrentAddress);
   1390 
   1391   // Restore TPL and return
   1392 exit_unlock:
   1393   gBS->RestoreTPL (SavedTpl);
   1394   return Status;
   1395 }
   1396 
   1397 /*
   1398 **  UEFI StationAddress() function
   1399 **
   1400 */
   1401 EFI_STATUS
   1402 EFIAPI
   1403 SnpStationAddress (
   1404   IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
   1405   IN        BOOLEAN Reset,
   1406   IN        EFI_MAC_ADDRESS *NewMac
   1407 )
   1408 {
   1409   LAN91X_DRIVER *LanDriver;
   1410   EFI_TPL        SavedTpl;
   1411   EFI_STATUS     Status;
   1412 
   1413   // Check Snp instance
   1414   if (Snp == NULL) {
   1415     return EFI_INVALID_PARAMETER;
   1416   }
   1417 
   1418   // Serialize access to data and registers
   1419   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1420 
   1421   // Check that driver was started and initialised
   1422   switch (Snp->Mode->State) {
   1423   case EfiSimpleNetworkInitialized:
   1424     break;
   1425   case EfiSimpleNetworkStarted:
   1426     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1427     ReturnUnlock (EFI_DEVICE_ERROR);
   1428   case EfiSimpleNetworkStopped:
   1429     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1430     ReturnUnlock (EFI_NOT_STARTED);
   1431   default:
   1432     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1433           (UINTN)Snp->Mode->State));
   1434     ReturnUnlock (EFI_DEVICE_ERROR);
   1435   }
   1436 
   1437   // Find the LanDriver structure
   1438   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1439 
   1440   if (Reset) {
   1441     Snp->Mode->CurrentAddress = Snp->Mode->PermanentAddress;
   1442   } else {
   1443     if (NewMac == NULL) {
   1444       ReturnUnlock (EFI_INVALID_PARAMETER);
   1445     }
   1446     Snp->Mode->CurrentAddress = *NewMac;
   1447   }
   1448 
   1449   Status = SetCurrentMacAddress (LanDriver, &Snp->Mode->CurrentAddress);
   1450 
   1451   // Restore TPL and return
   1452 exit_unlock:
   1453   gBS->RestoreTPL (SavedTpl);
   1454   return Status;
   1455 }
   1456 
   1457 /*
   1458 **  UEFI Statistics() function
   1459 **
   1460 */
   1461 EFI_STATUS
   1462 EFIAPI
   1463 SnpStatistics (
   1464   IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
   1465   IN        BOOLEAN Reset,
   1466   IN  OUT   UINTN *StatSize,
   1467       OUT   EFI_NETWORK_STATISTICS *Statistics
   1468   )
   1469 {
   1470   LAN91X_DRIVER *LanDriver;
   1471   EFI_TPL        SavedTpl;
   1472   EFI_STATUS     Status;
   1473 
   1474   // Check Snp instance
   1475   if (Snp == NULL) {
   1476     return EFI_INVALID_PARAMETER;
   1477   }
   1478 
   1479   // Check pointless condition
   1480   if ((!Reset) && (StatSize == NULL) && (Statistics == NULL)) {
   1481     return EFI_SUCCESS;
   1482   }
   1483 
   1484   // Check the parameters
   1485   if ((StatSize == NULL) && (Statistics != NULL)) {
   1486     return EFI_INVALID_PARAMETER;
   1487   }
   1488 
   1489   // Serialize access to data and registers
   1490   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1491 
   1492   // Check that driver was started and initialised
   1493   switch (Snp->Mode->State) {
   1494   case EfiSimpleNetworkInitialized:
   1495     break;
   1496   case EfiSimpleNetworkStarted:
   1497     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1498     ReturnUnlock (EFI_DEVICE_ERROR);
   1499   case EfiSimpleNetworkStopped:
   1500     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1501     ReturnUnlock (EFI_NOT_STARTED);
   1502   default:
   1503     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1504           (UINTN)Snp->Mode->State));
   1505     ReturnUnlock (EFI_DEVICE_ERROR);
   1506   }
   1507 
   1508   // Find the LanDriver structure
   1509   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1510 
   1511   // Do a reset if required
   1512   if (Reset) {
   1513     ZeroMem (&LanDriver->Stats, sizeof(EFI_NETWORK_STATISTICS));
   1514   }
   1515 
   1516   // Check buffer size
   1517   if (*StatSize < sizeof(EFI_NETWORK_STATISTICS)) {
   1518     *StatSize = sizeof(EFI_NETWORK_STATISTICS);
   1519     ReturnUnlock (EFI_BUFFER_TOO_SMALL);
   1520     goto exit_unlock;
   1521   }
   1522 
   1523   // Fill in the statistics
   1524   CopyMem(&Statistics, &LanDriver->Stats, sizeof(EFI_NETWORK_STATISTICS));
   1525   Status = EFI_SUCCESS;
   1526 
   1527   // Restore TPL and return
   1528 exit_unlock:
   1529   gBS->RestoreTPL (SavedTpl);
   1530   return Status;
   1531 }
   1532 
   1533 /*
   1534 **  UEFI MCastIPtoMAC() function
   1535 **
   1536 */
   1537 EFI_STATUS
   1538 EFIAPI
   1539 SnpMcastIptoMac (
   1540   IN        EFI_SIMPLE_NETWORK_PROTOCOL* Snp,
   1541   IN        BOOLEAN IsIpv6,
   1542   IN        EFI_IP_ADDRESS *Ip,
   1543       OUT   EFI_MAC_ADDRESS *McastMac
   1544   )
   1545 {
   1546   // Check Snp instance
   1547   if (Snp == NULL) {
   1548     return EFI_INVALID_PARAMETER;
   1549   }
   1550 
   1551   // Check parameters
   1552   if ((McastMac == NULL) || (Ip == NULL)) {
   1553     return EFI_INVALID_PARAMETER;
   1554   }
   1555 
   1556   // Make sure MAC address is empty
   1557   ZeroMem (McastMac, sizeof(EFI_MAC_ADDRESS));
   1558 
   1559   // If we need ipv4 address
   1560   if (!IsIpv6) {
   1561     // Most significant 25 bits of a multicast HW address are set
   1562     McastMac->Addr[0] = 0x01;
   1563     McastMac->Addr[1] = 0x00;
   1564     McastMac->Addr[2] = 0x5E;
   1565 
   1566     // Lower 23 bits from ipv4 address
   1567     McastMac->Addr[3] = (Ip->v4.Addr[1] & 0x7F); // Clear the ms bit (25th bit of MAC must be 0)
   1568     McastMac->Addr[4] = Ip->v4.Addr[2];
   1569     McastMac->Addr[5] = Ip->v4.Addr[3];
   1570   } else {
   1571     // Most significant 16 bits of multicast v6 HW address are set
   1572     McastMac->Addr[0] = 0x33;
   1573     McastMac->Addr[1] = 0x33;
   1574 
   1575     // lower four octets are taken from ipv6 address
   1576     McastMac->Addr[2] = Ip->v6.Addr[8];
   1577     McastMac->Addr[3] = Ip->v6.Addr[9];
   1578     McastMac->Addr[4] = Ip->v6.Addr[10];
   1579     McastMac->Addr[5] = Ip->v6.Addr[11];
   1580   }
   1581 
   1582   return EFI_SUCCESS;
   1583 }
   1584 
   1585 /*
   1586 **  UEFI NvData() function
   1587 **
   1588 */
   1589 EFI_STATUS
   1590 EFIAPI
   1591 SnpNvData (
   1592   IN        EFI_SIMPLE_NETWORK_PROTOCOL* pobj,
   1593   IN        BOOLEAN read_write,
   1594   IN        UINTN offset,
   1595   IN        UINTN buff_size,
   1596   IN  OUT   VOID *data
   1597   )
   1598 {
   1599   DEBUG((EFI_D_ERROR, "LAN91x: Non-volatile storage not supported\n"));
   1600 
   1601   return EFI_UNSUPPORTED;
   1602 }
   1603 
   1604 
   1605 /*
   1606 **  UEFI GetStatus () function
   1607 **
   1608 */
   1609 EFI_STATUS
   1610 EFIAPI
   1611 SnpGetStatus (
   1612   IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
   1613       OUT   UINT32   *IrqStat   OPTIONAL,
   1614       OUT   VOID    **TxBuff    OPTIONAL
   1615   )
   1616 {
   1617   LAN91X_DRIVER         *LanDriver;
   1618   EFI_TPL               SavedTpl;
   1619   EFI_STATUS            Status;
   1620   BOOLEAN               MediaPresent;
   1621   UINT8                 IstReg;
   1622   MSK_LINKED_SYSTEM_BUF *LinkedTXRecycleBuff;
   1623 
   1624   // Check preliminaries
   1625   if (Snp == NULL) {
   1626     return EFI_INVALID_PARAMETER;
   1627   }
   1628 
   1629   // Serialize access to data and registers
   1630   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1631 
   1632   // Check that driver was started and initialised
   1633   switch (Snp->Mode->State) {
   1634   case EfiSimpleNetworkInitialized:
   1635     break;
   1636   case EfiSimpleNetworkStarted:
   1637     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1638     ReturnUnlock (EFI_DEVICE_ERROR);
   1639   case EfiSimpleNetworkStopped:
   1640     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1641     ReturnUnlock (EFI_NOT_STARTED);
   1642   default:
   1643     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1644           (UINTN)Snp->Mode->State));
   1645     ReturnUnlock (EFI_DEVICE_ERROR);
   1646   }
   1647 
   1648   // Find the LanDriver structure
   1649   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1650 
   1651   // Arbitrarily set the interrupt status to 0
   1652   if (IrqStat != NULL) {
   1653     *IrqStat = 0;
   1654     IstReg = ReadIoReg8 (LanDriver, LAN91X_IST);
   1655     if ((IstReg & IST_RCV) != 0) {
   1656       *IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
   1657     }
   1658     if ((IstReg & IST_TX) != 0) {
   1659       *IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
   1660     }
   1661   }
   1662 
   1663   // Pass back the completed buffer address
   1664   // The transmit buffer status is not read when TxBuf is NULL
   1665   if (TxBuff != NULL) {
   1666     *((UINT8 **) TxBuff) = (UINT8 *) 0;
   1667     if( !IsListEmpty (&LanDriver->TransmitQueueHead))
   1668     {
   1669       LinkedTXRecycleBuff = CR (GetFirstNode (&LanDriver->TransmitQueueHead), MSK_LINKED_SYSTEM_BUF, Link, TX_MBUF_SIGNATURE);
   1670       if(LinkedTXRecycleBuff != NULL) {
   1671         *TxBuff = LinkedTXRecycleBuff->SystemBuf.Buf;
   1672         RemoveEntryList (&LinkedTXRecycleBuff->Link);
   1673         FreePool (LinkedTXRecycleBuff);
   1674       }
   1675     }
   1676   }
   1677 
   1678   // Update the media status
   1679   MediaPresent = CheckLinkStatus (LanDriver);
   1680   if (MediaPresent != Snp->Mode->MediaPresent) {
   1681     DEBUG((EFI_D_WARN, "LAN91x: Link %s\n", MediaPresent ? L"up" : L"down"));
   1682   }
   1683   Snp->Mode->MediaPresent = MediaPresent;
   1684   Status = EFI_SUCCESS;
   1685 
   1686   // Restore TPL and return
   1687 exit_unlock:
   1688   gBS->RestoreTPL (SavedTpl);
   1689   return Status;
   1690 }
   1691 
   1692 
   1693 /*
   1694 **  UEFI Transmit() function
   1695 **
   1696 */
   1697 EFI_STATUS
   1698 EFIAPI
   1699 SnpTransmit (
   1700   IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
   1701   IN        UINTN            HdrSize,
   1702   IN        UINTN            BufSize,
   1703   IN        VOID            *BufAddr,
   1704   IN        EFI_MAC_ADDRESS *SrcAddr    OPTIONAL,
   1705   IN        EFI_MAC_ADDRESS *DstAddr    OPTIONAL,
   1706   IN        UINT16          *Protocol   OPTIONAL
   1707   )
   1708 {
   1709   LAN91X_DRIVER   *LanDriver;
   1710   EFI_TPL          SavedTpl;
   1711   EFI_STATUS       Status;
   1712   UINT8           *Ptr;
   1713   UINTN            Len;
   1714   UINTN            MmuPages;
   1715   UINTN            Retries;
   1716   UINT16           Proto;
   1717   UINT8            PktNum;
   1718   MSK_LINKED_SYSTEM_BUF   *LinkedTXRecycleBuff;
   1719 
   1720 
   1721   // Check preliminaries
   1722   if ((Snp == NULL) || (BufAddr == NULL)) {
   1723     DEBUG((EFI_D_ERROR, "LAN91x: SnpTransmit(): NULL Snp (%p) or BufAddr (%p)\n",
   1724         Snp, BufAddr));
   1725     return EFI_INVALID_PARAMETER;
   1726   }
   1727 
   1728   // Serialize access to data and registers
   1729   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1730 
   1731   // Check that driver was started and initialised
   1732   switch (Snp->Mode->State) {
   1733   case EfiSimpleNetworkInitialized:
   1734     break;
   1735   case EfiSimpleNetworkStarted:
   1736     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1737     ReturnUnlock (EFI_DEVICE_ERROR);
   1738   case EfiSimpleNetworkStopped:
   1739     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1740     ReturnUnlock (EFI_NOT_STARTED);
   1741   default:
   1742     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1743           (UINTN)Snp->Mode->State));
   1744     ReturnUnlock (EFI_DEVICE_ERROR);
   1745   }
   1746 
   1747   // Find the LanDriver structure
   1748   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1749 
   1750   // Ensure header is correct size if non-zero
   1751   if (HdrSize != 0) {
   1752     if (HdrSize != Snp->Mode->MediaHeaderSize) {
   1753       DEBUG((EFI_D_ERROR, "LAN91x: SnpTransmit(): Invalid HdrSize %d\n", HdrSize));
   1754       ReturnUnlock (EFI_INVALID_PARAMETER);
   1755     }
   1756 
   1757     if ((DstAddr == NULL) || (Protocol == NULL)) {
   1758       DEBUG((EFI_D_ERROR, "LAN91x: SnpTransmit(): NULL DstAddr %p or Protocol %p\n",
   1759           DstAddr, Protocol));
   1760       ReturnUnlock (EFI_INVALID_PARAMETER);
   1761     }
   1762   }
   1763 
   1764   // Before transmitting check the link status
   1765   if (!Snp->Mode->MediaPresent) {
   1766     DEBUG((EFI_D_WARN, "LAN91x: SnpTransmit(): Link not ready\n"));
   1767     ReturnUnlock (EFI_NOT_READY);
   1768   }
   1769 
   1770   // Calculate the request size in 256-byte "pages" minus 1
   1771   // The 91C111 ignores this, but some older devices need it.
   1772   MmuPages = ((BufSize & ~1) + LAN91X_PKT_OVERHEAD - 1) >> 8;
   1773   if (MmuPages > 7) {
   1774     DEBUG((EFI_D_WARN, "LAN91x: Tx buffer too large (%d bytes)\n", BufSize));
   1775     LanDriver->Stats.TxOversizeFrames += 1;
   1776     LanDriver->Stats.TxDroppedFrames += 1;
   1777     ReturnUnlock (EFI_BAD_BUFFER_SIZE);
   1778   }
   1779 
   1780   // Request allocation of a transmit buffer
   1781   Status = MmuOperation (LanDriver, MMUCR_OP_TX_ALLOC | MmuPages);
   1782   if (EFI_ERROR (Status)) {
   1783     DEBUG((EFI_D_ERROR, "LAN91x: Tx buffer request failure: %d\n", Status));
   1784     ReturnUnlock (EFI_DEVICE_ERROR);
   1785   }
   1786 
   1787   // Wait for allocation request completion
   1788   Retries = LAN91X_MEMORY_ALLOC_POLLS;
   1789   while ((ReadIoReg8 (LanDriver, LAN91X_IST) & IST_ALLOC) == 0) {
   1790     if (--Retries == 0) {
   1791       DEBUG((EFI_D_ERROR, "LAN91x: Tx buffer allocation timeout\n"));
   1792       ReturnUnlock (EFI_TIMEOUT);
   1793     }
   1794   }
   1795 
   1796   // Check for successful allocation
   1797   PktNum = ReadIoReg8 (LanDriver, LAN91X_ARR);
   1798   if ((PktNum & ARR_FAILED) != 0) {
   1799     DEBUG((EFI_D_ERROR, "LAN91x: Tx buffer allocation failure: %02x\n", PktNum));
   1800     ReturnUnlock (EFI_NOT_READY);
   1801   }
   1802   PktNum &= ARR_PACKET;
   1803 
   1804   // Check for the nature of the frame
   1805   // If no destination address, it's ARP broadcast
   1806   if(DstAddr != NULL)
   1807   {
   1808     if (DstAddr->Addr[0] == 0xFF) {
   1809       LanDriver->Stats.TxBroadcastFrames += 1;
   1810     } else if ((DstAddr->Addr[0] & 0x1) == 1) {
   1811       LanDriver->Stats.TxMulticastFrames += 1;
   1812     } else {
   1813       LanDriver->Stats.TxUnicastFrames += 1;
   1814     }
   1815   } else {
   1816     LanDriver->Stats.TxBroadcastFrames += 1;
   1817   }
   1818 
   1819   // Set the Packet Number and Pointer registers
   1820   WriteIoReg8 (LanDriver, LAN91X_PNR, PktNum);
   1821   WriteIoReg16 (LanDriver, LAN91X_PTR, PTR_AUTO_INCR);
   1822 
   1823   // Set up mutable buffer information variables
   1824   Ptr = BufAddr;
   1825   Len = BufSize;
   1826 
   1827   // Write Status and Byte Count first
   1828   WriteIoReg16 (LanDriver, LAN91X_DATA0, 0);
   1829   WriteIoReg16 (LanDriver, LAN91X_DATA0, (Len + LAN91X_PKT_OVERHEAD) & BCW_COUNT);
   1830 
   1831   // This packet may come with a preconfigured Ethernet header.
   1832   // If not, we need to construct one from optional parameters.
   1833   if (HdrSize) {
   1834 
   1835     // Write the destination address
   1836     WriteIoData (LanDriver, DstAddr, NET_ETHER_ADDR_LEN);
   1837 
   1838     // Write the Source Address
   1839     if (SrcAddr != NULL) {
   1840       WriteIoData (LanDriver, SrcAddr, NET_ETHER_ADDR_LEN);
   1841     } else {
   1842       WriteIoData (LanDriver, &LanDriver->SnpMode.CurrentAddress, NET_ETHER_ADDR_LEN);
   1843     }
   1844 
   1845     // Write the Protocol word
   1846     Proto = HTONS (*Protocol);
   1847     WriteIoReg16 (LanDriver, LAN91X_DATA0, Proto);
   1848 
   1849     // Adjust the data start and length
   1850     Ptr += sizeof(ETHER_HEAD);
   1851     Len -= sizeof(ETHER_HEAD);
   1852   }
   1853 
   1854   // Copy the remainder data buffer, except the odd byte
   1855   WriteIoData (LanDriver, Ptr, Len & ~1);
   1856   Ptr += Len & ~1;
   1857   Len &= 1;
   1858 
   1859   // Write the Packet Control Word and odd byte
   1860   WriteIoReg16 (LanDriver, LAN91X_DATA0,
   1861       (Len != 0) ? (PCW_ODD | PCW_CRC | *Ptr) : PCW_CRC);
   1862 
   1863   // Release the packet for transmission
   1864   Status = MmuOperation (LanDriver, MMUCR_OP_TX_PUSH);
   1865   if (EFI_ERROR (Status)) {
   1866     DEBUG((EFI_D_ERROR, "LAN91x: Tx buffer release failure: %d\n", Status));
   1867     ReturnUnlock (EFI_DEVICE_ERROR);
   1868   }
   1869 
   1870   // Update the Tx statistics
   1871   LanDriver->Stats.TxTotalBytes += BufSize;
   1872   LanDriver->Stats.TxGoodFrames += 1;
   1873 
   1874   // Update the Tx Buffer cache
   1875   LinkedTXRecycleBuff = AllocateZeroPool (sizeof (MSK_LINKED_SYSTEM_BUF));
   1876   if (LinkedTXRecycleBuff == NULL) {
   1877     return EFI_OUT_OF_RESOURCES;
   1878   }
   1879   LinkedTXRecycleBuff->Signature = TX_MBUF_SIGNATURE;
   1880   //
   1881   // Add the passed Buffer to the transmit queue. Don't copy.
   1882   //
   1883   LinkedTXRecycleBuff->SystemBuf.Buf = BufAddr;
   1884   LinkedTXRecycleBuff->SystemBuf.Length = BufSize;
   1885   InsertTailList (&LanDriver->TransmitQueueHead, &LinkedTXRecycleBuff->Link);
   1886 
   1887   Status = EFI_SUCCESS;
   1888 
   1889   // Dump the packet header
   1890 #if LAN91X_PRINT_PACKET_HEADERS
   1891   Ptr = BufAddr;
   1892   DEBUG((EFI_D_ERROR, "LAN91X:SnpTransmit()\n"));
   1893   DEBUG((EFI_D_ERROR, "  HdrSize: %d, SrcAddr: %p, Length: %d, Last byte: %02x\n",
   1894          HdrSize, SrcAddr, BufSize, Ptr[BufSize - 1]));
   1895   PrintIpDgram (
   1896       (HdrSize == 0) ? (EFI_MAC_ADDRESS *)&Ptr[0] : DstAddr,
   1897       (HdrSize == 0) ? (EFI_MAC_ADDRESS *)&Ptr[6] : (SrcAddr != NULL) ? SrcAddr : &LanDriver->SnpMode.CurrentAddress,
   1898       (HdrSize == 0) ? (UINT16 *)&Ptr[12] : &Proto,
   1899       &Ptr[14]
   1900       );
   1901 #endif
   1902 
   1903   // Restore TPL and return
   1904 exit_unlock:
   1905   gBS->RestoreTPL (SavedTpl);
   1906   return Status;
   1907 }
   1908 
   1909 
   1910 /*
   1911 **  UEFI Receive() function
   1912 **
   1913 */
   1914 EFI_STATUS
   1915 EFIAPI
   1916 SnpReceive (
   1917   IN        EFI_SIMPLE_NETWORK_PROTOCOL *Snp,
   1918       OUT   UINTN           *HdrSize      OPTIONAL,
   1919   IN  OUT   UINTN           *BuffSize,
   1920       OUT   VOID            *Data,
   1921       OUT   EFI_MAC_ADDRESS *SrcAddr      OPTIONAL,
   1922       OUT   EFI_MAC_ADDRESS *DstAddr      OPTIONAL,
   1923       OUT   UINT16 *Protocol              OPTIONAL
   1924   )
   1925 {
   1926   EFI_TPL        SavedTpl;
   1927   EFI_STATUS     Status;
   1928   LAN91X_DRIVER *LanDriver;
   1929   UINT8         *DataPtr;
   1930   UINT16         PktStatus;
   1931   UINT16         PktLength;
   1932   UINT16         PktControl;
   1933   UINT8          IstReg;
   1934 
   1935   // Check preliminaries
   1936   if ((Snp == NULL) || (Data == NULL)) {
   1937     return EFI_INVALID_PARAMETER;
   1938   }
   1939 
   1940   // Serialize access to data and registers
   1941   SavedTpl = gBS->RaiseTPL (LAN91X_TPL);
   1942 
   1943   // Check that driver was started and initialised
   1944   switch (Snp->Mode->State) {
   1945   case EfiSimpleNetworkInitialized:
   1946     break;
   1947   case EfiSimpleNetworkStarted:
   1948     DEBUG((EFI_D_WARN, "LAN91x: Driver not yet initialized\n"));
   1949     ReturnUnlock (EFI_DEVICE_ERROR);
   1950   case EfiSimpleNetworkStopped:
   1951     DEBUG((EFI_D_WARN, "LAN91x: Driver not started\n"));
   1952     ReturnUnlock (EFI_NOT_STARTED);
   1953   default:
   1954     DEBUG((EFI_D_ERROR, "LAN91x: Driver in an invalid state: %u\n",
   1955           (UINTN)Snp->Mode->State));
   1956     ReturnUnlock (EFI_DEVICE_ERROR);
   1957   }
   1958 
   1959   // Find the LanDriver structure
   1960   LanDriver = INSTANCE_FROM_SNP_THIS(Snp);
   1961 
   1962   // Check for Rx Overrun
   1963   IstReg = ReadIoReg8 (LanDriver, LAN91X_IST);
   1964   if ((IstReg & IST_RX_OVRN) != 0) {
   1965     LanDriver->Stats.RxTotalFrames += 1;
   1966     LanDriver->Stats.RxDroppedFrames += 1;
   1967     WriteIoReg8 (LanDriver, LAN91X_IST, IST_RX_OVRN);
   1968     DEBUG((EFI_D_WARN, "LAN91x: Receiver overrun\n"));
   1969   }
   1970 
   1971   // Check for Rx data available
   1972   if ((IstReg & IST_RCV) == 0) {
   1973     ReturnUnlock (EFI_NOT_READY);
   1974   }
   1975 
   1976   // Configure the PTR register for reading
   1977   WriteIoReg16 (LanDriver, LAN91X_PTR, PTR_RCV | PTR_AUTO_INCR | PTR_READ);
   1978 
   1979   // Read the Packet Status and Packet Length words
   1980   PktStatus = ReadIoReg16 (LanDriver, LAN91X_DATA0);
   1981   PktLength = ReadIoReg16 (LanDriver, LAN91X_DATA0) & BCW_COUNT;
   1982 
   1983   // Check for valid received packet
   1984   if ((PktStatus == 0) && (PktLength == 0)) {
   1985     DEBUG((EFI_D_WARN, "LAN91x: Received zero-length packet. IST=%04x\n", IstReg));
   1986     ReturnUnlock (EFI_NOT_READY);
   1987   }
   1988   LanDriver->Stats.RxTotalFrames += 1;
   1989 
   1990   // Check if we got a CRC error
   1991   if ((PktStatus & RX_BAD_CRC) != 0) {
   1992     DEBUG((EFI_D_WARN, "LAN91x: Received frame CRC error\n"));
   1993     LanDriver->Stats.RxCrcErrorFrames += 1;
   1994     LanDriver->Stats.RxDroppedFrames += 1;
   1995     Status = EFI_DEVICE_ERROR;
   1996     goto exit_release;
   1997   }
   1998 
   1999   // Check if we got a too-short frame
   2000   if ((PktStatus & RX_TOO_SHORT) != 0) {
   2001     DEBUG((EFI_D_WARN, "LAN91x: Received frame too short (%d bytes)\n", PktLength));
   2002     LanDriver->Stats.RxUndersizeFrames += 1;
   2003     LanDriver->Stats.RxDroppedFrames += 1;
   2004     Status = EFI_DEVICE_ERROR;
   2005     goto exit_release;
   2006   }
   2007 
   2008    // Check if we got a too-long frame
   2009   if ((PktStatus & RX_TOO_LONG) != 0) {
   2010     DEBUG((EFI_D_WARN, "LAN91x: Received frame too long (%d bytes)\n", PktLength));
   2011     LanDriver->Stats.RxOversizeFrames += 1;
   2012     LanDriver->Stats.RxDroppedFrames += 1;
   2013     Status = EFI_DEVICE_ERROR;
   2014     goto exit_release;
   2015   }
   2016 
   2017    // Check if we got an alignment error
   2018   if ((PktStatus & RX_ALGN_ERR) != 0) {
   2019     DEBUG((EFI_D_WARN, "LAN91x: Received frame alignment error\n"));
   2020     // Don't seem to keep track of these specifically
   2021     LanDriver->Stats.RxDroppedFrames += 1;
   2022     Status = EFI_DEVICE_ERROR;
   2023     goto exit_release;
   2024   }
   2025 
   2026   // Classify the received fram
   2027   if ((PktStatus & RX_MULTICAST) != 0) {
   2028     LanDriver->Stats.RxMulticastFrames += 1;
   2029   } else if ((PktStatus & RX_BROADCAST) != 0) {
   2030     LanDriver->Stats.RxBroadcastFrames += 1;
   2031   } else {
   2032     LanDriver->Stats.RxUnicastFrames += 1;
   2033   }
   2034 
   2035   // Calculate the received packet data length
   2036   PktLength -= LAN91X_PKT_OVERHEAD;
   2037   if ((PktStatus & RX_ODD_FRAME) != 0) {
   2038     PktLength += 1;
   2039   }
   2040 
   2041   // Check buffer size
   2042   if (*BuffSize < PktLength) {
   2043     DEBUG((EFI_D_WARN, "LAN91x: Receive buffer too small for packet (%d < %d)\n",
   2044         *BuffSize, PktLength));
   2045     *BuffSize = PktLength;
   2046     Status = EFI_BUFFER_TOO_SMALL;
   2047     goto exit_release;
   2048   }
   2049 
   2050   // Transfer the data bytes
   2051   DataPtr = Data;
   2052   ReadIoData (LanDriver, DataPtr, PktLength & ~0x0001);
   2053 
   2054   // Read the PktControl and Odd Byte from the FIFO
   2055   PktControl = ReadIoReg16 (LanDriver, LAN91X_DATA0);
   2056   if ((PktControl & PCW_ODD) != 0) {
   2057     DataPtr[PktLength - 1] = PktControl & PCW_ODD_BYTE;
   2058   }
   2059 
   2060   // Update buffer size
   2061   *BuffSize = PktLength;
   2062 
   2063   if (HdrSize != NULL) {
   2064     *HdrSize = LanDriver->SnpMode.MediaHeaderSize;
   2065   }
   2066 
   2067   // Extract the destination address
   2068   if (DstAddr != NULL) {
   2069     CopyMem (DstAddr, &DataPtr[0], NET_ETHER_ADDR_LEN);
   2070   }
   2071 
   2072   // Get the source address
   2073   if (SrcAddr != NULL) {
   2074     CopyMem (SrcAddr, &DataPtr[6], NET_ETHER_ADDR_LEN);
   2075   }
   2076 
   2077   // Get the protocol
   2078   if (Protocol != NULL) {
   2079     *Protocol = NTOHS (*(UINT16*)(&DataPtr[12]));
   2080   }
   2081 
   2082   // Update the Rx statistics
   2083   LanDriver->Stats.RxTotalBytes += PktLength;
   2084   LanDriver->Stats.RxGoodFrames += 1;
   2085   Status = EFI_SUCCESS;
   2086 
   2087 #if LAN91X_PRINT_PACKET_HEADERS
   2088   // Dump the packet header
   2089   DEBUG((EFI_D_ERROR, "LAN91X:SnpReceive()\n"));
   2090   DEBUG((EFI_D_ERROR, "  HdrSize: %p, SrcAddr: %p, DstAddr: %p, Protocol: %p\n",
   2091          HdrSize, SrcAddr, DstAddr, Protocol));
   2092   DEBUG((EFI_D_ERROR, "  Length: %d, Last byte: %02x\n", PktLength, DataPtr[PktLength - 1]));
   2093   PrintIpDgram (&DataPtr[0], &DataPtr[6], &DataPtr[12], &DataPtr[14]);
   2094 #endif
   2095 
   2096   // Release the FIFO buffer
   2097 exit_release:
   2098   MmuOperation (LanDriver, MMUCR_OP_RX_POP_REL);
   2099 
   2100   // Restore TPL and return
   2101 exit_unlock:
   2102   gBS->RestoreTPL (SavedTpl);
   2103   return Status;
   2104 }
   2105 
   2106 
   2107 /*------------------ Driver Execution Environment main entry point ------------------*/
   2108 
   2109 /*
   2110 **  Entry point for the LAN91x driver
   2111 **
   2112 */
   2113 EFI_STATUS
   2114 Lan91xDxeEntry (
   2115   IN EFI_HANDLE Handle,
   2116   IN EFI_SYSTEM_TABLE *SystemTable
   2117   )
   2118 {
   2119   EFI_STATUS Status;
   2120   LAN91X_DRIVER *LanDriver;
   2121   EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
   2122   EFI_SIMPLE_NETWORK_MODE *SnpMode;
   2123   LAN91X_DEVICE_PATH *Lan91xPath;
   2124 
   2125   // The PcdLan91xDxeBaseAddress PCD must be defined
   2126   ASSERT(PcdGet32 (PcdLan91xDxeBaseAddress) != 0);
   2127 
   2128   // Allocate Resources
   2129   LanDriver = AllocateZeroPool (sizeof(LAN91X_DRIVER));
   2130   Lan91xPath = AllocateCopyPool (sizeof(LAN91X_DEVICE_PATH), &Lan91xPathTemplate);
   2131 
   2132   // Initialize I/O Space access info
   2133   LanDriver->IoBase = PcdGet32 (PcdLan91xDxeBaseAddress);
   2134   LanDriver->PhyAd = LAN91X_NO_PHY;
   2135   LanDriver->BankSel = 0xff;
   2136 
   2137   // Initialize pointers
   2138   Snp = &(LanDriver->Snp);
   2139   SnpMode = &(LanDriver->SnpMode);
   2140   Snp->Mode = SnpMode;
   2141 
   2142   // Set the signature of the LAN Driver structure
   2143   LanDriver->Signature = LAN91X_SIGNATURE;
   2144 
   2145   // Probe the device
   2146   Status = Probe (LanDriver);
   2147   if (EFI_ERROR(Status)) {
   2148     DEBUG((EFI_D_ERROR, "LAN91x:Lan91xDxeEntry(): Probe failed with status %d\n", Status));
   2149     return Status;
   2150   }
   2151 
   2152 #ifdef LAN91X_PRINT_REGISTERS
   2153   PrintIoRegisters (LanDriver);
   2154   PrintPhyRegisters (LanDriver);
   2155 #endif
   2156 
   2157   // Initialize transmit queue
   2158   InitializeListHead (&LanDriver->TransmitQueueHead);
   2159 
   2160   // Assign fields and func pointers
   2161   Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
   2162   Snp->WaitForPacket = NULL;
   2163   Snp->Initialize = SnpInitialize;
   2164   Snp->Start = SnpStart;
   2165   Snp->Stop = SnpStop;
   2166   Snp->Reset = SnpReset;
   2167   Snp->Shutdown = SnpShutdown;
   2168   Snp->ReceiveFilters = SnpReceiveFilters;
   2169   Snp->StationAddress = SnpStationAddress;
   2170   Snp->Statistics = SnpStatistics;
   2171   Snp->MCastIpToMac = SnpMcastIptoMac;
   2172   Snp->NvData = SnpNvData;
   2173   Snp->GetStatus = SnpGetStatus;
   2174   Snp->Transmit = SnpTransmit;
   2175   Snp->Receive = SnpReceive;
   2176 
   2177   // Fill in simple network mode structure
   2178   SnpMode->State = EfiSimpleNetworkStopped;
   2179   SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN;    // HW address is 6 bytes
   2180   SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD);  // Size of an Ethernet header
   2181   SnpMode->MaxPacketSize = EFI_PAGE_SIZE;         // Ethernet Frame (with VLAN tag +4 bytes)
   2182 
   2183   // Supported receive filters
   2184   SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
   2185                                EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
   2186                                EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
   2187                                EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
   2188                                EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
   2189 
   2190   // Initially-enabled receive filters
   2191   SnpMode->ReceiveFilterSetting = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
   2192                                   EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
   2193                                   EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
   2194 
   2195   // LAN91x has 64bit hash table. We can filter an infinite MACs, but
   2196   // higher-level software must filter out any hash collisions.
   2197   SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
   2198   SnpMode->MCastFilterCount = 0;
   2199   ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS));
   2200 
   2201   // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
   2202   SnpMode->IfType = NET_IFTYPE_ETHERNET;
   2203 
   2204   // Mac address is changeable
   2205   SnpMode->MacAddressChangeable = TRUE;
   2206 
   2207   // We can only transmit one packet at a time
   2208   SnpMode->MultipleTxSupported = FALSE;
   2209 
   2210   // MediaPresent checks for cable connection and partner link
   2211   SnpMode->MediaPresentSupported = TRUE;
   2212   SnpMode->MediaPresent = FALSE;
   2213 
   2214   //  Set broadcast address
   2215   SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);
   2216 
   2217   // Assign fields for device path
   2218   Lan91xPath->Lan91x.MacAddress = SnpMode->PermanentAddress;
   2219   Lan91xPath->Lan91x.IfType = SnpMode->IfType;
   2220 
   2221   // Initialise the protocol
   2222   Status = gBS->InstallMultipleProtocolInterfaces (
   2223                   &LanDriver->ControllerHandle,
   2224                   &gEfiSimpleNetworkProtocolGuid, Snp,
   2225                   &gEfiDevicePathProtocolGuid, Lan91xPath,
   2226                   NULL
   2227                   );
   2228 
   2229   // Say what the status of loading the protocol structure is
   2230   if (EFI_ERROR(Status)) {
   2231     FreePool (LanDriver);
   2232   }
   2233 
   2234   return Status;
   2235 }
   2236