• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Agere Systems Inc.
3  * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
4  *
5  * Copyright � 2005 Agere Systems Inc.
6  * All rights reserved.
7  *   http://www.agere.com
8  *
9  *------------------------------------------------------------------------------
10  *
11  * et1310_phy.c - Routines for configuring and accessing the PHY
12  *
13  *------------------------------------------------------------------------------
14  *
15  * SOFTWARE LICENSE
16  *
17  * This software is provided subject to the following terms and conditions,
18  * which you should read carefully before using the software.  Using this
19  * software indicates your acceptance of these terms and conditions.  If you do
20  * not agree with these terms and conditions, do not use the software.
21  *
22  * Copyright � 2005 Agere Systems Inc.
23  * All rights reserved.
24  *
25  * Redistribution and use in source or binary forms, with or without
26  * modifications, are permitted provided that the following conditions are met:
27  *
28  * . Redistributions of source code must retain the above copyright notice, this
29  *    list of conditions and the following Disclaimer as comments in the code as
30  *    well as in the documentation and/or other materials provided with the
31  *    distribution.
32  *
33  * . Redistributions in binary form must reproduce the above copyright notice,
34  *    this list of conditions and the following Disclaimer in the documentation
35  *    and/or other materials provided with the distribution.
36  *
37  * . Neither the name of Agere Systems Inc. nor the names of the contributors
38  *    may be used to endorse or promote products derived from this software
39  *    without specific prior written permission.
40  *
41  * Disclaimer
42  *
43  * THIS SOFTWARE IS PROVIDED �AS IS� AND ANY EXPRESS OR IMPLIED WARRANTIES,
44  * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
45  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
46  * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
47  * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
48  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
50  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
51  * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
52  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
53  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
54  * DAMAGE.
55  *
56  */
57 
58 #include "et131x_version.h"
59 #include "et131x_debug.h"
60 #include "et131x_defs.h"
61 
62 #include <linux/pci.h>
63 #include <linux/init.h>
64 #include <linux/module.h>
65 #include <linux/types.h>
66 #include <linux/kernel.h>
67 
68 #include <linux/sched.h>
69 #include <linux/ptrace.h>
70 #include <linux/slab.h>
71 #include <linux/ctype.h>
72 #include <linux/string.h>
73 #include <linux/timer.h>
74 #include <linux/interrupt.h>
75 #include <linux/in.h>
76 #include <linux/delay.h>
77 #include <asm/io.h>
78 #include <asm/system.h>
79 #include <asm/bitops.h>
80 
81 #include <linux/netdevice.h>
82 #include <linux/etherdevice.h>
83 #include <linux/skbuff.h>
84 #include <linux/if_arp.h>
85 #include <linux/ioport.h>
86 #include <linux/random.h>
87 
88 #include "et1310_phy.h"
89 #include "et1310_pm.h"
90 #include "et1310_jagcore.h"
91 
92 #include "et131x_adapter.h"
93 #include "et131x_netdev.h"
94 #include "et131x_initpci.h"
95 
96 #include "et1310_address_map.h"
97 #include "et1310_tx.h"
98 #include "et1310_rx.h"
99 #include "et1310_mac.h"
100 
101 /* Data for debugging facilities */
102 #ifdef CONFIG_ET131X_DEBUG
103 extern dbg_info_t *et131x_dbginfo;
104 #endif /* CONFIG_ET131X_DEBUG */
105 
106 /* Prototypes for functions with local scope */
107 static int et131x_xcvr_init(struct et131x_adapter *adapter);
108 
109 /**
110  * PhyMiRead - Read from the PHY through the MII Interface on the MAC
111  * @adapter: pointer to our private adapter structure
112  * @xcvrAddr: the address of the transciever
113  * @xcvrReg: the register to read
114  * @value: pointer to a 16-bit value in which the value will be stored
115  *
116  * Returns 0 on success, errno on failure (as defined in errno.h)
117  */
PhyMiRead(struct et131x_adapter * adapter,uint8_t xcvrAddr,uint8_t xcvrReg,uint16_t * value)118 int PhyMiRead(struct et131x_adapter *adapter, uint8_t xcvrAddr,
119 	      uint8_t xcvrReg, uint16_t *value)
120 {
121 	struct _MAC_t __iomem *mac = &adapter->CSRAddress->mac;
122 	int status = 0;
123 	uint32_t delay;
124 	MII_MGMT_ADDR_t miiAddr;
125 	MII_MGMT_CMD_t miiCmd;
126 	MII_MGMT_INDICATOR_t miiIndicator;
127 
128 	/* Save a local copy of the registers we are dealing with so we can
129 	 * set them back
130 	 */
131 	miiAddr.value = readl(&mac->mii_mgmt_addr.value);
132 	miiCmd.value = readl(&mac->mii_mgmt_cmd.value);
133 
134 	/* Stop the current operation */
135 	writel(0, &mac->mii_mgmt_cmd.value);
136 
137 	/* Set up the register we need to read from on the correct PHY */
138 	{
139 		MII_MGMT_ADDR_t mii_mgmt_addr = { 0 };
140 
141 		mii_mgmt_addr.bits.phy_addr = xcvrAddr;
142 		mii_mgmt_addr.bits.reg_addr = xcvrReg;
143 		writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value);
144 	}
145 
146 	/* Kick the read cycle off */
147 	delay = 0;
148 
149 	writel(0x1, &mac->mii_mgmt_cmd.value);
150 
151 	do {
152 		udelay(50);
153 		delay++;
154 		miiIndicator.value = readl(&mac->mii_mgmt_indicator.value);
155 	} while ((miiIndicator.bits.not_valid || miiIndicator.bits.busy) &&
156 		 delay < 50);
157 
158 	/* If we hit the max delay, we could not read the register */
159 	if (delay >= 50) {
160 		DBG_WARNING(et131x_dbginfo,
161 			    "xcvrReg 0x%08x could not be read\n", xcvrReg);
162 		DBG_WARNING(et131x_dbginfo, "status is  0x%08x\n",
163 			    miiIndicator.value);
164 
165 		status = -EIO;
166 	}
167 
168 	/* If we hit here we were able to read the register and we need to
169 	 * return the value to the caller
170 	 */
171 	/* TODO: make this stuff a simple readw()?! */
172 	{
173 		MII_MGMT_STAT_t mii_mgmt_stat;
174 
175 		mii_mgmt_stat.value = readl(&mac->mii_mgmt_stat.value);
176 		*value = (uint16_t) mii_mgmt_stat.bits.phy_stat;
177 	}
178 
179 	/* Stop the read operation */
180 	writel(0, &mac->mii_mgmt_cmd.value);
181 
182 	DBG_VERBOSE(et131x_dbginfo, "  xcvr_addr = 0x%02x, "
183 		    "xcvr_reg  = 0x%02x, "
184 		    "value     = 0x%04x.\n", xcvrAddr, xcvrReg, *value);
185 
186 	/* set the registers we touched back to the state at which we entered
187 	 * this function
188 	 */
189 	writel(miiAddr.value, &mac->mii_mgmt_addr.value);
190 	writel(miiCmd.value, &mac->mii_mgmt_cmd.value);
191 
192 	return status;
193 }
194 
195 /**
196  * MiWrite - Write to a PHY register through the MII interface of the MAC
197  * @adapter: pointer to our private adapter structure
198  * @xcvrReg: the register to read
199  * @value: 16-bit value to write
200  *
201  * Return 0 on success, errno on failure (as defined in errno.h)
202  */
MiWrite(struct et131x_adapter * adapter,uint8_t xcvrReg,uint16_t value)203 int MiWrite(struct et131x_adapter *adapter, uint8_t xcvrReg, uint16_t value)
204 {
205 	struct _MAC_t __iomem *mac = &adapter->CSRAddress->mac;
206 	int status = 0;
207 	uint8_t xcvrAddr = adapter->Stats.xcvr_addr;
208 	uint32_t delay;
209 	MII_MGMT_ADDR_t miiAddr;
210 	MII_MGMT_CMD_t miiCmd;
211 	MII_MGMT_INDICATOR_t miiIndicator;
212 
213 	/* Save a local copy of the registers we are dealing with so we can
214 	 * set them back
215 	 */
216 	miiAddr.value = readl(&mac->mii_mgmt_addr.value);
217 	miiCmd.value = readl(&mac->mii_mgmt_cmd.value);
218 
219 	/* Stop the current operation */
220 	writel(0, &mac->mii_mgmt_cmd.value);
221 
222 	/* Set up the register we need to write to on the correct PHY */
223 	{
224 		MII_MGMT_ADDR_t mii_mgmt_addr;
225 
226 		mii_mgmt_addr.bits.phy_addr = xcvrAddr;
227 		mii_mgmt_addr.bits.reg_addr = xcvrReg;
228 		writel(mii_mgmt_addr.value, &mac->mii_mgmt_addr.value);
229 	}
230 
231 	/* Add the value to write to the registers to the mac */
232 	writel(value, &mac->mii_mgmt_ctrl.value);
233 	delay = 0;
234 
235 	do {
236 		udelay(50);
237 		delay++;
238 		miiIndicator.value = readl(&mac->mii_mgmt_indicator.value);
239 	} while (miiIndicator.bits.busy && delay < 100);
240 
241 	/* If we hit the max delay, we could not write the register */
242 	if (delay == 100) {
243 		uint16_t TempValue;
244 
245 		DBG_WARNING(et131x_dbginfo,
246 			    "xcvrReg 0x%08x could not be written", xcvrReg);
247 		DBG_WARNING(et131x_dbginfo, "status is  0x%08x\n",
248 			    miiIndicator.value);
249 		DBG_WARNING(et131x_dbginfo, "command is  0x%08x\n",
250 			    readl(&mac->mii_mgmt_cmd.value));
251 
252 		MiRead(adapter, xcvrReg, &TempValue);
253 
254 		status = -EIO;
255 	}
256 
257 	/* Stop the write operation */
258 	writel(0, &mac->mii_mgmt_cmd.value);
259 
260 	/* set the registers we touched back to the state at which we entered
261          * this function
262          */
263 	writel(miiAddr.value, &mac->mii_mgmt_addr.value);
264 	writel(miiCmd.value, &mac->mii_mgmt_cmd.value);
265 
266 	DBG_VERBOSE(et131x_dbginfo, " xcvr_addr = 0x%02x, "
267 		    "xcvr_reg  = 0x%02x, "
268 		    "value     = 0x%04x.\n", xcvrAddr, xcvrReg, value);
269 
270 	return status;
271 }
272 
273 /**
274  * et131x_xcvr_find - Find the PHY ID
275  * @adapter: pointer to our private adapter structure
276  *
277  * Returns 0 on success, errno on failure (as defined in errno.h)
278  */
et131x_xcvr_find(struct et131x_adapter * adapter)279 int et131x_xcvr_find(struct et131x_adapter *adapter)
280 {
281 	int status = -ENODEV;
282 	uint8_t xcvr_addr;
283 	MI_IDR1_t idr1;
284 	MI_IDR2_t idr2;
285 	uint32_t xcvr_id;
286 
287 	DBG_ENTER(et131x_dbginfo);
288 
289 	/* We need to get xcvr id and address we just get the first one */
290 	for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) {
291 		/* Read the ID from the PHY */
292 		PhyMiRead(adapter, xcvr_addr,
293 			  (uint8_t) offsetof(MI_REGS_t, idr1),
294 			  &idr1.value);
295 		PhyMiRead(adapter, xcvr_addr,
296 			  (uint8_t) offsetof(MI_REGS_t, idr2),
297 			  &idr2.value);
298 
299 		xcvr_id = (uint32_t) ((idr1.value << 16) | idr2.value);
300 
301 		if ((idr1.value != 0) && (idr1.value != 0xffff)) {
302 			DBG_TRACE(et131x_dbginfo,
303 				  "Xcvr addr: 0x%02x\tXcvr_id: 0x%08x\n",
304 				  xcvr_addr, xcvr_id);
305 
306 			adapter->Stats.xcvr_id = xcvr_id;
307 			adapter->Stats.xcvr_addr = xcvr_addr;
308 
309 			status = 0;
310 			break;
311 		}
312 	}
313 
314 	DBG_LEAVE(et131x_dbginfo);
315 	return status;
316 }
317 
318 /**
319  * et131x_setphy_normal - Set PHY for normal operation.
320  * @adapter: pointer to our private adapter structure
321  *
322  * Used by Power Management to force the PHY into 10 Base T half-duplex mode,
323  * when going to D3 in WOL mode. Also used during initialization to set the
324  * PHY for normal operation.
325  */
et131x_setphy_normal(struct et131x_adapter * adapter)326 int et131x_setphy_normal(struct et131x_adapter *adapter)
327 {
328 	int status;
329 
330 	DBG_ENTER(et131x_dbginfo);
331 
332 	/* Make sure the PHY is powered up */
333 	ET1310_PhyPowerDown(adapter, 0);
334 	status = et131x_xcvr_init(adapter);
335 
336 	DBG_LEAVE(et131x_dbginfo);
337 	return status;
338 }
339 
340 /**
341  * et131x_xcvr_init - Init the phy if we are setting it into force mode
342  * @adapter: pointer to our private adapter structure
343  *
344  * Returns 0 on success, errno on failure (as defined in errno.h)
345  */
et131x_xcvr_init(struct et131x_adapter * adapter)346 static int et131x_xcvr_init(struct et131x_adapter *adapter)
347 {
348 	int status = 0;
349 	MI_IMR_t imr;
350 	MI_ISR_t isr;
351 	MI_LCR2_t lcr2;
352 
353 	DBG_ENTER(et131x_dbginfo);
354 
355 	/* Zero out the adapter structure variable representing BMSR */
356 	adapter->Bmsr.value = 0;
357 
358 	MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, isr), &isr.value);
359 
360 	MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, imr), &imr.value);
361 
362 	/* Set the link status interrupt only.  Bad behavior when link status
363 	 * and auto neg are set, we run into a nested interrupt problem
364 	 */
365 	imr.bits.int_en = 0x1;
366 	imr.bits.link_status = 0x1;
367 	imr.bits.autoneg_status = 0x1;
368 
369 	MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, imr), imr.value);
370 
371 	/* Set the LED behavior such that LED 1 indicates speed (off =
372 	 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
373 	 * link and activity (on for link, blink off for activity).
374 	 *
375 	 * NOTE: Some customizations have been added here for specific
376 	 * vendors; The LED behavior is now determined by vendor data in the
377 	 * EEPROM. However, the above description is the default.
378 	 */
379 	if ((adapter->eepromData[1] & 0x4) == 0) {
380 		MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
381 		       &lcr2.value);
382 		if ((adapter->eepromData[1] & 0x8) == 0)
383 			lcr2.bits.led_tx_rx = 0x3;
384 		else
385 			lcr2.bits.led_tx_rx = 0x4;
386 		lcr2.bits.led_link = 0xa;
387 		MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2),
388 			lcr2.value);
389 	}
390 
391 	/* Determine if we need to go into a force mode and set it */
392 	if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) {
393 		if ((adapter->RegistryFlowControl == TxOnly) ||
394 		    (adapter->RegistryFlowControl == Both)) {
395 			ET1310_PhyAccessMiBit(adapter,
396 					      TRUEPHY_BIT_SET, 4, 11, NULL);
397 		} else {
398 			ET1310_PhyAccessMiBit(adapter,
399 					      TRUEPHY_BIT_CLEAR, 4, 11, NULL);
400 		}
401 
402 		if (adapter->RegistryFlowControl == Both) {
403 			ET1310_PhyAccessMiBit(adapter,
404 					      TRUEPHY_BIT_SET, 4, 10, NULL);
405 		} else {
406 			ET1310_PhyAccessMiBit(adapter,
407 					      TRUEPHY_BIT_CLEAR, 4, 10, NULL);
408 		}
409 
410 		/* Set the phy to autonegotiation */
411 		ET1310_PhyAutoNeg(adapter, true);
412 
413 		/* NOTE - Do we need this? */
414 		ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL);
415 
416 		DBG_LEAVE(et131x_dbginfo);
417 		return status;
418 	} else {
419 		ET1310_PhyAutoNeg(adapter, false);
420 
421 		/* Set to the correct force mode. */
422 		if (adapter->AiForceDpx != 1) {
423 			if ((adapter->RegistryFlowControl == TxOnly) ||
424 			    (adapter->RegistryFlowControl == Both)) {
425 				ET1310_PhyAccessMiBit(adapter,
426 						      TRUEPHY_BIT_SET, 4, 11,
427 						      NULL);
428 			} else {
429 				ET1310_PhyAccessMiBit(adapter,
430 						      TRUEPHY_BIT_CLEAR, 4, 11,
431 						      NULL);
432 			}
433 
434 			if (adapter->RegistryFlowControl == Both) {
435 				ET1310_PhyAccessMiBit(adapter,
436 						      TRUEPHY_BIT_SET, 4, 10,
437 						      NULL);
438 			} else {
439 				ET1310_PhyAccessMiBit(adapter,
440 						      TRUEPHY_BIT_CLEAR, 4, 10,
441 						      NULL);
442 			}
443 		} else {
444 			ET1310_PhyAccessMiBit(adapter,
445 					      TRUEPHY_BIT_CLEAR, 4, 10, NULL);
446 			ET1310_PhyAccessMiBit(adapter,
447 					      TRUEPHY_BIT_CLEAR, 4, 11, NULL);
448 		}
449 
450 		switch (adapter->AiForceSpeed) {
451 		case 10:
452 			if (adapter->AiForceDpx == 1) {
453 				TPAL_SetPhy10HalfDuplex(adapter);
454 			} else if (adapter->AiForceDpx == 2) {
455 				TPAL_SetPhy10FullDuplex(adapter);
456 			} else {
457 				TPAL_SetPhy10Force(adapter);
458 			}
459 			break;
460 		case 100:
461 			if (adapter->AiForceDpx == 1) {
462 				TPAL_SetPhy100HalfDuplex(adapter);
463 			} else if (adapter->AiForceDpx == 2) {
464 				TPAL_SetPhy100FullDuplex(adapter);
465 			} else {
466 				TPAL_SetPhy100Force(adapter);
467 			}
468 			break;
469 		case 1000:
470 			TPAL_SetPhy1000FullDuplex(adapter);
471 			break;
472 		}
473 
474 		DBG_LEAVE(et131x_dbginfo);
475 		return status;
476 	}
477 }
478 
et131x_Mii_check(struct et131x_adapter * pAdapter,MI_BMSR_t bmsr,MI_BMSR_t bmsr_ints)479 void et131x_Mii_check(struct et131x_adapter *pAdapter,
480 		      MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints)
481 {
482 	uint8_t ucLinkStatus;
483 	uint32_t uiAutoNegStatus;
484 	uint32_t uiSpeed;
485 	uint32_t uiDuplex;
486 	uint32_t uiMdiMdix;
487 	uint32_t uiMasterSlave;
488 	uint32_t uiPolarity;
489 	unsigned long lockflags;
490 
491 	DBG_ENTER(et131x_dbginfo);
492 
493 	if (bmsr_ints.bits.link_status) {
494 		if (bmsr.bits.link_status) {
495 			pAdapter->PoMgmt.TransPhyComaModeOnBoot = 20;
496 
497 			/* Update our state variables and indicate the
498 			 * connected state
499 			 */
500 			spin_lock_irqsave(&pAdapter->Lock, lockflags);
501 
502 			pAdapter->MediaState = NETIF_STATUS_MEDIA_CONNECT;
503 			MP_CLEAR_FLAG(pAdapter, fMP_ADAPTER_LINK_DETECTION);
504 
505 			spin_unlock_irqrestore(&pAdapter->Lock, lockflags);
506 
507 			/* Don't indicate state if we're in loopback mode */
508 			if (pAdapter->RegistryPhyLoopbk == false) {
509 				netif_carrier_on(pAdapter->netdev);
510 			}
511 		} else {
512 			DBG_WARNING(et131x_dbginfo,
513 				    "Link down cable problem\n");
514 
515 			if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS) {
516 				// NOTE - Is there a way to query this without TruePHY?
517 				// && TRU_QueryCoreType(pAdapter->hTruePhy, 0) == EMI_TRUEPHY_A13O) {
518 				uint16_t Register18;
519 
520 				MiRead(pAdapter, 0x12, &Register18);
521 				MiWrite(pAdapter, 0x12, Register18 | 0x4);
522 				MiWrite(pAdapter, 0x10, Register18 | 0x8402);
523 				MiWrite(pAdapter, 0x11, Register18 | 511);
524 				MiWrite(pAdapter, 0x12, Register18);
525 			}
526 
527 			/* For the first N seconds of life, we are in "link
528 			 * detection" When we are in this state, we should
529 			 * only report "connected". When the LinkDetection
530 			 * Timer expires, we can report disconnected (handled
531 			 * in the LinkDetectionDPC).
532 			 */
533 			if ((MP_IS_FLAG_CLEAR
534 			     (pAdapter, fMP_ADAPTER_LINK_DETECTION))
535 			    || (pAdapter->MediaState ==
536 				NETIF_STATUS_MEDIA_DISCONNECT)) {
537 				spin_lock_irqsave(&pAdapter->Lock, lockflags);
538 				pAdapter->MediaState =
539 				    NETIF_STATUS_MEDIA_DISCONNECT;
540 				spin_unlock_irqrestore(&pAdapter->Lock,
541 						       lockflags);
542 
543 				/* Only indicate state if we're in loopback
544 				 * mode
545 				 */
546 				if (pAdapter->RegistryPhyLoopbk == false) {
547 					netif_carrier_off(pAdapter->netdev);
548 				}
549 			}
550 
551 			pAdapter->uiLinkSpeed = 0;
552 			pAdapter->uiDuplexMode = 0;
553 
554 			/* Free the packets being actively sent & stopped */
555 			et131x_free_busy_send_packets(pAdapter);
556 
557 			/* Re-initialize the send structures */
558 			et131x_init_send(pAdapter);
559 
560 			/* Reset the RFD list and re-start RU */
561 			et131x_reset_recv(pAdapter);
562 
563 			/*
564 			 * Bring the device back to the state it was during
565 			 * init prior to autonegotiation being complete. This
566 			 * way, when we get the auto-neg complete interrupt,
567 			 * we can complete init by calling ConfigMacREGS2.
568 			 */
569 			et131x_soft_reset(pAdapter);
570 
571 			/* Setup ET1310 as per the documentation */
572 			et131x_adapter_setup(pAdapter);
573 
574 			/* Setup the PHY into coma mode until the cable is
575 			 * plugged back in
576 			 */
577 			if (pAdapter->RegistryPhyComa == 1) {
578 				EnablePhyComa(pAdapter);
579 			}
580 		}
581 	}
582 
583 	if (bmsr_ints.bits.auto_neg_complete ||
584 	    ((pAdapter->AiForceDpx == 3) && (bmsr_ints.bits.link_status))) {
585 		if (bmsr.bits.auto_neg_complete || (pAdapter->AiForceDpx == 3)) {
586 			ET1310_PhyLinkStatus(pAdapter,
587 					     &ucLinkStatus, &uiAutoNegStatus,
588 					     &uiSpeed, &uiDuplex, &uiMdiMdix,
589 					     &uiMasterSlave, &uiPolarity);
590 
591 			pAdapter->uiLinkSpeed = uiSpeed;
592 			pAdapter->uiDuplexMode = uiDuplex;
593 
594 			DBG_TRACE(et131x_dbginfo,
595 				  "pAdapter->uiLinkSpeed 0x%04x, pAdapter->uiDuplex 0x%08x\n",
596 				  pAdapter->uiLinkSpeed,
597 				  pAdapter->uiDuplexMode);
598 
599 			pAdapter->PoMgmt.TransPhyComaModeOnBoot = 20;
600 
601 			if (pAdapter->uiLinkSpeed == TRUEPHY_SPEED_10MBPS) {
602 				// NOTE - Is there a way to query this without TruePHY?
603 				// && TRU_QueryCoreType(pAdapter->hTruePhy, 0) == EMI_TRUEPHY_A13O) {
604 				uint16_t Register18;
605 
606 				MiRead(pAdapter, 0x12, &Register18);
607 				MiWrite(pAdapter, 0x12, Register18 | 0x4);
608 				MiWrite(pAdapter, 0x10, Register18 | 0x8402);
609 				MiWrite(pAdapter, 0x11, Register18 | 511);
610 				MiWrite(pAdapter, 0x12, Register18);
611 			}
612 
613 			ConfigFlowControl(pAdapter);
614 
615 			if ((pAdapter->uiLinkSpeed == TRUEPHY_SPEED_1000MBPS) &&
616 			    (pAdapter->RegistryJumboPacket > 2048))
617 			{
618 				ET1310_PhyAndOrReg(pAdapter, 0x16, 0xcfff,
619 						   0x2000);
620 			}
621 
622 			SetRxDmaTimer(pAdapter);
623 			ConfigMACRegs2(pAdapter);
624 		}
625 	}
626 
627 	DBG_LEAVE(et131x_dbginfo);
628 }
629 
630 /**
631  * TPAL_SetPhy10HalfDuplex - Force the phy into 10 Base T Half Duplex mode.
632  * @pAdapter: pointer to the adapter structure
633  *
634  * Also sets the MAC so it is syncd up properly
635  */
TPAL_SetPhy10HalfDuplex(struct et131x_adapter * pAdapter)636 void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *pAdapter)
637 {
638 	DBG_ENTER(et131x_dbginfo);
639 
640 	/* Power down PHY */
641 	ET1310_PhyPowerDown(pAdapter, 1);
642 
643 	/* First we need to turn off all other advertisement */
644 	ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
645 
646 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
647 
648 	/* Set our advertise values accordingly */
649 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_HALF);
650 
651 	/* Power up PHY */
652 	ET1310_PhyPowerDown(pAdapter, 0);
653 
654 	DBG_LEAVE(et131x_dbginfo);
655 }
656 
657 /**
658  * TPAL_SetPhy10FullDuplex - Force the phy into 10 Base T Full Duplex mode.
659  * @pAdapter: pointer to the adapter structure
660  *
661  * Also sets the MAC so it is syncd up properly
662  */
TPAL_SetPhy10FullDuplex(struct et131x_adapter * pAdapter)663 void TPAL_SetPhy10FullDuplex(struct et131x_adapter *pAdapter)
664 {
665 	DBG_ENTER(et131x_dbginfo);
666 
667 	/* Power down PHY */
668 	ET1310_PhyPowerDown(pAdapter, 1);
669 
670 	/* First we need to turn off all other advertisement */
671 	ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
672 
673 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
674 
675 	/* Set our advertise values accordingly */
676 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
677 
678 	/* Power up PHY */
679 	ET1310_PhyPowerDown(pAdapter, 0);
680 
681 	DBG_LEAVE(et131x_dbginfo);
682 }
683 
684 /**
685  * TPAL_SetPhy10Force - Force Base-T FD mode WITHOUT using autonegotiation
686  * @pAdapter: pointer to the adapter structure
687  */
TPAL_SetPhy10Force(struct et131x_adapter * pAdapter)688 void TPAL_SetPhy10Force(struct et131x_adapter *pAdapter)
689 {
690 	DBG_ENTER(et131x_dbginfo);
691 
692 	/* Power down PHY */
693 	ET1310_PhyPowerDown(pAdapter, 1);
694 
695 	/* Disable autoneg */
696 	ET1310_PhyAutoNeg(pAdapter, false);
697 
698 	/* Disable all advertisement */
699 	ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
700 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
701 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
702 
703 	/* Force 10 Mbps */
704 	ET1310_PhySpeedSelect(pAdapter, TRUEPHY_SPEED_10MBPS);
705 
706 	/* Force Full duplex */
707 	ET1310_PhyDuplexMode(pAdapter, TRUEPHY_DUPLEX_FULL);
708 
709 	/* Power up PHY */
710 	ET1310_PhyPowerDown(pAdapter, 0);
711 
712 	DBG_LEAVE(et131x_dbginfo);
713 }
714 
715 /**
716  * TPAL_SetPhy100HalfDuplex - Force 100 Base T Half Duplex mode.
717  * @pAdapter: pointer to the adapter structure
718  *
719  * Also sets the MAC so it is syncd up properly.
720  */
TPAL_SetPhy100HalfDuplex(struct et131x_adapter * pAdapter)721 void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *pAdapter)
722 {
723 	DBG_ENTER(et131x_dbginfo);
724 
725 	/* Power down PHY */
726 	ET1310_PhyPowerDown(pAdapter, 1);
727 
728 	/* first we need to turn off all other advertisement */
729 	ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
730 
731 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
732 
733 	/* Set our advertise values accordingly */
734 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_HALF);
735 
736 	/* Set speed */
737 	ET1310_PhySpeedSelect(pAdapter, TRUEPHY_SPEED_100MBPS);
738 
739 	/* Power up PHY */
740 	ET1310_PhyPowerDown(pAdapter, 0);
741 
742 	DBG_LEAVE(et131x_dbginfo);
743 }
744 
745 /**
746  * TPAL_SetPhy100FullDuplex - Force 100 Base T Full Duplex mode.
747  * @pAdapter: pointer to the adapter structure
748  *
749  * Also sets the MAC so it is syncd up properly
750  */
TPAL_SetPhy100FullDuplex(struct et131x_adapter * pAdapter)751 void TPAL_SetPhy100FullDuplex(struct et131x_adapter *pAdapter)
752 {
753 	DBG_ENTER(et131x_dbginfo);
754 
755 	/* Power down PHY */
756 	ET1310_PhyPowerDown(pAdapter, 1);
757 
758 	/* First we need to turn off all other advertisement */
759 	ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
760 
761 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
762 
763 	/* Set our advertise values accordingly */
764 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
765 
766 	/* Power up PHY */
767 	ET1310_PhyPowerDown(pAdapter, 0);
768 
769 	DBG_LEAVE(et131x_dbginfo);
770 }
771 
772 /**
773  * TPAL_SetPhy100Force - Force 100 BaseT FD mode WITHOUT using autonegotiation
774  * @pAdapter: pointer to the adapter structure
775  */
TPAL_SetPhy100Force(struct et131x_adapter * pAdapter)776 void TPAL_SetPhy100Force(struct et131x_adapter *pAdapter)
777 {
778 	DBG_ENTER(et131x_dbginfo);
779 
780 	/* Power down PHY */
781 	ET1310_PhyPowerDown(pAdapter, 1);
782 
783 	/* Disable autoneg */
784 	ET1310_PhyAutoNeg(pAdapter, false);
785 
786 	/* Disable all advertisement */
787 	ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
788 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
789 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
790 
791 	/* Force 100 Mbps */
792 	ET1310_PhySpeedSelect(pAdapter, TRUEPHY_SPEED_100MBPS);
793 
794 	/* Force Full duplex */
795 	ET1310_PhyDuplexMode(pAdapter, TRUEPHY_DUPLEX_FULL);
796 
797 	/* Power up PHY */
798 	ET1310_PhyPowerDown(pAdapter, 0);
799 
800 	DBG_LEAVE(et131x_dbginfo);
801 }
802 
803 /**
804  * TPAL_SetPhy1000FullDuplex - Force 1000 Base T Full Duplex mode
805  * @pAdapter: pointer to the adapter structure
806  *
807  * Also sets the MAC so it is syncd up properly.
808  */
TPAL_SetPhy1000FullDuplex(struct et131x_adapter * pAdapter)809 void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *pAdapter)
810 {
811 	DBG_ENTER(et131x_dbginfo);
812 
813 	/* Power down PHY */
814 	ET1310_PhyPowerDown(pAdapter, 1);
815 
816 	/* first we need to turn off all other advertisement */
817 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
818 
819 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
820 
821 	/* set our advertise values accordingly */
822 	ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
823 
824 	/* power up PHY */
825 	ET1310_PhyPowerDown(pAdapter, 0);
826 
827 	DBG_LEAVE(et131x_dbginfo);
828 }
829 
830 /**
831  * TPAL_SetPhyAutoNeg - Set phy to autonegotiation mode.
832  * @pAdapter: pointer to the adapter structure
833  */
TPAL_SetPhyAutoNeg(struct et131x_adapter * pAdapter)834 void TPAL_SetPhyAutoNeg(struct et131x_adapter *pAdapter)
835 {
836 	DBG_ENTER(et131x_dbginfo);
837 
838 	/* Power down PHY */
839 	ET1310_PhyPowerDown(pAdapter, 1);
840 
841 	/* Turn on advertisement of all capabilities */
842 	ET1310_PhyAdvertise10BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_BOTH);
843 
844 	ET1310_PhyAdvertise100BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_BOTH);
845 
846 	if (pAdapter->DeviceID != ET131X_PCI_DEVICE_ID_FAST) {
847 		ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_FULL);
848 	} else {
849 		ET1310_PhyAdvertise1000BaseT(pAdapter, TRUEPHY_ADV_DUPLEX_NONE);
850 	}
851 
852 	/* Make sure auto-neg is ON (it is disabled in FORCE modes) */
853 	ET1310_PhyAutoNeg(pAdapter, true);
854 
855 	/* Power up PHY */
856 	ET1310_PhyPowerDown(pAdapter, 0);
857 
858 	DBG_LEAVE(et131x_dbginfo);
859 }
860 
861 
862 /*
863  * The routines which follow provide low-level access to the PHY, and are used
864  * primarily by the routines above (although there are a few places elsewhere
865  * in the driver where this level of access is required).
866  */
867 
868 static const uint16_t ConfigPhy[25][2] = {
869 	/* Reg      Value      Register */
870 	/* Addr                         */
871 	{0x880B, 0x0926},	/* AfeIfCreg4B1000Msbs */
872 	{0x880C, 0x0926},	/* AfeIfCreg4B100Msbs */
873 	{0x880D, 0x0926},	/* AfeIfCreg4B10Msbs */
874 
875 	{0x880E, 0xB4D3},	/* AfeIfCreg4B1000Lsbs */
876 	{0x880F, 0xB4D3},	/* AfeIfCreg4B100Lsbs */
877 	{0x8810, 0xB4D3},	/* AfeIfCreg4B10Lsbs */
878 
879 	{0x8805, 0xB03E},	/* AfeIfCreg3B1000Msbs */
880 	{0x8806, 0xB03E},	/* AfeIfCreg3B100Msbs */
881 	{0x8807, 0xFF00},	/* AfeIfCreg3B10Msbs */
882 
883 	{0x8808, 0xE090},	/* AfeIfCreg3B1000Lsbs */
884 	{0x8809, 0xE110},	/* AfeIfCreg3B100Lsbs */
885 	{0x880A, 0x0000},	/* AfeIfCreg3B10Lsbs */
886 
887 	{0x300D, 1},		/* DisableNorm */
888 
889 	{0x280C, 0x0180},	/* LinkHoldEnd */
890 
891 	{0x1C21, 0x0002},	/* AlphaM */
892 
893 	{0x3821, 6},		/* FfeLkgTx0 */
894 	{0x381D, 1},		/* FfeLkg1g4 */
895 	{0x381E, 1},		/* FfeLkg1g5 */
896 	{0x381F, 1},		/* FfeLkg1g6 */
897 	{0x3820, 1},		/* FfeLkg1g7 */
898 
899 	{0x8402, 0x01F0},	/* Btinact */
900 	{0x800E, 20},		/* LftrainTime */
901 	{0x800F, 24},		/* DvguardTime */
902 	{0x8010, 46},		/* IdlguardTime */
903 
904 	{0, 0}
905 
906 };
907 
908 /* condensed version of the phy initialization routine */
ET1310_PhyInit(struct et131x_adapter * pAdapter)909 void ET1310_PhyInit(struct et131x_adapter *pAdapter)
910 {
911 	uint16_t usData, usIndex;
912 
913 	if (pAdapter == NULL) {
914 		return;
915 	}
916 
917 	// get the identity (again ?)
918 	MiRead(pAdapter, PHY_ID_1, &usData);
919 	MiRead(pAdapter, PHY_ID_2, &usData);
920 
921 	// what does this do/achieve ?
922 	MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData);	// should read 0002
923 	MiWrite(pAdapter, PHY_MPHY_CONTROL_REG,	0x0006);
924 
925 	// read modem register 0402, should I do something with the return data ?
926 	MiWrite(pAdapter, PHY_INDEX_REG, 0x0402);
927 	MiRead(pAdapter, PHY_DATA_REG, &usData);
928 
929 	// what does this do/achieve ?
930 	MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0002);
931 
932 	// get the identity (again ?)
933 	MiRead(pAdapter, PHY_ID_1, &usData);
934 	MiRead(pAdapter, PHY_ID_2, &usData);
935 
936 	// what does this achieve ?
937 	MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData);	// should read 0002
938 	MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0006);
939 
940 	// read modem register 0402, should I do something with the return data?
941 	MiWrite(pAdapter, PHY_INDEX_REG, 0x0402);
942 	MiRead(pAdapter, PHY_DATA_REG, &usData);
943 
944 	MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0002);
945 
946 	// what does this achieve (should return 0x1040)
947 	MiRead(pAdapter, PHY_CONTROL, &usData);
948 	MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData);	// should read 0002
949 	MiWrite(pAdapter, PHY_CONTROL, 0x1840);
950 
951 	MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0007);
952 
953 	// here the writing of the array starts....
954 	usIndex = 0;
955 	while (ConfigPhy[usIndex][0] != 0x0000) {
956 		// write value
957 		MiWrite(pAdapter, PHY_INDEX_REG, ConfigPhy[usIndex][0]);
958 		MiWrite(pAdapter, PHY_DATA_REG, ConfigPhy[usIndex][1]);
959 
960 		// read it back
961 		MiWrite(pAdapter, PHY_INDEX_REG, ConfigPhy[usIndex][0]);
962 		MiRead(pAdapter, PHY_DATA_REG, &usData);
963 
964 		// do a check on the value read back ?
965 		usIndex++;
966 	}
967 	// here the writing of the array ends...
968 
969 	MiRead(pAdapter, PHY_CONTROL, &usData);	// 0x1840
970 	MiRead(pAdapter, PHY_MPHY_CONTROL_REG, &usData);	// should read 0007
971 	MiWrite(pAdapter, PHY_CONTROL, 0x1040);
972 	MiWrite(pAdapter, PHY_MPHY_CONTROL_REG, 0x0002);
973 }
974 
ET1310_PhyReset(struct et131x_adapter * pAdapter)975 void ET1310_PhyReset(struct et131x_adapter *pAdapter)
976 {
977 	MiWrite(pAdapter, PHY_CONTROL, 0x8000);
978 }
979 
ET1310_PhyPowerDown(struct et131x_adapter * pAdapter,bool down)980 void ET1310_PhyPowerDown(struct et131x_adapter *pAdapter, bool down)
981 {
982 	uint16_t usData;
983 
984 	MiRead(pAdapter, PHY_CONTROL, &usData);
985 
986 	if (down == false) {
987 		// Power UP
988 		usData &= ~0x0800;
989 		MiWrite(pAdapter, PHY_CONTROL, usData);
990 	} else {
991 		// Power DOWN
992 		usData |= 0x0800;
993 		MiWrite(pAdapter, PHY_CONTROL, usData);
994 	}
995 }
996 
ET1310_PhyAutoNeg(struct et131x_adapter * pAdapter,bool enable)997 void ET1310_PhyAutoNeg(struct et131x_adapter *pAdapter, bool enable)
998 {
999 	uint16_t usData;
1000 
1001 	MiRead(pAdapter, PHY_CONTROL, &usData);
1002 
1003 	if (enable == true) {
1004 		// Autonegotiation ON
1005 		usData |= 0x1000;
1006 		MiWrite(pAdapter, PHY_CONTROL, usData);
1007 	} else {
1008 		// Autonegotiation OFF
1009 		usData &= ~0x1000;
1010 		MiWrite(pAdapter, PHY_CONTROL, usData);
1011 	}
1012 }
1013 
ET1310_PhyDuplexMode(struct et131x_adapter * pAdapter,uint16_t duplex)1014 void ET1310_PhyDuplexMode(struct et131x_adapter *pAdapter, uint16_t duplex)
1015 {
1016 	uint16_t usData;
1017 
1018 	MiRead(pAdapter, PHY_CONTROL, &usData);
1019 
1020 	if (duplex == TRUEPHY_DUPLEX_FULL) {
1021 		// Set Full Duplex
1022 		usData |= 0x100;
1023 		MiWrite(pAdapter, PHY_CONTROL, usData);
1024 	} else {
1025 		// Set Half Duplex
1026 		usData &= ~0x100;
1027 		MiWrite(pAdapter, PHY_CONTROL, usData);
1028 	}
1029 }
1030 
ET1310_PhySpeedSelect(struct et131x_adapter * pAdapter,uint16_t speed)1031 void ET1310_PhySpeedSelect(struct et131x_adapter *pAdapter, uint16_t speed)
1032 {
1033 	uint16_t usData;
1034 
1035 	// Read the PHY control register
1036 	MiRead(pAdapter, PHY_CONTROL, &usData);
1037 
1038 	// Clear all Speed settings (Bits 6, 13)
1039 	usData &= ~0x2040;
1040 
1041 	// Reset the speed bits based on user selection
1042 	switch (speed) {
1043 	case TRUEPHY_SPEED_10MBPS:
1044 		// Bits already cleared above, do nothing
1045 		break;
1046 
1047 	case TRUEPHY_SPEED_100MBPS:
1048 		// 100M == Set bit 13
1049 		usData |= 0x2000;
1050 		break;
1051 
1052 	case TRUEPHY_SPEED_1000MBPS:
1053 	default:
1054 		usData |= 0x0040;
1055 		break;
1056 	}
1057 
1058 	// Write back the new speed
1059 	MiWrite(pAdapter, PHY_CONTROL, usData);
1060 }
1061 
ET1310_PhyAdvertise1000BaseT(struct et131x_adapter * pAdapter,uint16_t duplex)1062 void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *pAdapter,
1063 				  uint16_t duplex)
1064 {
1065 	uint16_t usData;
1066 
1067 	// Read the PHY 1000 Base-T Control Register
1068 	MiRead(pAdapter, PHY_1000_CONTROL, &usData);
1069 
1070 	// Clear Bits 8,9
1071 	usData &= ~0x0300;
1072 
1073 	switch (duplex) {
1074 	case TRUEPHY_ADV_DUPLEX_NONE:
1075 		// Duplex already cleared, do nothing
1076 		break;
1077 
1078 	case TRUEPHY_ADV_DUPLEX_FULL:
1079 		// Set Bit 9
1080 		usData |= 0x0200;
1081 		break;
1082 
1083 	case TRUEPHY_ADV_DUPLEX_HALF:
1084 		// Set Bit 8
1085 		usData |= 0x0100;
1086 		break;
1087 
1088 	case TRUEPHY_ADV_DUPLEX_BOTH:
1089 	default:
1090 		usData |= 0x0300;
1091 		break;
1092 	}
1093 
1094 	// Write back advertisement
1095 	MiWrite(pAdapter, PHY_1000_CONTROL, usData);
1096 }
1097 
ET1310_PhyAdvertise100BaseT(struct et131x_adapter * pAdapter,uint16_t duplex)1098 void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *pAdapter,
1099 				 uint16_t duplex)
1100 {
1101 	uint16_t usData;
1102 
1103 	// Read the Autonegotiation Register (10/100)
1104 	MiRead(pAdapter, PHY_AUTO_ADVERTISEMENT, &usData);
1105 
1106 	// Clear bits 7,8
1107 	usData &= ~0x0180;
1108 
1109 	switch (duplex) {
1110 	case TRUEPHY_ADV_DUPLEX_NONE:
1111 		// Duplex already cleared, do nothing
1112 		break;
1113 
1114 	case TRUEPHY_ADV_DUPLEX_FULL:
1115 		// Set Bit 8
1116 		usData |= 0x0100;
1117 		break;
1118 
1119 	case TRUEPHY_ADV_DUPLEX_HALF:
1120 		// Set Bit 7
1121 		usData |= 0x0080;
1122 		break;
1123 
1124 	case TRUEPHY_ADV_DUPLEX_BOTH:
1125 	default:
1126 		// Set Bits 7,8
1127 		usData |= 0x0180;
1128 		break;
1129 	}
1130 
1131 	// Write back advertisement
1132 	MiWrite(pAdapter, PHY_AUTO_ADVERTISEMENT, usData);
1133 }
1134 
ET1310_PhyAdvertise10BaseT(struct et131x_adapter * pAdapter,uint16_t duplex)1135 void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *pAdapter,
1136 				uint16_t duplex)
1137 {
1138 	uint16_t usData;
1139 
1140 	// Read the Autonegotiation Register (10/100)
1141 	MiRead(pAdapter, PHY_AUTO_ADVERTISEMENT, &usData);
1142 
1143 	// Clear bits 5,6
1144 	usData &= ~0x0060;
1145 
1146 	switch (duplex) {
1147 	case TRUEPHY_ADV_DUPLEX_NONE:
1148 		// Duplex already cleared, do nothing
1149 		break;
1150 
1151 	case TRUEPHY_ADV_DUPLEX_FULL:
1152 		// Set Bit 6
1153 		usData |= 0x0040;
1154 		break;
1155 
1156 	case TRUEPHY_ADV_DUPLEX_HALF:
1157 		// Set Bit 5
1158 		usData |= 0x0020;
1159 		break;
1160 
1161 	case TRUEPHY_ADV_DUPLEX_BOTH:
1162 	default:
1163 		// Set Bits 5,6
1164 		usData |= 0x0060;
1165 		break;
1166 	}
1167 
1168 	// Write back advertisement
1169 	MiWrite(pAdapter, PHY_AUTO_ADVERTISEMENT, usData);
1170 }
1171 
ET1310_PhyLinkStatus(struct et131x_adapter * pAdapter,uint8_t * ucLinkStatus,uint32_t * uiAutoNeg,uint32_t * uiLinkSpeed,uint32_t * uiDuplexMode,uint32_t * uiMdiMdix,uint32_t * uiMasterSlave,uint32_t * uiPolarity)1172 void ET1310_PhyLinkStatus(struct et131x_adapter *pAdapter,
1173 			  uint8_t *ucLinkStatus,
1174 			  uint32_t *uiAutoNeg,
1175 			  uint32_t *uiLinkSpeed,
1176 			  uint32_t *uiDuplexMode,
1177 			  uint32_t *uiMdiMdix,
1178 			  uint32_t *uiMasterSlave, uint32_t *uiPolarity)
1179 {
1180 	uint16_t usMiStatus = 0;
1181 	uint16_t us1000BaseT = 0;
1182 	uint16_t usVmiPhyStatus = 0;
1183 	uint16_t usControl = 0;
1184 
1185 	MiRead(pAdapter, PHY_STATUS, &usMiStatus);
1186 	MiRead(pAdapter, PHY_1000_STATUS, &us1000BaseT);
1187 	MiRead(pAdapter, PHY_PHY_STATUS, &usVmiPhyStatus);
1188 	MiRead(pAdapter, PHY_CONTROL, &usControl);
1189 
1190 	if (ucLinkStatus) {
1191 		*ucLinkStatus =
1192 		    (unsigned char)((usVmiPhyStatus & 0x0040) ? 1 : 0);
1193 	}
1194 
1195 	if (uiAutoNeg) {
1196 		*uiAutoNeg =
1197 		    (usControl & 0x1000) ? ((usVmiPhyStatus & 0x0020) ?
1198 					    TRUEPHY_ANEG_COMPLETE :
1199 					    TRUEPHY_ANEG_NOT_COMPLETE) :
1200 		    TRUEPHY_ANEG_DISABLED;
1201 	}
1202 
1203 	if (uiLinkSpeed) {
1204 		*uiLinkSpeed = (usVmiPhyStatus & 0x0300) >> 8;
1205 	}
1206 
1207 	if (uiDuplexMode) {
1208 		*uiDuplexMode = (usVmiPhyStatus & 0x0080) >> 7;
1209 	}
1210 
1211 	if (uiMdiMdix) {
1212 		/* NOTE: Need to complete this */
1213 		*uiMdiMdix = 0;
1214 	}
1215 
1216 	if (uiMasterSlave) {
1217 		*uiMasterSlave =
1218 		    (us1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER :
1219 		    TRUEPHY_CFG_SLAVE;
1220 	}
1221 
1222 	if (uiPolarity) {
1223 		*uiPolarity =
1224 		    (usVmiPhyStatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED :
1225 		    TRUEPHY_POLARITY_NORMAL;
1226 	}
1227 }
1228 
ET1310_PhyAndOrReg(struct et131x_adapter * pAdapter,uint16_t regnum,uint16_t andMask,uint16_t orMask)1229 void ET1310_PhyAndOrReg(struct et131x_adapter *pAdapter,
1230 			uint16_t regnum, uint16_t andMask, uint16_t orMask)
1231 {
1232 	uint16_t reg;
1233 
1234 	// Read the requested register
1235 	MiRead(pAdapter, regnum, &reg);
1236 
1237 	// Apply the AND mask
1238 	reg &= andMask;
1239 
1240 	// Apply the OR mask
1241 	reg |= orMask;
1242 
1243 	// Write the value back to the register
1244 	MiWrite(pAdapter, regnum, reg);
1245 }
1246 
ET1310_PhyAccessMiBit(struct et131x_adapter * pAdapter,uint16_t action,uint16_t regnum,uint16_t bitnum,uint8_t * value)1247 void ET1310_PhyAccessMiBit(struct et131x_adapter *pAdapter, uint16_t action,
1248 			   uint16_t regnum, uint16_t bitnum, uint8_t *value)
1249 {
1250 	uint16_t reg;
1251 	uint16_t mask = 0;
1252 
1253 	// Create a mask to isolate the requested bit
1254 	mask = 0x0001 << bitnum;
1255 
1256 	// Read the requested register
1257 	MiRead(pAdapter, regnum, &reg);
1258 
1259 	switch (action) {
1260 	case TRUEPHY_BIT_READ:
1261 		if (value != NULL) {
1262 			*value = (reg & mask) >> bitnum;
1263 		}
1264 		break;
1265 
1266 	case TRUEPHY_BIT_SET:
1267 		reg |= mask;
1268 		MiWrite(pAdapter, regnum, reg);
1269 		break;
1270 
1271 	case TRUEPHY_BIT_CLEAR:
1272 		reg &= ~mask;
1273 		MiWrite(pAdapter, regnum, reg);
1274 		break;
1275 
1276 	default:
1277 		break;
1278 	}
1279 }
1280