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