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