• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
MulticastHash(IN EFI_MAC_ADDRESS * Mac,IN UINT32 AddrLen)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
SelectIoBank(LAN91X_DRIVER * LanDriver,UINTN Register)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
ReadIoReg16(LAN91X_DRIVER * LanDriver,UINTN Register)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
WriteIoReg16(LAN91X_DRIVER * LanDriver,UINTN Register,UINT16 Value)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
ReadIoReg8(LAN91X_DRIVER * LanDriver,UINTN Register)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
WriteIoReg8(LAN91X_DRIVER * LanDriver,UINTN Register,UINT8 Value)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
MdioOutput(LAN91X_DRIVER * LanDriver,UINTN Bits,UINT32 Value)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
MdioInput(LAN91X_DRIVER * LanDriver,UINTN Bits)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
MdioIdle(LAN91X_DRIVER * LanDriver)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
WritePhyReg16(LAN91X_DRIVER * LanDriver,UINTN RegAd,UINT16 Value)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
ReadPhyReg16(LAN91X_DRIVER * LanDriver,UINTN RegAd)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
PrintIoRegisters(IN LAN91X_DRIVER * LanDriver)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
PrintPhyRegisters(IN LAN91X_DRIVER * LanDriver)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
PrintIpDgram(IN CONST VOID * DstMac,IN CONST VOID * SrcMac,IN CONST VOID * Proto,IN CONST VOID * IpDgram)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
PhyDetect(IN LAN91X_DRIVER * LanDriver)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
CheckLinkStatus(IN LAN91X_DRIVER * LanDriver)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
PhyAutoNegotiate(IN LAN91X_DRIVER * LanDriver)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
PhySoftReset(IN LAN91X_DRIVER * LanDriver)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
GetCurrentMacAddress(IN LAN91X_DRIVER * LanDriver)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
SetCurrentMacAddress(IN LAN91X_DRIVER * LanDriver,IN EFI_MAC_ADDRESS * MacAddress)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
MmuOperation(IN LAN91X_DRIVER * LanDriver,IN UINTN MmuOp)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
ReadIoData(IN LAN91X_DRIVER * LanDriver,IN VOID * Buffer,IN UINTN BufLen)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
WriteIoData(IN LAN91X_DRIVER * LanDriver,IN VOID * Buffer,IN UINTN BufLen)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
ChipDisable(IN LAN91X_DRIVER * LanDriver)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
ChipEnable(IN LAN91X_DRIVER * LanDriver)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
SoftReset(IN LAN91X_DRIVER * LanDriver)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
Probe(IN LAN91X_DRIVER * LanDriver)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
SnpStart(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp)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
SnpStop(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp)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
SnpInitialize(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN UINTN RxBufferSize OPTIONAL,IN UINTN TxBufferSize OPTIONAL)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
SnpReset(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN BOOLEAN Verification)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
SnpShutdown(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp)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
SnpReceiveFilters(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN UINT32 Enable,IN UINT32 Disable,IN BOOLEAN Reset,IN UINTN NumMfilter OPTIONAL,IN EFI_MAC_ADDRESS * Mfilter OPTIONAL)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
SnpStationAddress(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN BOOLEAN Reset,IN EFI_MAC_ADDRESS * NewMac)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
SnpStatistics(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN BOOLEAN Reset,IN OUT UINTN * StatSize,OUT EFI_NETWORK_STATISTICS * Statistics)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
SnpMcastIptoMac(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN BOOLEAN IsIpv6,IN EFI_IP_ADDRESS * Ip,OUT EFI_MAC_ADDRESS * McastMac)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
SnpNvData(IN EFI_SIMPLE_NETWORK_PROTOCOL * pobj,IN BOOLEAN read_write,IN UINTN offset,IN UINTN buff_size,IN OUT VOID * data)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
SnpGetStatus(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,OUT UINT32 * IrqStat OPTIONAL,OUT VOID ** TxBuff OPTIONAL)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
SnpTransmit(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,IN UINTN HdrSize,IN UINTN BufSize,IN VOID * BufAddr,IN EFI_MAC_ADDRESS * SrcAddr OPTIONAL,IN EFI_MAC_ADDRESS * DstAddr OPTIONAL,IN UINT16 * Protocol OPTIONAL)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
SnpReceive(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp,OUT UINTN * HdrSize OPTIONAL,IN OUT UINTN * BuffSize,OUT VOID * Data,OUT EFI_MAC_ADDRESS * SrcAddr OPTIONAL,OUT EFI_MAC_ADDRESS * DstAddr OPTIONAL,OUT UINT16 * Protocol OPTIONAL)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
Lan91xDxeEntry(IN EFI_HANDLE Handle,IN EFI_SYSTEM_TABLE * SystemTable)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