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