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