1 /******************************************************************************
2  *
3  * Name:	skxmac2.c
4  * Project:	Gigabit Ethernet Adapters, Common Modules
5  * Purpose:	Contains functions to initialize the MACs and PHYs
6  *
7  ******************************************************************************/
8 
9 /******************************************************************************
10  *
11  *	(C)Copyright 1998-2002 SysKonnect.
12  *	(C)Copyright 2002-2003 Marvell.
13  *
14  *	This program is free software; you can redistribute it and/or modify
15  *	it under the terms of the GNU General Public License as published by
16  *	the Free Software Foundation; either version 2 of the License, or
17  *	(at your option) any later version.
18  *
19  *	The information in this file is provided "AS IS" without warranty.
20  *
21  ******************************************************************************/
22 
23 #include "h/skdrv1st.h"
24 #include "h/skdrv2nd.h"
25 
26 /* typedefs *******************************************************************/
27 
28 /* BCOM PHY magic pattern list */
29 typedef struct s_PhyHack {
30 	int		PhyReg;		/* Phy register */
31 	SK_U16	PhyVal;		/* Value to write */
32 } BCOM_HACK;
33 
34 /* local variables ************************************************************/
35 
36 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
37 static const char SysKonnectFileId[] =
38 	"@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
39 #endif
40 
41 #ifdef GENESIS
42 BCOM_HACK BcomRegA1Hack[] = {
43  { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
44  { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
45  { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
46  { 0, 0 }
47 };
48 BCOM_HACK BcomRegC0Hack[] = {
49  { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
50  { 0x15, 0x0A04 }, { 0x18, 0x0420 },
51  { 0, 0 }
52 };
53 #endif
54 
55 /* function prototypes ********************************************************/
56 #ifdef GENESIS
57 static void	SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
58 static void	SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
59 static int	SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
60 static int	SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
61 #endif /* GENESIS */
62 #ifdef YUKON
63 static void	SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
64 static int	SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
65 #endif /* YUKON */
66 #ifdef OTHER_PHY
67 static void	SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
68 static void	SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
69 static int	SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
70 static int	SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
71 #endif /* OTHER_PHY */
72 
73 
74 #ifdef GENESIS
75 /******************************************************************************
76  *
77  *	SkXmPhyRead() - Read from XMAC PHY register
78  *
79  * Description:	reads a 16-bit word from XMAC PHY or ext. PHY
80  *
81  * Returns:
82  *	nothing
83  */
SkXmPhyRead(SK_AC * pAC,SK_IOC IoC,int Port,int PhyReg,SK_U16 SK_FAR * pVal)84 void SkXmPhyRead(
85 SK_AC	*pAC,			/* Adapter Context */
86 SK_IOC	IoC,			/* I/O Context */
87 int		Port,			/* Port Index (MAC_1 + n) */
88 int		PhyReg,			/* Register Address (Offset) */
89 SK_U16	SK_FAR *pVal)	/* Pointer to Value */
90 {
91 	SK_U16		Mmu;
92 	SK_GEPORT	*pPrt;
93 
94 	pPrt = &pAC->GIni.GP[Port];
95 
96 	/* write the PHY register's address */
97 	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
98 
99 	/* get the PHY register's value */
100 	XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
101 
102 	if (pPrt->PhyType != SK_PHY_XMAC) {
103 		do {
104 			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
105 			/* wait until 'Ready' is set */
106 		} while ((Mmu & XM_MMU_PHY_RDY) == 0);
107 
108 		/* get the PHY register's value */
109 		XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
110 	}
111 }	/* SkXmPhyRead */
112 
113 
114 /******************************************************************************
115  *
116  *	SkXmPhyWrite() - Write to XMAC PHY register
117  *
118  * Description:	writes a 16-bit word to XMAC PHY or ext. PHY
119  *
120  * Returns:
121  *	nothing
122  */
SkXmPhyWrite(SK_AC * pAC,SK_IOC IoC,int Port,int PhyReg,SK_U16 Val)123 void SkXmPhyWrite(
124 SK_AC	*pAC,		/* Adapter Context */
125 SK_IOC	IoC,		/* I/O Context */
126 int		Port,		/* Port Index (MAC_1 + n) */
127 int		PhyReg,		/* Register Address (Offset) */
128 SK_U16	Val)		/* Value */
129 {
130 	SK_U16		Mmu;
131 	SK_GEPORT	*pPrt;
132 
133 	pPrt = &pAC->GIni.GP[Port];
134 
135 	if (pPrt->PhyType != SK_PHY_XMAC) {
136 		do {
137 			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
138 			/* wait until 'Busy' is cleared */
139 		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
140 	}
141 
142 	/* write the PHY register's address */
143 	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
144 
145 	/* write the PHY register's value */
146 	XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
147 
148 	if (pPrt->PhyType != SK_PHY_XMAC) {
149 		do {
150 			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
151 			/* wait until 'Busy' is cleared */
152 		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
153 	}
154 }	/* SkXmPhyWrite */
155 #endif /* GENESIS */
156 
157 
158 #ifdef YUKON
159 /******************************************************************************
160  *
161  *	SkGmPhyRead() - Read from GPHY register
162  *
163  * Description:	reads a 16-bit word from GPHY through MDIO
164  *
165  * Returns:
166  *	nothing
167  */
SkGmPhyRead(SK_AC * pAC,SK_IOC IoC,int Port,int PhyReg,SK_U16 SK_FAR * pVal)168 void SkGmPhyRead(
169 SK_AC	*pAC,			/* Adapter Context */
170 SK_IOC	IoC,			/* I/O Context */
171 int		Port,			/* Port Index (MAC_1 + n) */
172 int		PhyReg,			/* Register Address (Offset) */
173 SK_U16	SK_FAR *pVal)	/* Pointer to Value */
174 {
175 	SK_U16	Ctrl;
176 	SK_GEPORT	*pPrt;
177 #ifdef VCPU
178 	u_long SimCyle;
179 	u_long SimLowTime;
180 
181 	VCPUgetTime(&SimCyle, &SimLowTime);
182 	VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
183 		PhyReg, SimCyle, SimLowTime);
184 #endif /* VCPU */
185 
186 	pPrt = &pAC->GIni.GP[Port];
187 
188 	/* set PHY-Register offset and 'Read' OpCode (= 1) */
189 	*pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
190 		GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
191 
192 	GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
193 
194 	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
195 
196 	/* additional check for MDC/MDIO activity */
197 	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
198 		*pVal = 0;
199 		return;
200 	}
201 
202 	*pVal |= GM_SMI_CT_BUSY;
203 
204 	do {
205 #ifdef VCPU
206 		VCPUwaitTime(1000);
207 #endif /* VCPU */
208 
209 		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
210 
211 	/* wait until 'ReadValid' is set */
212 	} while (Ctrl == *pVal);
213 
214 	/* get the PHY register's value */
215 	GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
216 
217 #ifdef VCPU
218 	VCPUgetTime(&SimCyle, &SimLowTime);
219 	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
220 		SimCyle, SimLowTime);
221 #endif /* VCPU */
222 
223 }	/* SkGmPhyRead */
224 
225 
226 /******************************************************************************
227  *
228  *	SkGmPhyWrite() - Write to GPHY register
229  *
230  * Description:	writes a 16-bit word to GPHY through MDIO
231  *
232  * Returns:
233  *	nothing
234  */
SkGmPhyWrite(SK_AC * pAC,SK_IOC IoC,int Port,int PhyReg,SK_U16 Val)235 void SkGmPhyWrite(
236 SK_AC	*pAC,		/* Adapter Context */
237 SK_IOC	IoC,		/* I/O Context */
238 int		Port,		/* Port Index (MAC_1 + n) */
239 int		PhyReg,		/* Register Address (Offset) */
240 SK_U16	Val)		/* Value */
241 {
242 	SK_U16	Ctrl;
243 	SK_GEPORT	*pPrt;
244 #ifdef VCPU
245 	SK_U32	DWord;
246 	u_long	SimCyle;
247 	u_long	SimLowTime;
248 
249 	VCPUgetTime(&SimCyle, &SimLowTime);
250 	VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
251 		PhyReg, Val, SimCyle, SimLowTime);
252 #endif /* VCPU */
253 
254 	pPrt = &pAC->GIni.GP[Port];
255 
256 	/* write the PHY register's value */
257 	GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
258 
259 	/* set PHY-Register offset and 'Write' OpCode (= 0) */
260 	Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
261 
262 	GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
263 
264 	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
265 
266 	/* additional check for MDC/MDIO activity */
267 	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
268 		return;
269 	}
270 
271 	Val |= GM_SMI_CT_BUSY;
272 
273 	do {
274 #ifdef VCPU
275 		/* read Timer value */
276 		SK_IN32(IoC, B2_TI_VAL, &DWord);
277 
278 		VCPUwaitTime(1000);
279 #endif /* VCPU */
280 
281 		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
282 
283 	/* wait until 'Busy' is cleared */
284 	} while (Ctrl == Val);
285 
286 #ifdef VCPU
287 	VCPUgetTime(&SimCyle, &SimLowTime);
288 	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
289 		SimCyle, SimLowTime);
290 #endif /* VCPU */
291 
292 }	/* SkGmPhyWrite */
293 #endif /* YUKON */
294 
295 
296 #ifdef SK_DIAG
297 /******************************************************************************
298  *
299  *	SkGePhyRead() - Read from PHY register
300  *
301  * Description:	calls a read PHY routine dep. on board type
302  *
303  * Returns:
304  *	nothing
305  */
SkGePhyRead(SK_AC * pAC,SK_IOC IoC,int Port,int PhyReg,SK_U16 * pVal)306 void SkGePhyRead(
307 SK_AC	*pAC,		/* Adapter Context */
308 SK_IOC	IoC,		/* I/O Context */
309 int		Port,		/* Port Index (MAC_1 + n) */
310 int		PhyReg,		/* Register Address (Offset) */
311 SK_U16	*pVal)		/* Pointer to Value */
312 {
313 	void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
314 
315 	if (pAC->GIni.GIGenesis) {
316 		r_func = SkXmPhyRead;
317 	}
318 	else {
319 		r_func = SkGmPhyRead;
320 	}
321 
322 	r_func(pAC, IoC, Port, PhyReg, pVal);
323 }	/* SkGePhyRead */
324 
325 
326 /******************************************************************************
327  *
328  *	SkGePhyWrite() - Write to PHY register
329  *
330  * Description:	calls a write PHY routine dep. on board type
331  *
332  * Returns:
333  *	nothing
334  */
SkGePhyWrite(SK_AC * pAC,SK_IOC IoC,int Port,int PhyReg,SK_U16 Val)335 void SkGePhyWrite(
336 SK_AC	*pAC,		/* Adapter Context */
337 SK_IOC	IoC,		/* I/O Context */
338 int		Port,		/* Port Index (MAC_1 + n) */
339 int		PhyReg,		/* Register Address (Offset) */
340 SK_U16	Val)		/* Value */
341 {
342 	void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
343 
344 	if (pAC->GIni.GIGenesis) {
345 		w_func = SkXmPhyWrite;
346 	}
347 	else {
348 		w_func = SkGmPhyWrite;
349 	}
350 
351 	w_func(pAC, IoC, Port, PhyReg, Val);
352 }	/* SkGePhyWrite */
353 #endif /* SK_DIAG */
354 
355 
356 /******************************************************************************
357  *
358  *	SkMacPromiscMode() - Enable / Disable Promiscuous Mode
359  *
360  * Description:
361  *   enables / disables promiscuous mode by setting Mode Register (XMAC) or
362  *   Receive Control Register (GMAC) dep. on board type
363  *
364  * Returns:
365  *	nothing
366  */
SkMacPromiscMode(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL Enable)367 void SkMacPromiscMode(
368 SK_AC	*pAC,	/* adapter context */
369 SK_IOC	IoC,	/* IO context */
370 int		Port,	/* Port Index (MAC_1 + n) */
371 SK_BOOL	Enable)	/* Enable / Disable */
372 {
373 #ifdef YUKON
374 	SK_U16	RcReg;
375 #endif
376 #ifdef GENESIS
377 	SK_U32	MdReg;
378 #endif
379 
380 #ifdef GENESIS
381 	if (pAC->GIni.GIGenesis) {
382 
383 		XM_IN32(IoC, Port, XM_MODE, &MdReg);
384 		/* enable or disable promiscuous mode */
385 		if (Enable) {
386 			MdReg |= XM_MD_ENA_PROM;
387 		}
388 		else {
389 			MdReg &= ~XM_MD_ENA_PROM;
390 		}
391 		/* setup Mode Register */
392 		XM_OUT32(IoC, Port, XM_MODE, MdReg);
393 	}
394 #endif /* GENESIS */
395 
396 #ifdef YUKON
397 	if (pAC->GIni.GIYukon) {
398 
399 		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
400 
401 		/* enable or disable unicast and multicast filtering */
402 		if (Enable) {
403 			RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
404 		}
405 		else {
406 			RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
407 		}
408 		/* setup Receive Control Register */
409 		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
410 	}
411 #endif /* YUKON */
412 
413 }	/* SkMacPromiscMode*/
414 
415 
416 /******************************************************************************
417  *
418  *	SkMacHashing() - Enable / Disable Hashing
419  *
420  * Description:
421  *   enables / disables hashing by setting Mode Register (XMAC) or
422  *   Receive Control Register (GMAC) dep. on board type
423  *
424  * Returns:
425  *	nothing
426  */
SkMacHashing(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL Enable)427 void SkMacHashing(
428 SK_AC	*pAC,	/* adapter context */
429 SK_IOC	IoC,	/* IO context */
430 int		Port,	/* Port Index (MAC_1 + n) */
431 SK_BOOL	Enable)	/* Enable / Disable */
432 {
433 #ifdef YUKON
434 	SK_U16	RcReg;
435 #endif
436 #ifdef GENESIS
437 	SK_U32	MdReg;
438 #endif
439 
440 #ifdef GENESIS
441 	if (pAC->GIni.GIGenesis) {
442 
443 		XM_IN32(IoC, Port, XM_MODE, &MdReg);
444 		/* enable or disable hashing */
445 		if (Enable) {
446 			MdReg |= XM_MD_ENA_HASH;
447 		}
448 		else {
449 			MdReg &= ~XM_MD_ENA_HASH;
450 		}
451 		/* setup Mode Register */
452 		XM_OUT32(IoC, Port, XM_MODE, MdReg);
453 	}
454 #endif /* GENESIS */
455 
456 #ifdef YUKON
457 	if (pAC->GIni.GIYukon) {
458 
459 		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
460 
461 		/* enable or disable multicast filtering */
462 		if (Enable) {
463 			RcReg |= GM_RXCR_MCF_ENA;
464 		}
465 		else {
466 			RcReg &= ~GM_RXCR_MCF_ENA;
467 		}
468 		/* setup Receive Control Register */
469 		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
470 	}
471 #endif /* YUKON */
472 
473 }	/* SkMacHashing*/
474 
475 
476 #ifdef SK_DIAG
477 /******************************************************************************
478  *
479  *	SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
480  *
481  * Description:
482  *	The features
483  *	 - FCS stripping,					SK_STRIP_FCS_ON/OFF
484  *	 - pad byte stripping,				SK_STRIP_PAD_ON/OFF
485  *	 - don't set XMR_FS_ERR in status	SK_LENERR_OK_ON/OFF
486  *	   for inrange length error frames
487  *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
488  *	   for frames > 1514 bytes
489  *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
490  *
491  *	for incoming packets may be enabled/disabled by this function.
492  *	Additional modes may be added later.
493  *	Multiple modes can be enabled/disabled at the same time.
494  *	The new configuration is written to the Rx Command register immediately.
495  *
496  * Returns:
497  *	nothing
498  */
SkXmSetRxCmd(SK_AC * pAC,SK_IOC IoC,int Port,int Mode)499 static void SkXmSetRxCmd(
500 SK_AC	*pAC,		/* adapter context */
501 SK_IOC	IoC,		/* IO context */
502 int		Port,		/* Port Index (MAC_1 + n) */
503 int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
504 					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
505 {
506 	SK_U16	OldRxCmd;
507 	SK_U16	RxCmd;
508 
509 	XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
510 
511 	RxCmd = OldRxCmd;
512 
513 	switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
514 	case SK_STRIP_FCS_ON:
515 		RxCmd |= XM_RX_STRIP_FCS;
516 		break;
517 	case SK_STRIP_FCS_OFF:
518 		RxCmd &= ~XM_RX_STRIP_FCS;
519 		break;
520 	}
521 
522 	switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
523 	case SK_STRIP_PAD_ON:
524 		RxCmd |= XM_RX_STRIP_PAD;
525 		break;
526 	case SK_STRIP_PAD_OFF:
527 		RxCmd &= ~XM_RX_STRIP_PAD;
528 		break;
529 	}
530 
531 	switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
532 	case SK_LENERR_OK_ON:
533 		RxCmd |= XM_RX_LENERR_OK;
534 		break;
535 	case SK_LENERR_OK_OFF:
536 		RxCmd &= ~XM_RX_LENERR_OK;
537 		break;
538 	}
539 
540 	switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
541 	case SK_BIG_PK_OK_ON:
542 		RxCmd |= XM_RX_BIG_PK_OK;
543 		break;
544 	case SK_BIG_PK_OK_OFF:
545 		RxCmd &= ~XM_RX_BIG_PK_OK;
546 		break;
547 	}
548 
549 	switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
550 	case SK_SELF_RX_ON:
551 		RxCmd |= XM_RX_SELF_RX;
552 		break;
553 	case SK_SELF_RX_OFF:
554 		RxCmd &= ~XM_RX_SELF_RX;
555 		break;
556 	}
557 
558 	/* Write the new mode to the Rx command register if required */
559 	if (OldRxCmd != RxCmd) {
560 		XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
561 	}
562 }	/* SkXmSetRxCmd */
563 
564 
565 /******************************************************************************
566  *
567  *	SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
568  *
569  * Description:
570  *	The features
571  *	 - FCS (CRC) stripping,				SK_STRIP_FCS_ON/OFF
572  *	 - don't set GMR_FS_LONG_ERR		SK_BIG_PK_OK_ON/OFF
573  *	   for frames > 1514 bytes
574  *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
575  *
576  *	for incoming packets may be enabled/disabled by this function.
577  *	Additional modes may be added later.
578  *	Multiple modes can be enabled/disabled at the same time.
579  *	The new configuration is written to the Rx Command register immediately.
580  *
581  * Returns:
582  *	nothing
583  */
SkGmSetRxCmd(SK_AC * pAC,SK_IOC IoC,int Port,int Mode)584 static void SkGmSetRxCmd(
585 SK_AC	*pAC,		/* adapter context */
586 SK_IOC	IoC,		/* IO context */
587 int		Port,		/* Port Index (MAC_1 + n) */
588 int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
589 					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
590 {
591 	SK_U16	OldRxCmd;
592 	SK_U16	RxCmd;
593 
594 	if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
595 
596 		GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
597 
598 		RxCmd = OldRxCmd;
599 
600 		if ((Mode & SK_STRIP_FCS_ON) != 0) {
601 			RxCmd |= GM_RXCR_CRC_DIS;
602 		}
603 		else {
604 			RxCmd &= ~GM_RXCR_CRC_DIS;
605 		}
606 		/* Write the new mode to the Rx control register if required */
607 		if (OldRxCmd != RxCmd) {
608 			GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
609 		}
610 	}
611 
612 	if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
613 
614 		GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
615 
616 		RxCmd = OldRxCmd;
617 
618 		if ((Mode & SK_BIG_PK_OK_ON) != 0) {
619 			RxCmd |= GM_SMOD_JUMBO_ENA;
620 		}
621 		else {
622 			RxCmd &= ~GM_SMOD_JUMBO_ENA;
623 		}
624 		/* Write the new mode to the Rx control register if required */
625 		if (OldRxCmd != RxCmd) {
626 			GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
627 		}
628 	}
629 }	/* SkGmSetRxCmd */
630 
631 
632 /******************************************************************************
633  *
634  *	SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
635  *
636  * Description:	modifies the MAC's Rx Control reg. dep. on board type
637  *
638  * Returns:
639  *	nothing
640  */
SkMacSetRxCmd(SK_AC * pAC,SK_IOC IoC,int Port,int Mode)641 void SkMacSetRxCmd(
642 SK_AC	*pAC,		/* adapter context */
643 SK_IOC	IoC,		/* IO context */
644 int		Port,		/* Port Index (MAC_1 + n) */
645 int		Mode)		/* Rx Mode */
646 {
647 	if (pAC->GIni.GIGenesis) {
648 
649 		SkXmSetRxCmd(pAC, IoC, Port, Mode);
650 	}
651 	else {
652 
653 		SkGmSetRxCmd(pAC, IoC, Port, Mode);
654 	}
655 
656 }	/* SkMacSetRxCmd */
657 
658 
659 /******************************************************************************
660  *
661  *	SkMacCrcGener() - Enable / Disable CRC Generation
662  *
663  * Description:	enables / disables CRC generation dep. on board type
664  *
665  * Returns:
666  *	nothing
667  */
SkMacCrcGener(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL Enable)668 void SkMacCrcGener(
669 SK_AC	*pAC,	/* adapter context */
670 SK_IOC	IoC,	/* IO context */
671 int		Port,	/* Port Index (MAC_1 + n) */
672 SK_BOOL	Enable)	/* Enable / Disable */
673 {
674 	SK_U16	Word;
675 
676 	if (pAC->GIni.GIGenesis) {
677 
678 		XM_IN16(IoC, Port, XM_TX_CMD, &Word);
679 
680 		if (Enable) {
681 			Word &= ~XM_TX_NO_CRC;
682 		}
683 		else {
684 			Word |= XM_TX_NO_CRC;
685 		}
686 		/* setup Tx Command Register */
687 		XM_OUT16(IoC, Port, XM_TX_CMD, Word);
688 	}
689 	else {
690 
691 		GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
692 
693 		if (Enable) {
694 			Word &= ~GM_TXCR_CRC_DIS;
695 		}
696 		else {
697 			Word |= GM_TXCR_CRC_DIS;
698 		}
699 		/* setup Tx Control Register */
700 		GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
701 	}
702 
703 }	/* SkMacCrcGener*/
704 
705 #endif /* SK_DIAG */
706 
707 
708 #ifdef GENESIS
709 /******************************************************************************
710  *
711  *	SkXmClrExactAddr() - Clear Exact Match Address Registers
712  *
713  * Description:
714  *	All Exact Match Address registers of the XMAC 'Port' will be
715  *	cleared starting with 'StartNum' up to (and including) the
716  *	Exact Match address number of 'StopNum'.
717  *
718  * Returns:
719  *	nothing
720  */
SkXmClrExactAddr(SK_AC * pAC,SK_IOC IoC,int Port,int StartNum,int StopNum)721 void SkXmClrExactAddr(
722 SK_AC	*pAC,		/* adapter context */
723 SK_IOC	IoC,		/* IO context */
724 int		Port,		/* Port Index (MAC_1 + n) */
725 int		StartNum,	/* Begin with this Address Register Index (0..15) */
726 int		StopNum)	/* Stop after finished with this Register Idx (0..15) */
727 {
728 	int		i;
729 	SK_U16	ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
730 
731 	if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
732 		StartNum > StopNum) {
733 
734 		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
735 		return;
736 	}
737 
738 	for (i = StartNum; i <= StopNum; i++) {
739 		XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
740 	}
741 }	/* SkXmClrExactAddr */
742 #endif /* GENESIS */
743 
744 
745 /******************************************************************************
746  *
747  *	SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
748  *
749  * Description:
750  *	Flush the transmit FIFO of the MAC specified by the index 'Port'
751  *
752  * Returns:
753  *	nothing
754  */
SkMacFlushTxFifo(SK_AC * pAC,SK_IOC IoC,int Port)755 void SkMacFlushTxFifo(
756 SK_AC	*pAC,	/* adapter context */
757 SK_IOC	IoC,	/* IO context */
758 int		Port)	/* Port Index (MAC_1 + n) */
759 {
760 #ifdef GENESIS
761 	SK_U32	MdReg;
762 
763 	if (pAC->GIni.GIGenesis) {
764 
765 		XM_IN32(IoC, Port, XM_MODE, &MdReg);
766 
767 		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
768 	}
769 #endif /* GENESIS */
770 
771 #ifdef YUKON
772 	if (pAC->GIni.GIYukon) {
773 		/* no way to flush the FIFO we have to issue a reset */
774 		/* TBD */
775 	}
776 #endif /* YUKON */
777 
778 }	/* SkMacFlushTxFifo */
779 
780 
781 /******************************************************************************
782  *
783  *	SkMacFlushRxFifo() - Flush the MAC's receive FIFO
784  *
785  * Description:
786  *	Flush the receive FIFO of the MAC specified by the index 'Port'
787  *
788  * Returns:
789  *	nothing
790  */
SkMacFlushRxFifo(SK_AC * pAC,SK_IOC IoC,int Port)791 void SkMacFlushRxFifo(
792 SK_AC	*pAC,	/* adapter context */
793 SK_IOC	IoC,	/* IO context */
794 int		Port)	/* Port Index (MAC_1 + n) */
795 {
796 #ifdef GENESIS
797 	SK_U32	MdReg;
798 
799 	if (pAC->GIni.GIGenesis) {
800 
801 		XM_IN32(IoC, Port, XM_MODE, &MdReg);
802 
803 		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
804 	}
805 #endif /* GENESIS */
806 
807 #ifdef YUKON
808 	if (pAC->GIni.GIYukon) {
809 		/* no way to flush the FIFO we have to issue a reset */
810 		/* TBD */
811 	}
812 #endif /* YUKON */
813 
814 }	/* SkMacFlushRxFifo */
815 
816 
817 #ifdef GENESIS
818 /******************************************************************************
819  *
820  *	SkXmSoftRst() - Do a XMAC software reset
821  *
822  * Description:
823  *	The PHY registers should not be destroyed during this
824  *	kind of software reset. Therefore the XMAC Software Reset
825  *	(XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
826  *
827  *	The software reset is done by
828  *		- disabling the Rx and Tx state machine,
829  *		- resetting the statistics module,
830  *		- clear all other significant XMAC Mode,
831  *		  Command, and Control Registers
832  *		- clearing the Hash Register and the
833  *		  Exact Match Address registers, and
834  *		- flushing the XMAC's Rx and Tx FIFOs.
835  *
836  * Note:
837  *	Another requirement when stopping the XMAC is to
838  *	avoid sending corrupted frames on the network.
839  *	Disabling the Tx state machine will NOT interrupt
840  *	the currently transmitted frame. But we must take care
841  *	that the Tx FIFO is cleared AFTER the current frame
842  *	is complete sent to the network.
843  *
844  *	It takes about 12ns to send a frame with 1538 bytes.
845  *	One PCI clock goes at least 15ns (66MHz). Therefore
846  *	after reading XM_GP_PORT back, we are sure that the
847  *	transmitter is disabled AND idle. And this means
848  *	we may flush the transmit FIFO now.
849  *
850  * Returns:
851  *	nothing
852  */
SkXmSoftRst(SK_AC * pAC,SK_IOC IoC,int Port)853 static void SkXmSoftRst(
854 SK_AC	*pAC,	/* adapter context */
855 SK_IOC	IoC,	/* IO context */
856 int		Port)	/* Port Index (MAC_1 + n) */
857 {
858 	SK_U16	ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
859 
860 	/* reset the statistics module */
861 	XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
862 
863 	/* disable all XMAC IRQs */
864 	XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
865 
866 	XM_OUT32(IoC, Port, XM_MODE, 0);		/* clear Mode Reg */
867 
868 	XM_OUT16(IoC, Port, XM_TX_CMD, 0);		/* reset TX CMD Reg */
869 	XM_OUT16(IoC, Port, XM_RX_CMD, 0);		/* reset RX CMD Reg */
870 
871 	/* disable all PHY IRQs */
872 	switch (pAC->GIni.GP[Port].PhyType) {
873 	case SK_PHY_BCOM:
874 			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
875 			break;
876 #ifdef OTHER_PHY
877 		case SK_PHY_LONE:
878 			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
879 			break;
880 		case SK_PHY_NAT:
881 			/* todo: National
882 			 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
883 			break;
884 #endif /* OTHER_PHY */
885 	}
886 
887 	/* clear the Hash Register */
888 	XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
889 
890 	/* clear the Exact Match Address registers */
891 	SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
892 
893 	/* clear the Source Check Address registers */
894 	XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
895 
896 }	/* SkXmSoftRst */
897 
898 
899 /******************************************************************************
900  *
901  *	SkXmHardRst() - Do a XMAC hardware reset
902  *
903  * Description:
904  *	The XMAC of the specified 'Port' and all connected devices
905  *	(PHY and SERDES) will receive a reset signal on its *Reset pins.
906  *	External PHYs must be reset by clearing a bit in the GPIO register
907  *  (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
908  *
909  * ATTENTION:
910  * 	It is absolutely necessary to reset the SW_RST Bit first
911  *	before calling this function.
912  *
913  * Returns:
914  *	nothing
915  */
SkXmHardRst(SK_AC * pAC,SK_IOC IoC,int Port)916 static void SkXmHardRst(
917 SK_AC	*pAC,	/* adapter context */
918 SK_IOC	IoC,	/* IO context */
919 int		Port)	/* Port Index (MAC_1 + n) */
920 {
921 	SK_U32	Reg;
922 	int		i;
923 	int		TOut;
924 	SK_U16	Word;
925 
926 	for (i = 0; i < 4; i++) {
927 		/* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
928 		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
929 
930 		TOut = 0;
931 		do {
932 			if (TOut++ > 10000) {
933 				/*
934 				 * Adapter seems to be in RESET state.
935 				 * Registers cannot be written.
936 				 */
937 				return;
938 			}
939 
940 			SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
941 
942 			SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
943 
944 		} while ((Word & MFF_SET_MAC_RST) == 0);
945 	}
946 
947 	/* For external PHYs there must be special handling */
948 	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
949 
950 		SK_IN32(IoC, B2_GP_IO, &Reg);
951 
952 		if (Port == 0) {
953 			Reg |= GP_DIR_0; 	/* set to output */
954 			Reg &= ~GP_IO_0;	/* set PHY reset (active low) */
955 		}
956 		else {
957 			Reg |= GP_DIR_2;	/* set to output */
958 			Reg &= ~GP_IO_2;	/* set PHY reset (active low) */
959 		}
960 		/* reset external PHY */
961 		SK_OUT32(IoC, B2_GP_IO, Reg);
962 
963 		/* short delay */
964 		SK_IN32(IoC, B2_GP_IO, &Reg);
965 	}
966 }	/* SkXmHardRst */
967 
968 
969 /******************************************************************************
970  *
971  *	SkXmClearRst() - Release the PHY & XMAC reset
972  *
973  * Description:
974  *
975  * Returns:
976  *	nothing
977  */
SkXmClearRst(SK_AC * pAC,SK_IOC IoC,int Port)978 static void SkXmClearRst(
979 SK_AC	*pAC,	/* adapter context */
980 SK_IOC	IoC,	/* IO context */
981 int		Port)	/* Port Index (MAC_1 + n) */
982 {
983 	SK_U32	DWord;
984 
985 	/* clear HW reset */
986 	SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
987 
988 	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
989 
990 		SK_IN32(IoC, B2_GP_IO, &DWord);
991 
992 		if (Port == 0) {
993 			DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
994 		}
995 		else {
996 			DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
997 		}
998 		/* Clear PHY reset */
999 		SK_OUT32(IoC, B2_GP_IO, DWord);
1000 
1001 		/* Enable GMII interface */
1002 		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
1003 	}
1004 }	/* SkXmClearRst */
1005 #endif /* GENESIS */
1006 
1007 
1008 #ifdef YUKON
1009 /******************************************************************************
1010  *
1011  *	SkGmSoftRst() - Do a GMAC software reset
1012  *
1013  * Description:
1014  *	The GPHY registers should not be destroyed during this
1015  *	kind of software reset.
1016  *
1017  * Returns:
1018  *	nothing
1019  */
SkGmSoftRst(SK_AC * pAC,SK_IOC IoC,int Port)1020 static void SkGmSoftRst(
1021 SK_AC	*pAC,	/* adapter context */
1022 SK_IOC	IoC,	/* IO context */
1023 int		Port)	/* Port Index (MAC_1 + n) */
1024 {
1025 	SK_U16	EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1026 	SK_U16  RxCtrl;
1027 
1028 	/* reset the statistics module */
1029 
1030 	/* disable all GMAC IRQs */
1031 	SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
1032 
1033 	/* disable all PHY IRQs */
1034 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
1035 
1036 	/* clear the Hash Register */
1037 	GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
1038 
1039 	/* Enable Unicast and Multicast filtering */
1040 	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
1041 
1042 	GM_OUT16(IoC, Port, GM_RX_CTRL,
1043 		(SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
1044 
1045 }	/* SkGmSoftRst */
1046 
1047 
1048 /******************************************************************************
1049  *
1050  *	SkGmHardRst() - Do a GMAC hardware reset
1051  *
1052  * Description:
1053  *
1054  * Returns:
1055  *	nothing
1056  */
SkGmHardRst(SK_AC * pAC,SK_IOC IoC,int Port)1057 static void SkGmHardRst(
1058 SK_AC	*pAC,	/* adapter context */
1059 SK_IOC	IoC,	/* IO context */
1060 int		Port)	/* Port Index (MAC_1 + n) */
1061 {
1062 	SK_U32	DWord;
1063 
1064 	/* WA code for COMA mode */
1065 	if (pAC->GIni.GIYukonLite &&
1066 		pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
1067 
1068 		SK_IN32(IoC, B2_GP_IO, &DWord);
1069 
1070 		DWord |= (GP_DIR_9 | GP_IO_9);
1071 
1072 		/* set PHY reset */
1073 		SK_OUT32(IoC, B2_GP_IO, DWord);
1074 	}
1075 
1076 	/* set GPHY Control reset */
1077 	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1078 
1079 	/* set GMAC Control reset */
1080 	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1081 
1082 }	/* SkGmHardRst */
1083 
1084 
1085 /******************************************************************************
1086  *
1087  *	SkGmClearRst() - Release the GPHY & GMAC reset
1088  *
1089  * Description:
1090  *
1091  * Returns:
1092  *	nothing
1093  */
SkGmClearRst(SK_AC * pAC,SK_IOC IoC,int Port)1094 static void SkGmClearRst(
1095 SK_AC	*pAC,	/* adapter context */
1096 SK_IOC	IoC,	/* IO context */
1097 int		Port)	/* Port Index (MAC_1 + n) */
1098 {
1099 	SK_U32	DWord;
1100 
1101 #ifdef XXX
1102 		/* clear GMAC Control reset */
1103 		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
1104 
1105 		/* set GMAC Control reset */
1106 		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1107 #endif /* XXX */
1108 
1109 	/* WA code for COMA mode */
1110 	if (pAC->GIni.GIYukonLite &&
1111 		pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
1112 
1113 		SK_IN32(IoC, B2_GP_IO, &DWord);
1114 
1115 		DWord |= GP_DIR_9;		/* set to output */
1116 		DWord &= ~GP_IO_9;		/* clear PHY reset (active high) */
1117 
1118 		/* clear PHY reset */
1119 		SK_OUT32(IoC, B2_GP_IO, DWord);
1120 	}
1121 
1122 	/* set HWCFG_MODE */
1123 	DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
1124 		GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
1125 		(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
1126 		GPC_HWCFG_GMII_FIB);
1127 
1128 	/* set GPHY Control reset */
1129 	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
1130 
1131 	/* release GPHY Control reset */
1132 	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
1133 
1134 #ifdef VCPU
1135 	VCpuWait(9000);
1136 #endif /* VCPU */
1137 
1138 	/* clear GMAC Control reset */
1139 	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
1140 
1141 #ifdef VCPU
1142 	VCpuWait(2000);
1143 
1144 	SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
1145 
1146 	SK_IN32(IoC, B0_ISRC, &DWord);
1147 #endif /* VCPU */
1148 
1149 }	/* SkGmClearRst */
1150 #endif /* YUKON */
1151 
1152 
1153 /******************************************************************************
1154  *
1155  *	SkMacSoftRst() - Do a MAC software reset
1156  *
1157  * Description:	calls a MAC software reset routine dep. on board type
1158  *
1159  * Returns:
1160  *	nothing
1161  */
SkMacSoftRst(SK_AC * pAC,SK_IOC IoC,int Port)1162 void SkMacSoftRst(
1163 SK_AC	*pAC,	/* adapter context */
1164 SK_IOC	IoC,	/* IO context */
1165 int		Port)	/* Port Index (MAC_1 + n) */
1166 {
1167 	SK_GEPORT	*pPrt;
1168 
1169 	pPrt = &pAC->GIni.GP[Port];
1170 
1171 	/* disable receiver and transmitter */
1172 	SkMacRxTxDisable(pAC, IoC, Port);
1173 
1174 #ifdef GENESIS
1175 	if (pAC->GIni.GIGenesis) {
1176 
1177 		SkXmSoftRst(pAC, IoC, Port);
1178 	}
1179 #endif /* GENESIS */
1180 
1181 #ifdef YUKON
1182 	if (pAC->GIni.GIYukon) {
1183 
1184 		SkGmSoftRst(pAC, IoC, Port);
1185 	}
1186 #endif /* YUKON */
1187 
1188 	/* flush the MAC's Rx and Tx FIFOs */
1189 	SkMacFlushTxFifo(pAC, IoC, Port);
1190 
1191 	SkMacFlushRxFifo(pAC, IoC, Port);
1192 
1193 	pPrt->PState = SK_PRT_STOP;
1194 
1195 }	/* SkMacSoftRst */
1196 
1197 
1198 /******************************************************************************
1199  *
1200  *	SkMacHardRst() - Do a MAC hardware reset
1201  *
1202  * Description:	calls a MAC hardware reset routine dep. on board type
1203  *
1204  * Returns:
1205  *	nothing
1206  */
SkMacHardRst(SK_AC * pAC,SK_IOC IoC,int Port)1207 void SkMacHardRst(
1208 SK_AC	*pAC,	/* adapter context */
1209 SK_IOC	IoC,	/* IO context */
1210 int		Port)	/* Port Index (MAC_1 + n) */
1211 {
1212 
1213 #ifdef GENESIS
1214 	if (pAC->GIni.GIGenesis) {
1215 
1216 		SkXmHardRst(pAC, IoC, Port);
1217 	}
1218 #endif /* GENESIS */
1219 
1220 #ifdef YUKON
1221 	if (pAC->GIni.GIYukon) {
1222 
1223 		SkGmHardRst(pAC, IoC, Port);
1224 	}
1225 #endif /* YUKON */
1226 
1227 	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
1228 
1229 }	/* SkMacHardRst */
1230 
1231 
1232 /******************************************************************************
1233  *
1234  *	SkMacClearRst() - Clear the MAC reset
1235  *
1236  * Description:	calls a clear MAC reset routine dep. on board type
1237  *
1238  * Returns:
1239  *	nothing
1240  */
SkMacClearRst(SK_AC * pAC,SK_IOC IoC,int Port)1241 void SkMacClearRst(
1242 SK_AC	*pAC,	/* adapter context */
1243 SK_IOC	IoC,	/* IO context */
1244 int		Port)	/* Port Index (MAC_1 + n) */
1245 {
1246 
1247 #ifdef GENESIS
1248 	if (pAC->GIni.GIGenesis) {
1249 
1250 		SkXmClearRst(pAC, IoC, Port);
1251 	}
1252 #endif /* GENESIS */
1253 
1254 #ifdef YUKON
1255 	if (pAC->GIni.GIYukon) {
1256 
1257 		SkGmClearRst(pAC, IoC, Port);
1258 	}
1259 #endif /* YUKON */
1260 
1261 }	/* SkMacClearRst */
1262 
1263 
1264 #ifdef GENESIS
1265 /******************************************************************************
1266  *
1267  *	SkXmInitMac() - Initialize the XMAC II
1268  *
1269  * Description:
1270  *	Initialize the XMAC of the specified port.
1271  *	The XMAC must be reset or stopped before calling this function.
1272  *
1273  * Note:
1274  *	The XMAC's Rx and Tx state machine is still disabled when returning.
1275  *
1276  * Returns:
1277  *	nothing
1278  */
SkXmInitMac(SK_AC * pAC,SK_IOC IoC,int Port)1279 void SkXmInitMac(
1280 SK_AC	*pAC,		/* adapter context */
1281 SK_IOC	IoC,		/* IO context */
1282 int		Port)		/* Port Index (MAC_1 + n) */
1283 {
1284 	SK_GEPORT	*pPrt;
1285 	int			i;
1286 	SK_U16		SWord;
1287 
1288 	pPrt = &pAC->GIni.GP[Port];
1289 
1290 	if (pPrt->PState == SK_PRT_STOP) {
1291 		/* Port State: SK_PRT_STOP */
1292 		/* Verify that the reset bit is cleared */
1293 		SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1294 
1295 		if ((SWord & MFF_SET_MAC_RST) != 0) {
1296 			/* PState does not match HW state */
1297 			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1298 			/* Correct it */
1299 			pPrt->PState = SK_PRT_RESET;
1300 		}
1301 	}
1302 
1303 	if (pPrt->PState == SK_PRT_RESET) {
1304 
1305 		SkXmClearRst(pAC, IoC, Port);
1306 
1307 		if (pPrt->PhyType != SK_PHY_XMAC) {
1308 			/* read Id from external PHY (all have the same address) */
1309 			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1310 
1311 			/*
1312 			 * Optimize MDIO transfer by suppressing preamble.
1313 			 * Must be done AFTER first access to BCOM chip.
1314 			 */
1315 			XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
1316 
1317 			XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1318 
1319 			if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1320 				/*
1321 				 * Workaround BCOM Errata for the C0 type.
1322 				 * Write magic patterns to reserved registers.
1323 				 */
1324 				i = 0;
1325 				while (BcomRegC0Hack[i].PhyReg != 0) {
1326 					SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1327 						BcomRegC0Hack[i].PhyVal);
1328 					i++;
1329 				}
1330 			}
1331 			else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1332 				/*
1333 				 * Workaround BCOM Errata for the A1 type.
1334 				 * Write magic patterns to reserved registers.
1335 				 */
1336 				i = 0;
1337 				while (BcomRegA1Hack[i].PhyReg != 0) {
1338 					SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1339 						BcomRegA1Hack[i].PhyVal);
1340 					i++;
1341 				}
1342 			}
1343 
1344 			/*
1345 			 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1346 			 * Disable Power Management after reset.
1347 			 */
1348 			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
1349 
1350 			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1351 				(SK_U16)(SWord | PHY_B_AC_DIS_PM));
1352 
1353 			/* PHY LED initialization is done in SkGeXmitLED() */
1354 		}
1355 
1356 		/* Dummy read the Interrupt source register */
1357 		XM_IN16(IoC, Port, XM_ISRC, &SWord);
1358 
1359 		/*
1360 		 * The auto-negotiation process starts immediately after
1361 		 * clearing the reset. The auto-negotiation process should be
1362 		 * started by the SIRQ, therefore stop it here immediately.
1363 		 */
1364 		SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1365 
1366 #ifdef TEST_ONLY
1367 		/* temp. code: enable signal detect */
1368 		/* WARNING: do not override GMII setting above */
1369 		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1370 #endif
1371 	}
1372 
1373 	/*
1374 	 * configure the XMACs Station Address
1375 	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1376 	 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1377 	 */
1378 	for (i = 0; i < 3; i++) {
1379 		/*
1380 		 * The following 2 statements are together endianess
1381 		 * independent. Remember this when changing.
1382 		 */
1383 		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1384 
1385 		XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1386 	}
1387 
1388 	/* Tx Inter Packet Gap (XM_TX_IPG):	use default */
1389 	/* Tx High Water Mark (XM_TX_HI_WM):	use default */
1390 	/* Tx Low Water Mark (XM_TX_LO_WM):	use default */
1391 	/* Host Request Threshold (XM_HT_THR):	use default */
1392 	/* Rx Request Threshold (XM_RX_THR):	use default */
1393 	/* Rx Low Water Mark (XM_RX_LO_WM):	use default */
1394 
1395 	/* configure Rx High Water Mark (XM_RX_HI_WM) */
1396 	XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1397 
1398 	/* Configure Tx Request Threshold */
1399 	SWord = SK_XM_THR_SL;				/* for single port */
1400 
1401 	if (pAC->GIni.GIMacsFound > 1) {
1402 		switch (pAC->GIni.GIPortUsage) {
1403 		case SK_RED_LINK:
1404 			SWord = SK_XM_THR_REDL;		/* redundant link */
1405 			break;
1406 		case SK_MUL_LINK:
1407 			SWord = SK_XM_THR_MULL;		/* load balancing */
1408 			break;
1409 		case SK_JUMBO_LINK:
1410 			SWord = SK_XM_THR_JUMBO;	/* jumbo frames */
1411 			break;
1412 		default:
1413 			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1414 			break;
1415 		}
1416 	}
1417 	XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1418 
1419 	/* setup register defaults for the Tx Command Register */
1420 	XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1421 
1422 	/* setup register defaults for the Rx Command Register */
1423 	SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1424 
1425 	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1426 		SWord |= XM_RX_BIG_PK_OK;
1427 	}
1428 
1429 	if (pPrt->PLinkMode == SK_LMODE_HALF) {
1430 		/*
1431 		 * If in manual half duplex mode the other side might be in
1432 		 * full duplex mode, so ignore if a carrier extension is not seen
1433 		 * on frames received
1434 		 */
1435 		SWord |= XM_RX_DIS_CEXT;
1436 	}
1437 
1438 	XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1439 
1440 	/*
1441 	 * setup register defaults for the Mode Register
1442 	 *	- Don't strip error frames to avoid Store & Forward
1443 	 *	  on the Rx side.
1444 	 *	- Enable 'Check Station Address' bit
1445 	 *	- Enable 'Check Address Array' bit
1446 	 */
1447 	XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1448 
1449 	/*
1450 	 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1451 	 *	- Enable all bits excepting 'Octets Rx OK Low CntOv'
1452 	 *	  and 'Octets Rx OK Hi Cnt Ov'.
1453 	 */
1454 	XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1455 
1456 	/*
1457 	 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1458 	 *	- Enable all bits excepting 'Octets Tx OK Low CntOv'
1459 	 *	  and 'Octets Tx OK Hi Cnt Ov'.
1460 	 */
1461 	XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1462 
1463 	/*
1464 	 * Do NOT init XMAC interrupt mask here.
1465 	 * All interrupts remain disable until link comes up!
1466 	 */
1467 
1468 	/*
1469 	 * Any additional configuration changes may be done now.
1470 	 * The last action is to enable the Rx and Tx state machine.
1471 	 * This should be done after the auto-negotiation process
1472 	 * has been completed successfully.
1473 	 */
1474 }	/* SkXmInitMac */
1475 #endif /* GENESIS */
1476 
1477 
1478 #ifdef YUKON
1479 /******************************************************************************
1480  *
1481  *	SkGmInitMac() - Initialize the GMAC
1482  *
1483  * Description:
1484  *	Initialize the GMAC of the specified port.
1485  *	The GMAC must be reset or stopped before calling this function.
1486  *
1487  * Note:
1488  *	The GMAC's Rx and Tx state machine is still disabled when returning.
1489  *
1490  * Returns:
1491  *	nothing
1492  */
SkGmInitMac(SK_AC * pAC,SK_IOC IoC,int Port)1493 void SkGmInitMac(
1494 SK_AC	*pAC,		/* adapter context */
1495 SK_IOC	IoC,		/* IO context */
1496 int		Port)		/* Port Index (MAC_1 + n) */
1497 {
1498 	SK_GEPORT	*pPrt;
1499 	int			i;
1500 	SK_U16		SWord;
1501 	SK_U32		DWord;
1502 
1503 	pPrt = &pAC->GIni.GP[Port];
1504 
1505 	if (pPrt->PState == SK_PRT_STOP) {
1506 		/* Port State: SK_PRT_STOP */
1507 		/* Verify that the reset bit is cleared */
1508 		SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
1509 
1510 		if ((DWord & GMC_RST_SET) != 0) {
1511 			/* PState does not match HW state */
1512 			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1513 			/* Correct it */
1514 			pPrt->PState = SK_PRT_RESET;
1515 		}
1516 	}
1517 
1518 	if (pPrt->PState == SK_PRT_RESET) {
1519 
1520 		SkGmHardRst(pAC, IoC, Port);
1521 
1522 		SkGmClearRst(pAC, IoC, Port);
1523 
1524 		/* Auto-negotiation ? */
1525 		if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1526 			/* Auto-negotiation disabled */
1527 
1528 			/* get General Purpose Control */
1529 			GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
1530 
1531 			/* disable auto-update for speed, duplex and flow-control */
1532 			SWord |= GM_GPCR_AU_ALL_DIS;
1533 
1534 			/* setup General Purpose Control Register */
1535 			GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1536 
1537 			SWord = GM_GPCR_AU_ALL_DIS;
1538 		}
1539 		else {
1540 			SWord = 0;
1541 		}
1542 
1543 		/* speed settings */
1544 		switch (pPrt->PLinkSpeed) {
1545 		case SK_LSPEED_AUTO:
1546 		case SK_LSPEED_1000MBPS:
1547 			SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1548 			break;
1549 		case SK_LSPEED_100MBPS:
1550 			SWord |= GM_GPCR_SPEED_100;
1551 			break;
1552 		case SK_LSPEED_10MBPS:
1553 			break;
1554 		}
1555 
1556 		/* duplex settings */
1557 		if (pPrt->PLinkMode != SK_LMODE_HALF) {
1558 			/* set full duplex */
1559 			SWord |= GM_GPCR_DUP_FULL;
1560 		}
1561 
1562 		/* flow-control settings */
1563 		switch (pPrt->PFlowCtrlMode) {
1564 		case SK_FLOW_MODE_NONE:
1565 			/* set Pause Off */
1566 			SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
1567 			/* disable Tx & Rx flow-control */
1568 			SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1569 			break;
1570 		case SK_FLOW_MODE_LOC_SEND:
1571 			/* disable Rx flow-control */
1572 			SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1573 			break;
1574 		case SK_FLOW_MODE_SYMMETRIC:
1575 		case SK_FLOW_MODE_SYM_OR_REM:
1576 			/* enable Tx & Rx flow-control */
1577 			break;
1578 		}
1579 
1580 		/* setup General Purpose Control Register */
1581 		GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1582 
1583 		/* dummy read the Interrupt Source Register */
1584 		SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
1585 
1586 #ifndef VCPU
1587 		/* read Id from PHY */
1588 		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
1589 
1590 		SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1591 #endif /* VCPU */
1592 	}
1593 
1594 	(void)SkGmResetCounter(pAC, IoC, Port);
1595 
1596 	/* setup Transmit Control Register */
1597 	GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
1598 
1599 	/* setup Receive Control Register */
1600 	GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1601 		GM_RXCR_CRC_DIS);
1602 
1603 	/* setup Transmit Flow Control Register */
1604 	GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1605 
1606 	/* setup Transmit Parameter Register */
1607 #ifdef VCPU
1608 	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1609 #endif /* VCPU */
1610 
1611     SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
1612 			TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
1613 			TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
1614 
1615 	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1616 
1617 	/* configure the Serial Mode Register */
1618 #ifdef VCPU
1619 	GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1620 #endif /* VCPU */
1621 
1622 	SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
1623 
1624 	if (pPrt->PMacLimit4) {
1625 		/* reset of collision counter after 4 consecutive collisions */
1626 		SWord |= GM_SMOD_LIMIT_4;
1627 	}
1628 
1629 	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1630 		/* enable jumbo mode (Max. Frame Length = 9018) */
1631 		SWord |= GM_SMOD_JUMBO_ENA;
1632 	}
1633 
1634 	GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
1635 
1636 	/*
1637 	 * configure the GMACs Station Addresses
1638 	 * in PROM you can find our addresses at:
1639 	 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1640 	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1641 	 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1642 	 */
1643 
1644 	for (i = 0; i < 3; i++) {
1645 		/*
1646 		 * The following 2 statements are together endianess
1647 		 * independent. Remember this when changing.
1648 		 */
1649 		/* physical address: will be used for pause frames */
1650 		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1651 
1652 #ifdef WA_DEV_16
1653 		/* WA for deviation #16 */
1654 		if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
1655 			/* swap the address bytes */
1656 			SWord = ((SWord & 0xff00) >> 8)	| ((SWord & 0x00ff) << 8);
1657 
1658 			/* write to register in reversed order */
1659 			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
1660 		}
1661 		else {
1662 			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1663 		}
1664 #else
1665 		GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1666 #endif /* WA_DEV_16 */
1667 
1668 		/* virtual address: will be used for data */
1669 		SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
1670 
1671 		GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
1672 
1673 		/* reset Multicast filtering Hash registers 1-3 */
1674 		GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
1675 	}
1676 
1677 	/* reset Multicast filtering Hash register 4 */
1678 	GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
1679 
1680 	/* enable interrupt mask for counter overflows */
1681 	GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
1682 	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
1683 	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
1684 
1685 #if defined(SK_DIAG) || defined(DEBUG)
1686 	/* read General Purpose Status */
1687 	GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
1688 
1689 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1690 		("MAC Stat Reg.=0x%04X\n", SWord));
1691 #endif /* SK_DIAG || DEBUG */
1692 
1693 #ifdef SK_DIAG
1694 	c_print("MAC Stat Reg=0x%04X\n", SWord);
1695 #endif /* SK_DIAG */
1696 
1697 }	/* SkGmInitMac */
1698 #endif /* YUKON */
1699 
1700 
1701 #ifdef GENESIS
1702 /******************************************************************************
1703  *
1704  *	SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1705  *
1706  * Description:
1707  *	This function initializes the XMACs Duplex Mode.
1708  *	It should be called after successfully finishing
1709  *	the Auto-negotiation Process
1710  *
1711  * Returns:
1712  *	nothing
1713  */
SkXmInitDupMd(SK_AC * pAC,SK_IOC IoC,int Port)1714 void SkXmInitDupMd(
1715 SK_AC	*pAC,		/* adapter context */
1716 SK_IOC	IoC,		/* IO context */
1717 int		Port)		/* Port Index (MAC_1 + n) */
1718 {
1719 	switch (pAC->GIni.GP[Port].PLinkModeStatus) {
1720 	case SK_LMODE_STAT_AUTOHALF:
1721 	case SK_LMODE_STAT_HALF:
1722 		/* Configuration Actions for Half Duplex Mode */
1723 		/*
1724 		 * XM_BURST = default value. We are probable not quick
1725 		 * 	enough at the 'XMAC' bus to burst 8kB.
1726 		 *	The XMAC stops bursting if no transmit frames
1727 		 *	are available or the burst limit is exceeded.
1728 		 */
1729 		/* XM_TX_RT_LIM = default value (15) */
1730 		/* XM_TX_STIME = default value (0xff = 4096 bit times) */
1731 		break;
1732 	case SK_LMODE_STAT_AUTOFULL:
1733 	case SK_LMODE_STAT_FULL:
1734 		/* Configuration Actions for Full Duplex Mode */
1735 		/*
1736 		 * The duplex mode is configured by the PHY,
1737 		 * therefore it seems to be that there is nothing
1738 		 * to do here.
1739 		 */
1740 		break;
1741 	case SK_LMODE_STAT_UNKNOWN:
1742 	default:
1743 		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
1744 		break;
1745 	}
1746 }	/* SkXmInitDupMd */
1747 
1748 
1749 /******************************************************************************
1750  *
1751  *	SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1752  *
1753  * Description:
1754  *	This function initializes the Pause Mode which should
1755  *	be used for this port.
1756  *	It should be called after successfully finishing
1757  *	the Auto-negotiation Process
1758  *
1759  * Returns:
1760  *	nothing
1761  */
SkXmInitPauseMd(SK_AC * pAC,SK_IOC IoC,int Port)1762 void SkXmInitPauseMd(
1763 SK_AC	*pAC,		/* adapter context */
1764 SK_IOC	IoC,		/* IO context */
1765 int		Port)		/* Port Index (MAC_1 + n) */
1766 {
1767 	SK_GEPORT	*pPrt;
1768 	SK_U32		DWord;
1769 	SK_U16		Word;
1770 
1771 	pPrt = &pAC->GIni.GP[Port];
1772 
1773 	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
1774 
1775 	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
1776 		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1777 
1778 		/* Disable Pause Frame Reception */
1779 		Word |= XM_MMU_IGN_PF;
1780 	}
1781 	else {
1782 		/*
1783 		 * enabling pause frame reception is required for 1000BT
1784 		 * because the XMAC is not reset if the link is going down
1785 		 */
1786 		/* Enable Pause Frame Reception */
1787 		Word &= ~XM_MMU_IGN_PF;
1788 	}
1789 
1790 	XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
1791 
1792 	XM_IN32(IoC, Port, XM_MODE, &DWord);
1793 
1794 	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
1795 		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1796 
1797 		/*
1798 		 * Configure Pause Frame Generation
1799 		 * Use internal and external Pause Frame Generation.
1800 		 * Sending pause frames is edge triggered.
1801 		 * Send a Pause frame with the maximum pause time if
1802 		 * internal oder external FIFO full condition occurs.
1803 		 * Send a zero pause time frame to re-start transmission.
1804 		 */
1805 
1806 		/* XM_PAUSE_DA = '010000C28001' (default) */
1807 
1808 		/* XM_MAC_PTIME = 0xffff (maximum) */
1809 		/* remember this value is defined in big endian (!) */
1810 		XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
1811 
1812 		/* Set Pause Mode in Mode Register */
1813 		DWord |= XM_PAUSE_MODE;
1814 
1815 		/* Set Pause Mode in MAC Rx FIFO */
1816 		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
1817 	}
1818 	else {
1819 		/*
1820 		 * disable pause frame generation is required for 1000BT
1821 		 * because the XMAC is not reset if the link is going down
1822 		 */
1823 		/* Disable Pause Mode in Mode Register */
1824 		DWord &= ~XM_PAUSE_MODE;
1825 
1826 		/* Disable Pause Mode in MAC Rx FIFO */
1827 		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
1828 	}
1829 
1830 	XM_OUT32(IoC, Port, XM_MODE, DWord);
1831 }	/* SkXmInitPauseMd*/
1832 
1833 
1834 /******************************************************************************
1835  *
1836  *	SkXmInitPhyXmac() - Initialize the XMAC Phy registers
1837  *
1838  * Description:	initializes all the XMACs Phy registers
1839  *
1840  * Note:
1841  *
1842  * Returns:
1843  *	nothing
1844  */
SkXmInitPhyXmac(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL DoLoop)1845 static void SkXmInitPhyXmac(
1846 SK_AC	*pAC,		/* adapter context */
1847 SK_IOC	IoC,		/* IO context */
1848 int		Port,		/* Port Index (MAC_1 + n) */
1849 SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
1850 {
1851 	SK_GEPORT	*pPrt;
1852 	SK_U16		Ctrl;
1853 
1854 	pPrt = &pAC->GIni.GP[Port];
1855 	Ctrl = 0;
1856 
1857 	/* Auto-negotiation ? */
1858 	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1859 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1860 			("InitPhyXmac: no auto-negotiation Port %d\n", Port));
1861 		/* Set DuplexMode in Config register */
1862 		if (pPrt->PLinkMode == SK_LMODE_FULL) {
1863 			Ctrl |= PHY_CT_DUP_MD;
1864 		}
1865 
1866 		/*
1867 		 * Do NOT enable Auto-negotiation here. This would hold
1868 		 * the link down because no IDLEs are transmitted
1869 		 */
1870 	}
1871 	else {
1872 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1873 			("InitPhyXmac: with auto-negotiation Port %d\n", Port));
1874 		/* Set Auto-negotiation advertisement */
1875 
1876 		/* Set Full/half duplex capabilities */
1877 		switch (pPrt->PLinkMode) {
1878 		case SK_LMODE_AUTOHALF:
1879 			Ctrl |= PHY_X_AN_HD;
1880 			break;
1881 		case SK_LMODE_AUTOFULL:
1882 			Ctrl |= PHY_X_AN_FD;
1883 			break;
1884 		case SK_LMODE_AUTOBOTH:
1885 			Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
1886 			break;
1887 		default:
1888 			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
1889 				SKERR_HWI_E015MSG);
1890 		}
1891 
1892 		/* Set Flow-control capabilities */
1893 		switch (pPrt->PFlowCtrlMode) {
1894 		case SK_FLOW_MODE_NONE:
1895 			Ctrl |= PHY_X_P_NO_PAUSE;
1896 			break;
1897 		case SK_FLOW_MODE_LOC_SEND:
1898 			Ctrl |= PHY_X_P_ASYM_MD;
1899 			break;
1900 		case SK_FLOW_MODE_SYMMETRIC:
1901 			Ctrl |= PHY_X_P_SYM_MD;
1902 			break;
1903 		case SK_FLOW_MODE_SYM_OR_REM:
1904 			Ctrl |= PHY_X_P_BOTH_MD;
1905 			break;
1906 		default:
1907 			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
1908 				SKERR_HWI_E016MSG);
1909 		}
1910 
1911 		/* Write AutoNeg Advertisement Register */
1912 		SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
1913 
1914 		/* Restart Auto-negotiation */
1915 		Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
1916 	}
1917 
1918 	if (DoLoop) {
1919 		/* Set the Phy Loopback bit, too */
1920 		Ctrl |= PHY_CT_LOOP;
1921 	}
1922 
1923 	/* Write to the Phy control register */
1924 	SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
1925 }	/* SkXmInitPhyXmac */
1926 
1927 
1928 /******************************************************************************
1929  *
1930  *	SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
1931  *
1932  * Description:	initializes all the Broadcom Phy registers
1933  *
1934  * Note:
1935  *
1936  * Returns:
1937  *	nothing
1938  */
SkXmInitPhyBcom(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL DoLoop)1939 static void SkXmInitPhyBcom(
1940 SK_AC	*pAC,		/* adapter context */
1941 SK_IOC	IoC,		/* IO context */
1942 int		Port,		/* Port Index (MAC_1 + n) */
1943 SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
1944 {
1945 	SK_GEPORT	*pPrt;
1946 	SK_U16		Ctrl1;
1947 	SK_U16		Ctrl2;
1948 	SK_U16		Ctrl3;
1949 	SK_U16		Ctrl4;
1950 	SK_U16		Ctrl5;
1951 
1952 	Ctrl1 = PHY_CT_SP1000;
1953 	Ctrl2 = 0;
1954 	Ctrl3 = PHY_SEL_TYPE;
1955 	Ctrl4 = PHY_B_PEC_EN_LTR;
1956 	Ctrl5 = PHY_B_AC_TX_TST;
1957 
1958 	pPrt = &pAC->GIni.GP[Port];
1959 
1960 	/* manually Master/Slave ? */
1961 	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
1962 		Ctrl2 |= PHY_B_1000C_MSE;
1963 
1964 		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
1965 			Ctrl2 |= PHY_B_1000C_MSC;
1966 		}
1967 	}
1968 	/* Auto-negotiation ? */
1969 	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1970 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1971 			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
1972 		/* Set DuplexMode in Config register */
1973 		if (pPrt->PLinkMode == SK_LMODE_FULL) {
1974 			Ctrl1 |= PHY_CT_DUP_MD;
1975 		}
1976 
1977 		/* Determine Master/Slave manually if not already done */
1978 		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
1979 			Ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
1980 		}
1981 
1982 		/*
1983 		 * Do NOT enable Auto-negotiation here. This would hold
1984 		 * the link down because no IDLES are transmitted
1985 		 */
1986 	}
1987 	else {
1988 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1989 			("InitPhyBcom: with auto-negotiation Port %d\n", Port));
1990 		/* Set Auto-negotiation advertisement */
1991 
1992 		/*
1993 		 * Workaround BCOM Errata #1 for the C5 type.
1994 		 * 1000Base-T Link Acquisition Failure in Slave Mode
1995 		 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
1996 		 */
1997 		Ctrl2 |= PHY_B_1000C_RD;
1998 
1999 		 /* Set Full/half duplex capabilities */
2000 		switch (pPrt->PLinkMode) {
2001 		case SK_LMODE_AUTOHALF:
2002 			Ctrl2 |= PHY_B_1000C_AHD;
2003 			break;
2004 		case SK_LMODE_AUTOFULL:
2005 			Ctrl2 |= PHY_B_1000C_AFD;
2006 			break;
2007 		case SK_LMODE_AUTOBOTH:
2008 			Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
2009 			break;
2010 		default:
2011 			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2012 				SKERR_HWI_E015MSG);
2013 		}
2014 
2015 		/* Set Flow-control capabilities */
2016 		switch (pPrt->PFlowCtrlMode) {
2017 		case SK_FLOW_MODE_NONE:
2018 			Ctrl3 |= PHY_B_P_NO_PAUSE;
2019 			break;
2020 		case SK_FLOW_MODE_LOC_SEND:
2021 			Ctrl3 |= PHY_B_P_ASYM_MD;
2022 			break;
2023 		case SK_FLOW_MODE_SYMMETRIC:
2024 			Ctrl3 |= PHY_B_P_SYM_MD;
2025 			break;
2026 		case SK_FLOW_MODE_SYM_OR_REM:
2027 			Ctrl3 |= PHY_B_P_BOTH_MD;
2028 			break;
2029 		default:
2030 			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2031 				SKERR_HWI_E016MSG);
2032 		}
2033 
2034 		/* Restart Auto-negotiation */
2035 		Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2036 	}
2037 
2038 	/* Initialize LED register here? */
2039 	/* No. Please do it in SkDgXmitLed() (if required) and swap
2040 	   init order of LEDs and XMAC. (MAl) */
2041 
2042 	/* Write 1000Base-T Control Register */
2043 	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2044 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2045 		("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2046 
2047 	/* Write AutoNeg Advertisement Register */
2048 	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2049 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2050 		("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2051 
2052 	if (DoLoop) {
2053 		/* Set the Phy Loopback bit, too */
2054 		Ctrl1 |= PHY_CT_LOOP;
2055 	}
2056 
2057 	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2058 		/* configure FIFO to high latency for transmission of ext. packets */
2059 		Ctrl4 |= PHY_B_PEC_HIGH_LA;
2060 
2061 		/* configure reception of extended packets */
2062 		Ctrl5 |= PHY_B_AC_LONG_PACK;
2063 
2064 		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2065 	}
2066 
2067 	/* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2068 	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
2069 
2070 	/* Write to the Phy control register */
2071 	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2072 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2073 		("PHY Control Reg=0x%04X\n", Ctrl1));
2074 }	/* SkXmInitPhyBcom */
2075 #endif /* GENESIS */
2076 
2077 
2078 #ifdef YUKON
2079 #ifndef SK_SLIM
2080 /******************************************************************************
2081  *
2082  *	SkGmEnterLowPowerMode()
2083  *
2084  * Description:
2085  *	This function sets the Marvell Alaska PHY to the low power mode
2086  *	given by parameter mode.
2087  *	The following low power modes are available:
2088  *
2089  *		- Coma Mode (Deep Sleep):
2090  *			Power consumption: ~15 - 30 mW
2091  *			The PHY cannot wake up on its own.
2092  *
2093  *		- IEEE 22.2.4.1.5 compatible power down mode
2094  *			Power consumption: ~240 mW
2095  *			The PHY cannot wake up on its own.
2096  *
2097  *		- energy detect mode
2098  *			Power consumption: ~160 mW
2099  *			The PHY can wake up on its own by detecting activity
2100  *			on the CAT 5 cable.
2101  *
2102  *		- energy detect plus mode
2103  *			Power consumption: ~150 mW
2104  *			The PHY can wake up on its own by detecting activity
2105  *			on the CAT 5 cable.
2106  *			Connected devices can be woken up by sending normal link
2107  *			pulses every one second.
2108  *
2109  * Note:
2110  *
2111  * Returns:
2112  *		0: ok
2113  *		1: error
2114  */
SkGmEnterLowPowerMode(SK_AC * pAC,SK_IOC IoC,int Port,SK_U8 Mode)2115 int SkGmEnterLowPowerMode(
2116 SK_AC	*pAC,		/* adapter context */
2117 SK_IOC	IoC,		/* IO context */
2118 int		Port,		/* Port Index (e.g. MAC_1) */
2119 SK_U8	Mode)		/* low power mode */
2120 {
2121 	SK_U16	Word;
2122 	SK_U32	DWord;
2123 	SK_U8	LastMode;
2124 	int		Ret = 0;
2125 
2126 	if (pAC->GIni.GIYukonLite &&
2127 	    pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
2128 
2129 		/* save current power mode */
2130 		LastMode = pAC->GIni.GP[Port].PPhyPowerState;
2131 		pAC->GIni.GP[Port].PPhyPowerState = Mode;
2132 
2133 		switch (Mode) {
2134 			/* coma mode (deep sleep) */
2135 			case PHY_PM_DEEP_SLEEP:
2136 				/* setup General Purpose Control Register */
2137 				GM_OUT16(IoC, 0, GM_GP_CTRL, GM_GPCR_FL_PASS |
2138 					GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
2139 
2140 				/* apply COMA mode workaround */
2141 				SkGmPhyWrite(pAC, IoC, Port, 29, 0x001f);
2142 				SkGmPhyWrite(pAC, IoC, Port, 30, 0xfff3);
2143 
2144 				SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
2145 
2146 				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
2147 
2148 				/* Set PHY to Coma Mode */
2149 				SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord | PCI_PHY_COMA);
2150 
2151 				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
2152 
2153 			break;
2154 
2155 			/* IEEE 22.2.4.1.5 compatible power down mode */
2156 			case PHY_PM_IEEE_POWER_DOWN:
2157 				/*
2158 				 * - disable MAC 125 MHz clock
2159 				 * - allow MAC power down
2160 				 */
2161 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2162 				Word |= PHY_M_PC_DIS_125CLK;
2163 				Word &=	~PHY_M_PC_MAC_POW_UP;
2164 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2165 
2166 				/*
2167 				 * register changes must be followed by a software
2168 				 * reset to take effect
2169 				 */
2170 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2171 				Word |= PHY_CT_RESET;
2172 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2173 
2174 				/* switch IEEE compatible power down mode on */
2175 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2176 				Word |= PHY_CT_PDOWN;
2177 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2178 			break;
2179 
2180 			/* energy detect and energy detect plus mode */
2181 			case PHY_PM_ENERGY_DETECT:
2182 			case PHY_PM_ENERGY_DETECT_PLUS:
2183 				/*
2184 				 * - disable MAC 125 MHz clock
2185 				 */
2186 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2187 				Word |= PHY_M_PC_DIS_125CLK;
2188 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2189 
2190 				/* activate energy detect mode 1 */
2191 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2192 
2193 				/* energy detect mode */
2194 				if (Mode == PHY_PM_ENERGY_DETECT) {
2195 					Word |= PHY_M_PC_EN_DET;
2196 				}
2197 				/* energy detect plus mode */
2198 				else {
2199 					Word |= PHY_M_PC_EN_DET_PLUS;
2200 				}
2201 
2202 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2203 
2204 				/*
2205 				 * reinitialize the PHY to force a software reset
2206 				 * which is necessary after the register settings
2207 				 * for the energy detect modes.
2208 				 * Furthermore reinitialisation prevents that the
2209 				 * PHY is running out of a stable state.
2210 				 */
2211 				SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
2212 			break;
2213 
2214 			/* don't change current power mode */
2215 			default:
2216 				pAC->GIni.GP[Port].PPhyPowerState = LastMode;
2217 				Ret = 1;
2218 			break;
2219 		}
2220 	}
2221 	/* low power modes are not supported by this chip */
2222 	else {
2223 		Ret = 1;
2224 	}
2225 
2226 	return(Ret);
2227 
2228 }	/* SkGmEnterLowPowerMode */
2229 
2230 /******************************************************************************
2231  *
2232  *	SkGmLeaveLowPowerMode()
2233  *
2234  * Description:
2235  *	Leave the current low power mode and switch to normal mode
2236  *
2237  * Note:
2238  *
2239  * Returns:
2240  *		0:	ok
2241  *		1:	error
2242  */
SkGmLeaveLowPowerMode(SK_AC * pAC,SK_IOC IoC,int Port)2243 int SkGmLeaveLowPowerMode(
2244 SK_AC	*pAC,		/* adapter context */
2245 SK_IOC	IoC,		/* IO context */
2246 int		Port)		/* Port Index (e.g. MAC_1) */
2247 {
2248 	SK_U32	DWord;
2249 	SK_U16	Word;
2250 	SK_U8	LastMode;
2251 	int		Ret = 0;
2252 
2253 	if (pAC->GIni.GIYukonLite &&
2254 		pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
2255 
2256 		/* save current power mode */
2257 		LastMode = pAC->GIni.GP[Port].PPhyPowerState;
2258 		pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
2259 
2260 		switch (LastMode) {
2261 			/* coma mode (deep sleep) */
2262 			case PHY_PM_DEEP_SLEEP:
2263 				SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
2264 
2265 				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
2266 
2267 				/* Release PHY from Coma Mode */
2268 				SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord & ~PCI_PHY_COMA);
2269 
2270 				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
2271 
2272 				SK_IN32(IoC, B2_GP_IO, &DWord);
2273 
2274 				/* set to output */
2275 				DWord |= (GP_DIR_9 | GP_IO_9);
2276 
2277 				/* set PHY reset */
2278 				SK_OUT32(IoC, B2_GP_IO, DWord);
2279 
2280 				DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
2281 
2282 				/* clear PHY reset */
2283 				SK_OUT32(IoC, B2_GP_IO, DWord);
2284 			break;
2285 
2286 			/* IEEE 22.2.4.1.5 compatible power down mode */
2287 			case PHY_PM_IEEE_POWER_DOWN:
2288 				/*
2289 				 * - enable MAC 125 MHz clock
2290 				 * - set MAC power up
2291 				 */
2292 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2293 				Word &= ~PHY_M_PC_DIS_125CLK;
2294 				Word |=	PHY_M_PC_MAC_POW_UP;
2295 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2296 
2297 				/*
2298 				 * register changes must be followed by a software
2299 				 * reset to take effect
2300 				 */
2301 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2302 				Word |= PHY_CT_RESET;
2303 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2304 
2305 				/* switch IEEE compatible power down mode off */
2306 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2307 				Word &= ~PHY_CT_PDOWN;
2308 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2309 			break;
2310 
2311 			/* energy detect and energy detect plus mode */
2312 			case PHY_PM_ENERGY_DETECT:
2313 			case PHY_PM_ENERGY_DETECT_PLUS:
2314 				/*
2315 				 * - enable MAC 125 MHz clock
2316 				 */
2317 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2318 				Word &= ~PHY_M_PC_DIS_125CLK;
2319 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2320 
2321 				/* disable energy detect mode */
2322 				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2323 				Word &= ~PHY_M_PC_EN_DET_MSK;
2324 				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2325 
2326 				/*
2327 				 * reinitialize the PHY to force a software reset
2328 				 * which is necessary after the register settings
2329 				 * for the energy detect modes.
2330 				 * Furthermore reinitialisation prevents that the
2331 				 * PHY is running out of a stable state.
2332 				 */
2333 				SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
2334 			break;
2335 
2336 			/* don't change current power mode */
2337 			default:
2338 				pAC->GIni.GP[Port].PPhyPowerState = LastMode;
2339 				Ret = 1;
2340 			break;
2341 		}
2342 	}
2343 	/* low power modes are not supported by this chip */
2344 	else {
2345 		Ret = 1;
2346 	}
2347 
2348 	return(Ret);
2349 
2350 }	/* SkGmLeaveLowPowerMode */
2351 #endif /* !SK_SLIM */
2352 
2353 
2354 /******************************************************************************
2355  *
2356  *	SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2357  *
2358  * Description:	initializes all the Marvell Phy registers
2359  *
2360  * Note:
2361  *
2362  * Returns:
2363  *	nothing
2364  */
SkGmInitPhyMarv(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL DoLoop)2365 static void SkGmInitPhyMarv(
2366 SK_AC	*pAC,		/* adapter context */
2367 SK_IOC	IoC,		/* IO context */
2368 int		Port,		/* Port Index (MAC_1 + n) */
2369 SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
2370 {
2371 	SK_GEPORT	*pPrt;
2372 	SK_U16		PhyCtrl;
2373 	SK_U16		C1000BaseT;
2374 	SK_U16		AutoNegAdv;
2375 	SK_U16		ExtPhyCtrl;
2376 	SK_U16		LedCtrl;
2377 	SK_BOOL		AutoNeg;
2378 #if defined(SK_DIAG) || defined(DEBUG)
2379 	SK_U16		PhyStat;
2380 	SK_U16		PhyStat1;
2381 	SK_U16		PhySpecStat;
2382 #endif /* SK_DIAG || DEBUG */
2383 
2384 	pPrt = &pAC->GIni.GP[Port];
2385 
2386 	/* Auto-negotiation ? */
2387 	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2388 		AutoNeg = SK_FALSE;
2389 	}
2390 	else {
2391 		AutoNeg = SK_TRUE;
2392 	}
2393 
2394 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2395 		("InitPhyMarv: Port %d, auto-negotiation %s\n",
2396 		 Port, AutoNeg ? "ON" : "OFF"));
2397 
2398 #ifdef VCPU
2399 	VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2400 		Port, DoLoop);
2401 #else /* VCPU */
2402 	if (DoLoop) {
2403 		/* Set 'MAC Power up'-bit, set Manual MDI configuration */
2404 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2405 			PHY_M_PC_MAC_POW_UP);
2406 	}
2407 	else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
2408 		/* Read Ext. PHY Specific Control */
2409 		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2410 
2411 		ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2412 			PHY_M_EC_MAC_S_MSK);
2413 
2414 		ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
2415 			PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
2416 
2417 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2418 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2419 			("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2420 	}
2421 
2422 	/* Read PHY Control */
2423 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2424 
2425 	if (!AutoNeg) {
2426 		/* Disable Auto-negotiation */
2427 		PhyCtrl &= ~PHY_CT_ANE;
2428 	}
2429 
2430 	PhyCtrl |= PHY_CT_RESET;
2431 	/* Assert software reset */
2432 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2433 #endif /* VCPU */
2434 
2435 	PhyCtrl = 0 /* PHY_CT_COL_TST */;
2436 	C1000BaseT = 0;
2437 	AutoNegAdv = PHY_SEL_TYPE;
2438 
2439 	/* manually Master/Slave ? */
2440 	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2441 		/* enable Manual Master/Slave */
2442 		C1000BaseT |= PHY_M_1000C_MSE;
2443 
2444 		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2445 			C1000BaseT |= PHY_M_1000C_MSC;	/* set it to Master */
2446 		}
2447 	}
2448 
2449 	/* Auto-negotiation ? */
2450 	if (!AutoNeg) {
2451 
2452 		if (pPrt->PLinkMode == SK_LMODE_FULL) {
2453 			/* Set Full Duplex Mode */
2454 			PhyCtrl |= PHY_CT_DUP_MD;
2455 		}
2456 
2457 		/* Set Master/Slave manually if not already done */
2458 		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2459 			C1000BaseT |= PHY_M_1000C_MSE;	/* set it to Slave */
2460 		}
2461 
2462 		/* Set Speed */
2463 		switch (pPrt->PLinkSpeed) {
2464 		case SK_LSPEED_AUTO:
2465 		case SK_LSPEED_1000MBPS:
2466 			PhyCtrl |= PHY_CT_SP1000;
2467 			break;
2468 		case SK_LSPEED_100MBPS:
2469 			PhyCtrl |= PHY_CT_SP100;
2470 			break;
2471 		case SK_LSPEED_10MBPS:
2472 			break;
2473 		default:
2474 			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2475 				SKERR_HWI_E019MSG);
2476 		}
2477 
2478 		if (!DoLoop) {
2479 			PhyCtrl |= PHY_CT_RESET;
2480 		}
2481 	}
2482 	else {
2483 		/* Set Auto-negotiation advertisement */
2484 
2485 		if (pAC->GIni.GICopperType) {
2486 			/* Set Speed capabilities */
2487 			switch (pPrt->PLinkSpeed) {
2488 			case SK_LSPEED_AUTO:
2489 				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2490 				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2491 					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2492 				break;
2493 			case SK_LSPEED_1000MBPS:
2494 				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2495 				break;
2496 			case SK_LSPEED_100MBPS:
2497 				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2498 					/* advertise 10Base-T also */
2499 					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2500 				break;
2501 			case SK_LSPEED_10MBPS:
2502 				AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2503 				break;
2504 			default:
2505 				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2506 					SKERR_HWI_E019MSG);
2507 			}
2508 
2509 			/* Set Full/half duplex capabilities */
2510 			switch (pPrt->PLinkMode) {
2511 			case SK_LMODE_AUTOHALF:
2512 				C1000BaseT &= ~PHY_M_1000C_AFD;
2513 				AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2514 				break;
2515 			case SK_LMODE_AUTOFULL:
2516 				C1000BaseT &= ~PHY_M_1000C_AHD;
2517 				AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2518 				break;
2519 			case SK_LMODE_AUTOBOTH:
2520 				break;
2521 			default:
2522 				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2523 					SKERR_HWI_E015MSG);
2524 			}
2525 
2526 			/* Set Flow-control capabilities */
2527 			switch (pPrt->PFlowCtrlMode) {
2528 			case SK_FLOW_MODE_NONE:
2529 				AutoNegAdv |= PHY_B_P_NO_PAUSE;
2530 				break;
2531 			case SK_FLOW_MODE_LOC_SEND:
2532 				AutoNegAdv |= PHY_B_P_ASYM_MD;
2533 				break;
2534 			case SK_FLOW_MODE_SYMMETRIC:
2535 				AutoNegAdv |= PHY_B_P_SYM_MD;
2536 				break;
2537 			case SK_FLOW_MODE_SYM_OR_REM:
2538 				AutoNegAdv |= PHY_B_P_BOTH_MD;
2539 				break;
2540 			default:
2541 				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2542 					SKERR_HWI_E016MSG);
2543 			}
2544 		}
2545 		else {	/* special defines for FIBER (88E1011S only) */
2546 
2547 			/* Set Full/half duplex capabilities */
2548 			switch (pPrt->PLinkMode) {
2549 			case SK_LMODE_AUTOHALF:
2550 				AutoNegAdv |= PHY_M_AN_1000X_AHD;
2551 				break;
2552 			case SK_LMODE_AUTOFULL:
2553 				AutoNegAdv |= PHY_M_AN_1000X_AFD;
2554 				break;
2555 			case SK_LMODE_AUTOBOTH:
2556 				AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2557 				break;
2558 			default:
2559 				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2560 					SKERR_HWI_E015MSG);
2561 			}
2562 
2563 			/* Set Flow-control capabilities */
2564 			switch (pPrt->PFlowCtrlMode) {
2565 			case SK_FLOW_MODE_NONE:
2566 				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2567 				break;
2568 			case SK_FLOW_MODE_LOC_SEND:
2569 				AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2570 				break;
2571 			case SK_FLOW_MODE_SYMMETRIC:
2572 				AutoNegAdv |= PHY_M_P_SYM_MD_X;
2573 				break;
2574 			case SK_FLOW_MODE_SYM_OR_REM:
2575 				AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2576 				break;
2577 			default:
2578 				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2579 					SKERR_HWI_E016MSG);
2580 			}
2581 		}
2582 
2583 		if (!DoLoop) {
2584 			/* Restart Auto-negotiation */
2585 			PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
2586 		}
2587 	}
2588 
2589 #ifdef VCPU
2590 	/*
2591 	 * E-mail from Gu Lin (08-03-2002):
2592 	 */
2593 
2594 	/* Program PHY register 30 as 16'h0708 for simulation speed up */
2595 	SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
2596 
2597 	VCpuWait(2000);
2598 
2599 #else /* VCPU */
2600 
2601 	/* Write 1000Base-T Control Register */
2602 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2603 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2604 		("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
2605 
2606 	/* Write AutoNeg Advertisement Register */
2607 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2608 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2609 		("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
2610 #endif /* VCPU */
2611 
2612 	if (DoLoop) {
2613 		/* Set the PHY Loopback bit */
2614 		PhyCtrl |= PHY_CT_LOOP;
2615 
2616 #ifdef XXX
2617 		/* Program PHY register 16 as 16'h0400 to force link good */
2618 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2619 #endif /* XXX */
2620 
2621 #ifndef VCPU
2622 		if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2623 			/* Write Ext. PHY Specific Control */
2624 			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2625 				(SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2626 		}
2627 #endif /* VCPU */
2628 	}
2629 #ifdef TEST_ONLY
2630 	else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2631 			/* Write PHY Specific Control */
2632 			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2633 				PHY_M_PC_EN_DET_MSK);
2634 	}
2635 #endif
2636 
2637 	/* Write to the PHY Control register */
2638 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2639 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2640 		("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2641 
2642 #ifdef VCPU
2643 	VCpuWait(2000);
2644 #else
2645 
2646 	LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2647 
2648 	if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
2649 		LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2650 	}
2651 
2652 	if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
2653 		LedCtrl |= PHY_M_LEDC_DP_CTRL;
2654 	}
2655 
2656 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2657 
2658 	if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
2659 		/* only in forced 100 Mbps mode */
2660 		if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
2661 
2662 			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
2663 				PHY_M_LED_MO_100(MO_LED_ON));
2664 		}
2665 	}
2666 
2667 #ifdef SK_DIAG
2668 	c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2669 	c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2670 	c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2671 	c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2672 #endif /* SK_DIAG */
2673 
2674 #if defined(SK_DIAG) || defined(DEBUG)
2675 	/* Read PHY Control */
2676 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2677 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2678 		("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2679 
2680 	/* Read 1000Base-T Control Register */
2681 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2682 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2683 		("1000B-T Ctrl =0x%04X\n", C1000BaseT));
2684 
2685 	/* Read AutoNeg Advertisement Register */
2686 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2687 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2688 		("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
2689 
2690 	/* Read Ext. PHY Specific Control */
2691 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2692 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2693 		("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2694 
2695 	/* Read PHY Status */
2696 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2697 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2698 		("PHY Stat Reg.=0x%04X\n", PhyStat));
2699 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2700 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2701 		("PHY Stat Reg.=0x%04X\n", PhyStat1));
2702 
2703 	/* Read PHY Specific Status */
2704 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2705 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2706 		("PHY Spec Stat=0x%04X\n", PhySpecStat));
2707 #endif /* SK_DIAG || DEBUG */
2708 
2709 #ifdef SK_DIAG
2710 	c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2711 	c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2712 	c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2713 	c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2714 	c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2715 	c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2716 	c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2717 #endif /* SK_DIAG */
2718 
2719 #endif /* VCPU */
2720 
2721 }	/* SkGmInitPhyMarv */
2722 #endif /* YUKON */
2723 
2724 
2725 #ifdef OTHER_PHY
2726 /******************************************************************************
2727  *
2728  *	SkXmInitPhyLone() - Initialize the Level One Phy registers
2729  *
2730  * Description:	initializes all the Level One Phy registers
2731  *
2732  * Note:
2733  *
2734  * Returns:
2735  *	nothing
2736  */
SkXmInitPhyLone(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL DoLoop)2737 static void SkXmInitPhyLone(
2738 SK_AC	*pAC,		/* adapter context */
2739 SK_IOC	IoC,		/* IO context */
2740 int		Port,		/* Port Index (MAC_1 + n) */
2741 SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
2742 {
2743 	SK_GEPORT	*pPrt;
2744 	SK_U16		Ctrl1;
2745 	SK_U16		Ctrl2;
2746 	SK_U16		Ctrl3;
2747 
2748 	Ctrl1 = PHY_CT_SP1000;
2749 	Ctrl2 = 0;
2750 	Ctrl3 = PHY_SEL_TYPE;
2751 
2752 	pPrt = &pAC->GIni.GP[Port];
2753 
2754 	/* manually Master/Slave ? */
2755 	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2756 		Ctrl2 |= PHY_L_1000C_MSE;
2757 
2758 		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2759 			Ctrl2 |= PHY_L_1000C_MSC;
2760 		}
2761 	}
2762 	/* Auto-negotiation ? */
2763 	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2764 		/*
2765 		 * level one spec say: "1000 Mbps: manual mode not allowed"
2766 		 * but lets see what happens...
2767 		 */
2768 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2769 			("InitPhyLone: no auto-negotiation Port %d\n", Port));
2770 		/* Set DuplexMode in Config register */
2771 		if (pPrt->PLinkMode == SK_LMODE_FULL) {
2772 			Ctrl1 |= PHY_CT_DUP_MD;
2773 		}
2774 
2775 		/* Determine Master/Slave manually if not already done */
2776 		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2777 			Ctrl2 |= PHY_L_1000C_MSE;	/* set it to Slave */
2778 		}
2779 
2780 		/*
2781 		 * Do NOT enable Auto-negotiation here. This would hold
2782 		 * the link down because no IDLES are transmitted
2783 		 */
2784 	}
2785 	else {
2786 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2787 			("InitPhyLone: with auto-negotiation Port %d\n", Port));
2788 		/* Set Auto-negotiation advertisement */
2789 
2790 		/* Set Full/half duplex capabilities */
2791 		switch (pPrt->PLinkMode) {
2792 		case SK_LMODE_AUTOHALF:
2793 			Ctrl2 |= PHY_L_1000C_AHD;
2794 			break;
2795 		case SK_LMODE_AUTOFULL:
2796 			Ctrl2 |= PHY_L_1000C_AFD;
2797 			break;
2798 		case SK_LMODE_AUTOBOTH:
2799 			Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2800 			break;
2801 		default:
2802 			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2803 				SKERR_HWI_E015MSG);
2804 		}
2805 
2806 		/* Set Flow-control capabilities */
2807 		switch (pPrt->PFlowCtrlMode) {
2808 		case SK_FLOW_MODE_NONE:
2809 			Ctrl3 |= PHY_L_P_NO_PAUSE;
2810 			break;
2811 		case SK_FLOW_MODE_LOC_SEND:
2812 			Ctrl3 |= PHY_L_P_ASYM_MD;
2813 			break;
2814 		case SK_FLOW_MODE_SYMMETRIC:
2815 			Ctrl3 |= PHY_L_P_SYM_MD;
2816 			break;
2817 		case SK_FLOW_MODE_SYM_OR_REM:
2818 			Ctrl3 |= PHY_L_P_BOTH_MD;
2819 			break;
2820 		default:
2821 			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2822 				SKERR_HWI_E016MSG);
2823 		}
2824 
2825 		/* Restart Auto-negotiation */
2826 		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2827 	}
2828 
2829 	/* Write 1000Base-T Control Register */
2830 	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2831 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2832 		("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2833 
2834 	/* Write AutoNeg Advertisement Register */
2835 	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2836 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2837 		("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2838 
2839 	if (DoLoop) {
2840 		/* Set the Phy Loopback bit, too */
2841 		Ctrl1 |= PHY_CT_LOOP;
2842 	}
2843 
2844 	/* Write to the Phy control register */
2845 	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2846 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2847 		("PHY Control Reg=0x%04X\n", Ctrl1));
2848 }	/* SkXmInitPhyLone */
2849 
2850 
2851 /******************************************************************************
2852  *
2853  *	SkXmInitPhyNat() - Initialize the National Phy registers
2854  *
2855  * Description:	initializes all the National Phy registers
2856  *
2857  * Note:
2858  *
2859  * Returns:
2860  *	nothing
2861  */
SkXmInitPhyNat(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL DoLoop)2862 static void SkXmInitPhyNat(
2863 SK_AC	*pAC,		/* adapter context */
2864 SK_IOC	IoC,		/* IO context */
2865 int		Port,		/* Port Index (MAC_1 + n) */
2866 SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
2867 {
2868 /* todo: National */
2869 }	/* SkXmInitPhyNat */
2870 #endif /* OTHER_PHY */
2871 
2872 
2873 /******************************************************************************
2874  *
2875  *	SkMacInitPhy() - Initialize the PHY registers
2876  *
2877  * Description:	calls the Init PHY routines dep. on board type
2878  *
2879  * Note:
2880  *
2881  * Returns:
2882  *	nothing
2883  */
SkMacInitPhy(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL DoLoop)2884 void SkMacInitPhy(
2885 SK_AC	*pAC,		/* adapter context */
2886 SK_IOC	IoC,		/* IO context */
2887 int		Port,		/* Port Index (MAC_1 + n) */
2888 SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
2889 {
2890 	SK_GEPORT	*pPrt;
2891 
2892 	pPrt = &pAC->GIni.GP[Port];
2893 
2894 #ifdef GENESIS
2895 	if (pAC->GIni.GIGenesis) {
2896 
2897 		switch (pPrt->PhyType) {
2898 		case SK_PHY_XMAC:
2899 			SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2900 			break;
2901 		case SK_PHY_BCOM:
2902 			SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2903 			break;
2904 #ifdef OTHER_PHY
2905 		case SK_PHY_LONE:
2906 			SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2907 			break;
2908 		case SK_PHY_NAT:
2909 			SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2910 			break;
2911 #endif /* OTHER_PHY */
2912 		}
2913 	}
2914 #endif /* GENESIS */
2915 
2916 #ifdef YUKON
2917 	if (pAC->GIni.GIYukon) {
2918 
2919 		SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2920 	}
2921 #endif /* YUKON */
2922 
2923 }	/* SkMacInitPhy */
2924 
2925 
2926 #ifdef GENESIS
2927 /******************************************************************************
2928  *
2929  *	SkXmAutoNegDoneXmac() - Auto-negotiation handling
2930  *
2931  * Description:
2932  *	This function handles the auto-negotiation if the Done bit is set.
2933  *
2934  * Returns:
2935  *	SK_AND_OK	o.k.
2936  *	SK_AND_DUP_CAP 	Duplex capability error happened
2937  *	SK_AND_OTHER 	Other error happened
2938  */
SkXmAutoNegDoneXmac(SK_AC * pAC,SK_IOC IoC,int Port)2939 static int SkXmAutoNegDoneXmac(
2940 SK_AC	*pAC,		/* adapter context */
2941 SK_IOC	IoC,		/* IO context */
2942 int		Port)		/* Port Index (MAC_1 + n) */
2943 {
2944 	SK_GEPORT	*pPrt;
2945 	SK_U16		ResAb;		/* Resolved Ability */
2946 	SK_U16		LPAb;		/* Link Partner Ability */
2947 
2948 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2949 		("AutoNegDoneXmac, Port %d\n", Port));
2950 
2951 	pPrt = &pAC->GIni.GP[Port];
2952 
2953 	/* Get PHY parameters */
2954 	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
2955 	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
2956 
2957 	if ((LPAb & PHY_X_AN_RFB) != 0) {
2958 		/* At least one of the remote fault bit is set */
2959 		/* Error */
2960 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2961 			("AutoNegFail: Remote fault bit set Port %d\n", Port));
2962 		pPrt->PAutoNegFail = SK_TRUE;
2963 		return(SK_AND_OTHER);
2964 	}
2965 
2966 	/* Check Duplex mismatch */
2967 	if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
2968 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
2969 	}
2970 	else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
2971 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
2972 	}
2973 	else {
2974 		/* Error */
2975 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2976 			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2977 		pPrt->PAutoNegFail = SK_TRUE;
2978 		return(SK_AND_DUP_CAP);
2979 	}
2980 
2981 	/* Check PAUSE mismatch */
2982 	/* We are NOT using chapter 4.23 of the Xaqti manual */
2983 	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
2984 	if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
2985 	     pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
2986 	    (LPAb & PHY_X_P_SYM_MD) != 0) {
2987 		/* Symmetric PAUSE */
2988 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2989 	}
2990 	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
2991 		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
2992 		/* Enable PAUSE receive, disable PAUSE transmit */
2993 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2994 	}
2995 	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
2996 		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
2997 		/* Disable PAUSE receive, enable PAUSE transmit */
2998 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2999 	}
3000 	else {
3001 		/* PAUSE mismatch -> no PAUSE */
3002 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3003 	}
3004 	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
3005 
3006 	return(SK_AND_OK);
3007 }	/* SkXmAutoNegDoneXmac */
3008 
3009 
3010 /******************************************************************************
3011  *
3012  *	SkXmAutoNegDoneBcom() - Auto-negotiation handling
3013  *
3014  * Description:
3015  *	This function handles the auto-negotiation if the Done bit is set.
3016  *
3017  * Returns:
3018  *	SK_AND_OK	o.k.
3019  *	SK_AND_DUP_CAP 	Duplex capability error happened
3020  *	SK_AND_OTHER 	Other error happened
3021  */
SkXmAutoNegDoneBcom(SK_AC * pAC,SK_IOC IoC,int Port)3022 static int SkXmAutoNegDoneBcom(
3023 SK_AC	*pAC,		/* adapter context */
3024 SK_IOC	IoC,		/* IO context */
3025 int		Port)		/* Port Index (MAC_1 + n) */
3026 {
3027 	SK_GEPORT	*pPrt;
3028 	SK_U16		LPAb;		/* Link Partner Ability */
3029 	SK_U16		AuxStat;	/* Auxiliary Status */
3030 
3031 #ifdef TEST_ONLY
3032 01-Sep-2000 RA;:;:
3033 	SK_U16		ResAb;		/* Resolved Ability */
3034 #endif	/* 0 */
3035 
3036 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3037 		("AutoNegDoneBcom, Port %d\n", Port));
3038 	pPrt = &pAC->GIni.GP[Port];
3039 
3040 	/* Get PHY parameters */
3041 	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
3042 #ifdef TEST_ONLY
3043 01-Sep-2000 RA;:;:
3044 	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
3045 #endif	/* 0 */
3046 
3047 	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
3048 
3049 	if ((LPAb & PHY_B_AN_RF) != 0) {
3050 		/* Remote fault bit is set: Error */
3051 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3052 			("AutoNegFail: Remote fault bit set Port %d\n", Port));
3053 		pPrt->PAutoNegFail = SK_TRUE;
3054 		return(SK_AND_OTHER);
3055 	}
3056 
3057 	/* Check Duplex mismatch */
3058 	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
3059 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
3060 	}
3061 	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
3062 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
3063 	}
3064 	else {
3065 		/* Error */
3066 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3067 			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3068 		pPrt->PAutoNegFail = SK_TRUE;
3069 		return(SK_AND_DUP_CAP);
3070 	}
3071 
3072 #ifdef TEST_ONLY
3073 01-Sep-2000 RA;:;:
3074 	/* Check Master/Slave resolution */
3075 	if ((ResAb & PHY_B_1000S_MSF) != 0) {
3076 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3077 			("Master/Slave Fault Port %d\n", Port));
3078 		pPrt->PAutoNegFail = SK_TRUE;
3079 		pPrt->PMSStatus = SK_MS_STAT_FAULT;
3080 		return(SK_AND_OTHER);
3081 	}
3082 
3083 	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3084 		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
3085 #endif	/* 0 */
3086 
3087 	/* Check PAUSE mismatch ??? */
3088 	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
3089 	if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
3090 		/* Symmetric PAUSE */
3091 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3092 	}
3093 	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
3094 		/* Enable PAUSE receive, disable PAUSE transmit */
3095 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3096 	}
3097 	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
3098 		/* Disable PAUSE receive, enable PAUSE transmit */
3099 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3100 	}
3101 	else {
3102 		/* PAUSE mismatch -> no PAUSE */
3103 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3104 	}
3105 	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
3106 
3107 	return(SK_AND_OK);
3108 }	/* SkXmAutoNegDoneBcom */
3109 #endif /* GENESIS */
3110 
3111 
3112 #ifdef YUKON
3113 /******************************************************************************
3114  *
3115  *	SkGmAutoNegDoneMarv() - Auto-negotiation handling
3116  *
3117  * Description:
3118  *	This function handles the auto-negotiation if the Done bit is set.
3119  *
3120  * Returns:
3121  *	SK_AND_OK	o.k.
3122  *	SK_AND_DUP_CAP 	Duplex capability error happened
3123  *	SK_AND_OTHER 	Other error happened
3124  */
SkGmAutoNegDoneMarv(SK_AC * pAC,SK_IOC IoC,int Port)3125 static int SkGmAutoNegDoneMarv(
3126 SK_AC	*pAC,		/* adapter context */
3127 SK_IOC	IoC,		/* IO context */
3128 int		Port)		/* Port Index (MAC_1 + n) */
3129 {
3130 	SK_GEPORT	*pPrt;
3131 	SK_U16		LPAb;		/* Link Partner Ability */
3132 	SK_U16		ResAb;		/* Resolved Ability */
3133 	SK_U16		AuxStat;	/* Auxiliary Status */
3134 
3135 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3136 		("AutoNegDoneMarv, Port %d\n", Port));
3137 	pPrt = &pAC->GIni.GP[Port];
3138 
3139 	/* Get PHY parameters */
3140 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
3141 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3142 		("Link P.Abil.=0x%04X\n", LPAb));
3143 
3144 	if ((LPAb & PHY_M_AN_RF) != 0) {
3145 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3146 			("AutoNegFail: Remote fault bit set Port %d\n", Port));
3147 		pPrt->PAutoNegFail = SK_TRUE;
3148 		return(SK_AND_OTHER);
3149 	}
3150 
3151 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
3152 
3153 	/* Check Master/Slave resolution */
3154 	if ((ResAb & PHY_B_1000S_MSF) != 0) {
3155 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3156 			("Master/Slave Fault Port %d\n", Port));
3157 		pPrt->PAutoNegFail = SK_TRUE;
3158 		pPrt->PMSStatus = SK_MS_STAT_FAULT;
3159 		return(SK_AND_OTHER);
3160 	}
3161 
3162 	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3163 		(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
3164 
3165 	/* Read PHY Specific Status */
3166 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
3167 
3168 	/* Check Speed & Duplex resolved */
3169 	if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
3170 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3171 			("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
3172 		pPrt->PAutoNegFail = SK_TRUE;
3173 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
3174 		return(SK_AND_DUP_CAP);
3175 	}
3176 
3177 	if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
3178 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
3179 	}
3180 	else {
3181 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
3182 	}
3183 
3184 	/* Check PAUSE mismatch ??? */
3185 	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
3186 	if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
3187 		/* Symmetric PAUSE */
3188 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3189 	}
3190 	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
3191 		/* Enable PAUSE receive, disable PAUSE transmit */
3192 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3193 	}
3194 	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
3195 		/* Disable PAUSE receive, enable PAUSE transmit */
3196 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3197 	}
3198 	else {
3199 		/* PAUSE mismatch -> no PAUSE */
3200 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3201 	}
3202 
3203 	/* set used link speed */
3204 	switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
3205 	case (unsigned)PHY_M_PS_SPEED_1000:
3206 		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
3207 		break;
3208 	case PHY_M_PS_SPEED_100:
3209 		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
3210 		break;
3211 	default:
3212 		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
3213 	}
3214 
3215 	return(SK_AND_OK);
3216 }	/* SkGmAutoNegDoneMarv */
3217 #endif /* YUKON */
3218 
3219 
3220 #ifdef OTHER_PHY
3221 /******************************************************************************
3222  *
3223  *	SkXmAutoNegDoneLone() - Auto-negotiation handling
3224  *
3225  * Description:
3226  *	This function handles the auto-negotiation if the Done bit is set.
3227  *
3228  * Returns:
3229  *	SK_AND_OK	o.k.
3230  *	SK_AND_DUP_CAP 	Duplex capability error happened
3231  *	SK_AND_OTHER 	Other error happened
3232  */
SkXmAutoNegDoneLone(SK_AC * pAC,SK_IOC IoC,int Port)3233 static int SkXmAutoNegDoneLone(
3234 SK_AC	*pAC,		/* adapter context */
3235 SK_IOC	IoC,		/* IO context */
3236 int		Port)		/* Port Index (MAC_1 + n) */
3237 {
3238 	SK_GEPORT	*pPrt;
3239 	SK_U16		ResAb;		/* Resolved Ability */
3240 	SK_U16		LPAb;		/* Link Partner Ability */
3241 	SK_U16		QuickStat;	/* Auxiliary Status */
3242 
3243 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3244 		("AutoNegDoneLone, Port %d\n", Port));
3245 	pPrt = &pAC->GIni.GP[Port];
3246 
3247 	/* Get PHY parameters */
3248 	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
3249 	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
3250 	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
3251 
3252 	if ((LPAb & PHY_L_AN_RF) != 0) {
3253 		/* Remote fault bit is set */
3254 		/* Error */
3255 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3256 			("AutoNegFail: Remote fault bit set Port %d\n", Port));
3257 		pPrt->PAutoNegFail = SK_TRUE;
3258 		return(SK_AND_OTHER);
3259 	}
3260 
3261 	/* Check Duplex mismatch */
3262 	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
3263 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
3264 	}
3265 	else {
3266 		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
3267 	}
3268 
3269 	/* Check Master/Slave resolution */
3270 	if ((ResAb & PHY_L_1000S_MSF) != 0) {
3271 		/* Error */
3272 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3273 			("Master/Slave Fault Port %d\n", Port));
3274 		pPrt->PAutoNegFail = SK_TRUE;
3275 		pPrt->PMSStatus = SK_MS_STAT_FAULT;
3276 		return(SK_AND_OTHER);
3277 	}
3278 	else if (ResAb & PHY_L_1000S_MSR) {
3279 		pPrt->PMSStatus = SK_MS_STAT_MASTER;
3280 	}
3281 	else {
3282 		pPrt->PMSStatus = SK_MS_STAT_SLAVE;
3283 	}
3284 
3285 	/* Check PAUSE mismatch */
3286 	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
3287 	/* we must manually resolve the abilities here */
3288 	pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3289 
3290 	switch (pPrt->PFlowCtrlMode) {
3291 	case SK_FLOW_MODE_NONE:
3292 		/* default */
3293 		break;
3294 	case SK_FLOW_MODE_LOC_SEND:
3295 		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3296 			(PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
3297 			/* Disable PAUSE receive, enable PAUSE transmit */
3298 			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3299 		}
3300 		break;
3301 	case SK_FLOW_MODE_SYMMETRIC:
3302 		if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3303 			/* Symmetric PAUSE */
3304 			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3305 		}
3306 		break;
3307 	case SK_FLOW_MODE_SYM_OR_REM:
3308 		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3309 			PHY_L_QS_AS_PAUSE) {
3310 			/* Enable PAUSE receive, disable PAUSE transmit */
3311 			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3312 		}
3313 		else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3314 			/* Symmetric PAUSE */
3315 			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3316 		}
3317 		break;
3318 	default:
3319 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3320 			SKERR_HWI_E016MSG);
3321 	}
3322 
3323 	return(SK_AND_OK);
3324 }	/* SkXmAutoNegDoneLone */
3325 
3326 
3327 /******************************************************************************
3328  *
3329  *	SkXmAutoNegDoneNat() - Auto-negotiation handling
3330  *
3331  * Description:
3332  *	This function handles the auto-negotiation if the Done bit is set.
3333  *
3334  * Returns:
3335  *	SK_AND_OK	o.k.
3336  *	SK_AND_DUP_CAP 	Duplex capability error happened
3337  *	SK_AND_OTHER 	Other error happened
3338  */
SkXmAutoNegDoneNat(SK_AC * pAC,SK_IOC IoC,int Port)3339 static int SkXmAutoNegDoneNat(
3340 SK_AC	*pAC,		/* adapter context */
3341 SK_IOC	IoC,		/* IO context */
3342 int		Port)		/* Port Index (MAC_1 + n) */
3343 {
3344 /* todo: National */
3345 	return(SK_AND_OK);
3346 }	/* SkXmAutoNegDoneNat */
3347 #endif /* OTHER_PHY */
3348 
3349 
3350 /******************************************************************************
3351  *
3352  *	SkMacAutoNegDone() - Auto-negotiation handling
3353  *
3354  * Description:	calls the auto-negotiation done routines dep. on board type
3355  *
3356  * Returns:
3357  *	SK_AND_OK	o.k.
3358  *	SK_AND_DUP_CAP 	Duplex capability error happened
3359  *	SK_AND_OTHER 	Other error happened
3360  */
SkMacAutoNegDone(SK_AC * pAC,SK_IOC IoC,int Port)3361 int	SkMacAutoNegDone(
3362 SK_AC	*pAC,		/* adapter context */
3363 SK_IOC	IoC,		/* IO context */
3364 int		Port)		/* Port Index (MAC_1 + n) */
3365 {
3366 	SK_GEPORT	*pPrt;
3367 	int	Rtv;
3368 
3369 	Rtv = SK_AND_OK;
3370 
3371 	pPrt = &pAC->GIni.GP[Port];
3372 
3373 #ifdef GENESIS
3374 	if (pAC->GIni.GIGenesis) {
3375 
3376 		switch (pPrt->PhyType) {
3377 
3378 		case SK_PHY_XMAC:
3379 			Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3380 			break;
3381 		case SK_PHY_BCOM:
3382 			Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3383 			break;
3384 #ifdef OTHER_PHY
3385 		case SK_PHY_LONE:
3386 			Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3387 			break;
3388 		case SK_PHY_NAT:
3389 			Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3390 			break;
3391 #endif /* OTHER_PHY */
3392 		default:
3393 			return(SK_AND_OTHER);
3394 		}
3395 	}
3396 #endif /* GENESIS */
3397 
3398 #ifdef YUKON
3399 	if (pAC->GIni.GIYukon) {
3400 
3401 		Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3402 	}
3403 #endif /* YUKON */
3404 
3405 	if (Rtv != SK_AND_OK) {
3406 		return(Rtv);
3407 	}
3408 
3409 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3410 		("AutoNeg done Port %d\n", Port));
3411 
3412 	/* We checked everything and may now enable the link */
3413 	pPrt->PAutoNegFail = SK_FALSE;
3414 
3415 	SkMacRxTxEnable(pAC, IoC, Port);
3416 
3417 	return(SK_AND_OK);
3418 }	/* SkMacAutoNegDone */
3419 
3420 
3421 #ifdef GENESIS
3422 /******************************************************************************
3423  *
3424  *	SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3425  *
3426  * Description:
3427  *  sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3428  *  enables Rx/Tx
3429  *
3430  * Returns: N/A
3431  */
SkXmSetRxTxEn(SK_AC * pAC,SK_IOC IoC,int Port,int Para)3432 static void SkXmSetRxTxEn(
3433 SK_AC	*pAC,		/* Adapter Context */
3434 SK_IOC	IoC,		/* IO context */
3435 int		Port,		/* Port Index (MAC_1 + n) */
3436 int		Para)		/* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3437 {
3438 	SK_U16	Word;
3439 
3440 	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3441 
3442 	switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3443 	case SK_MAC_LOOPB_ON:
3444 		Word |= XM_MMU_MAC_LB;
3445 		break;
3446 	case SK_MAC_LOOPB_OFF:
3447 		Word &= ~XM_MMU_MAC_LB;
3448 		break;
3449 	}
3450 
3451 	switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
3452 	case SK_PHY_LOOPB_ON:
3453 		Word |= XM_MMU_GMII_LOOP;
3454 		break;
3455 	case SK_PHY_LOOPB_OFF:
3456 		Word &= ~XM_MMU_GMII_LOOP;
3457 		break;
3458 	}
3459 
3460 	switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3461 	case SK_PHY_FULLD_ON:
3462 		Word |= XM_MMU_GMII_FD;
3463 		break;
3464 	case SK_PHY_FULLD_OFF:
3465 		Word &= ~XM_MMU_GMII_FD;
3466 		break;
3467 	}
3468 
3469 	XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3470 
3471 	/* dummy read to ensure writing */
3472 	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3473 
3474 }	/* SkXmSetRxTxEn */
3475 #endif /* GENESIS */
3476 
3477 
3478 #ifdef YUKON
3479 /******************************************************************************
3480  *
3481  *	SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3482  *
3483  * Description:
3484  *  sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3485  *  enables Rx/Tx
3486  *
3487  * Returns: N/A
3488  */
SkGmSetRxTxEn(SK_AC * pAC,SK_IOC IoC,int Port,int Para)3489 static void SkGmSetRxTxEn(
3490 SK_AC	*pAC,		/* Adapter Context */
3491 SK_IOC	IoC,		/* IO context */
3492 int		Port,		/* Port Index (MAC_1 + n) */
3493 int		Para)		/* Parameter to set: MAC LoopBack, Duplex Mode */
3494 {
3495 	SK_U16	Ctrl;
3496 
3497 	GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3498 
3499 	switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3500 	case SK_MAC_LOOPB_ON:
3501 		Ctrl |= GM_GPCR_LOOP_ENA;
3502 		break;
3503 	case SK_MAC_LOOPB_OFF:
3504 		Ctrl &= ~GM_GPCR_LOOP_ENA;
3505 		break;
3506 	}
3507 
3508 	switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3509 	case SK_PHY_FULLD_ON:
3510 		Ctrl |= GM_GPCR_DUP_FULL;
3511 		break;
3512 	case SK_PHY_FULLD_OFF:
3513 		Ctrl &= ~GM_GPCR_DUP_FULL;
3514 		break;
3515 	}
3516 
3517     GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Ctrl | GM_GPCR_RX_ENA |
3518 		GM_GPCR_TX_ENA));
3519 
3520 	/* dummy read to ensure writing */
3521 	GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3522 
3523 }	/* SkGmSetRxTxEn */
3524 #endif /* YUKON */
3525 
3526 
3527 #ifndef SK_SLIM
3528 /******************************************************************************
3529  *
3530  *	SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3531  *
3532  * Description:	calls the Special Set Rx/Tx Enable routines dep. on board type
3533  *
3534  * Returns: N/A
3535  */
SkMacSetRxTxEn(SK_AC * pAC,SK_IOC IoC,int Port,int Para)3536 void SkMacSetRxTxEn(
3537 SK_AC	*pAC,		/* Adapter Context */
3538 SK_IOC	IoC,		/* IO context */
3539 int		Port,		/* Port Index (MAC_1 + n) */
3540 int		Para)
3541 {
3542 #ifdef GENESIS
3543 	if (pAC->GIni.GIGenesis) {
3544 
3545 		SkXmSetRxTxEn(pAC, IoC, Port, Para);
3546 	}
3547 #endif /* GENESIS */
3548 
3549 #ifdef YUKON
3550 	if (pAC->GIni.GIYukon) {
3551 
3552 		SkGmSetRxTxEn(pAC, IoC, Port, Para);
3553 	}
3554 #endif /* YUKON */
3555 
3556 }	/* SkMacSetRxTxEn */
3557 #endif /* !SK_SLIM */
3558 
3559 
3560 /******************************************************************************
3561  *
3562  *	SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3563  *
3564  * Description:	enables Rx/Tx dep. on board type
3565  *
3566  * Returns:
3567  *	0	o.k.
3568  *	!= 0	Error happened
3569  */
SkMacRxTxEnable(SK_AC * pAC,SK_IOC IoC,int Port)3570 int SkMacRxTxEnable(
3571 SK_AC	*pAC,		/* adapter context */
3572 SK_IOC	IoC,		/* IO context */
3573 int		Port)		/* Port Index (MAC_1 + n) */
3574 {
3575 	SK_GEPORT	*pPrt;
3576 	SK_U16		Reg;		/* 16-bit register value */
3577 	SK_U16		IntMask;	/* MAC interrupt mask */
3578 #ifdef GENESIS
3579 	SK_U16		SWord;
3580 #endif
3581 
3582 	pPrt = &pAC->GIni.GP[Port];
3583 
3584 	if (!pPrt->PHWLinkUp) {
3585 		/* The Hardware link is NOT up */
3586 		return(0);
3587 	}
3588 
3589 	if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3590 	     pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3591 	     pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3592 	     pPrt->PAutoNegFail) {
3593 		/* Auto-negotiation is not done or failed */
3594 		return(0);
3595 	}
3596 
3597 #ifdef GENESIS
3598 	if (pAC->GIni.GIGenesis) {
3599 		/* set Duplex Mode and Pause Mode */
3600 		SkXmInitDupMd(pAC, IoC, Port);
3601 
3602 		SkXmInitPauseMd(pAC, IoC, Port);
3603 
3604 		/*
3605 		 * Initialize the Interrupt Mask Register. Default IRQs are...
3606 		 *	- Link Asynchronous Event
3607 		 *	- Link Partner requests config
3608 		 *	- Auto Negotiation Done
3609 		 *	- Rx Counter Event Overflow
3610 		 *	- Tx Counter Event Overflow
3611 		 *	- Transmit FIFO Underrun
3612 		 */
3613 		IntMask = XM_DEF_MSK;
3614 
3615 #ifdef DEBUG
3616 		/* add IRQ for Receive FIFO Overflow */
3617 		IntMask &= ~XM_IS_RXF_OV;
3618 #endif /* DEBUG */
3619 
3620 		if (pPrt->PhyType != SK_PHY_XMAC) {
3621 			/* disable GP0 interrupt bit */
3622 			IntMask |= XM_IS_INP_ASS;
3623 		}
3624 		XM_OUT16(IoC, Port, XM_IMSK, IntMask);
3625 
3626 		/* get MMU Command Reg. */
3627 		XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
3628 
3629 		if (pPrt->PhyType != SK_PHY_XMAC &&
3630 			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3631 			 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3632 			/* set to Full Duplex */
3633 			Reg |= XM_MMU_GMII_FD;
3634 		}
3635 
3636 		switch (pPrt->PhyType) {
3637 		case SK_PHY_BCOM:
3638 			/*
3639 			 * Workaround BCOM Errata (#10523) for all BCom Phys
3640 			 * Enable Power Management after link up
3641 			 */
3642 			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3643 			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3644 				(SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3645             SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
3646 				(SK_U16)PHY_B_DEF_MSK);
3647 			break;
3648 #ifdef OTHER_PHY
3649 		case SK_PHY_LONE:
3650 			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3651 			break;
3652 		case SK_PHY_NAT:
3653 			/* todo National:
3654 			SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3655 			/* no interrupts possible from National ??? */
3656 			break;
3657 #endif /* OTHER_PHY */
3658 		}
3659 
3660 		/* enable Rx/Tx */
3661 		XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3662 	}
3663 #endif /* GENESIS */
3664 
3665 #ifdef YUKON
3666 	if (pAC->GIni.GIYukon) {
3667 		/*
3668 		 * Initialize the Interrupt Mask Register. Default IRQs are...
3669 		 *	- Rx Counter Event Overflow
3670 		 *	- Tx Counter Event Overflow
3671 		 *	- Transmit FIFO Underrun
3672 		 */
3673 		IntMask = GMAC_DEF_MSK;
3674 
3675 #ifdef DEBUG
3676 		/* add IRQ for Receive FIFO Overrun */
3677 		IntMask |= GM_IS_RX_FF_OR;
3678 #endif /* DEBUG */
3679 
3680 		SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
3681 
3682 		/* get General Purpose Control */
3683 		GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
3684 
3685 		if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3686 			pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3687 			/* set to Full Duplex */
3688 			Reg |= GM_GPCR_DUP_FULL;
3689 		}
3690 
3691 		/* enable Rx/Tx */
3692         GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
3693 			GM_GPCR_TX_ENA));
3694 
3695 #ifndef VCPU
3696 		/* Enable all PHY interrupts */
3697         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
3698 			(SK_U16)PHY_M_DEF_MSK);
3699 #endif /* VCPU */
3700 	}
3701 #endif /* YUKON */
3702 
3703 	return(0);
3704 
3705 }	/* SkMacRxTxEnable */
3706 
3707 
3708 /******************************************************************************
3709  *
3710  *	SkMacRxTxDisable() - Disable Receiver and Transmitter
3711  *
3712  * Description:	disables Rx/Tx dep. on board type
3713  *
3714  * Returns: N/A
3715  */
SkMacRxTxDisable(SK_AC * pAC,SK_IOC IoC,int Port)3716 void SkMacRxTxDisable(
3717 SK_AC	*pAC,		/* Adapter Context */
3718 SK_IOC	IoC,		/* IO context */
3719 int		Port)		/* Port Index (MAC_1 + n) */
3720 {
3721 	SK_U16	Word;
3722 
3723 #ifdef GENESIS
3724 	if (pAC->GIni.GIGenesis) {
3725 
3726 		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3727 
3728 		XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
3729 
3730 		/* dummy read to ensure writing */
3731 		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3732 	}
3733 #endif /* GENESIS */
3734 
3735 #ifdef YUKON
3736 	if (pAC->GIni.GIYukon) {
3737 
3738 		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3739 
3740         GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
3741 			GM_GPCR_TX_ENA)));
3742 
3743 		/* dummy read to ensure writing */
3744 		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3745 	}
3746 #endif /* YUKON */
3747 
3748 }	/* SkMacRxTxDisable */
3749 
3750 
3751 /******************************************************************************
3752  *
3753  *	SkMacIrqDisable() - Disable IRQ from MAC
3754  *
3755  * Description:	sets the IRQ-mask to disable IRQ dep. on board type
3756  *
3757  * Returns: N/A
3758  */
SkMacIrqDisable(SK_AC * pAC,SK_IOC IoC,int Port)3759 void SkMacIrqDisable(
3760 SK_AC	*pAC,		/* Adapter Context */
3761 SK_IOC	IoC,		/* IO context */
3762 int		Port)		/* Port Index (MAC_1 + n) */
3763 {
3764 	SK_GEPORT	*pPrt;
3765 #ifdef GENESIS
3766 	SK_U16		Word;
3767 #endif
3768 
3769 	pPrt = &pAC->GIni.GP[Port];
3770 
3771 #ifdef GENESIS
3772 	if (pAC->GIni.GIGenesis) {
3773 
3774 		/* disable all XMAC IRQs */
3775 		XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
3776 
3777 		/* Disable all PHY interrupts */
3778 		switch (pPrt->PhyType) {
3779 			case SK_PHY_BCOM:
3780 				/* Make sure that PHY is initialized */
3781 				if (pPrt->PState != SK_PRT_RESET) {
3782 					/* NOT allowed if BCOM is in RESET state */
3783 					/* Workaround BCOM Errata (#10523) all BCom */
3784 					/* Disable Power Management if link is down */
3785 					SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3786 					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3787 						(SK_U16)(Word | PHY_B_AC_DIS_PM));
3788 					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3789 				}
3790 				break;
3791 #ifdef OTHER_PHY
3792 			case SK_PHY_LONE:
3793 				SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3794 				break;
3795 			case SK_PHY_NAT:
3796 				/* todo: National
3797 				SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3798 				break;
3799 #endif /* OTHER_PHY */
3800 		}
3801 	}
3802 #endif /* GENESIS */
3803 
3804 #ifdef YUKON
3805 	if (pAC->GIni.GIYukon) {
3806 		/* disable all GMAC IRQs */
3807 		SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
3808 
3809 #ifndef VCPU
3810 		/* Disable all PHY interrupts */
3811 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3812 #endif /* VCPU */
3813 	}
3814 #endif /* YUKON */
3815 
3816 }	/* SkMacIrqDisable */
3817 
3818 
3819 #ifdef SK_DIAG
3820 /******************************************************************************
3821  *
3822  *	SkXmSendCont() - Enable / Disable Send Continuous Mode
3823  *
3824  * Description:	enable / disable Send Continuous Mode on XMAC
3825  *
3826  * Returns:
3827  *	nothing
3828  */
SkXmSendCont(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL Enable)3829 void SkXmSendCont(
3830 SK_AC	*pAC,	/* adapter context */
3831 SK_IOC	IoC,	/* IO context */
3832 int		Port,	/* Port Index (MAC_1 + n) */
3833 SK_BOOL	Enable)	/* Enable / Disable */
3834 {
3835 	SK_U32	MdReg;
3836 
3837 	XM_IN32(IoC, Port, XM_MODE, &MdReg);
3838 
3839 	if (Enable) {
3840 		MdReg |= XM_MD_TX_CONT;
3841 	}
3842 	else {
3843 		MdReg &= ~XM_MD_TX_CONT;
3844 	}
3845 	/* setup Mode Register */
3846 	XM_OUT32(IoC, Port, XM_MODE, MdReg);
3847 
3848 }	/* SkXmSendCont */
3849 
3850 
3851 /******************************************************************************
3852  *
3853  *	SkMacTimeStamp() - Enable / Disable Time Stamp
3854  *
3855  * Description:	enable / disable Time Stamp generation for Rx packets
3856  *
3857  * Returns:
3858  *	nothing
3859  */
SkMacTimeStamp(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL Enable)3860 void SkMacTimeStamp(
3861 SK_AC	*pAC,	/* adapter context */
3862 SK_IOC	IoC,	/* IO context */
3863 int		Port,	/* Port Index (MAC_1 + n) */
3864 SK_BOOL	Enable)	/* Enable / Disable */
3865 {
3866 	SK_U32	MdReg;
3867 	SK_U8	TimeCtrl;
3868 
3869 	if (pAC->GIni.GIGenesis) {
3870 
3871 		XM_IN32(IoC, Port, XM_MODE, &MdReg);
3872 
3873 		if (Enable) {
3874 			MdReg |= XM_MD_ATS;
3875 		}
3876 		else {
3877 			MdReg &= ~XM_MD_ATS;
3878 		}
3879 		/* setup Mode Register */
3880 		XM_OUT32(IoC, Port, XM_MODE, MdReg);
3881 	}
3882 	else {
3883 		if (Enable) {
3884 			TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3885 		}
3886 		else {
3887 			TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3888 		}
3889 		/* Start/Stop Time Stamp Timer */
3890 		SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
3891 	}
3892 
3893 }	/* SkMacTimeStamp*/
3894 
3895 #else /* !SK_DIAG */
3896 
3897 #ifdef GENESIS
3898 /******************************************************************************
3899  *
3900  *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
3901  *
3902  *	This function analyses the Interrupt status word. If any of the
3903  *	Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
3904  *	is set true.
3905  */
SkXmAutoNegLipaXmac(SK_AC * pAC,SK_IOC IoC,int Port,SK_U16 IStatus)3906 void SkXmAutoNegLipaXmac(
3907 SK_AC	*pAC,		/* adapter context */
3908 SK_IOC	IoC,		/* IO context */
3909 int		Port,		/* Port Index (MAC_1 + n) */
3910 SK_U16	IStatus)	/* Interrupt Status word to analyse */
3911 {
3912 	SK_GEPORT	*pPrt;
3913 
3914 	pPrt = &pAC->GIni.GP[Port];
3915 
3916 	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3917 		(IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
3918 
3919 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3920 			("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
3921 			Port, IStatus));
3922 		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
3923 	}
3924 }	/* SkXmAutoNegLipaXmac */
3925 #endif /* GENESIS */
3926 
3927 
3928 /******************************************************************************
3929  *
3930  *	SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
3931  *
3932  *	This function analyses the PHY status word.
3933  *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
3934  *	is set true.
3935  */
SkMacAutoNegLipaPhy(SK_AC * pAC,SK_IOC IoC,int Port,SK_U16 PhyStat)3936 void SkMacAutoNegLipaPhy(
3937 SK_AC	*pAC,		/* adapter context */
3938 SK_IOC	IoC,		/* IO context */
3939 int		Port,		/* Port Index (MAC_1 + n) */
3940 SK_U16	PhyStat)	/* PHY Status word to analyse */
3941 {
3942 	SK_GEPORT	*pPrt;
3943 
3944 	pPrt = &pAC->GIni.GP[Port];
3945 
3946 	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3947 		(PhyStat & PHY_ST_AN_OVER) != 0) {
3948 
3949 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3950 			("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
3951 			Port, PhyStat));
3952 		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
3953 	}
3954 }	/* SkMacAutoNegLipaPhy */
3955 
3956 
3957 #ifdef GENESIS
3958 /******************************************************************************
3959  *
3960  *	SkXmIrq() - Interrupt Service Routine
3961  *
3962  * Description:	services an Interrupt Request of the XMAC
3963  *
3964  * Note:
3965  *	With an external PHY, some interrupt bits are not meaningfull any more:
3966  *	- LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
3967  *	- LinkPartnerReqConfig (bit #10)	XM_IS_LIPA_RC
3968  *	- Page Received (bit #9)		XM_IS_RX_PAGE
3969  *	- NextPageLoadedForXmt (bit #8)		XM_IS_TX_PAGE
3970  *	- AutoNegDone (bit #7)			XM_IS_AND
3971  *	Also probably not valid any more is the GP0 input bit:
3972  *	- GPRegisterBit0set			XM_IS_INP_ASS
3973  *
3974  * Returns:
3975  *	nothing
3976  */
SkXmIrq(SK_AC * pAC,SK_IOC IoC,int Port)3977 void SkXmIrq(
3978 SK_AC	*pAC,		/* adapter context */
3979 SK_IOC	IoC,		/* IO context */
3980 int		Port)		/* Port Index (MAC_1 + n) */
3981 {
3982 	SK_GEPORT	*pPrt;
3983 	SK_EVPARA	Para;
3984 	SK_U16		IStatus;	/* Interrupt status read from the XMAC */
3985 	SK_U16		IStatus2;
3986 #ifdef SK_SLIM
3987     SK_U64      OverflowStatus;
3988 #endif
3989 
3990 	pPrt = &pAC->GIni.GP[Port];
3991 
3992 	XM_IN16(IoC, Port, XM_ISRC, &IStatus);
3993 
3994 	/* LinkPartner Auto-negable? */
3995 	if (pPrt->PhyType == SK_PHY_XMAC) {
3996 		SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
3997 	}
3998 	else {
3999 		/* mask bits that are not used with ext. PHY */
4000 		IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
4001 			XM_IS_RX_PAGE | XM_IS_TX_PAGE |
4002 			XM_IS_AND | XM_IS_INP_ASS);
4003 	}
4004 
4005 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4006 		("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
4007 
4008 	if (!pPrt->PHWLinkUp) {
4009 		/* Spurious XMAC interrupt */
4010 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4011 			("SkXmIrq: spurious interrupt on Port %d\n", Port));
4012 		return;
4013 	}
4014 
4015 	if ((IStatus & XM_IS_INP_ASS) != 0) {
4016 		/* Reread ISR Register if link is not in sync */
4017 		XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
4018 
4019 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4020 			("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
4021 			 Port, IStatus, IStatus2));
4022 		IStatus &= ~XM_IS_INP_ASS;
4023 		IStatus |= IStatus2;
4024 	}
4025 
4026 	if ((IStatus & XM_IS_LNK_AE) != 0) {
4027 		/* not used, GP0 is used instead */
4028 	}
4029 
4030 	if ((IStatus & XM_IS_TX_ABORT) != 0) {
4031 		/* not used */
4032 	}
4033 
4034 	if ((IStatus & XM_IS_FRC_INT) != 0) {
4035 		/* not used, use ASIC IRQ instead if needed */
4036 	}
4037 
4038 	if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
4039 		SkHWLinkDown(pAC, IoC, Port);
4040 
4041 		/* Signal to RLMT */
4042 		Para.Para32[0] = (SK_U32)Port;
4043 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
4044 
4045 		/* Start workaround Errata #2 timer */
4046 		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
4047 			SKGE_HWAC, SK_HWEV_WATIM, Para);
4048 	}
4049 
4050 	if ((IStatus & XM_IS_RX_PAGE) != 0) {
4051 		/* not used */
4052 	}
4053 
4054 	if ((IStatus & XM_IS_TX_PAGE) != 0) {
4055 		/* not used */
4056 	}
4057 
4058 	if ((IStatus & XM_IS_AND) != 0) {
4059 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4060 			("SkXmIrq: AND on link that is up Port %d\n", Port));
4061 	}
4062 
4063 	if ((IStatus & XM_IS_TSC_OV) != 0) {
4064 		/* not used */
4065 	}
4066 
4067 	/* Combined Tx & Rx Counter Overflow SIRQ Event */
4068 	if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
4069 #ifdef SK_SLIM
4070 		SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
4071 #else
4072 		Para.Para32[0] = (SK_U32)Port;
4073 		Para.Para32[1] = (SK_U32)IStatus;
4074 		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
4075 #endif /* SK_SLIM */
4076 	}
4077 
4078 	if ((IStatus & XM_IS_RXF_OV) != 0) {
4079 		/* normal situation -> no effect */
4080 #ifdef DEBUG
4081 		pPrt->PRxOverCnt++;
4082 #endif /* DEBUG */
4083 	}
4084 
4085 	if ((IStatus & XM_IS_TXF_UR) != 0) {
4086 		/* may NOT happen -> error log */
4087 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
4088 	}
4089 
4090 	if ((IStatus & XM_IS_TX_COMP) != 0) {
4091 		/* not served here */
4092 	}
4093 
4094 	if ((IStatus & XM_IS_RX_COMP) != 0) {
4095 		/* not served here */
4096 	}
4097 }	/* SkXmIrq */
4098 #endif /* GENESIS */
4099 
4100 
4101 #ifdef YUKON
4102 /******************************************************************************
4103  *
4104  *	SkGmIrq() - Interrupt Service Routine
4105  *
4106  * Description:	services an Interrupt Request of the GMAC
4107  *
4108  * Note:
4109  *
4110  * Returns:
4111  *	nothing
4112  */
SkGmIrq(SK_AC * pAC,SK_IOC IoC,int Port)4113 void SkGmIrq(
4114 SK_AC	*pAC,		/* adapter context */
4115 SK_IOC	IoC,		/* IO context */
4116 int		Port)		/* Port Index (MAC_1 + n) */
4117 {
4118 	SK_GEPORT	*pPrt;
4119 	SK_U8		IStatus;	/* Interrupt status */
4120 #ifdef SK_SLIM
4121     SK_U64      OverflowStatus;
4122 #else
4123 	SK_EVPARA	Para;
4124 #endif
4125 
4126 	pPrt = &pAC->GIni.GP[Port];
4127 
4128 	SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
4129 
4130 #ifdef XXX
4131 	/* LinkPartner Auto-negable? */
4132 	SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
4133 #endif /* XXX */
4134 
4135 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4136 		("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
4137 
4138 	/* Combined Tx & Rx Counter Overflow SIRQ Event */
4139 	if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
4140 		/* these IRQs will be cleared by reading GMACs register */
4141 #ifdef SK_SLIM
4142         SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
4143 #else
4144 		Para.Para32[0] = (SK_U32)Port;
4145 		Para.Para32[1] = (SK_U32)IStatus;
4146 		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
4147 #endif
4148 	}
4149 
4150 	if (IStatus & GM_IS_RX_FF_OR) {
4151 		/* clear GMAC Rx FIFO Overrun IRQ */
4152 		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
4153 #ifdef DEBUG
4154 		pPrt->PRxOverCnt++;
4155 #endif /* DEBUG */
4156 	}
4157 
4158 	if (IStatus & GM_IS_TX_FF_UR) {
4159 		/* clear GMAC Tx FIFO Underrun IRQ */
4160 		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
4161 		/* may NOT happen -> error log */
4162 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
4163 	}
4164 
4165 	if (IStatus & GM_IS_TX_COMPL) {
4166 		/* not served here */
4167 	}
4168 
4169 	if (IStatus & GM_IS_RX_COMPL) {
4170 		/* not served here */
4171 	}
4172 }	/* SkGmIrq */
4173 #endif /* YUKON */
4174 
4175 
4176 /******************************************************************************
4177  *
4178  *	SkMacIrq() - Interrupt Service Routine for MAC
4179  *
4180  * Description:	calls the Interrupt Service Routine dep. on board type
4181  *
4182  * Returns:
4183  *	nothing
4184  */
SkMacIrq(SK_AC * pAC,SK_IOC IoC,int Port)4185 void SkMacIrq(
4186 SK_AC	*pAC,		/* adapter context */
4187 SK_IOC	IoC,		/* IO context */
4188 int		Port)		/* Port Index (MAC_1 + n) */
4189 {
4190 #ifdef GENESIS
4191 	if (pAC->GIni.GIGenesis) {
4192 		/* IRQ from XMAC */
4193 		SkXmIrq(pAC, IoC, Port);
4194 	}
4195 #endif /* GENESIS */
4196 
4197 #ifdef YUKON
4198 	if (pAC->GIni.GIYukon) {
4199 		/* IRQ from GMAC */
4200 		SkGmIrq(pAC, IoC, Port);
4201 	}
4202 #endif /* YUKON */
4203 
4204 }	/* SkMacIrq */
4205 
4206 #endif /* !SK_DIAG */
4207 
4208 #ifdef GENESIS
4209 /******************************************************************************
4210  *
4211  *	SkXmUpdateStats() - Force the XMAC to output the current statistic
4212  *
4213  * Description:
4214  *	The XMAC holds its statistic internally. To obtain the current
4215  *	values a command must be sent so that the statistic data will
4216  *	be written to a predefined memory area on the adapter.
4217  *
4218  * Returns:
4219  *	0:  success
4220  *	1:  something went wrong
4221  */
SkXmUpdateStats(SK_AC * pAC,SK_IOC IoC,unsigned int Port)4222 int SkXmUpdateStats(
4223 SK_AC	*pAC,		/* adapter context */
4224 SK_IOC	IoC,		/* IO context */
4225 unsigned int Port)	/* Port Index (MAC_1 + n) */
4226 {
4227 	SK_GEPORT	*pPrt;
4228 	SK_U16		StatReg;
4229 	int			WaitIndex;
4230 
4231 	pPrt = &pAC->GIni.GP[Port];
4232 	WaitIndex = 0;
4233 
4234 	/* Send an update command to XMAC specified */
4235 	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
4236 
4237 	/*
4238 	 * It is an auto-clearing register. If the command bits
4239 	 * went to zero again, the statistics are transferred.
4240 	 * Normally the command should be executed immediately.
4241 	 * But just to be sure we execute a loop.
4242 	 */
4243 	do {
4244 
4245 		XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
4246 
4247 		if (++WaitIndex > 10) {
4248 
4249 			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
4250 
4251 			return(1);
4252 		}
4253 	} while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
4254 
4255 	return(0);
4256 }	/* SkXmUpdateStats */
4257 
4258 
4259 /******************************************************************************
4260  *
4261  *	SkXmMacStatistic() - Get XMAC counter value
4262  *
4263  * Description:
4264  *	Gets the 32bit counter value. Except for the octet counters
4265  *	the lower 32bit are counted in hardware and the upper 32bit
4266  *	must be counted in software by monitoring counter overflow interrupts.
4267  *
4268  * Returns:
4269  *	0:  success
4270  *	1:  something went wrong
4271  */
SkXmMacStatistic(SK_AC * pAC,SK_IOC IoC,unsigned int Port,SK_U16 StatAddr,SK_U32 SK_FAR * pVal)4272 int SkXmMacStatistic(
4273 SK_AC	*pAC,			/* adapter context */
4274 SK_IOC	IoC,			/* IO context */
4275 unsigned int Port,		/* Port Index (MAC_1 + n) */
4276 SK_U16	StatAddr,		/* MIB counter base address */
4277 SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
4278 {
4279 	if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
4280 
4281 		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4282 
4283 		return(1);
4284 	}
4285 
4286 	XM_IN32(IoC, Port, StatAddr, pVal);
4287 
4288 	return(0);
4289 }	/* SkXmMacStatistic */
4290 
4291 
4292 /******************************************************************************
4293  *
4294  *	SkXmResetCounter() - Clear MAC statistic counter
4295  *
4296  * Description:
4297  *	Force the XMAC to clear its statistic counter.
4298  *
4299  * Returns:
4300  *	0:  success
4301  *	1:  something went wrong
4302  */
SkXmResetCounter(SK_AC * pAC,SK_IOC IoC,unsigned int Port)4303 int SkXmResetCounter(
4304 SK_AC	*pAC,		/* adapter context */
4305 SK_IOC	IoC,		/* IO context */
4306 unsigned int Port)	/* Port Index (MAC_1 + n) */
4307 {
4308 	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4309 	/* Clear two times according to Errata #3 */
4310 	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4311 
4312 	return(0);
4313 }	/* SkXmResetCounter */
4314 
4315 
4316 /******************************************************************************
4317  *
4318  *	SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4319  *
4320  * Description:
4321  *	Checks the source causing an counter overflow interrupt. On success the
4322  *	resulting counter overflow status is written to <pStatus>, whereas the
4323  *	upper dword stores the XMAC ReceiveCounterEvent register and the lower
4324  *	dword the XMAC TransmitCounterEvent register.
4325  *
4326  * Note:
4327  *	For XMAC the interrupt source is a self-clearing register, so the source
4328  *	must be checked only once. SIRQ module does another check to be sure
4329  *	that no interrupt get lost during process time.
4330  *
4331  * Returns:
4332  *	0:  success
4333  *	1:  something went wrong
4334  */
SkXmOverflowStatus(SK_AC * pAC,SK_IOC IoC,unsigned int Port,SK_U16 IStatus,SK_U64 SK_FAR * pStatus)4335 int SkXmOverflowStatus(
4336 SK_AC	*pAC,				/* adapter context */
4337 SK_IOC	IoC,				/* IO context */
4338 unsigned int Port,			/* Port Index (MAC_1 + n) */
4339 SK_U16	IStatus,			/* Interupt Status from MAC */
4340 SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
4341 {
4342 	SK_U64	Status;	/* Overflow status */
4343 	SK_U32	RegVal;
4344 
4345 	Status = 0;
4346 
4347 	if ((IStatus & XM_IS_RXC_OV) != 0) {
4348 
4349 		XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
4350 		Status |= (SK_U64)RegVal << 32;
4351 	}
4352 
4353 	if ((IStatus & XM_IS_TXC_OV) != 0) {
4354 
4355 		XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
4356 		Status |= (SK_U64)RegVal;
4357 	}
4358 
4359 	*pStatus = Status;
4360 
4361 	return(0);
4362 }	/* SkXmOverflowStatus */
4363 #endif /* GENESIS */
4364 
4365 
4366 #ifdef YUKON
4367 /******************************************************************************
4368  *
4369  *	SkGmUpdateStats() - Force the GMAC to output the current statistic
4370  *
4371  * Description:
4372  *	Empty function for GMAC. Statistic data is accessible in direct way.
4373  *
4374  * Returns:
4375  *	0:  success
4376  *	1:  something went wrong
4377  */
SkGmUpdateStats(SK_AC * pAC,SK_IOC IoC,unsigned int Port)4378 int SkGmUpdateStats(
4379 SK_AC	*pAC,		/* adapter context */
4380 SK_IOC	IoC,		/* IO context */
4381 unsigned int Port)	/* Port Index (MAC_1 + n) */
4382 {
4383 	return(0);
4384 }
4385 
4386 
4387 /******************************************************************************
4388  *
4389  *	SkGmMacStatistic() - Get GMAC counter value
4390  *
4391  * Description:
4392  *	Gets the 32bit counter value. Except for the octet counters
4393  *	the lower 32bit are counted in hardware and the upper 32bit
4394  *	must be counted in software by monitoring counter overflow interrupts.
4395  *
4396  * Returns:
4397  *	0:  success
4398  *	1:  something went wrong
4399  */
SkGmMacStatistic(SK_AC * pAC,SK_IOC IoC,unsigned int Port,SK_U16 StatAddr,SK_U32 SK_FAR * pVal)4400 int SkGmMacStatistic(
4401 SK_AC	*pAC,			/* adapter context */
4402 SK_IOC	IoC,			/* IO context */
4403 unsigned int Port,		/* Port Index (MAC_1 + n) */
4404 SK_U16	StatAddr,		/* MIB counter base address */
4405 SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
4406 {
4407 
4408 	if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
4409 
4410 		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4411 
4412 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4413 			("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
4414 		return(1);
4415 	}
4416 
4417 	GM_IN32(IoC, Port, StatAddr, pVal);
4418 
4419 	return(0);
4420 }	/* SkGmMacStatistic */
4421 
4422 
4423 /******************************************************************************
4424  *
4425  *	SkGmResetCounter() - Clear MAC statistic counter
4426  *
4427  * Description:
4428  *	Force GMAC to clear its statistic counter.
4429  *
4430  * Returns:
4431  *	0:  success
4432  *	1:  something went wrong
4433  */
SkGmResetCounter(SK_AC * pAC,SK_IOC IoC,unsigned int Port)4434 int SkGmResetCounter(
4435 SK_AC	*pAC,		/* adapter context */
4436 SK_IOC	IoC,		/* IO context */
4437 unsigned int Port)	/* Port Index (MAC_1 + n) */
4438 {
4439 	SK_U16	Reg;	/* Phy Address Register */
4440 	SK_U16	Word;
4441 	int		i;
4442 
4443 	GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4444 
4445 	/* set MIB Clear Counter Mode */
4446 	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
4447 
4448 	/* read all MIB Counters with Clear Mode set */
4449 	for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4450 		/* the reset is performed only when the lower 16 bits are read */
4451 		GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4452 	}
4453 
4454 	/* clear MIB Clear Counter Mode */
4455 	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4456 
4457 	return(0);
4458 }	/* SkGmResetCounter */
4459 
4460 
4461 /******************************************************************************
4462  *
4463  *	SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4464  *
4465  * Description:
4466  *	Checks the source causing an counter overflow interrupt. On success the
4467  *	resulting counter overflow status is written to <pStatus>, whereas the
4468  *	the following bit coding is used:
4469  *	63:56 - unused
4470  *	55:48 - TxRx interrupt register bit7:0
4471  *	32:47 - Rx interrupt register
4472  *	31:24 - unused
4473  *	23:16 - TxRx interrupt register bit15:8
4474  *	15:0  - Tx interrupt register
4475  *
4476  * Returns:
4477  *	0:  success
4478  *	1:  something went wrong
4479  */
SkGmOverflowStatus(SK_AC * pAC,SK_IOC IoC,unsigned int Port,SK_U16 IStatus,SK_U64 SK_FAR * pStatus)4480 int SkGmOverflowStatus(
4481 SK_AC	*pAC,				/* adapter context */
4482 SK_IOC	IoC,				/* IO context */
4483 unsigned int Port,			/* Port Index (MAC_1 + n) */
4484 SK_U16	IStatus,			/* Interupt Status from MAC */
4485 SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
4486 {
4487 	SK_U64	Status;		/* Overflow status */
4488 	SK_U16	RegVal;
4489 
4490 	Status = 0;
4491 
4492 	if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4493 		/* this register is self-clearing after read */
4494 		GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4495 		Status |= (SK_U64)RegVal << 32;
4496 	}
4497 
4498 	if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4499 		/* this register is self-clearing after read */
4500 		GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4501 		Status |= (SK_U64)RegVal;
4502 	}
4503 
4504 	/* this register is self-clearing after read */
4505 	GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4506 	/* Rx overflow interrupt register bits (LoByte)*/
4507 	Status |= (SK_U64)((SK_U8)RegVal) << 48;
4508 	/* Tx overflow interrupt register bits (HiByte)*/
4509 	Status |= (SK_U64)(RegVal >> 8) << 16;
4510 
4511 	*pStatus = Status;
4512 
4513 	return(0);
4514 }	/* SkGmOverflowStatus */
4515 
4516 
4517 #ifndef SK_SLIM
4518 /******************************************************************************
4519  *
4520  *	SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4521  *
4522  * Description:
4523  *  starts the cable diagnostic test if 'StartTest' is true
4524  *  gets the results if 'StartTest' is true
4525  *
4526  * NOTE:	this test is meaningful only when link is down
4527  *
4528  * Returns:
4529  *	0:  success
4530  *	1:	no YUKON copper
4531  *	2:	test in progress
4532  */
SkGmCableDiagStatus(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL StartTest)4533 int SkGmCableDiagStatus(
4534 SK_AC	*pAC,		/* adapter context */
4535 SK_IOC	IoC,   		/* IO context */
4536 int		Port,		/* Port Index (MAC_1 + n) */
4537 SK_BOOL	StartTest)	/* flag for start / get result */
4538 {
4539 	int		i;
4540 	SK_U16	RegVal;
4541 	SK_GEPORT	*pPrt;
4542 
4543 	pPrt = &pAC->GIni.GP[Port];
4544 
4545 	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
4546 
4547 		return(1);
4548 	}
4549 
4550 	if (StartTest) {
4551 		/* only start the cable test */
4552 		if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4553 			/* apply TDR workaround from Marvell */
4554 			SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
4555 
4556 			SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4557 			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4558 			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4559 			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4560 			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4561 		}
4562 
4563 		/* set address to 0 for MDI[0] */
4564 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4565 
4566 		/* Read Cable Diagnostic Reg */
4567 		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4568 
4569 		/* start Cable Diagnostic Test */
4570 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4571 			(SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
4572 
4573 		return(0);
4574 	}
4575 
4576 	/* Read Cable Diagnostic Reg */
4577 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4578 
4579 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4580 		("PHY Cable Diag.=0x%04X\n", RegVal));
4581 
4582 	if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4583 		/* test is running */
4584 		return(2);
4585 	}
4586 
4587 	/* get the test results */
4588 	for (i = 0; i < 4; i++)  {
4589 		/* set address to i for MDI[i] */
4590 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4591 
4592 		/* get Cable Diagnostic values */
4593 		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4594 
4595 		pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4596 
4597 		pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4598 	}
4599 
4600 	return(0);
4601 }	/* SkGmCableDiagStatus */
4602 #endif /* !SK_SLIM */
4603 #endif /* YUKON */
4604 
4605 /* End of file */
4606