MdeModulePkg/TerminalDxe: Some improvements
[mirror_edk2.git] / EmbeddedPkg / Drivers / Lan9118Dxe / Lan9118Dxe.c
CommitLineData
46f2c53b
OM
1/** @file\r
2*\r
3* Copyright (c) 2012-2014, ARM Limited. All rights reserved.\r
4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
15#include "Lan9118Dxe.h"\r
16\r
17\r
18typedef struct {\r
19 MAC_ADDR_DEVICE_PATH Lan9118;\r
20 EFI_DEVICE_PATH_PROTOCOL End;\r
21} LAN9118_DEVICE_PATH;\r
22\r
23LAN9118_DEVICE_PATH Lan9118PathTemplate = {\r
24 {\r
25 {\r
26 MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP,\r
27 { (UINT8) (sizeof(MAC_ADDR_DEVICE_PATH)), (UINT8) ((sizeof(MAC_ADDR_DEVICE_PATH)) >> 8) }\r
28 },\r
b0fdce95 29 { { 0 } },\r
46f2c53b
OM
30 0\r
31 },\r
32 {\r
33 END_DEVICE_PATH_TYPE,\r
34 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
b0fdce95 35 { sizeof(EFI_DEVICE_PATH_PROTOCOL), 0 }\r
46f2c53b
OM
36 }\r
37};\r
38\r
39/*\r
40** Entry point for the LAN9118 driver\r
41**\r
42*/\r
43EFI_STATUS\r
44Lan9118DxeEntry (\r
45 IN EFI_HANDLE Handle,\r
46 IN EFI_SYSTEM_TABLE *SystemTable\r
47 )\r
48{\r
49 EFI_STATUS Status;\r
50 LAN9118_DRIVER *LanDriver;\r
51 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
52 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
53 LAN9118_DEVICE_PATH *Lan9118Path;\r
54 EFI_HANDLE ControllerHandle;\r
55\r
56 // The PcdLan9118DxeBaseAddress PCD must be defined\r
57 ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress) != 0);\r
58\r
59 // Allocate Resources\r
60 LanDriver = AllocateZeroPool (sizeof (LAN9118_DRIVER));\r
61 if (LanDriver == NULL) {\r
62 return EFI_OUT_OF_RESOURCES;\r
63 }\r
64 Lan9118Path = (LAN9118_DEVICE_PATH*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH), &Lan9118PathTemplate);\r
65 if (Lan9118Path == NULL) {\r
66 return EFI_OUT_OF_RESOURCES;\r
67 }\r
68\r
69 // Initialize pointers\r
70 Snp = &(LanDriver->Snp);\r
71 SnpMode = &(LanDriver->SnpMode);\r
72 Snp->Mode = SnpMode;\r
73\r
74 // Set the signature of the LAN Driver structure\r
75 LanDriver->Signature = LAN9118_SIGNATURE;\r
76\r
77 // Assign fields and func pointers\r
78 Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
79 Snp->WaitForPacket = NULL;\r
80 Snp->Initialize = SnpInitialize;\r
81 Snp->Start = SnpStart;\r
82 Snp->Stop = SnpStop;\r
83 Snp->Reset = SnpReset;\r
84 Snp->Shutdown = SnpShutdown;\r
85 Snp->ReceiveFilters = SnpReceiveFilters;\r
86 Snp->StationAddress = SnpStationAddress;\r
87 Snp->Statistics = SnpStatistics;\r
88 Snp->MCastIpToMac = SnpMcastIptoMac;\r
89 Snp->NvData = SnpNvData;\r
90 Snp->GetStatus = SnpGetStatus;\r
91 Snp->Transmit = SnpTransmit;\r
92 Snp->Receive = SnpReceive;\r
93\r
94 // Start completing simple network mode structure\r
95 SnpMode->State = EfiSimpleNetworkStopped;\r
96 SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes\r
97 SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this\r
98 SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)\r
99 SnpMode->NvRamSize = 0; // No NVRAM with this device\r
100 SnpMode->NvRamAccessSize = 0; // No NVRAM with this device\r
101\r
11bbc257
RC
102 //\r
103 // Claim that all receive filter settings are supported, though the MULTICAST mode\r
104 // is not completely supported. The LAN9118 Ethernet controller is only able to\r
105 // do a "hash filtering" and not a perfect filtering on multicast addresses. The\r
106 // controller does not filter the multicast addresses directly but a hash value\r
107 // of them. The hash value of a multicast address is derived from its CRC and\r
108 // ranges from 0 to 63 included.\r
109 // We claim that the perfect MULTICAST filtering mode is supported because\r
110 // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode\r
111 // and thus not being able to take advantage of the hash filtering.\r
112 //\r
113 SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |\r
114 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |\r
115 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |\r
116 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |\r
117 EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
118\r
119 // We do not intend to receive anything for the time being.\r
120 SnpMode->ReceiveFilterSetting = 0;\r
46f2c53b
OM
121\r
122 // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses\r
123 SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;\r
124 SnpMode->MCastFilterCount = 0;\r
125 ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS));\r
126\r
127 // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)\r
128 SnpMode->IfType = NET_IFTYPE_ETHERNET;\r
129\r
130 // Mac address is changeable as it is loaded from erasable memory\r
131 SnpMode->MacAddressChangeable = TRUE;\r
132\r
133 // Can only transmit one packet at a time\r
134 SnpMode->MultipleTxSupported = FALSE;\r
135\r
136 // MediaPresent checks for cable connection and partner link\r
137 SnpMode->MediaPresentSupported = TRUE;\r
138 SnpMode->MediaPresent = FALSE;\r
139\r
140 // Set broadcast address\r
141 SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);\r
142\r
143 // Power up the device so we can find the MAC address\r
144 Status = Lan9118Initialize (Snp);\r
145 if (EFI_ERROR (Status)) {\r
146 DEBUG ((EFI_D_ERROR, "Lan9118: Error initialising hardware\n"));\r
147 return EFI_DEVICE_ERROR;\r
148 }\r
149\r
150 // Assign fields for device path\r
151 CopyMem (&Lan9118Path->Lan9118.MacAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN);\r
152 Lan9118Path->Lan9118.IfType = Snp->Mode->IfType;\r
153\r
154 // Initialise the protocol\r
155 ControllerHandle = NULL;\r
156 Status = gBS->InstallMultipleProtocolInterfaces (\r
157 &ControllerHandle,\r
158 &gEfiSimpleNetworkProtocolGuid, Snp,\r
159 &gEfiDevicePathProtocolGuid, Lan9118Path,\r
160 NULL\r
161 );\r
162 // Say what the status of loading the protocol structure is\r
163 if (EFI_ERROR(Status)) {\r
164 FreePool (LanDriver);\r
165 } else {\r
166 LanDriver->ControllerHandle = ControllerHandle;\r
167 }\r
168\r
169 return Status;\r
170}\r
171\r
172/*\r
173 * UEFI Start() function\r
174 *\r
175 * Parameters:\r
176 *\r
177 * @param Snp: A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.\r
178 *\r
179 * Description:\r
180 *\r
181 * This function starts a network interface. If the network interface successfully starts, then\r
182 * EFI_SUCCESS will be returned.\r
183 */\r
184EFI_STATUS\r
185EFIAPI\r
186SnpStart (\r
0150e14d 187 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
46f2c53b
OM
188 )\r
189{\r
190 // Check Snp instance\r
191 if (Snp == NULL) {\r
192 return EFI_INVALID_PARAMETER;\r
193 }\r
194\r
195 // Check state\r
0150e14d
RC
196 if ((Snp->Mode->State == EfiSimpleNetworkStarted) ||\r
197 (Snp->Mode->State == EfiSimpleNetworkInitialized) ) {\r
46f2c53b 198 return EFI_ALREADY_STARTED;\r
46f2c53b
OM
199 }\r
200\r
201 // Change state\r
202 Snp->Mode->State = EfiSimpleNetworkStarted;\r
203 return EFI_SUCCESS;\r
204}\r
205\r
206/*\r
207 * UEFI Stop() function\r
208 *\r
209 */\r
210EFI_STATUS\r
211EFIAPI\r
212SnpStop (\r
213 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp\r
214 )\r
215{\r
216 // Check Snp Instance\r
217 if (Snp == NULL) {\r
218 return EFI_INVALID_PARAMETER;\r
219 }\r
220\r
221 // Check state of the driver\r
0150e14d 222 if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
46f2c53b
OM
223 return EFI_NOT_STARTED;\r
224 }\r
225\r
226 // Stop the Tx and Rx\r
227 StopTx (STOP_TX_CFG | STOP_TX_MAC, Snp);\r
228 StopRx (0, Snp);\r
229\r
230 // Change the state\r
231 switch (Snp->Mode->State) {\r
232 case EfiSimpleNetworkStarted:\r
233 case EfiSimpleNetworkInitialized:\r
234 Snp->Mode->State = EfiSimpleNetworkStopped;\r
235 break;\r
236 default:\r
237 return EFI_DEVICE_ERROR;\r
238 }\r
239\r
240 // Put the device into a power saving mode ?\r
241 return EFI_SUCCESS;\r
242}\r
243\r
244\r
245// Allocated receive and transmit buffers\r
246STATIC UINT32 gTxBuffer = 0;\r
247\r
248/*\r
249 * UEFI Initialize() function\r
250 *\r
251 */\r
252EFI_STATUS\r
253EFIAPI\r
254SnpInitialize (\r
255 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,\r
256 IN UINTN RxBufferSize OPTIONAL,\r
257 IN UINTN TxBufferSize OPTIONAL\r
258 )\r
259{\r
260 EFI_STATUS Status;\r
261 UINT32 PmConf;\r
262 INT32 AllocResult;\r
263 UINT32 RxStatusSize;\r
264 UINT32 TxStatusSize;\r
265\r
266 // Initialize variables\r
267 // Global variables to hold tx and rx FIFO allocation\r
268 gTxBuffer = 0;\r
269\r
270 // Check Snp Instance\r
271 if (Snp == NULL) {\r
272 return EFI_INVALID_PARAMETER;\r
273 }\r
274\r
275 // First check that driver has not already been initialized\r
276 if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
277 DEBUG ((EFI_D_WARN, "LAN9118 Driver already initialized\n"));\r
278 return EFI_SUCCESS;\r
279 } else\r
280 if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
281 DEBUG ((EFI_D_WARN, "LAN9118 Driver not started\n"));\r
282 return EFI_NOT_STARTED;\r
283 }\r
284\r
285 // Initiate a PHY reset\r
6382e5df 286 Status = PhySoftReset (PHY_RESET_PMT, Snp);\r
42589b9a 287 if (EFI_ERROR (Status)) {\r
46f2c53b
OM
288 Snp->Mode->State = EfiSimpleNetworkStopped;\r
289 DEBUG ((EFI_D_WARN, "Warning: Link not ready after TimeOut. Check ethernet cable\n"));\r
290 return EFI_NOT_STARTED;\r
291 }\r
292\r
293 // Initiate a software reset\r
294 Status = SoftReset (0, Snp);\r
295 if (EFI_ERROR(Status)) {\r
296 DEBUG ((EFI_D_WARN, "Soft Reset Failed: Hardware Error\n"));\r
297 return EFI_DEVICE_ERROR;\r
298 }\r
299\r
300 // Read the PM register\r
301 PmConf = MmioRead32 (LAN9118_PMT_CTRL);\r
302\r
303 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets\r
304 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode\r
305 // MPTCTRL_PME_EN: Allow Power Management Events\r
306 PmConf = 0;\r
307 PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN);\r
308\r
309 // Write the current configuration to the register\r
310 MmioWrite32 (LAN9118_PMT_CTRL, PmConf);\r
311 gBS->Stall (LAN9118_STALL);\r
312 gBS->Stall (LAN9118_STALL);\r
313\r
314 // Configure GPIO and HW\r
315 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);\r
316 if (EFI_ERROR(Status)) {\r
317 return Status;\r
318 }\r
319\r
320 // Assign the transmitter buffer size (default values)\r
321 TxStatusSize = LAN9118_TX_STATUS_SIZE;\r
322 RxStatusSize = LAN9118_RX_STATUS_SIZE;\r
323\r
324 // Check that a buff size was specified\r
325 if (TxBufferSize > 0) {\r
326 if (RxBufferSize == 0) {\r
327 RxBufferSize = LAN9118_RX_DATA_SIZE;\r
328 }\r
329\r
330 AllocResult = ChangeFifoAllocation (\r
331 ALLOC_USE_FIFOS,\r
332 &TxBufferSize,\r
333 &RxBufferSize,\r
334 &TxStatusSize,\r
335 &RxStatusSize,\r
336 Snp\r
337 );\r
338\r
339 if (AllocResult < 0) {\r
340 return EFI_OUT_OF_RESOURCES;\r
341 }\r
342 }\r
343\r
344 // Do auto-negotiation if supported\r
345 Status = AutoNegotiate (AUTO_NEGOTIATE_ADVERTISE_ALL, Snp);\r
346 if (EFI_ERROR(Status)) {\r
347 DEBUG ((EFI_D_WARN, "Lan9118: Auto Negociation not supported.\n"));\r
348 }\r
349\r
350 // Configure flow control depending on speed capabilities\r
351 Status = ConfigureFlow (0, 0, 0, 0, Snp);\r
352 if (EFI_ERROR(Status)) {\r
353 return Status;\r
354 }\r
355\r
11bbc257 356 // Enable the transmitter\r
46f2c53b
OM
357 Status = StartTx (START_TX_MAC | START_TX_CFG, Snp);\r
358 if (EFI_ERROR(Status)) {\r
359 return Status;\r
360 }\r
361\r
362 // Now acknowledge all interrupts\r
363 MmioWrite32 (LAN9118_INT_STS, ~0);\r
364\r
365 // Declare the driver as initialized\r
366 Snp->Mode->State = EfiSimpleNetworkInitialized;\r
367\r
368 return Status;\r
369}\r
370\r
371/*\r
372 * UEFI Reset () function\r
373 *\r
374 */\r
375EFI_STATUS\r
376EFIAPI\r
377SnpReset (\r
378 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,\r
379 IN BOOLEAN Verification\r
380 )\r
381{\r
42589b9a
OM
382 UINT32 PmConf;\r
383 UINT32 HwConf;\r
384 UINT32 ResetFlags;\r
385 EFI_STATUS Status;\r
46f2c53b
OM
386\r
387 PmConf = 0;\r
388 HwConf = 0;\r
389 ResetFlags = 0;\r
390\r
391 // Check Snp Instance\r
392 if (Snp == NULL) {\r
393 return EFI_INVALID_PARAMETER;\r
394 }\r
395\r
396 // First check that driver has not already been initialized\r
397 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
398 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not yet initialized\n"));\r
399 return EFI_DEVICE_ERROR;\r
400 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
401 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not started\n"));\r
402 return EFI_NOT_STARTED;\r
403 }\r
404\r
405 // Initiate a PHY reset\r
6382e5df 406 Status = PhySoftReset (PHY_RESET_PMT, Snp);\r
42589b9a 407 if (EFI_ERROR (Status)) {\r
46f2c53b
OM
408 Snp->Mode->State = EfiSimpleNetworkStopped;\r
409 return EFI_NOT_STARTED;\r
410 }\r
411\r
412 // Initiate a software reset\r
413 ResetFlags |= SOFT_RESET_CHECK_MAC_ADDR_LOAD | SOFT_RESET_CLEAR_INT;\r
414\r
415 if (Verification) {\r
416 ResetFlags |= SOFT_RESET_SELF_TEST;\r
417 }\r
418\r
42589b9a
OM
419 Status = SoftReset (ResetFlags, Snp);\r
420 if (EFI_ERROR (Status)) {\r
46f2c53b
OM
421 DEBUG ((EFI_D_WARN, "Warning: Soft Reset Failed: Hardware Error\n"));\r
422 return EFI_DEVICE_ERROR;\r
423 }\r
424\r
425 // Read the PM register\r
426 PmConf = MmioRead32 (LAN9118_PMT_CTRL);\r
427\r
428 // MPTCTRL_WOL_EN: Allow Wake-On-Lan to detect wake up frames or magic packets\r
429 // MPTCTRL_ED_EN: Allow energy detection to allow lowest power consumption mode\r
430 // MPTCTRL_PME_EN: Allow Power Management Events\r
431 PmConf |= (MPTCTRL_WOL_EN | MPTCTRL_ED_EN | MPTCTRL_PME_EN);\r
432\r
433 // Write the current configuration to the register\r
434 MmioWrite32 (LAN9118_PMT_CTRL, PmConf);\r
435 gBS->Stall (LAN9118_STALL);\r
436\r
ac8f1e10
RC
437 // Reactivate the LEDs\r
438 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);\r
439 if (EFI_ERROR (Status)) {\r
440 return Status;\r
441 }\r
442\r
46f2c53b
OM
443 // Check that a buffer size was specified in SnpInitialize\r
444 if (gTxBuffer != 0) {\r
445 HwConf = MmioRead32 (LAN9118_HW_CFG); // Read the HW register\r
446 HwConf &= ~HW_CFG_TX_FIFO_SIZE_MASK; // Clear buffer bits first\r
447 HwConf |= HW_CFG_TX_FIFO_SIZE(gTxBuffer); // assign size chosen in SnpInitialize\r
448\r
449 MmioWrite32 (LAN9118_HW_CFG, HwConf); // Write the conf\r
450 gBS->Stall (LAN9118_STALL);\r
451 }\r
452\r
453 // Enable the receiver and transmitter and clear their contents\r
454 StartRx (START_RX_CLEAR, Snp);\r
455 StartTx (START_TX_MAC | START_TX_CFG | START_TX_CLEAR, Snp);\r
456\r
457 // Now acknowledge all interrupts\r
458 MmioWrite32 (LAN9118_INT_STS, ~0);\r
459\r
460 return EFI_SUCCESS;\r
461}\r
462\r
463/*\r
464 * UEFI Shutdown () function\r
465 *\r
466 */\r
467EFI_STATUS\r
468EFIAPI\r
469SnpShutdown (\r
470 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp\r
471 )\r
472{\r
42589b9a
OM
473 EFI_STATUS Status;\r
474\r
46f2c53b
OM
475 // Check Snp Instance\r
476 if (Snp == NULL) {\r
477 return EFI_INVALID_PARAMETER;\r
478 }\r
479\r
480 // First check that driver has not already been initialized\r
481 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
482 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not yet initialized\n"));\r
483 return EFI_DEVICE_ERROR;\r
484 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
0150e14d 485 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not started\n"));\r
46f2c53b
OM
486 return EFI_NOT_STARTED;\r
487 }\r
488\r
489 // Initiate a PHY reset\r
42589b9a
OM
490 Status = PhySoftReset (PHY_RESET_PMT, Snp);\r
491 if (EFI_ERROR (Status)) {\r
492 return Status;\r
493 }\r
46f2c53b
OM
494\r
495 // Initiate a software reset\r
42589b9a
OM
496 Status = SoftReset (0, Snp);\r
497 if (EFI_ERROR (Status)) {\r
46f2c53b 498 DEBUG ((EFI_D_WARN, "Warning: Soft Reset Failed: Hardware Error\n"));\r
42589b9a 499 return Status;\r
46f2c53b
OM
500 }\r
501\r
0f0a6fe9
RC
502 // Back to the started and thus not initialized state\r
503 Snp->Mode->State = EfiSimpleNetworkStarted;\r
504\r
46f2c53b
OM
505 return EFI_SUCCESS;\r
506}\r
507\r
0150e14d
RC
508/**\r
509 Enable and/or disable the receive filters of the LAN9118\r
510\r
511 Please refer to the UEFI specification for the precedence rules among the\r
512 Enable, Disable and ResetMCastFilter parameters.\r
513\r
514 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL\r
515 instance.\r
516 @param[in] Enable A bit mask of receive filters to enable.\r
517 @param[in] Disable A bit mask of receive filters to disable.\r
518 @param[in] ResetMCastFilter Set to TRUE to reset the contents of the multicast\r
519 receive filters on the network interface to\r
520 their default values.\r
521 @param[in] MCastFilterCnt Number of multicast HW MAC addresses in the new\r
522 MCastFilter list. This value must be less than or\r
523 equal to the MCastFilterCnt field of\r
524 EFI_SIMPLE_NETWORK_MODE. This field is optional if\r
525 ResetMCastFilter is TRUE.\r
526 @param[in] MCastFilter A pointer to a list of new multicast receive\r
527 filter HW MAC addresses. This list will replace\r
528 any existing multicast HW MAC address list. This\r
529 field is optional if ResetMCastFilter is TRUE.\r
530\r
531 @retval EFI_SUCCESS The receive filters of the LAN9118 were updated.\r
532 @retval EFI_NOT_STARTED The LAN9118 has not been started.\r
533 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :\r
534 . This is NULL\r
535 . Multicast is being enabled (the\r
536 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is set in\r
537 Enable, it is not set in Disable, and ResetMCastFilter\r
538 is FALSE) and MCastFilterCount is zero.\r
539 . Multicast is being enabled and MCastFilterCount is\r
540 greater than Snp->Mode->MaxMCastFilterCount.\r
541 . Multicast is being enabled and MCastFilter is NULL\r
542 . Multicast is being enabled and one or more of the\r
543 addresses in the MCastFilter list are not valid\r
544 multicast MAC addresses.\r
545 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.\r
46f2c53b 546\r
0150e14d 547**/\r
46f2c53b
OM
548EFI_STATUS\r
549EFIAPI\r
550SnpReceiveFilters (\r
0150e14d
RC
551 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,\r
552 IN UINT32 Enable,\r
553 IN UINT32 Disable,\r
554 IN BOOLEAN ResetMCastFilter,\r
555 IN UINTN MCastFilterCnt OPTIONAL,\r
556 IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL\r
46f2c53b
OM
557 )\r
558{\r
0150e14d
RC
559 EFI_SIMPLE_NETWORK_MODE *Mode;\r
560 UINT32 MultHashTableHigh;\r
561 UINT32 MultHashTableLow;\r
562 UINT32 Count;\r
563 UINT32 Crc;\r
564 UINT8 HashValue;\r
565 UINT32 MacCSRValue;\r
11bbc257 566 UINT32 ReceiveFilterSetting;\r
0150e14d 567 EFI_MAC_ADDRESS *Mac;\r
11bbc257 568 EFI_MAC_ADDRESS ZeroMac;\r
46f2c53b 569\r
0150e14d
RC
570 // Check Snp Instance\r
571 if (Snp == NULL) {\r
572 return EFI_INVALID_PARAMETER;\r
573 }\r
574 Mode = Snp->Mode;\r
46f2c53b
OM
575\r
576 // Check that driver was started and initialised\r
0150e14d 577 if (Mode->State == EfiSimpleNetworkStarted) {\r
46f2c53b
OM
578 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));\r
579 return EFI_DEVICE_ERROR;\r
0150e14d 580 } else if (Mode->State == EfiSimpleNetworkStopped) {\r
46f2c53b
OM
581 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));\r
582 return EFI_NOT_STARTED;\r
583 }\r
584\r
0150e14d
RC
585 if ((Enable & (~Mode->ReceiveFilterMask)) ||\r
586 (Disable & (~Mode->ReceiveFilterMask)) ) {\r
587 return EFI_INVALID_PARAMETER;\r
46f2c53b
OM
588 }\r
589\r
0150e14d
RC
590 //\r
591 // Check the validity of the multicast setting and compute the\r
592 // hash values of the multicast mac addresses to listen to.\r
593 //\r
46f2c53b 594\r
0150e14d
RC
595 MultHashTableHigh = 0;\r
596 MultHashTableLow = 0;\r
597 if ((!ResetMCastFilter) &&\r
598 ((Disable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) == 0) &&\r
599 ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) ) {\r
600 if ((MCastFilterCnt == 0) ||\r
601 (MCastFilterCnt > Mode->MaxMCastFilterCount) ||\r
602 (MCastFilter == NULL) ) {\r
603 return EFI_INVALID_PARAMETER;\r
604 }\r
605 //\r
606 // Check the validity of all multicast addresses before to change\r
607 // anything.\r
608 //\r
609 for (Count = 0; Count < MCastFilterCnt; Count++) {\r
610 if ((MCastFilter[Count].Addr[0] & 1) == 0) {\r
611 return EFI_INVALID_PARAMETER;\r
612 }\r
613 }\r
46f2c53b 614\r
0150e14d 615 //\r
46f2c53b 616 // Go through each filter address and set appropriate bits on hash table\r
0150e14d
RC
617 //\r
618 for (Count = 0; Count < MCastFilterCnt; Count++) {\r
619 Mac = &(MCastFilter[Count]);\r
620 CopyMem (&Mode->MCastFilter[Count], Mac, sizeof(EFI_MAC_ADDRESS));\r
46f2c53b 621\r
0150e14d 622 Crc = GenEtherCrc32 (Mac, NET_ETHER_ADDR_LEN);\r
46f2c53b
OM
623 //gBS->CalculateCrc32 ((VOID*)&Mfilter[Count],6,&Crc); <-- doesn't work as desired\r
624\r
0150e14d
RC
625 //\r
626 // The most significant 6 bits of the MAC address CRC constitute the hash\r
627 // value of the MAC address.\r
628 //\r
629 HashValue = (Crc >> 26) & 0x3F;\r
46f2c53b
OM
630\r
631 // Select hashlow register if MSB is not set\r
0150e14d
RC
632 if ((HashValue & 0x20) == 0) {\r
633 MultHashTableLow |= (1 << HashValue);\r
46f2c53b 634 } else {\r
0150e14d 635 MultHashTableHigh |= (1 << (HashValue & 0x1F));\r
46f2c53b
OM
636 }\r
637 }\r
0150e14d
RC
638 Mode->MCastFilterCount = MCastFilterCnt;\r
639 } else if (ResetMCastFilter) {\r
640 Mode->MCastFilterCount = 0;\r
641 } else {\r
642 MultHashTableLow = IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHL);\r
643 MultHashTableHigh = IndirectMACRead32 (INDIRECT_MAC_INDEX_HASHH);\r
46f2c53b
OM
644 }\r
645\r
11bbc257
RC
646 //\r
647 // Before to change anything, stop and reset the reception of\r
648 // packets.\r
649 //\r
650 StopRx (STOP_RX_CLEAR, Snp);\r
651\r
0150e14d
RC
652 //\r
653 // Write the mask of the selected hash values for the multicast filtering.\r
654 // The two masks are set to zero if the multicast filtering is not enabled.\r
655 //\r
656 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHL, MultHashTableLow);\r
657 IndirectMACWrite32 (INDIRECT_MAC_INDEX_HASHH, MultHashTableHigh);\r
658\r
11bbc257
RC
659 ReceiveFilterSetting = (Mode->ReceiveFilterSetting | Enable) & (~Disable);\r
660\r
661 //\r
46f2c53b 662 // Read MAC controller\r
11bbc257
RC
663 //\r
664 MacCSRValue = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR);\r
665 MacCSRValue &= ~(MACCR_HPFILT | MACCR_BCAST | MACCR_PRMS | MACCR_MCPAS);\r
46f2c53b 666\r
11bbc257
RC
667 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) {\r
668 Lan9118SetMacAddress (&Mode->CurrentAddress, Snp);\r
46f2c53b 669 DEBUG ((DEBUG_NET, "Allowing Unicast Frame Reception\n"));\r
11bbc257
RC
670 } else {\r
671 //\r
672 // The Unicast packets do not have to be listen to, set the MAC\r
673 // address of the LAN9118 to be the "not configured" all zeroes\r
674 // ethernet MAC address.\r
675 //\r
676 ZeroMem (&ZeroMac, NET_ETHER_ADDR_LEN);\r
677 Lan9118SetMacAddress (&ZeroMac, Snp);\r
46f2c53b
OM
678 }\r
679\r
11bbc257 680 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) {\r
46f2c53b
OM
681 MacCSRValue |= MACCR_HPFILT;\r
682 DEBUG ((DEBUG_NET, "Allowing Multicast Frame Reception\n"));\r
683 }\r
684\r
11bbc257
RC
685 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {\r
686 MacCSRValue |= MACCR_MCPAS;\r
687 DEBUG ((DEBUG_NET, "Enabling Promiscuous Multicast Mode\n"));\r
46f2c53b
OM
688 }\r
689\r
11bbc257 690 if ((ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) == 0) {\r
46f2c53b 691 MacCSRValue |= MACCR_BCAST;\r
11bbc257
RC
692 } else {\r
693 DEBUG ((DEBUG_NET, "Allowing Broadcast Frame Reception\n"));\r
46f2c53b
OM
694 }\r
695\r
11bbc257 696 if (ReceiveFilterSetting & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) {\r
46f2c53b
OM
697 MacCSRValue |= MACCR_PRMS;\r
698 DEBUG ((DEBUG_NET, "Enabling Promiscuous Mode\n"));\r
699 }\r
700\r
11bbc257 701 //\r
46f2c53b 702 // Write the options to the MAC_CSR\r
11bbc257 703 //\r
46f2c53b
OM
704 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCSRValue);\r
705 gBS->Stall (LAN9118_STALL);\r
706\r
11bbc257
RC
707 //\r
708 // If we have to retrieve something, start packet reception.\r
709 //\r
710 Mode->ReceiveFilterSetting = ReceiveFilterSetting;\r
711 if (ReceiveFilterSetting != 0) {\r
712 StartRx (0, Snp);\r
713 }\r
714\r
46f2c53b
OM
715 return EFI_SUCCESS;\r
716}\r
717\r
0150e14d
RC
718/**\r
719 Modify of reset the current station address\r
720\r
721 @param[in] Snp A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL\r
722 instance.\r
723 @param[in] Reset Flag used to reset the station address to the\r
724 LAN9118's permanent address.\r
725 @param[in] New New station address to be used for the network interface.\r
726\r
727 @retval EFI_SUCCESS The LAN9118's station address was updated.\r
728 @retval EFI_NOT_STARTED The LAN9118 has not been started.\r
729 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE :\r
730 . The "New" station address is invalid.\r
731 . "Reset" is FALSE and "New" is NULL.\r
732 @retval EFI_DEVICE_ERROR The LAN9118 has been started but not initialized.\r
733\r
734**/\r
46f2c53b
OM
735EFI_STATUS\r
736EFIAPI\r
737SnpStationAddress (\r
0150e14d
RC
738 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,\r
739 IN BOOLEAN Reset,\r
740 IN EFI_MAC_ADDRESS *New\r
46f2c53b
OM
741)\r
742{\r
46f2c53b 743 UINT32 Count;\r
0150e14d 744 UINT8 PermAddr[NET_ETHER_ADDR_LEN];\r
46f2c53b 745\r
0150e14d 746 DEBUG ((DEBUG_NET, "SnpStationAddress()\n"));\r
46f2c53b
OM
747\r
748 // Check Snp instance\r
749 if (Snp == NULL) {\r
750 return EFI_INVALID_PARAMETER;\r
751 }\r
752\r
753 // Check that driver was started and initialised\r
754 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
755 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));\r
756 return EFI_DEVICE_ERROR;\r
757 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
758 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));\r
759 return EFI_NOT_STARTED;\r
760 }\r
761\r
762 // Get the Permanent MAC address if need reset\r
763 if (Reset) {\r
764 // Try using EEPROM first. Read the first byte of data from EEPROM at the address 0x0\r
765 if ((IndirectEEPROMRead32 (0) & 0xFF) == EEPROM_EXTERNAL_SERIAL_EEPROM) {\r
0150e14d
RC
766 for (Count = 0; Count < NET_ETHER_ADDR_LEN; Count++) {\r
767 PermAddr[Count] = IndirectEEPROMRead32 (Count + 1);\r
46f2c53b 768 }\r
0150e14d 769 New = (EFI_MAC_ADDRESS *) PermAddr;\r
46f2c53b
OM
770 Lan9118SetMacAddress ((EFI_MAC_ADDRESS *) PermAddr, Snp);\r
771 } else {\r
772 DEBUG ((EFI_D_ERROR, "Lan9118: Warning: No valid MAC address in EEPROM, using fallback\n"));\r
0150e14d 773 New = (EFI_MAC_ADDRESS*) (FixedPcdGet64 (PcdLan9118DefaultMacAddress));\r
46f2c53b
OM
774 }\r
775 } else {\r
776 // Otherwise use the specified new MAC address\r
0150e14d
RC
777 if (New == NULL) {\r
778 return EFI_INVALID_PARAMETER;\r
779 }\r
780 //\r
781 // If it is a multicast address, it is not valid.\r
782 //\r
783 if (New->Addr[0] & 0x01) {\r
46f2c53b
OM
784 return EFI_INVALID_PARAMETER;\r
785 }\r
46f2c53b
OM
786 }\r
787\r
11bbc257
RC
788 CopyMem (&Snp->Mode->CurrentAddress, New, NET_ETHER_ADDR_LEN);\r
789\r
790 //\r
791 // If packet reception is currently activated, stop and reset it,\r
792 // set the new ethernet address and restart the packet reception.\r
793 // Otherwise, nothing to do, the MAC address will be updated in\r
794 // SnpReceiveFilters() when the UNICAST packet reception will be\r
795 // activated.\r
796 //\r
797 if (Snp->Mode->ReceiveFilterSetting != 0) {\r
798 StopRx (STOP_RX_CLEAR, Snp);\r
799 Lan9118SetMacAddress (New, Snp);\r
800 StartRx (0, Snp);\r
801 }\r
0150e14d 802\r
46f2c53b
OM
803 return EFI_SUCCESS;\r
804}\r
805\r
806/*\r
807 * UEFI Statistics() function\r
808 *\r
809 */\r
810EFI_STATUS\r
811EFIAPI\r
812SnpStatistics (\r
813 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,\r
814 IN BOOLEAN Reset,\r
815 IN OUT UINTN *StatSize,\r
816 OUT EFI_NETWORK_STATISTICS *Statistics\r
817 )\r
818{\r
0150e14d
RC
819 LAN9118_DRIVER *LanDriver;\r
820 EFI_STATUS Status;\r
46f2c53b
OM
821\r
822 LanDriver = INSTANCE_FROM_SNP_THIS (Snp);\r
823\r
824 DEBUG ((DEBUG_NET, "SnpStatistics()\n"));\r
825\r
826 // Check Snp instance\r
827 if (Snp == NULL) {\r
828 return EFI_INVALID_PARAMETER;\r
829 }\r
830\r
831 // Check that driver was started and initialised\r
832 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
833 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));\r
834 return EFI_DEVICE_ERROR;\r
835 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
836 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));\r
837 return EFI_NOT_STARTED;\r
838 }\r
839\r
0150e14d
RC
840 //\r
841 // Do a reset if required. It is not clearly stated in the UEFI specification\r
842 // whether the reset has to be done before to copy the statistics in "Statictics"\r
843 // or after. It is a bit strange to do it before but that is what is expected by\r
844 // the SCT test on Statistics() with reset : "0x3de76704,0x4bf5,0x42cd,0x8c,0x89,\r
845 // 0x54,0x7e,0x4f,0xad,0x4f,0x24".\r
846 //\r
46f2c53b
OM
847 if (Reset) {\r
848 ZeroMem (&LanDriver->Stats, sizeof(EFI_NETWORK_STATISTICS));\r
849 }\r
850\r
0150e14d
RC
851 Status = EFI_SUCCESS;\r
852 if (StatSize == NULL) {\r
853 if (Statistics != NULL) {\r
854 return EFI_INVALID_PARAMETER;\r
855 }\r
856 } else {\r
857 if (Statistics == NULL) {\r
858 Status = EFI_BUFFER_TOO_SMALL;\r
859 } else {\r
860 // Fill in the statistics\r
861 CopyMem (\r
862 Statistics, &LanDriver->Stats,\r
863 MIN (*StatSize, sizeof (EFI_NETWORK_STATISTICS))\r
864 );\r
865 if (*StatSize < sizeof (EFI_NETWORK_STATISTICS)) {\r
866 Status = EFI_BUFFER_TOO_SMALL;\r
867 }\r
868 }\r
869 *StatSize = sizeof (EFI_NETWORK_STATISTICS);\r
46f2c53b
OM
870 }\r
871\r
0150e14d 872 return Status;\r
46f2c53b
OM
873}\r
874\r
875/*\r
876 * UEFI MCastIPtoMAC() function\r
877 *\r
878 */\r
879EFI_STATUS\r
880EFIAPI\r
881SnpMcastIptoMac (\r
882 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,\r
883 IN BOOLEAN IsIpv6,\r
884 IN EFI_IP_ADDRESS *Ip,\r
885 OUT EFI_MAC_ADDRESS *McastMac\r
886 )\r
887{\r
888 DEBUG ((DEBUG_NET, "SnpMcastIptoMac()\n"));\r
889\r
890 // Check Snp instance\r
891 if (Snp == NULL) {\r
892 return EFI_INVALID_PARAMETER;\r
893 }\r
894\r
895 // Check that driver was started and initialised\r
896 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
897 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));\r
898 return EFI_DEVICE_ERROR;\r
899 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
900 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));\r
901 return EFI_NOT_STARTED;\r
902 }\r
903\r
904 // Check parameters\r
905 if ((McastMac == NULL) || (Ip == NULL)) {\r
906 return EFI_INVALID_PARAMETER;\r
907 }\r
908\r
909 // Make sure MAC address is empty\r
910 ZeroMem (McastMac, sizeof(EFI_MAC_ADDRESS));\r
911\r
912 // If we need ipv4 address\r
913 if (!IsIpv6) {\r
914 // Most significant 25 bits of a multicast HW address are set.\r
915 // 01-00-5E is the IPv4 Ethernet Multicast Address (see RFC 1112)\r
916 McastMac->Addr[0] = 0x01;\r
917 McastMac->Addr[1] = 0x00;\r
918 McastMac->Addr[2] = 0x5E;\r
919\r
920 // Lower 23 bits from ipv4 address\r
921 McastMac->Addr[3] = (Ip->v4.Addr[1] & 0x7F); // Clear the most significant bit (25th bit of MAC must be 0)\r
922 McastMac->Addr[4] = Ip->v4.Addr[2];\r
923 McastMac->Addr[5] = Ip->v4.Addr[3];\r
924 } else {\r
925 // Most significant 16 bits of multicast v6 HW address are set\r
926 // 33-33 is the IPv6 Ethernet Multicast Address (see RFC 2464)\r
927 McastMac->Addr[0] = 0x33;\r
928 McastMac->Addr[1] = 0x33;\r
929\r
930 // lower four octets are taken from ipv6 address\r
931 McastMac->Addr[2] = Ip->v6.Addr[8];\r
932 McastMac->Addr[3] = Ip->v6.Addr[9];\r
933 McastMac->Addr[4] = Ip->v6.Addr[10];\r
934 McastMac->Addr[5] = Ip->v6.Addr[11];\r
935 }\r
936\r
937 return EFI_SUCCESS;\r
938}\r
939\r
940/*\r
941 * UEFI NvData() function\r
942 *\r
943 */\r
944EFI_STATUS\r
945EFIAPI\r
946SnpNvData (\r
947 IN EFI_SIMPLE_NETWORK_PROTOCOL* pobj,\r
948 IN BOOLEAN read_write,\r
949 IN UINTN offset,\r
950 IN UINTN buff_size,\r
951 IN OUT VOID *data\r
952 )\r
953{\r
954 DEBUG ((DEBUG_NET, "SnpNvData()\n"));\r
955\r
956 return EFI_UNSUPPORTED;\r
957}\r
958\r
959\r
960/*\r
961 * UEFI GetStatus () function\r
962 *\r
963 */\r
964EFI_STATUS\r
965EFIAPI\r
966SnpGetStatus (\r
0150e14d
RC
967 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,\r
968 OUT UINT32 *IrqStat OPTIONAL,\r
969 OUT VOID **TxBuff OPTIONAL\r
46f2c53b
OM
970 )\r
971{\r
972 UINT32 FifoInt;\r
973 EFI_STATUS Status;\r
974 UINTN NumTxStatusEntries;\r
975 UINT32 TxStatus;\r
976 UINT16 PacketTag;\r
977 UINT32 Interrupts;\r
978 LAN9118_DRIVER *LanDriver;\r
979\r
980 LanDriver = INSTANCE_FROM_SNP_THIS (Snp);\r
981\r
982 // Check preliminaries\r
983 if (Snp == NULL) {\r
984 return EFI_INVALID_PARAMETER;\r
985 }\r
986\r
0150e14d
RC
987 // Check that driver was started and initialised\r
988 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
989 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));\r
990 return EFI_DEVICE_ERROR;\r
991 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
992 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));\r
46f2c53b
OM
993 return EFI_NOT_STARTED;\r
994 }\r
995\r
996 // Check and acknowledge TX Status interrupt (this will happen if the\r
997 // consumer of SNP does not call GetStatus.)\r
998 // TODO will we lose TxStatuses if this happens? Maybe in SnpTransmit we\r
999 // should check for it and dump the TX Status FIFO.\r
1000 FifoInt = MmioRead32 (LAN9118_FIFO_INT);\r
1001\r
1002 // Clear the TX Status FIFO Overflow\r
1003 if ((FifoInt & INSTS_TXSO) == 0) {\r
1004 FifoInt |= INSTS_TXSO;\r
1005 MmioWrite32 (LAN9118_FIFO_INT, FifoInt);\r
1006 }\r
1007\r
1008 // Read interrupt status if IrqStat is not NULL\r
1009 if (IrqStat != NULL) {\r
e52aee5d 1010 *IrqStat = 0;\r
46f2c53b
OM
1011\r
1012 // Check for receive interrupt\r
1013 if (MmioRead32 (LAN9118_INT_STS) & INSTS_RSFL) { // Data moved from rx FIFO\r
1014 *IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;\r
1015 MmioWrite32 (LAN9118_INT_STS,INSTS_RSFL);\r
46f2c53b
OM
1016 }\r
1017\r
1018 // Check for transmit interrupt\r
1019 if (MmioRead32 (LAN9118_INT_STS) & INSTS_TSFL) {\r
1020 *IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;\r
1021 MmioWrite32 (LAN9118_INT_STS,INSTS_TSFL);\r
46f2c53b
OM
1022 }\r
1023\r
1024 // Check for software interrupt\r
1025 if (MmioRead32 (LAN9118_INT_STS) & INSTS_SW_INT) {\r
1026 *IrqStat |= EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT;\r
1027 MmioWrite32 (LAN9118_INT_STS,INSTS_SW_INT);\r
46f2c53b
OM
1028 }\r
1029 }\r
1030\r
1031 // Check Status of transmitted packets\r
1032 // (We ignore TXSTATUS_NO_CA has it might happen in Full Duplex)\r
1033\r
1034 NumTxStatusEntries = MmioRead32(LAN9118_TX_FIFO_INF) & TXFIFOINF_TXSUSED_MASK;\r
1035 if (NumTxStatusEntries > 0) {\r
1036 TxStatus = MmioRead32 (LAN9118_TX_STATUS);\r
1037 PacketTag = TxStatus >> 16;\r
1038 TxStatus = TxStatus & 0xFFFF;\r
a537c717 1039 if ((TxStatus & TXSTATUS_ES) && (TxStatus != (TXSTATUS_ES | TXSTATUS_NO_CA))) {\r
46f2c53b
OM
1040 DEBUG ((EFI_D_ERROR, "LAN9118: There was an error transmitting. TxStatus=0x%08x:", TxStatus));\r
1041 if (TxStatus & TXSTATUS_NO_CA) {\r
1042 DEBUG ((EFI_D_ERROR, "- No carrier\n"));\r
1043 }\r
1044 if (TxStatus & TXSTATUS_DEF) {\r
1045 DEBUG ((EFI_D_ERROR, "- Packet tx was deferred\n"));\r
1046 }\r
1047 if (TxStatus & TXSTATUS_EDEF) {\r
1048 DEBUG ((EFI_D_ERROR, "- Tx ended because of excessive deferral\n"));\r
1049 }\r
1050 if (TxStatus & TXSTATUS_ECOLL) {\r
1051 DEBUG ((EFI_D_ERROR, "- Tx ended because of Excessive Collisions\n"));\r
1052 }\r
1053 if (TxStatus & TXSTATUS_LCOLL) {\r
1054 DEBUG ((EFI_D_ERROR, "- Packet Tx aborted after coll window of 64 bytes\n"));\r
1055 }\r
1056 if (TxStatus & TXSTATUS_LOST_CA) {\r
1057 DEBUG ((EFI_D_ERROR, "- Lost carrier during Tx\n"));\r
1058 }\r
1059 return EFI_DEVICE_ERROR;\r
a537c717 1060 } else if (TxBuff != NULL) {\r
46f2c53b
OM
1061 LanDriver->Stats.TxTotalFrames += 1;\r
1062 *TxBuff = LanDriver->TxRing[PacketTag % LAN9118_TX_RING_NUM_ENTRIES];\r
1063 }\r
1064 }\r
1065\r
1066 // Check for a TX Error interrupt\r
1067 Interrupts = MmioRead32 (LAN9118_INT_STS);\r
1068 if (Interrupts & INSTS_TXE) {\r
1069 DEBUG ((EFI_D_ERROR, "LAN9118: Transmitter error. Restarting..."));\r
1070\r
ac8f1e10 1071 // Software reset, the TXE interrupt is cleared by the reset.\r
42589b9a
OM
1072 Status = SoftReset (0, Snp);\r
1073 if (EFI_ERROR (Status)) {\r
46f2c53b
OM
1074 DEBUG ((EFI_D_ERROR, "\n\tSoft Reset Failed: Hardware Error\n"));\r
1075 return EFI_DEVICE_ERROR;\r
1076 }\r
1077\r
ac8f1e10
RC
1078 // Reactivate the LEDs\r
1079 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);\r
1080 if (EFI_ERROR (Status)) {\r
1081 return Status;\r
1082 }\r
46f2c53b 1083\r
ac8f1e10
RC
1084 //\r
1085 // Restart the transmitter and if necessary the receiver.\r
1086 // Do not ask for FIFO reset as it has already been done\r
1087 // by SoftReset().\r
1088 //\r
46f2c53b 1089 StartTx (START_TX_MAC | START_TX_CFG, Snp);\r
ac8f1e10
RC
1090 if (Snp->Mode->ReceiveFilterSetting != 0) {\r
1091 StartRx (0, Snp);\r
1092 }\r
46f2c53b
OM
1093 }\r
1094\r
1095 // Update the media status\r
1096 Status = CheckLinkStatus (0, Snp);\r
1097 if (EFI_ERROR(Status)) {\r
1098 Snp->Mode->MediaPresent = FALSE;\r
1099 } else {\r
1100 Snp->Mode->MediaPresent = TRUE;\r
1101 }\r
1102\r
1103 return EFI_SUCCESS;\r
1104}\r
1105\r
1106\r
1107/*\r
1108 * UEFI Transmit() function\r
1109 *\r
1110 */\r
1111EFI_STATUS\r
1112EFIAPI\r
1113SnpTransmit (\r
1114 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp,\r
1115 IN UINTN HdrSize,\r
1116 IN UINTN BuffSize,\r
1117 IN VOID* Data,\r
1118 IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
1119 IN EFI_MAC_ADDRESS *DstAddr OPTIONAL,\r
1120 IN UINT16 *Protocol OPTIONAL\r
1121 )\r
1122{\r
1123 LAN9118_DRIVER *LanDriver;\r
1124 UINT32 TxFreeSpace;\r
1125 UINT32 TxStatusSpace;\r
1126 INT32 Count;\r
1127 UINT32 CommandA;\r
1128 UINT32 CommandB;\r
1129 UINT16 LocalProtocol;\r
1130 UINT32 *LocalData;\r
1131 UINT16 PacketTag;\r
1132\r
1133#if defined(EVAL_PERFORMANCE)\r
1134 UINT64 Perf;\r
1135 UINT64 StartClock;\r
1136 UINT64 EndClock;\r
1137\r
1138 Perf = GetPerformanceCounterProperties (NULL, NULL);\r
1139 StartClock = GetPerformanceCounter ();\r
1140#endif\r
1141\r
1142 LanDriver = INSTANCE_FROM_SNP_THIS (Snp);\r
1143\r
1144 // Check preliminaries\r
1145 if ((Snp == NULL) || (Data == NULL)) {\r
1146 return EFI_INVALID_PARAMETER;\r
1147 }\r
0150e14d
RC
1148\r
1149 // Check that driver was started and initialised\r
1150 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
1151 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));\r
1152 return EFI_DEVICE_ERROR;\r
1153 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
1154 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));\r
46f2c53b
OM
1155 return EFI_NOT_STARTED;\r
1156 }\r
1157\r
1158 // Ensure header is correct size if non-zero\r
1159 if (HdrSize) {\r
1160 if (HdrSize != Snp->Mode->MediaHeaderSize) {\r
1161 return EFI_INVALID_PARAMETER;\r
1162 }\r
1163\r
1164 if ((DstAddr == NULL) || (Protocol == NULL)) {\r
1165 return EFI_INVALID_PARAMETER;\r
1166 }\r
1167 }\r
1168\r
0150e14d
RC
1169 //\r
1170 // Check validity of BufferSize\r
1171 //\r
1172 if (BuffSize < Snp->Mode->MediaHeaderSize) {\r
1173 return EFI_BUFFER_TOO_SMALL;\r
1174 }\r
1175\r
46f2c53b
OM
1176 // Before transmitting check the link status\r
1177 /*if (CheckLinkStatus (0, Snp) < 0) {\r
1178 return EFI_NOT_READY;\r
1179 }*/\r
1180\r
1181 // Get DATA FIFO free space in bytes\r
1182 TxFreeSpace = TxDataFreeSpace (0, Snp);\r
1183 if (TxFreeSpace < BuffSize) {\r
1184 return EFI_NOT_READY;\r
1185 }\r
1186\r
1187 // Get STATUS FIFO used space in bytes\r
1188 TxStatusSpace = TxStatusUsedSpace (0, Snp);\r
1189 if (TxStatusSpace > 500) {\r
1190 return EFI_NOT_READY;\r
1191 }\r
1192\r
1193 // If DstAddr is not provided, get it from Buffer (we trust that the caller\r
1194 // has provided a well-formed frame).\r
1195 if (DstAddr == NULL) {\r
1196 DstAddr = (EFI_MAC_ADDRESS *) Data;\r
1197 }\r
1198\r
1199 // Check for the nature of the frame\r
1200 if ((DstAddr->Addr[0] & 0x1) == 1) {\r
1201 LanDriver->Stats.TxMulticastFrames += 1;\r
1202 } else {\r
1203 LanDriver->Stats.TxUnicastFrames += 1;\r
1204 }\r
1205\r
1206 // Check if broadcast\r
1207 if (DstAddr->Addr[0] == 0xFF) {\r
1208 LanDriver->Stats.TxBroadcastFrames += 1;\r
1209 }\r
1210\r
1211 PacketTag = LanDriver->NextPacketTag;\r
1212 LanDriver->NextPacketTag++;\r
1213\r
1214 if (HdrSize) {\r
1215\r
1216 // Format pointer\r
1217 LocalData = (UINT32*) Data;\r
1218 LocalProtocol = *Protocol;\r
1219\r
1220 // Create first buffer to pass to controller (for the header)\r
1221 CommandA = TX_CMD_A_FIRST_SEGMENT | TX_CMD_A_BUFF_SIZE (HdrSize);\r
1222 CommandB = TX_CMD_B_PACKET_TAG (PacketTag) | TX_CMD_B_PACKET_LENGTH (BuffSize);\r
1223\r
1224 // Write the commands first\r
1225 MmioWrite32 (LAN9118_TX_DATA, CommandA);\r
1226 MmioWrite32 (LAN9118_TX_DATA, CommandB);\r
1227\r
1228 // Write the destination address\r
1229 MmioWrite32 (LAN9118_TX_DATA,\r
1230 (DstAddr->Addr[0]) |\r
1231 (DstAddr->Addr[1] << 8) |\r
1232 (DstAddr->Addr[2] << 16) |\r
1233 (DstAddr->Addr[3] << 24)\r
1234 );\r
1235\r
1236 MmioWrite32 (LAN9118_TX_DATA,\r
1237 (DstAddr->Addr[4]) |\r
1238 (DstAddr->Addr[5] << 8) |\r
1239 (SrcAddr->Addr[0] << 16) | // Write the Source Address\r
1240 (SrcAddr->Addr[1] << 24)\r
1241 );\r
1242\r
1243 MmioWrite32 (LAN9118_TX_DATA,\r
1244 (SrcAddr->Addr[2]) |\r
1245 (SrcAddr->Addr[3] << 8) |\r
1246 (SrcAddr->Addr[4] << 16) |\r
1247 (SrcAddr->Addr[5] << 24)\r
1248 );\r
1249\r
1250 // Write the Protocol\r
1251 MmioWrite32 (LAN9118_TX_DATA, (UINT32)(HTONS (LocalProtocol)));\r
1252\r
1253 // Next buffer is the payload\r
1254 CommandA = TX_CMD_A_LAST_SEGMENT | TX_CMD_A_BUFF_SIZE (BuffSize - HdrSize) | TX_CMD_A_COMPLETION_INT | TX_CMD_A_DATA_START_OFFSET (2); // 2 bytes beginning offset\r
1255\r
1256 // Write the commands\r
1257 MmioWrite32 (LAN9118_TX_DATA, CommandA);\r
1258 MmioWrite32 (LAN9118_TX_DATA, CommandB);\r
1259\r
1260 // Write the payload\r
1261 for (Count = 0; Count < ((BuffSize + 3) >> 2) - 3; Count++) {\r
1262 MmioWrite32 (LAN9118_TX_DATA, LocalData[Count + 3]);\r
1263 }\r
1264 } else {\r
1265 // Format pointer\r
1266 LocalData = (UINT32*) Data;\r
1267\r
1268 // Create a buffer to pass to controller\r
1269 CommandA = TX_CMD_A_FIRST_SEGMENT | TX_CMD_A_LAST_SEGMENT | TX_CMD_A_BUFF_SIZE (BuffSize) | TX_CMD_A_COMPLETION_INT;\r
1270 CommandB = TX_CMD_B_PACKET_TAG (PacketTag) | TX_CMD_B_PACKET_LENGTH (BuffSize);\r
1271\r
1272 // Write the commands first\r
1273 MmioWrite32 (LAN9118_TX_DATA, CommandA);\r
1274 MmioWrite32 (LAN9118_TX_DATA, CommandB);\r
1275\r
1276 // Write all the data\r
1277 for (Count = 0; Count < ((BuffSize + 3) >> 2); Count++) {\r
1278 MmioWrite32 (LAN9118_TX_DATA, LocalData[Count]);\r
1279 }\r
1280 }\r
1281\r
1282 // Save the address of the submitted packet so we can notify the consumer that\r
1283 // it has been sent in GetStatus. When the packet tag appears in the Tx Status\r
1284 // Fifo, we will return Buffer in the TxBuff parameter of GetStatus.\r
1285 LanDriver->TxRing[PacketTag % LAN9118_TX_RING_NUM_ENTRIES] = Data;\r
1286\r
1287#if defined(EVAL_PERFORMANCE)\r
1288 EndClock = GetPerformanceCounter ();\r
1289 DEBUG ((EFI_D_ERROR, "Time processing: %d counts @ %d Hz\n", StartClock - EndClock,Perf));\r
1290#endif\r
1291\r
1292 LanDriver->Stats.TxGoodFrames += 1;\r
1293\r
1294 return EFI_SUCCESS;\r
1295}\r
1296\r
1297\r
1298/*\r
1299 * UEFI Receive() function\r
1300 *\r
1301 */\r
1302EFI_STATUS\r
1303EFIAPI\r
1304SnpReceive (\r
1305 IN EFI_SIMPLE_NETWORK_PROTOCOL* Snp,\r
1306 OUT UINTN *HdrSize OPTIONAL,\r
1307 IN OUT UINTN *BuffSize,\r
1308 OUT VOID *Data,\r
1309 OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
1310 OUT EFI_MAC_ADDRESS *DstAddr OPTIONAL,\r
1311 OUT UINT16 *Protocol OPTIONAL\r
1312 )\r
1313{\r
42589b9a
OM
1314 LAN9118_DRIVER *LanDriver;\r
1315 UINT32 RxFifoStatus;\r
1316 UINT32 NumPackets;\r
1317 UINT32 RxCfgValue;\r
1318 UINT32 PLength; // Packet length\r
1319 UINT32 ReadLimit;\r
1320 UINT32 Count;\r
1321 UINT32 Padding;\r
1322 UINT32 *RawData;\r
46f2c53b
OM
1323 EFI_MAC_ADDRESS Dst;\r
1324 EFI_MAC_ADDRESS Src;\r
42589b9a
OM
1325 UINTN DroppedFrames;\r
1326 EFI_STATUS Status;\r
46f2c53b
OM
1327\r
1328 LanDriver = INSTANCE_FROM_SNP_THIS (Snp);\r
1329\r
1330#if defined(EVAL_PERFORMANCE)\r
1331 UINT64 Perf = GetPerformanceCounterProperties (NULL, NULL);\r
1332 UINT64 StartClock = GetPerformanceCounter ();\r
1333#endif\r
1334\r
1335 // Check preliminaries\r
0150e14d 1336 if ((Snp == NULL) || (Data == NULL) || (BuffSize == NULL)) {\r
46f2c53b
OM
1337 return EFI_INVALID_PARAMETER;\r
1338 }\r
1339\r
0150e14d
RC
1340 // Check that driver was started and initialised\r
1341 if (Snp->Mode->State == EfiSimpleNetworkStarted) {\r
1342 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver not initialized\n"));\r
1343 return EFI_DEVICE_ERROR;\r
1344 } else if (Snp->Mode->State == EfiSimpleNetworkStopped) {\r
1345 DEBUG ((EFI_D_WARN, "Warning: LAN9118 Driver in stopped state\n"));\r
46f2c53b
OM
1346 return EFI_NOT_STARTED;\r
1347 }\r
1348\r
1349 // Count dropped frames\r
1350 DroppedFrames = MmioRead32 (LAN9118_RX_DROP);\r
1351 LanDriver->Stats.RxDroppedFrames += DroppedFrames;\r
1352\r
1353 NumPackets = RxStatusUsedSpace (0, Snp) / 4;\r
1354 if (!NumPackets) {\r
1355 return EFI_NOT_READY;\r
1356 }\r
1357\r
1358 // Read Rx Status (only if not empty)\r
1359 RxFifoStatus = MmioRead32 (LAN9118_RX_STATUS);\r
1360 LanDriver->Stats.RxTotalFrames += 1;\r
1361\r
1362 // First check for errors\r
1363 if ((RxFifoStatus & RXSTATUS_MII_ERROR) ||\r
1364 (RxFifoStatus & RXSTATUS_RXW_TO) ||\r
1365 (RxFifoStatus & RXSTATUS_FTL) ||\r
1366 (RxFifoStatus & RXSTATUS_LCOLL) ||\r
1367 (RxFifoStatus & RXSTATUS_LE) ||\r
1368 (RxFifoStatus & RXSTATUS_DB))\r
1369 {\r
1370 DEBUG ((EFI_D_WARN, "Warning: There was an error on frame reception.\n"));\r
1371 return EFI_DEVICE_ERROR;\r
1372 }\r
1373\r
1374 // Check if we got a CRC error\r
1375 if (RxFifoStatus & RXSTATUS_CRC_ERROR) {\r
1376 DEBUG ((EFI_D_WARN, "Warning: Crc Error\n"));\r
1377 LanDriver->Stats.RxCrcErrorFrames += 1;\r
1378 LanDriver->Stats.RxDroppedFrames += 1;\r
1379 return EFI_DEVICE_ERROR;\r
1380 }\r
1381\r
1382 // Check if we got a runt frame\r
1383 if (RxFifoStatus & RXSTATUS_RUNT) {\r
1384 DEBUG ((EFI_D_WARN, "Warning: Runt Frame\n"));\r
1385 LanDriver->Stats.RxUndersizeFrames += 1;\r
1386 LanDriver->Stats.RxDroppedFrames += 1;\r
1387 return EFI_DEVICE_ERROR;\r
1388 }\r
1389\r
1390 // Check filtering status for this packet\r
1391 if (RxFifoStatus & RXSTATUS_FILT_FAIL) {\r
1392 DEBUG ((EFI_D_WARN, "Warning: Frame Failed Filtering\n"));\r
1393 // fast forward?\r
1394 }\r
1395\r
1396 // Check if we got a broadcast frame\r
1397 if (RxFifoStatus & RXSTATUS_BCF) {\r
1398 LanDriver->Stats.RxBroadcastFrames += 1;\r
1399 }\r
1400\r
1401 // Check if we got a multicast frame\r
1402 if (RxFifoStatus & RXSTATUS_MCF) {\r
1403 LanDriver->Stats.RxMulticastFrames += 1;\r
1404 }\r
1405\r
1406 // Check if we got a unicast frame\r
1407 if ((RxFifoStatus & RXSTATUS_BCF) && ((RxFifoStatus & RXSTATUS_MCF) == 0)) {\r
1408 LanDriver->Stats.RxUnicastFrames += 1;\r
1409 }\r
1410\r
1411 // Get the received packet length\r
1412 PLength = GET_RXSTATUS_PACKET_LENGTH(RxFifoStatus);\r
1413 LanDriver->Stats.RxTotalBytes += (PLength - 4);\r
1414\r
46f2c53b
OM
1415 // If padding is applied, read more DWORDs\r
1416 if (PLength % 4) {\r
1417 Padding = 4 - (PLength % 4);\r
1418 ReadLimit = (PLength + Padding)/4;\r
1419 } else {\r
1420 ReadLimit = PLength/4;\r
1421 Padding = 0;\r
1422 }\r
1423\r
f22e9658
OM
1424 // Check buffer size\r
1425 if (*BuffSize < (PLength + Padding)) {\r
1426 *BuffSize = PLength + Padding;\r
1427 return EFI_BUFFER_TOO_SMALL;\r
1428 }\r
1429\r
46f2c53b
OM
1430 // Set the amount of data to be transfered out of FIFO for THIS packet\r
1431 // This can be used to trigger an interrupt, and status can be checked\r
1432 RxCfgValue = MmioRead32 (LAN9118_RX_CFG);\r
1433 RxCfgValue &= ~(RXCFG_RX_DMA_CNT_MASK);\r
1434 RxCfgValue |= RXCFG_RX_DMA_CNT (ReadLimit);\r
1435\r
1436 // Set end alignment to 4-bytes\r
1437 RxCfgValue &= ~(RXCFG_RX_END_ALIGN_MASK);\r
1438 MmioWrite32 (LAN9118_RX_CFG, RxCfgValue);\r
1439\r
1440 // Update buffer size\r
1441 *BuffSize = PLength; // -4 bytes may be needed: Received in buffer as\r
1442 // 4 bytes longer than packet actually is, unless\r
1443 // packet is < 64 bytes\r
1444\r
1445 if (HdrSize != NULL)\r
1446 *HdrSize = Snp->Mode->MediaHeaderSize;\r
1447\r
1448 // Format the pointer\r
1449 RawData = (UINT32*)Data;\r
1450\r
1451 // Read Rx Packet\r
1452 for (Count = 0; Count < ReadLimit; Count++) {\r
1453 RawData[Count] = MmioRead32 (LAN9118_RX_DATA);\r
1454 }\r
1455\r
1456 // Check for Rx errors (worst possible error)\r
1457 if (MmioRead32 (LAN9118_INT_STS) & INSTS_RXE) {\r
1458 DEBUG ((EFI_D_WARN, "Warning: Receiver Error. Restarting...\n"));\r
1459\r
ac8f1e10 1460 // Software reset, the RXE interrupt is cleared by the reset.\r
42589b9a
OM
1461 Status = SoftReset (0, Snp);\r
1462 if (EFI_ERROR (Status)) {\r
46f2c53b
OM
1463 DEBUG ((EFI_D_ERROR, "Error: Soft Reset Failed: Hardware Error.\n"));\r
1464 return EFI_DEVICE_ERROR;\r
1465 }\r
1466\r
ac8f1e10
RC
1467 // Reactivate the LEDs\r
1468 Status = ConfigureHardware (HW_CONF_USE_LEDS, Snp);\r
1469 if (EFI_ERROR (Status)) {\r
1470 return Status;\r
1471 }\r
46f2c53b 1472\r
ac8f1e10
RC
1473 //\r
1474 // Restart the receiver and the transmitter without reseting the FIFOs\r
1475 // as it has been done by SoftReset().\r
1476 //\r
46f2c53b 1477 StartRx (0, Snp);\r
ac8f1e10 1478 StartTx (START_TX_MAC | START_TX_CFG, Snp);\r
46f2c53b
OM
1479\r
1480 // Say that command could not be sent\r
1481 return EFI_DEVICE_ERROR;\r
1482 }\r
1483\r
1484 // Get the destination address\r
1485 if (DstAddr != NULL) {\r
1486 Dst.Addr[0] = (RawData[0] & 0xFF);\r
1487 Dst.Addr[1] = (RawData[0] & 0xFF00) >> 8;\r
1488 Dst.Addr[2] = (RawData[0] & 0xFF0000) >> 16;\r
1489 Dst.Addr[3] = (RawData[0] & 0xFF000000) >> 24;\r
1490 Dst.Addr[4] = (RawData[1] & 0xFF);\r
1491 Dst.Addr[5] = (RawData[1] & 0xFF00) >> 8;\r
1492 CopyMem (DstAddr, &Dst, NET_ETHER_ADDR_LEN);\r
1493 }\r
1494\r
1495 // Get the source address\r
1496 if (SrcAddr != NULL) {\r
1497 Src.Addr[0] = (RawData[1] & 0xFF0000) >> 16;\r
1498 Src.Addr[1] = (RawData[1] & 0xFF000000) >> 24;\r
1499 Src.Addr[2] = (RawData[2] & 0xFF);\r
1500 Src.Addr[3] = (RawData[2] & 0xFF00) >> 8;\r
1501 Src.Addr[4] = (RawData[2] & 0xFF0000) >> 16;\r
1502 Src.Addr[5] = (RawData[2] & 0xFF000000) >> 24;\r
1503 CopyMem (SrcAddr,&Src, NET_ETHER_ADDR_LEN);\r
1504 }\r
1505\r
1506 // Get the protocol\r
1507 if (Protocol != NULL) {\r
1508 *Protocol = NTOHS (RawData[3] & 0xFFFF);\r
1509 }\r
1510\r
1511#if defined(EVAL_PERFORMANCE)\r
1512 UINT64 EndClock = GetPerformanceCounter ();\r
1513 DEBUG ((EFI_D_ERROR, "Receive Time processing: %d counts @ %d Hz\n", StartClock - EndClock,Perf));\r
1514#endif\r
1515\r
1516 LanDriver->Stats.RxGoodFrames += 1;\r
1517\r
1518 return EFI_SUCCESS;\r
1519}\r