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