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