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