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