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