]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Drivers/Lan9118Dxe/Lan9118DxeUtil.c
EmbeddedPkg: Fix various typos
[mirror_edk2.git] / EmbeddedPkg / Drivers / Lan9118Dxe / Lan9118DxeUtil.c
1 /** @file
2 *
3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-2-Clause-Patent
6 *
7 **/
8
9 #include "Lan9118Dxe.h"
10
11 STATIC EFI_MAC_ADDRESS mZeroMac = { { 0 } };
12
13 /**
14 This internal function reverses bits for 32bit data.
15
16 @param Value The data to be reversed.
17
18 @return Data reversed.
19
20 **/
21 UINT32
22 ReverseBits (
23 UINT32 Value
24 )
25 {
26 UINTN Index;
27 UINT32 NewValue;
28
29 NewValue = 0;
30 for (Index = 0; Index < 32; Index++) {
31 if ((Value & (1 << Index)) != 0) {
32 NewValue = NewValue | (1 << (31 - Index));
33 }
34 }
35
36 return NewValue;
37 }
38
39 /*
40 ** Create Ethernet CRC
41 **
42 ** INFO USED:
43 ** 1: http://en.wikipedia.org/wiki/Cyclic_redundancy_check
44 **
45 ** 2: http://www.erg.abdn.ac.uk/~gorry/eg3567/dl-pages/crc.html
46 **
47 ** 3: http://en.wikipedia.org/wiki/Computation_of_CRC
48 */
49 UINT32
50 GenEtherCrc32 (
51 IN EFI_MAC_ADDRESS *Mac,
52 IN UINT32 AddrLen
53 )
54 {
55 INT32 Iter;
56 UINT32 Remainder;
57 UINT8 *Ptr;
58
59 Iter = 0;
60 Remainder = 0xFFFFFFFF; // 0xFFFFFFFF is standard seed for Ethernet
61
62 // Convert Mac Address to array of bytes
63 Ptr = (UINT8*)Mac;
64
65 // Generate the Crc bit-by-bit (LSB first)
66 while (AddrLen--) {
67 Remainder ^= *Ptr++;
68 for (Iter = 0;Iter < 8;Iter++) {
69 // Check if exponent is set
70 if (Remainder & 1) {
71 Remainder = (Remainder >> 1) ^ CRC_POLYNOMIAL;
72 } else {
73 Remainder = (Remainder >> 1) ^ 0;
74 }
75 }
76 }
77
78 // Reverse the bits before returning (to Big Endian)
79 //TODO: Need to be reviewed. Do we want to do a bit reverse or a byte reverse (in this case use SwapBytes32())
80 return ReverseBits (Remainder);
81 }
82
83 // Function to read from MAC indirect registers
84 UINT32
85 IndirectMACRead32 (
86 UINT32 Index
87 )
88 {
89 UINT32 MacCSR;
90
91 // Check index is in the range
92 ASSERT(Index <= 12);
93
94 // Wait until CSR busy bit is cleared
95 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY);
96
97 // Set CSR busy bit to ensure read will occur
98 // Set the R/W bit to indicate we are reading
99 // Set the index of CSR Address to access desired register
100 MacCSR = MAC_CSR_BUSY | MAC_CSR_READ | MAC_CSR_ADDR(Index);
101
102 // Write to the register
103 Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR);
104
105 // Wait until CSR busy bit is cleared
106 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY);
107
108 // Now read from data register to get read value
109 return Lan9118MmioRead32 (LAN9118_MAC_CSR_DATA);
110 }
111
112 /*
113 * LAN9118 chips have special restrictions on some back-to-back Write/Read or
114 * Read/Read pairs of accesses. After a read or write that changes the state of
115 * the device, there is a period in which stale values may be returned in
116 * response to a read. This period is dependent on the registers accessed.
117 *
118 * We must delay prior reads by this period. This can either be achieved by
119 * timer-based delays, or by performing dummy reads of the BYTE_TEST register,
120 * for which the recommended number of reads is described in the LAN9118 data
121 * sheet. This is required in addition to any memory barriers.
122 *
123 * This function performs a number of dummy reads of the BYTE_TEST register, as
124 * a building block for the above.
125 */
126 VOID
127 WaitDummyReads (
128 UINTN Count
129 )
130 {
131 while (Count--)
132 MmioRead32(LAN9118_BYTE_TEST);
133 }
134
135 UINT32
136 Lan9118RawMmioRead32(
137 UINTN Address,
138 UINTN Delay
139 )
140 {
141 UINT32 Value;
142
143 Value = MmioRead32(Address);
144 WaitDummyReads(Delay);
145 return Value;
146 }
147
148 UINT32
149 Lan9118RawMmioWrite32(
150 UINTN Address,
151 UINT32 Value,
152 UINTN Delay
153 )
154 {
155 MmioWrite32(Address, Value);
156 WaitDummyReads(Delay);
157 return Value;
158 }
159
160 // Function to write to MAC indirect registers
161 UINT32
162 IndirectMACWrite32 (
163 UINT32 Index,
164 UINT32 Value
165 )
166 {
167 UINT32 ValueWritten;
168 UINT32 MacCSR;
169
170 // Check index is in the range
171 ASSERT(Index <= 12);
172
173 // Wait until CSR busy bit is cleared
174 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY);
175
176 // Set CSR busy bit to ensure read will occur
177 // Set the R/W bit to indicate we are writing
178 // Set the index of CSR Address to access desired register
179 MacCSR = MAC_CSR_BUSY | MAC_CSR_WRITE | MAC_CSR_ADDR(Index);
180
181 // Now write the value to the register before issuing the write command
182 ValueWritten = Lan9118MmioWrite32 (LAN9118_MAC_CSR_DATA, Value);
183
184 // Write the config to the register
185 Lan9118MmioWrite32 (LAN9118_MAC_CSR_CMD, MacCSR);
186
187 // Wait until CSR busy bit is cleared
188 while ((Lan9118MmioRead32 (LAN9118_MAC_CSR_CMD) & MAC_CSR_BUSY) == MAC_CSR_BUSY);
189
190 return ValueWritten;
191 }
192
193 // Function to read from MII register (PHY Access)
194 UINT32
195 IndirectPHYRead32 (
196 UINT32 Index
197 )
198 {
199 UINT32 ValueRead;
200 UINT32 MiiAcc;
201
202 // Check it is a valid index
203 ASSERT(Index < 31);
204
205 // Wait for busy bit to clear
206 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY);
207
208 // Clear the R/W bit to indicate we are reading
209 // Set the index of the MII register
210 // Set the PHY Address
211 // Set the MII busy bit to allow read
212 MiiAcc = MII_ACC_MII_READ | MII_ACC_MII_REG_INDEX(Index) | MII_ACC_PHY_VALUE | MII_ACC_MII_BUSY;
213
214 // Now write this config to register
215 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC, MiiAcc & 0xFFFF);
216
217 // Wait for busy bit to clear
218 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY);
219
220 // Now read the value of the register
221 ValueRead = (IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_DATA) & 0xFFFF); // only lower 16 bits are valid for any PHY register
222
223 return ValueRead;
224 }
225
226
227 // Function to write to the MII register (PHY Access)
228 UINT32
229 IndirectPHYWrite32 (
230 UINT32 Index,
231 UINT32 Value
232 )
233 {
234 UINT32 MiiAcc;
235 UINT32 ValueWritten;
236
237 // Check it is a valid index
238 ASSERT(Index < 31);
239
240 // Wait for busy bit to clear
241 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY);
242
243 // Clear the R/W bit to indicate we are reading
244 // Set the index of the MII register
245 // Set the PHY Address
246 // Set the MII busy bit to allow read
247 MiiAcc = MII_ACC_MII_WRITE | MII_ACC_MII_REG_INDEX(Index) | MII_ACC_PHY_VALUE | MII_ACC_MII_BUSY;
248
249 // Write the desired value to the register first
250 ValueWritten = IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_DATA, (Value & 0xFFFF));
251
252 // Now write the config to register
253 IndirectMACWrite32 (INDIRECT_MAC_INDEX_MII_ACC, MiiAcc & 0xFFFF);
254
255 // Wait for operation to terminate
256 while ((IndirectMACRead32 (INDIRECT_MAC_INDEX_MII_ACC) & MII_ACC_MII_BUSY) == MII_ACC_MII_BUSY);
257
258 return ValueWritten;
259 }
260
261
262 /* ---------------- EEPROM Operations ------------------ */
263
264
265 // Function to read from EEPROM memory
266 UINT32
267 IndirectEEPROMRead32 (
268 UINT32 Index
269 )
270 {
271 UINT32 EepromCmd;
272
273 // Set the busy bit to ensure read will occur
274 EepromCmd = E2P_EPC_BUSY | E2P_EPC_CMD_READ;
275
276 // Set the index to access desired EEPROM memory location
277 EepromCmd |= E2P_EPC_ADDRESS(Index);
278
279 // Write to Eeprom command register
280 Lan9118MmioWrite32 (LAN9118_E2P_CMD, EepromCmd);
281
282 // Wait until operation has completed
283 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY);
284
285 // Check that operation didn't time out
286 if (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) {
287 DEBUG ((EFI_D_ERROR, "EEPROM Operation Timed out: Read command on index %x\n",Index));
288 return 0;
289 }
290
291 // Wait until operation has completed
292 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY);
293
294 // Finally read the value
295 return Lan9118MmioRead32 (LAN9118_E2P_DATA);
296 }
297
298 // Function to write to EEPROM memory
299 UINT32
300 IndirectEEPROMWrite32 (
301 UINT32 Index,
302 UINT32 Value
303 )
304 {
305 UINT32 ValueWritten;
306 UINT32 EepromCmd;
307
308 ValueWritten = 0;
309
310 // Read the EEPROM Command register
311 EepromCmd = Lan9118MmioRead32 (LAN9118_E2P_CMD);
312
313 // Set the busy bit to ensure read will occur
314 EepromCmd |= ((UINT32)1 << 31);
315
316 // Set the EEPROM command to write(0b011)
317 EepromCmd &= ~(7 << 28); // Clear the command first
318 EepromCmd |= (3 << 28); // Write 011
319
320 // Set the index to access desired EEPROM memory location
321 EepromCmd |= (Index & 0xF);
322
323 // Write the value to the data register first
324 ValueWritten = Lan9118MmioWrite32 (LAN9118_E2P_DATA, Value);
325
326 // Write to Eeprom command register
327 Lan9118MmioWrite32 (LAN9118_E2P_CMD, EepromCmd);
328
329 // Wait until operation has completed
330 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY);
331
332 // Check that operation didn't time out
333 if (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_TIMEOUT) {
334 DEBUG ((EFI_D_ERROR, "EEPROM Operation Timed out: Write command at memloc 0x%x, with value 0x%x\n",Index, Value));
335 return 0;
336 }
337
338 // Wait until operation has completed
339 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY);
340
341 return ValueWritten;
342 }
343
344 /* ---------------- General Operations ----------------- */
345
346 VOID
347 Lan9118SetMacAddress (
348 EFI_MAC_ADDRESS *Mac,
349 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
350 )
351 {
352 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRL,
353 (Mac->Addr[0] & 0xFF) |
354 ((Mac->Addr[1] & 0xFF) << 8) |
355 ((Mac->Addr[2] & 0xFF) << 16) |
356 ((Mac->Addr[3] & 0xFF) << 24)
357 );
358
359 IndirectMACWrite32 (INDIRECT_MAC_INDEX_ADDRH,
360 (UINT32)(Mac->Addr[4] & 0xFF) |
361 ((Mac->Addr[5] & 0xFF) << 8)
362 );
363 }
364
365 VOID
366 Lan9118ReadMacAddress (
367 OUT EFI_MAC_ADDRESS *MacAddress
368 )
369 {
370 UINT32 MacAddrHighValue;
371 UINT32 MacAddrLowValue;
372
373 // Read the Mac Addr high register
374 MacAddrHighValue = (IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRH) & 0xFFFF);
375 // Read the Mac Addr low register
376 MacAddrLowValue = IndirectMACRead32 (INDIRECT_MAC_INDEX_ADDRL);
377
378 SetMem (MacAddress, sizeof(*MacAddress), 0);
379 MacAddress->Addr[0] = (MacAddrLowValue & 0xFF);
380 MacAddress->Addr[1] = (MacAddrLowValue & 0xFF00) >> 8;
381 MacAddress->Addr[2] = (MacAddrLowValue & 0xFF0000) >> 16;
382 MacAddress->Addr[3] = (MacAddrLowValue & 0xFF000000) >> 24;
383 MacAddress->Addr[4] = (MacAddrHighValue & 0xFF);
384 MacAddress->Addr[5] = (MacAddrHighValue & 0xFF00) >> 8;
385 }
386
387 /*
388 * Power up the 9118 and find its MAC address.
389 *
390 * This operation can be carried out when the LAN9118 is in any power state
391 *
392 */
393 EFI_STATUS
394 Lan9118Initialize (
395 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
396 )
397 {
398 UINTN Retries;
399 UINT64 DefaultMacAddress;
400
401 // Attempt to wake-up the device if it is in a lower power state
402 if (((Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PM_MODE_MASK) >> 12) != 0) {
403 DEBUG ((DEBUG_NET, "Waking from reduced power state.\n"));
404 Lan9118MmioWrite32 (LAN9118_BYTE_TEST, 0xFFFFFFFF);
405 }
406
407 // Check that device is active
408 Retries = 20;
409 while ((Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_READY) == 0 && --Retries) {
410 gBS->Stall (LAN9118_STALL);
411 }
412 if (!Retries) {
413 return EFI_TIMEOUT;
414 }
415
416 // Check that EEPROM isn't active
417 Retries = 20;
418 while ((Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY) && --Retries){
419 gBS->Stall (LAN9118_STALL);
420 }
421 if (!Retries) {
422 return EFI_TIMEOUT;
423 }
424
425 // Check if a MAC address was loaded from EEPROM, and if it was, set it as the
426 // current address.
427 if ((Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_MAC_ADDRESS_LOADED) == 0) {
428 DEBUG ((EFI_D_ERROR, "Warning: There was an error detecting EEPROM or loading the MAC Address.\n"));
429
430 // If we had an address before (set by StationAddress), continue to use it
431 if (CompareMem (&Snp->Mode->CurrentAddress, &mZeroMac, NET_ETHER_ADDR_LEN)) {
432 Lan9118SetMacAddress (&Snp->Mode->CurrentAddress, Snp);
433 } else {
434 // If there are no cached addresses, then fall back to a default
435 DEBUG ((EFI_D_WARN, "Warning: using driver-default MAC address\n"));
436 DefaultMacAddress = FixedPcdGet64 (PcdLan9118DefaultMacAddress);
437 Lan9118SetMacAddress((EFI_MAC_ADDRESS *) &DefaultMacAddress, Snp);
438 CopyMem (&Snp->Mode->CurrentAddress, &DefaultMacAddress, NET_ETHER_ADDR_LEN);
439 }
440 } else {
441 // Store the MAC address that was loaded from EEPROM
442 Lan9118ReadMacAddress (&Snp->Mode->CurrentAddress);
443 CopyMem (&Snp->Mode->PermanentAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN);
444 }
445
446 // Clear and acknowledge interrupts
447 Lan9118MmioWrite32 (LAN9118_INT_EN, 0);
448 Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0);
449 Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF);
450
451 // Do self tests here?
452
453 return EFI_SUCCESS;
454 }
455
456
457 // Perform software reset on the LAN9118
458 // Return 0 on success, -1 on error
459 EFI_STATUS
460 SoftReset (
461 UINT32 Flags,
462 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
463 )
464 {
465 UINT32 HwConf;
466 UINT32 ResetTime;
467
468 // Initialize variable
469 ResetTime = 0;
470
471 // Stop Rx and Tx
472 StopTx (STOP_TX_MAC | STOP_TX_CFG | STOP_TX_CLEAR, Snp);
473 StopRx (STOP_RX_CLEAR, Snp); // Clear receiver FIFO
474
475 // Issue the reset
476 HwConf = Lan9118MmioRead32 (LAN9118_HW_CFG);
477 HwConf |= 1;
478
479 // Set the Must Be One (MBO) bit
480 if (((HwConf & HWCFG_MBO) >> 20) == 0) {
481 HwConf |= HWCFG_MBO;
482 }
483
484 // Check that EEPROM isn't active
485 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY);
486
487 // Write the configuration
488 Lan9118MmioWrite32 (LAN9118_HW_CFG, HwConf);
489
490 // Wait for reset to complete
491 while (Lan9118MmioRead32 (LAN9118_HW_CFG) & HWCFG_SRST) {
492
493 gBS->Stall (LAN9118_STALL);
494 ResetTime += 1;
495
496 // If time taken exceeds 100us, then there was an error condition
497 if (ResetTime > 1000) {
498 Snp->Mode->State = EfiSimpleNetworkStopped;
499 return EFI_TIMEOUT;
500 }
501 }
502
503 // Check that EEPROM isn't active
504 while (Lan9118MmioRead32 (LAN9118_E2P_CMD) & E2P_EPC_BUSY);
505
506 // TODO we probably need to re-set the mac address here.
507
508 // Clear and acknowledge all interrupts
509 if (Flags & SOFT_RESET_CLEAR_INT) {
510 Lan9118MmioWrite32 (LAN9118_INT_EN, 0);
511 Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0);
512 Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF);
513 }
514
515 // Do self tests here?
516 if (Flags & SOFT_RESET_SELF_TEST) {
517
518 }
519
520 return EFI_SUCCESS;
521 }
522
523
524 // Perform PHY software reset
525 EFI_STATUS
526 PhySoftReset (
527 UINT32 Flags,
528 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
529 )
530 {
531 UINT32 PmtCtrl = 0;
532
533 // PMT PHY reset takes precedence over BCR
534 if (Flags & PHY_RESET_PMT) {
535 PmtCtrl = Lan9118MmioRead32 (LAN9118_PMT_CTRL);
536 PmtCtrl |= MPTCTRL_PHY_RST;
537 Lan9118MmioWrite32 (LAN9118_PMT_CTRL,PmtCtrl);
538
539 // Wait for completion
540 while (Lan9118MmioRead32 (LAN9118_PMT_CTRL) & MPTCTRL_PHY_RST) {
541 gBS->Stall (LAN9118_STALL);
542 }
543 // PHY Basic Control Register reset
544 } else if (Flags & PHY_RESET_BCR) {
545 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL, PHYCR_RESET);
546
547 // Wait for completion
548 while (IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL) & PHYCR_RESET) {
549 gBS->Stall (LAN9118_STALL);
550 }
551 }
552
553 // Clear and acknowledge all interrupts
554 if (Flags & PHY_SOFT_RESET_CLEAR_INT) {
555 Lan9118MmioWrite32 (LAN9118_INT_EN, 0);
556 Lan9118MmioWrite32 (LAN9118_IRQ_CFG, 0);
557 Lan9118MmioWrite32 (LAN9118_INT_STS, 0xFFFFFFFF);
558 }
559
560 return EFI_SUCCESS;
561 }
562
563
564 // Configure hardware for LAN9118
565 EFI_STATUS
566 ConfigureHardware (
567 UINT32 Flags,
568 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
569 )
570 {
571 UINT32 GpioConf;
572
573 // Check if we want to use LEDs on GPIO
574 if (Flags & HW_CONF_USE_LEDS) {
575 GpioConf = Lan9118MmioRead32 (LAN9118_GPIO_CFG);
576
577 // Enable GPIO as LEDs and Config as Push-Pull driver
578 GpioConf |= GPIO_GPIO0_PUSH_PULL | GPIO_GPIO1_PUSH_PULL | GPIO_GPIO2_PUSH_PULL |
579 GPIO_LED1_ENABLE | GPIO_LED2_ENABLE | GPIO_LED3_ENABLE;
580
581 // Write the configuration
582 Lan9118MmioWrite32 (LAN9118_GPIO_CFG, GpioConf);
583 }
584
585 return EFI_SUCCESS;
586 }
587
588 // Configure flow control
589 EFI_STATUS
590 ConfigureFlow (
591 UINT32 Flags,
592 UINT32 HighTrig,
593 UINT32 LowTrig,
594 UINT32 BPDuration,
595 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
596 )
597 {
598 return EFI_SUCCESS;
599 }
600
601 // Do auto-negotiation
602 EFI_STATUS
603 AutoNegotiate (
604 UINT32 Flags,
605 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
606 )
607 {
608 UINT32 PhyControl;
609 UINT32 PhyStatus;
610 UINT32 Features;
611 UINT32 Retries;
612
613 // First check that auto-negotiation is supported
614 PhyStatus = IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS);
615 if ((PhyStatus & PHYSTS_AUTO_CAP) == 0) {
616 DEBUG ((EFI_D_ERROR, "Auto-negotiation not supported.\n"));
617 return EFI_DEVICE_ERROR;
618 }
619
620 // Check that link is up first
621 if ((PhyStatus & PHYSTS_LINK_STS) == 0) {
622 // Wait until it is up or until Time Out
623 Retries = FixedPcdGet32 (PcdLan9118DefaultNegotiationTimeout) / LAN9118_STALL;
624 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS) & PHYSTS_LINK_STS) == 0) {
625 gBS->Stall (LAN9118_STALL);
626 Retries--;
627 if (!Retries) {
628 DEBUG ((EFI_D_ERROR, "Link timeout in auto-negotiation.\n"));
629 return EFI_TIMEOUT;
630 }
631 }
632 }
633
634 // Configure features to advertise
635 Features = IndirectPHYRead32 (PHY_INDEX_AUTO_NEG_ADVERT);
636
637 if ((Flags & AUTO_NEGOTIATE_ADVERTISE_ALL) > 0) {
638 // Link speed capabilities
639 Features |= (PHYANA_10BASET | PHYANA_10BASETFD | PHYANA_100BASETX | PHYANA_100BASETXFD);
640
641 // Pause frame capabilities
642 Features &= ~(PHYANA_PAUSE_OP_MASK);
643 Features |= 3 << 10;
644 }
645 Features &= FixedPcdGet32 (PcdLan9118NegotiationFeatureMask);
646
647 // Write the features
648 IndirectPHYWrite32 (PHY_INDEX_AUTO_NEG_ADVERT, Features);
649
650 // Read control register
651 PhyControl = IndirectPHYRead32 (PHY_INDEX_BASIC_CTRL);
652
653 // Enable Auto-Negotiation
654 if ((PhyControl & PHYCR_AUTO_EN) == 0) {
655 PhyControl |= PHYCR_AUTO_EN;
656 }
657
658 // Restart auto-negotiation
659 PhyControl |= PHYCR_RST_AUTO;
660
661 // Enable collision test if required to do so
662 if (Flags & AUTO_NEGOTIATE_COLLISION_TEST) {
663 PhyControl |= PHYCR_COLL_TEST;
664 } else {
665 PhyControl &= ~ PHYCR_COLL_TEST;
666 }
667
668 // Write this configuration
669 IndirectPHYWrite32 (PHY_INDEX_BASIC_CTRL, PhyControl);
670
671 // Wait until process has completed
672 while ((IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS) & PHYSTS_AUTO_COMP) == 0);
673
674 return EFI_SUCCESS;
675 }
676
677 // Check the Link Status and take appropriate action
678 EFI_STATUS
679 CheckLinkStatus (
680 UINT32 Flags,
681 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
682 )
683 {
684 // Get the PHY Status
685 UINT32 PhyBStatus = IndirectPHYRead32 (PHY_INDEX_BASIC_STATUS);
686
687 if (PhyBStatus & PHYSTS_LINK_STS) {
688 return EFI_SUCCESS;
689 } else {
690 return EFI_DEVICE_ERROR;
691 }
692 }
693
694 // Stop the transmitter
695 EFI_STATUS
696 StopTx (
697 UINT32 Flags,
698 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
699 )
700 {
701 UINT32 MacCsr;
702 UINT32 TxCfg;
703
704 MacCsr = 0;
705 TxCfg = 0;
706
707 // Check if we want to clear tx
708 if (Flags & STOP_TX_CLEAR) {
709 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG);
710 TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP;
711 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg);
712 }
713
714 // Check if already stopped
715 if (Flags & STOP_TX_MAC) {
716 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR);
717
718 if (MacCsr & MACCR_TX_EN) {
719 MacCsr &= ~MACCR_TX_EN;
720 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr);
721 }
722 }
723
724 if (Flags & STOP_TX_CFG) {
725 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG);
726
727 if (TxCfg & TXCFG_TX_ON) {
728 TxCfg |= TXCFG_STOP_TX;
729 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg);
730
731 // Wait for Tx to finish transmitting
732 while (Lan9118MmioRead32 (LAN9118_TX_CFG) & TXCFG_STOP_TX);
733 }
734 }
735
736 return EFI_SUCCESS;
737 }
738
739 // Stop the receiver
740 EFI_STATUS
741 StopRx (
742 UINT32 Flags,
743 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
744 )
745 {
746 UINT32 MacCsr;
747 UINT32 RxCfg;
748
749 RxCfg = 0;
750
751 // Check if already stopped
752 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR);
753
754 if (MacCsr & MACCR_RX_EN) {
755 MacCsr &= ~ MACCR_RX_EN;
756 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr);
757 }
758
759 // Check if we want to clear receiver FIFOs
760 if (Flags & STOP_RX_CLEAR) {
761 RxCfg = Lan9118MmioRead32 (LAN9118_RX_CFG);
762 RxCfg |= RXCFG_RX_DUMP;
763 Lan9118MmioWrite32 (LAN9118_RX_CFG, RxCfg);
764
765 while (Lan9118MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP);
766 }
767
768 return EFI_SUCCESS;
769 }
770
771 // Start the transmitter
772 EFI_STATUS
773 StartTx (
774 UINT32 Flags,
775 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
776 )
777 {
778 UINT32 MacCsr;
779 UINT32 TxCfg;
780
781 MacCsr = 0;
782 TxCfg = 0;
783
784 // Check if we want to clear tx
785 if (Flags & START_TX_CLEAR) {
786 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG);
787 TxCfg |= TXCFG_TXS_DUMP | TXCFG_TXD_DUMP;
788 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg);
789 }
790
791 // Check if tx was started from MAC and enable if not
792 if (Flags & START_TX_MAC) {
793 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR);
794 if ((MacCsr & MACCR_TX_EN) == 0) {
795 MacCsr |= MACCR_TX_EN;
796 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr);
797 }
798 }
799
800 // Check if tx was started from TX_CFG and enable if not
801 if (Flags & START_TX_CFG) {
802 TxCfg = Lan9118MmioRead32 (LAN9118_TX_CFG);
803 if ((TxCfg & TXCFG_TX_ON) == 0) {
804 TxCfg |= TXCFG_TX_ON;
805 Lan9118MmioWrite32 (LAN9118_TX_CFG, TxCfg);
806 }
807 }
808
809 // Set the tx data trigger level
810
811 return EFI_SUCCESS;
812 }
813
814 // Start the receiver
815 EFI_STATUS
816 StartRx (
817 UINT32 Flags,
818 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
819 )
820 {
821 UINT32 MacCsr;
822 UINT32 RxCfg;
823
824 RxCfg = 0;
825
826 // Check if already started
827 MacCsr = IndirectMACRead32 (INDIRECT_MAC_INDEX_CR);
828
829 if ((MacCsr & MACCR_RX_EN) == 0) {
830 // Check if we want to clear receiver FIFOs before starting
831 if (Flags & START_RX_CLEAR) {
832 RxCfg = Lan9118MmioRead32 (LAN9118_RX_CFG);
833 RxCfg |= RXCFG_RX_DUMP;
834 Lan9118MmioWrite32 (LAN9118_RX_CFG, RxCfg);
835
836 while (Lan9118MmioRead32 (LAN9118_RX_CFG) & RXCFG_RX_DUMP);
837 }
838
839 MacCsr |= MACCR_RX_EN;
840 IndirectMACWrite32 (INDIRECT_MAC_INDEX_CR, MacCsr);
841 }
842
843 return EFI_SUCCESS;
844 }
845
846 // Check Tx Data available space
847 UINT32
848 TxDataFreeSpace (
849 UINT32 Flags,
850 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
851 )
852 {
853 UINT32 TxInf;
854 UINT32 FreeSpace;
855
856 // Get the amount of free space from information register
857 TxInf = Lan9118MmioRead32 (LAN9118_TX_FIFO_INF);
858 FreeSpace = (TxInf & TXFIFOINF_TDFREE_MASK);
859
860 return FreeSpace; // Value in bytes
861 }
862
863 // Check Tx Status used space
864 UINT32
865 TxStatusUsedSpace (
866 UINT32 Flags,
867 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
868 )
869 {
870 UINT32 TxInf;
871 UINT32 UsedSpace;
872
873 // Get the amount of used space from information register
874 TxInf = Lan9118MmioRead32 (LAN9118_TX_FIFO_INF);
875 UsedSpace = (TxInf & TXFIFOINF_TXSUSED_MASK) >> 16;
876
877 return UsedSpace << 2; // Value in bytes
878 }
879
880 // Check Rx Data used space
881 UINT32
882 RxDataUsedSpace (
883 UINT32 Flags,
884 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
885 )
886 {
887 UINT32 RxInf;
888 UINT32 UsedSpace;
889
890 // Get the amount of used space from information register
891 RxInf = Lan9118MmioRead32 (LAN9118_RX_FIFO_INF);
892 UsedSpace = (RxInf & RXFIFOINF_RXDUSED_MASK);
893
894 return UsedSpace; // Value in bytes (rounded up to nearest DWORD)
895 }
896
897 // Check Rx Status used space
898 UINT32
899 RxStatusUsedSpace (
900 UINT32 Flags,
901 EFI_SIMPLE_NETWORK_PROTOCOL *Snp
902 )
903 {
904 UINT32 RxInf;
905 UINT32 UsedSpace;
906
907 // Get the amount of used space from information register
908 RxInf = Lan9118MmioRead32 (LAN9118_RX_FIFO_INF);
909 UsedSpace = (RxInf & RXFIFOINF_RXSUSED_MASK) >> 16;
910
911 return UsedSpace << 2; // Value in bytes
912 }
913
914
915 // Change the allocation of FIFOs
916 EFI_STATUS
917 ChangeFifoAllocation (
918 IN UINT32 Flags,
919 IN OUT UINTN *TxDataSize OPTIONAL,
920 IN OUT UINTN *RxDataSize OPTIONAL,
921 IN OUT UINT32 *TxStatusSize OPTIONAL,
922 IN OUT UINT32 *RxStatusSize OPTIONAL,
923 IN OUT EFI_SIMPLE_NETWORK_PROTOCOL *Snp
924 )
925 {
926 UINT32 HwConf;
927 UINT32 TxFifoOption;
928
929 // Check that desired sizes don't exceed limits
930 if (*TxDataSize > TX_FIFO_MAX_SIZE)
931 return EFI_INVALID_PARAMETER;
932
933 #if defined(RX_FIFO_MIN_SIZE) && defined(RX_FIFO_MAX_SIZE)
934 if (*RxDataSize > RX_FIFO_MAX_SIZE) {
935 return EFI_INVALID_PARAMETER;
936 }
937 #endif
938
939 if (Flags & ALLOC_USE_DEFAULT) {
940 return EFI_SUCCESS;
941 }
942
943 // If we use the FIFOs (always use this first)
944 if (Flags & ALLOC_USE_FIFOS) {
945 // Read the current value of allocation
946 HwConf = Lan9118MmioRead32 (LAN9118_HW_CFG);
947 TxFifoOption = (HwConf >> 16) & 0xF;
948
949 // Choose the correct size (always use larger than requested if possible)
950 if (*TxDataSize < TX_FIFO_MIN_SIZE) {
951 *TxDataSize = TX_FIFO_MIN_SIZE;
952 *RxDataSize = 13440;
953 *RxStatusSize = 896;
954 TxFifoOption = 2;
955 } else if ((*TxDataSize > TX_FIFO_MIN_SIZE) && (*TxDataSize <= 2560)) {
956 *TxDataSize = 2560;
957 *RxDataSize = 12480;
958 *RxStatusSize = 832;
959 TxFifoOption = 3;
960 } else if ((*TxDataSize > 2560) && (*TxDataSize <= 3584)) {
961 *TxDataSize = 3584;
962 *RxDataSize = 11520;
963 *RxStatusSize = 768;
964 TxFifoOption = 4;
965 } else if ((*TxDataSize > 3584) && (*TxDataSize <= 4608)) { // default option
966 *TxDataSize = 4608;
967 *RxDataSize = 10560;
968 *RxStatusSize = 704;
969 TxFifoOption = 5;
970 } else if ((*TxDataSize > 4608) && (*TxDataSize <= 5632)) {
971 *TxDataSize = 5632;
972 *RxDataSize = 9600;
973 *RxStatusSize = 640;
974 TxFifoOption = 6;
975 } else if ((*TxDataSize > 5632) && (*TxDataSize <= 6656)) {
976 *TxDataSize = 6656;
977 *RxDataSize = 8640;
978 *RxStatusSize = 576;
979 TxFifoOption = 7;
980 } else if ((*TxDataSize > 6656) && (*TxDataSize <= 7680)) {
981 *TxDataSize = 7680;
982 *RxDataSize = 7680;
983 *RxStatusSize = 512;
984 TxFifoOption = 8;
985 } else if ((*TxDataSize > 7680) && (*TxDataSize <= 8704)) {
986 *TxDataSize = 8704;
987 *RxDataSize = 6720;
988 *RxStatusSize = 448;
989 TxFifoOption = 9;
990 } else if ((*TxDataSize > 8704) && (*TxDataSize <= 9728)) {
991 *TxDataSize = 9728;
992 *RxDataSize = 5760;
993 *RxStatusSize = 384;
994 TxFifoOption = 10;
995 } else if ((*TxDataSize > 9728) && (*TxDataSize <= 10752)) {
996 *TxDataSize = 10752;
997 *RxDataSize = 4800;
998 *RxStatusSize = 320;
999 TxFifoOption = 11;
1000 } else if ((*TxDataSize > 10752) && (*TxDataSize <= 11776)) {
1001 *TxDataSize = 11776;
1002 *RxDataSize = 3840;
1003 *RxStatusSize = 256;
1004 TxFifoOption = 12;
1005 } else if ((*TxDataSize > 11776) && (*TxDataSize <= 12800)) {
1006 *TxDataSize = 12800;
1007 *RxDataSize = 2880;
1008 *RxStatusSize = 192;
1009 TxFifoOption = 13;
1010 } else if ((*TxDataSize > 12800) && (*TxDataSize <= 13824)) {
1011 *TxDataSize = 13824;
1012 *RxDataSize = 1920;
1013 *RxStatusSize = 128;
1014 TxFifoOption = 14;
1015 }
1016 } else {
1017 ASSERT(0); // Untested code path
1018 HwConf = 0;
1019 TxFifoOption = 0;
1020 }
1021
1022 // Do we need DMA?
1023 if (Flags & ALLOC_USE_DMA) {
1024 return EFI_UNSUPPORTED; // Unsupported as of now
1025 }
1026 // Clear and assign the new size option
1027 HwConf &= ~(0xF0000);
1028 HwConf |= ((TxFifoOption & 0xF) << 16);
1029 Lan9118MmioWrite32 (LAN9118_HW_CFG, HwConf);
1030
1031 return EFI_SUCCESS;
1032 }