1 /******************************************************************************
2  *
3  * Name:	skgesirq.c
4  * Project:	Gigabit Ethernet Adapters, Common Modules
5  * Purpose:	Special IRQ module
6  *
7  ******************************************************************************/
8 
9 /******************************************************************************
10  *
11  *	(C)Copyright 1998-2002 SysKonnect.
12  *	(C)Copyright 2002-2003 Marvell.
13  *
14  *	This program is free software; you can redistribute it and/or modify
15  *	it under the terms of the GNU General Public License as published by
16  *	the Free Software Foundation; either version 2 of the License, or
17  *	(at your option) any later version.
18  *
19  *	The information in this file is provided "AS IS" without warranty.
20  *
21  ******************************************************************************/
22 
23 /*
24  *	Special Interrupt handler
25  *
26  *	The following abstract should show how this module is included
27  *	in the driver path:
28  *
29  *	In the ISR of the driver the bits for frame transmission complete and
30  *	for receive complete are checked and handled by the driver itself.
31  *	The bits of the slow path mask are checked after that and then the
32  *	entry into the so-called "slow path" is prepared. It is an implementors
33  *	decision whether this is executed directly or just scheduled by
34  *	disabling the mask. In the interrupt service routine some events may be
35  *	generated, so it would be a good idea to call the EventDispatcher
36  *	right after this ISR.
37  *
38  *	The Interrupt source register of the adapter is NOT read by this module.
39  *  SO if the drivers implementor needs a while loop around the
40  *	slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
41  *	each loop entered.
42  *
43  *	However, the MAC Interrupt status registers are read in a while loop.
44  *
45  */
46 
47 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
48 static const char SysKonnectFileId[] =
49 	"@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
50 #endif
51 
52 #include "h/skdrv1st.h"		/* Driver Specific Definitions */
53 #ifndef SK_SLIM
54 #include "h/skgepnmi.h"		/* PNMI Definitions */
55 #include "h/skrlmt.h"		/* RLMT Definitions */
56 #endif
57 #include "h/skdrv2nd.h"		/* Adapter Control and Driver specific Def. */
58 
59 /* local function prototypes */
60 #ifdef GENESIS
61 static int	SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
62 static int	SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
63 static void	SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
64 #endif /* GENESIS */
65 #ifdef YUKON
66 static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
67 static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
68 #endif /* YUKON */
69 #ifdef OTHER_PHY
70 static int	SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
71 static int	SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
72 static void	SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
73 #endif /* OTHER_PHY */
74 
75 #ifdef GENESIS
76 /*
77  * array of Rx counter from XMAC which are checked
78  * in AutoSense mode to check whether a link is not able to auto-negotiate.
79  */
80 static const SK_U16 SkGeRxRegs[]= {
81 	XM_RXF_64B,
82 	XM_RXF_127B,
83 	XM_RXF_255B,
84 	XM_RXF_511B,
85 	XM_RXF_1023B,
86 	XM_RXF_MAX_SZ
87 } ;
88 #endif /* GENESIS */
89 
90 #ifdef __C2MAN__
91 /*
92  *	Special IRQ function
93  *
94  *	General Description:
95  *
96  */
intro()97 intro()
98 {}
99 #endif
100 
101 /******************************************************************************
102  *
103  *	SkHWInitDefSense() - Default Autosensing mode initialization
104  *
105  * Description: sets the PLinkMode for HWInit
106  *
107  * Returns: N/A
108  */
SkHWInitDefSense(SK_AC * pAC,SK_IOC IoC,int Port)109 static void SkHWInitDefSense(
110 SK_AC	*pAC,	/* adapter context */
111 SK_IOC	IoC,	/* IO context */
112 int		Port)	/* Port Index (MAC_1 + n) */
113 {
114 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
115 
116 	pPrt = &pAC->GIni.GP[Port];
117 
118 	pPrt->PAutoNegTimeOut = 0;
119 
120 	if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
121 		pPrt->PLinkMode = pPrt->PLinkModeConf;
122 		return;
123 	}
124 
125 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
126 		("AutoSensing: First mode %d on Port %d\n",
127 		(int)SK_LMODE_AUTOFULL, Port));
128 
129 	pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
130 
131 	return;
132 }	/* SkHWInitDefSense */
133 
134 
135 #ifdef GENESIS
136 /******************************************************************************
137  *
138  *	SkHWSenseGetNext() - Get Next Autosensing Mode
139  *
140  * Description: gets the appropriate next mode
141  *
142  * Note:
143  *
144  */
SkHWSenseGetNext(SK_AC * pAC,SK_IOC IoC,int Port)145 static SK_U8 SkHWSenseGetNext(
146 SK_AC	*pAC,	/* adapter context */
147 SK_IOC	IoC,	/* IO context */
148 int		Port)	/* Port Index (MAC_1 + n) */
149 {
150 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
151 
152 	pPrt = &pAC->GIni.GP[Port];
153 
154 	pPrt->PAutoNegTimeOut = 0;
155 
156     if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
157 		/* Leave all as configured */
158 		return(pPrt->PLinkModeConf);
159 	}
160 
161     if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
162 		/* Return next mode AUTOBOTH */
163         return ((SK_U8)SK_LMODE_AUTOBOTH);
164 	}
165 
166 	/* Return default autofull */
167     return ((SK_U8)SK_LMODE_AUTOFULL);
168 }	/* SkHWSenseGetNext */
169 
170 
171 /******************************************************************************
172  *
173  *	SkHWSenseSetNext() - Autosensing Set next mode
174  *
175  * Description:	sets the appropriate next mode
176  *
177  * Returns: N/A
178  */
SkHWSenseSetNext(SK_AC * pAC,SK_IOC IoC,int Port,SK_U8 NewMode)179 static void SkHWSenseSetNext(
180 SK_AC	*pAC,		/* adapter context */
181 SK_IOC	IoC,		/* IO context */
182 int		Port,		/* Port Index (MAC_1 + n) */
183 SK_U8	NewMode)	/* New Mode to be written in sense mode */
184 {
185 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
186 
187 	pPrt = &pAC->GIni.GP[Port];
188 
189 	pPrt->PAutoNegTimeOut = 0;
190 
191     if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
192 		return;
193 	}
194 
195 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
196 		("AutoSensing: next mode %d on Port %d\n",
197 		(int)NewMode, Port));
198 
199 	pPrt->PLinkMode = NewMode;
200 
201 	return;
202 }	/* SkHWSenseSetNext */
203 #endif /* GENESIS */
204 
205 
206 /******************************************************************************
207  *
208  *	SkHWLinkDown() - Link Down handling
209  *
210  * Description: handles the hardware link down signal
211  *
212  * Returns: N/A
213  */
SkHWLinkDown(SK_AC * pAC,SK_IOC IoC,int Port)214 void SkHWLinkDown(
215 SK_AC	*pAC,		/* adapter context */
216 SK_IOC	IoC,		/* IO context */
217 int		Port)		/* Port Index (MAC_1 + n) */
218 {
219 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
220 
221 	pPrt = &pAC->GIni.GP[Port];
222 
223 	/* Disable all MAC interrupts */
224 	SkMacIrqDisable(pAC, IoC, Port);
225 
226 	/* Disable Receiver and Transmitter */
227 	SkMacRxTxDisable(pAC, IoC, Port);
228 
229 	/* Init default sense mode */
230 	SkHWInitDefSense(pAC, IoC, Port);
231 
232 	if (pPrt->PHWLinkUp == SK_FALSE) {
233 		return;
234 	}
235 
236 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
237 		("Link down Port %d\n", Port));
238 
239 	/* Set Link to DOWN */
240 	pPrt->PHWLinkUp = SK_FALSE;
241 
242 	/* Reset Port stati */
243     pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
244     pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
245 	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
246 
247 	/* Re-init Phy especially when the AutoSense default is set now */
248 	SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
249 
250 	/* GP0: used for workaround of Rev. C Errata 2 */
251 
252 	/* Do NOT signal to RLMT */
253 
254 	/* Do NOT start the timer here */
255 }	/* SkHWLinkDown */
256 
257 
258 /******************************************************************************
259  *
260  *	SkHWLinkUp() - Link Up handling
261  *
262  * Description: handles the hardware link up signal
263  *
264  * Returns: N/A
265  */
SkHWLinkUp(SK_AC * pAC,SK_IOC IoC,int Port)266 void SkHWLinkUp(
267 SK_AC	*pAC,	/* adapter context */
268 SK_IOC	IoC,	/* IO context */
269 int		Port)	/* Port Index (MAC_1 + n) */
270 {
271 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
272 
273 	pPrt = &pAC->GIni.GP[Port];
274 
275 	if (pPrt->PHWLinkUp) {
276 		/* We do NOT need to proceed on active link */
277 		return;
278 	}
279 
280 	pPrt->PHWLinkUp = SK_TRUE;
281 	pPrt->PAutoNegFail = SK_FALSE;
282     pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
283 
284     if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
285         pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
286         pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
287 		/* Link is up and no Auto-negotiation should be done */
288 
289 		/* Link speed should be the configured one */
290 		switch (pPrt->PLinkSpeed) {
291 		case SK_LSPEED_AUTO:
292 			/* default is 1000 Mbps */
293 		case SK_LSPEED_1000MBPS:
294 			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
295 			break;
296 		case SK_LSPEED_100MBPS:
297 			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
298 			break;
299 		case SK_LSPEED_10MBPS:
300 			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
301 			break;
302 		}
303 
304 		/* Set Link Mode Status */
305 		if (pPrt->PLinkMode == SK_LMODE_FULL) {
306 			pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
307 		}
308 		else {
309             pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
310 		}
311 
312 		/* No flow control without auto-negotiation */
313         pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
314 
315 		/* enable Rx/Tx */
316         (void)SkMacRxTxEnable(pAC, IoC, Port);
317 	}
318 }	/* SkHWLinkUp */
319 
320 
321 /******************************************************************************
322  *
323  *	SkMacParity() - MAC parity workaround
324  *
325  * Description: handles MAC parity errors correctly
326  *
327  * Returns: N/A
328  */
SkMacParity(SK_AC * pAC,SK_IOC IoC,int Port)329 static void SkMacParity(
330 SK_AC	*pAC,	/* adapter context */
331 SK_IOC	IoC,	/* IO context */
332 int		Port)	/* Port Index of the port failed */
333 {
334 	SK_EVPARA	Para;
335 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
336 	SK_U32		TxMax;		/* Tx Max Size Counter */
337 
338 	pPrt = &pAC->GIni.GP[Port];
339 
340 	/* Clear IRQ Tx Parity Error */
341 #ifdef GENESIS
342 	if (pAC->GIni.GIGenesis) {
343 
344 		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
345 	}
346 #endif /* GENESIS */
347 
348 #ifdef YUKON
349 	if (pAC->GIni.GIYukon) {
350 		/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
351 		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
352 			(SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
353 			pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
354 	}
355 #endif /* YUKON */
356 
357 	if (pPrt->PCheckPar) {
358 
359 		if (Port == MAC_1) {
360 			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
361 		}
362 		else {
363 			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
364 		}
365 		Para.Para64 = Port;
366 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
367 
368 		Para.Para32[0] = Port;
369 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
370 
371 		return;
372 	}
373 
374 	/* Check whether frames with a size of 1k were sent */
375 #ifdef GENESIS
376 	if (pAC->GIni.GIGenesis) {
377 		/* Snap statistic counters */
378 		(void)SkXmUpdateStats(pAC, IoC, Port);
379 
380 		(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
381 	}
382 #endif /* GENESIS */
383 
384 #ifdef YUKON
385 	if (pAC->GIni.GIYukon) {
386 
387 		(void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
388 	}
389 #endif /* YUKON */
390 
391 	if (TxMax > 0) {
392 		/* From now on check the parity */
393 		pPrt->PCheckPar = SK_TRUE;
394 	}
395 }	/* SkMacParity */
396 
397 
398 /******************************************************************************
399  *
400  *	SkGeHwErr() - Hardware Error service routine
401  *
402  * Description: handles all HW Error interrupts
403  *
404  * Returns: N/A
405  */
SkGeHwErr(SK_AC * pAC,SK_IOC IoC,SK_U32 HwStatus)406 static void SkGeHwErr(
407 SK_AC	*pAC,		/* adapter context */
408 SK_IOC	IoC,		/* IO context */
409 SK_U32	HwStatus)	/* Interrupt status word */
410 {
411 	SK_EVPARA	Para;
412 	SK_U16		Word;
413 
414 	if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
415 		/* PCI Errors occured */
416 		if ((HwStatus & IS_IRQ_STAT) != 0) {
417 			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
418 		}
419 		else {
420 			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
421 		}
422 
423 		/* Reset all bits in the PCI STATUS register */
424 		SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
425 
426 		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
427         SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
428 		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
429 
430 		Para.Para64 = 0;
431 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
432 	}
433 
434 #ifdef GENESIS
435 	if (pAC->GIni.GIGenesis) {
436 
437 		if ((HwStatus & IS_NO_STAT_M1) != 0) {
438 			/* Ignore it */
439 			/* This situation is also indicated in the descriptor */
440 			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
441 		}
442 
443 		if ((HwStatus & IS_NO_STAT_M2) != 0) {
444 			/* Ignore it */
445 			/* This situation is also indicated in the descriptor */
446 			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
447 		}
448 
449 		if ((HwStatus & IS_NO_TIST_M1) != 0) {
450 			/* Ignore it */
451 			/* This situation is also indicated in the descriptor */
452 			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
453 		}
454 
455 		if ((HwStatus & IS_NO_TIST_M2) != 0) {
456 			/* Ignore it */
457 			/* This situation is also indicated in the descriptor */
458 			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
459 		}
460 	}
461 #endif /* GENESIS */
462 
463 #ifdef YUKON
464 	if (pAC->GIni.GIYukon) {
465 		/* This is necessary only for Rx timing measurements */
466 		if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
467 			/* increment Time Stamp Timer counter (high) */
468 			pAC->GIni.GITimeStampCnt++;
469 
470 			/* Clear Time Stamp Timer IRQ */
471 			SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
472 		}
473 
474 		if ((HwStatus & IS_IRQ_SENSOR) != 0) {
475 			/* no sensors on 32-bit Yukon */
476 			if (pAC->GIni.GIYukon32Bit) {
477 				/* disable HW Error IRQ */
478 				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
479 			}
480 		}
481 	}
482 #endif /* YUKON */
483 
484 	if ((HwStatus & IS_RAM_RD_PAR) != 0) {
485 		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
486 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
487 		Para.Para64 = 0;
488 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
489 	}
490 
491 	if ((HwStatus & IS_RAM_WR_PAR) != 0) {
492 		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
493 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
494 		Para.Para64 = 0;
495 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
496 	}
497 
498 	if ((HwStatus & IS_M1_PAR_ERR) != 0) {
499 		SkMacParity(pAC, IoC, MAC_1);
500 	}
501 
502 	if ((HwStatus & IS_M2_PAR_ERR) != 0) {
503 		SkMacParity(pAC, IoC, MAC_2);
504 	}
505 
506 	if ((HwStatus & IS_R1_PAR_ERR) != 0) {
507 		/* Clear IRQ */
508 		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
509 
510 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
511 		Para.Para64 = MAC_1;
512 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
513 
514 		Para.Para32[0] = MAC_1;
515 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
516 	}
517 
518 	if ((HwStatus & IS_R2_PAR_ERR) != 0) {
519 		/* Clear IRQ */
520 		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
521 
522 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
523 		Para.Para64 = MAC_2;
524 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
525 
526 		Para.Para32[0] = MAC_2;
527 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
528 	}
529 }	/* SkGeHwErr */
530 
531 
532 /******************************************************************************
533  *
534  *	SkGeSirqIsr() - Special Interrupt Service Routine
535  *
536  * Description: handles all non data transfer specific interrupts (slow path)
537  *
538  * Returns: N/A
539  */
SkGeSirqIsr(SK_AC * pAC,SK_IOC IoC,SK_U32 Istatus)540 void SkGeSirqIsr(
541 SK_AC	*pAC,		/* adapter context */
542 SK_IOC	IoC,		/* IO context */
543 SK_U32	Istatus)	/* Interrupt status word */
544 {
545 	SK_EVPARA	Para;
546 	SK_U32		RegVal32;	/* Read register value */
547 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
548 	SK_U16 		PhyInt;
549 	int			i;
550 
551 	if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
552 		/* read the HW Error Interrupt source */
553 		SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
554 
555 		SkGeHwErr(pAC, IoC, RegVal32);
556 	}
557 
558 	/*
559 	 * Packet Timeout interrupts
560 	 */
561 	/* Check whether MACs are correctly initialized */
562 	if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
563 		pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
564 		/* MAC 1 was not initialized but Packet timeout occured */
565 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
566 			SKERR_SIRQ_E004MSG);
567 	}
568 
569 	if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
570 	    pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
571 		/* MAC 2 was not initialized but Packet timeout occured */
572 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
573 			SKERR_SIRQ_E005MSG);
574 	}
575 
576 	if ((Istatus & IS_PA_TO_RX1) != 0) {
577 		/* Means network is filling us up */
578 		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
579 			SKERR_SIRQ_E002MSG);
580 		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
581 	}
582 
583 	if ((Istatus & IS_PA_TO_RX2) != 0) {
584 		/* Means network is filling us up */
585 		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
586 			SKERR_SIRQ_E003MSG);
587 		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
588 	}
589 
590 	if ((Istatus & IS_PA_TO_TX1) != 0) {
591 
592 		pPrt = &pAC->GIni.GP[0];
593 
594 		/* May be a normal situation in a server with a slow network */
595 		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
596 
597 #ifdef GENESIS
598 		if (pAC->GIni.GIGenesis) {
599 			/*
600 			 * workaround: if in half duplex mode, check for Tx hangup.
601 			 * Read number of TX'ed bytes, wait for 10 ms, then compare
602 			 * the number with current value. If nothing changed, we assume
603 			 * that Tx is hanging and do a FIFO flush (see event routine).
604 			 */
605 			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
606 				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
607 				!pPrt->HalfDupTimerActive) {
608 				/*
609 				 * many more pack. arb. timeouts may come in between,
610 				 * we ignore those
611 				 */
612 				pPrt->HalfDupTimerActive = SK_TRUE;
613 #ifdef XXX
614 				Len = sizeof(SK_U64);
615 				SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
616 					&Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 0),
617 					pAC->Rlmt.Port[0].Net->NetNumber);
618 
619 				pPrt->LastOctets = Octets;
620 #endif /* XXX */
621 				/* Snap statistic counters */
622 				(void)SkXmUpdateStats(pAC, IoC, 0);
623 
624 				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
625 
626 				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
627 
628 				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
629 
630 				pPrt->LastOctets += RegVal32;
631 
632 				Para.Para32[0] = 0;
633 				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
634 					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
635 			}
636 		}
637 #endif /* GENESIS */
638 	}
639 
640 	if ((Istatus & IS_PA_TO_TX2) != 0) {
641 
642 		pPrt = &pAC->GIni.GP[1];
643 
644 		/* May be a normal situation in a server with a slow network */
645 		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
646 
647 #ifdef GENESIS
648 		if (pAC->GIni.GIGenesis) {
649 			/* workaround: see above */
650 			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
651 				 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
652 				!pPrt->HalfDupTimerActive) {
653 				pPrt->HalfDupTimerActive = SK_TRUE;
654 #ifdef XXX
655 				Len = sizeof(SK_U64);
656 				SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
657 					&Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 1),
658 					pAC->Rlmt.Port[1].Net->NetNumber);
659 
660 				pPrt->LastOctets = Octets;
661 #endif /* XXX */
662 				/* Snap statistic counters */
663 				(void)SkXmUpdateStats(pAC, IoC, 1);
664 
665 				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
666 
667 				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
668 
669 				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
670 
671 				pPrt->LastOctets += RegVal32;
672 
673 				Para.Para32[0] = 1;
674 				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
675 					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
676 			}
677 		}
678 #endif /* GENESIS */
679 	}
680 
681 	/* Check interrupts of the particular queues */
682 	if ((Istatus & IS_R1_C) != 0) {
683 		/* Clear IRQ */
684 		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
685 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
686 			SKERR_SIRQ_E006MSG);
687 		Para.Para64 = MAC_1;
688 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
689 		Para.Para32[0] = MAC_1;
690 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
691 	}
692 
693 	if ((Istatus & IS_R2_C) != 0) {
694 		/* Clear IRQ */
695 		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
696 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
697 			SKERR_SIRQ_E007MSG);
698 		Para.Para64 = MAC_2;
699 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
700 		Para.Para32[0] = MAC_2;
701 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
702 	}
703 
704 	if ((Istatus & IS_XS1_C) != 0) {
705 		/* Clear IRQ */
706 		SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
707 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
708 			SKERR_SIRQ_E008MSG);
709 		Para.Para64 = MAC_1;
710 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
711 		Para.Para32[0] = MAC_1;
712 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
713 	}
714 
715 	if ((Istatus & IS_XA1_C) != 0) {
716 		/* Clear IRQ */
717 		SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
718 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
719 			SKERR_SIRQ_E009MSG);
720 		Para.Para64 = MAC_1;
721 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
722 		Para.Para32[0] = MAC_1;
723 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
724 	}
725 
726 	if ((Istatus & IS_XS2_C) != 0) {
727 		/* Clear IRQ */
728 		SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
729 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
730 			SKERR_SIRQ_E010MSG);
731 		Para.Para64 = MAC_2;
732 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
733 		Para.Para32[0] = MAC_2;
734 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
735 	}
736 
737 	if ((Istatus & IS_XA2_C) != 0) {
738 		/* Clear IRQ */
739 		SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
740 		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
741 			SKERR_SIRQ_E011MSG);
742 		Para.Para64 = MAC_2;
743 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
744 		Para.Para32[0] = MAC_2;
745 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
746 	}
747 
748 	/* External reg interrupt */
749 	if ((Istatus & IS_EXT_REG) != 0) {
750 		/* Test IRQs from PHY */
751 		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
752 
753 			pPrt = &pAC->GIni.GP[i];
754 
755 			if (pPrt->PState == SK_PRT_RESET) {
756 				continue;
757 			}
758 
759 #ifdef GENESIS
760 			if (pAC->GIni.GIGenesis) {
761 
762 				switch (pPrt->PhyType) {
763 
764 				case SK_PHY_XMAC:
765 					break;
766 
767 				case SK_PHY_BCOM:
768 					SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
769 
770 					if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
771 						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
772 							("Port %d Bcom Int: 0x%04X\n",
773 							i, PhyInt));
774 						SkPhyIsrBcom(pAC, IoC, i, PhyInt);
775 					}
776 					break;
777 #ifdef OTHER_PHY
778 				case SK_PHY_LONE:
779 					SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
780 
781 					if ((PhyInt & PHY_L_DEF_MSK) != 0) {
782 						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
783 							("Port %d Lone Int: %x\n",
784 							i, PhyInt));
785 						SkPhyIsrLone(pAC, IoC, i, PhyInt);
786 					}
787 					break;
788 #endif /* OTHER_PHY */
789 				}
790 			}
791 #endif /* GENESIS */
792 
793 #ifdef YUKON
794 			if (pAC->GIni.GIYukon) {
795 				/* Read PHY Interrupt Status */
796 				SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
797 
798 				if ((PhyInt & PHY_M_DEF_MSK) != 0) {
799 					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
800 						("Port %d Marv Int: 0x%04X\n",
801 						i, PhyInt));
802 					SkPhyIsrGmac(pAC, IoC, i, PhyInt);
803 				}
804 			}
805 #endif /* YUKON */
806 		}
807 	}
808 
809 	/* I2C Ready interrupt */
810 	if ((Istatus & IS_I2C_READY) != 0) {
811 #ifdef SK_SLIM
812         SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
813 #else
814 		SkI2cIsr(pAC, IoC);
815 #endif
816 	}
817 
818 	/* SW forced interrupt */
819 	if ((Istatus & IS_IRQ_SW) != 0) {
820 		/* clear the software IRQ */
821 		SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
822 	}
823 
824 	if ((Istatus & IS_LNK_SYNC_M1) != 0) {
825 		/*
826 		 * We do NOT need the Link Sync interrupt, because it shows
827 		 * us only a link going down.
828 		 */
829 		/* clear interrupt */
830 		SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
831 	}
832 
833 	/* Check MAC after link sync counter */
834 	if ((Istatus & IS_MAC1) != 0) {
835 		/* IRQ from MAC 1 */
836 		SkMacIrq(pAC, IoC, MAC_1);
837 	}
838 
839 	if ((Istatus & IS_LNK_SYNC_M2) != 0) {
840 		/*
841 		 * We do NOT need the Link Sync interrupt, because it shows
842 		 * us only a link going down.
843 		 */
844 		/* clear interrupt */
845 		SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
846 	}
847 
848 	/* Check MAC after link sync counter */
849 	if ((Istatus & IS_MAC2) != 0) {
850 		/* IRQ from MAC 2 */
851 		SkMacIrq(pAC, IoC, MAC_2);
852 	}
853 
854 	/* Timer interrupt (served last) */
855 	if ((Istatus & IS_TIMINT) != 0) {
856 		/* check for HW Errors */
857 		if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
858 			/* read the HW Error Interrupt source */
859 			SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
860 
861 			SkGeHwErr(pAC, IoC, RegVal32);
862 		}
863 
864 		SkHwtIsr(pAC, IoC);
865 	}
866 
867 }	/* SkGeSirqIsr */
868 
869 
870 #ifdef GENESIS
871 /******************************************************************************
872  *
873  * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
874  *
875  * return:
876  *	0	o.k. nothing needed
877  *	1	Restart needed on this port
878  */
SkGePortCheckShorts(SK_AC * pAC,SK_IOC IoC,int Port)879 static int SkGePortCheckShorts(
880 SK_AC	*pAC,		/* Adapter Context */
881 SK_IOC	IoC,		/* IO Context */
882 int		Port)		/* Which port should be checked */
883 {
884 	SK_U32		Shorts;			/* Short Event Counter */
885 	SK_U32		CheckShorts;	/* Check value for Short Event Counter */
886 	SK_U64		RxCts;			/* Rx Counter (packets on network) */
887 	SK_U32		RxTmp;			/* Rx temp. Counter */
888 	SK_U32		FcsErrCts;		/* FCS Error Counter */
889 	SK_GEPORT	*pPrt;			/* GIni Port struct pointer */
890 	int			Rtv;			/* Return value */
891 	int			i;
892 
893 	pPrt = &pAC->GIni.GP[Port];
894 
895 	/* Default: no action */
896 	Rtv = SK_HW_PS_NONE;
897 
898 	(void)SkXmUpdateStats(pAC, IoC, Port);
899 
900 	/* Extra precaution: check for short Event counter */
901 	(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
902 
903 	/*
904 	 * Read Rx counters (packets seen on the network and not necessarily
905 	 * really received.
906 	 */
907 	RxCts = 0;
908 
909 	for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
910 
911 		(void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
912 
913 		RxCts += (SK_U64)RxTmp;
914 	}
915 
916 	/* On default: check shorts against zero */
917 	CheckShorts = 0;
918 
919 	/* Extra precaution on active links */
920 	if (pPrt->PHWLinkUp) {
921 		/* Reset Link Restart counter */
922 		pPrt->PLinkResCt = 0;
923 		pPrt->PAutoNegTOCt = 0;
924 
925 		/* If link is up check for 2 */
926 		CheckShorts = 2;
927 
928 		(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
929 
930 		if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
931 		    pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
932 		    (pPrt->PLinkMode == SK_LMODE_HALF ||
933 			 pPrt->PLinkMode == SK_LMODE_FULL)) {
934 			/*
935 			 * This is autosensing and we are in the fallback
936 			 * manual full/half duplex mode.
937 			 */
938 			if (RxCts == pPrt->PPrevRx) {
939 				/* Nothing received, restart link */
940 				pPrt->PPrevFcs = FcsErrCts;
941 				pPrt->PPrevShorts = Shorts;
942 
943 				return(SK_HW_PS_RESTART);
944 			}
945 			else {
946 				pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
947 			}
948 		}
949 
950 		if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
951 		    (!(FcsErrCts - pPrt->PPrevFcs))) {
952 			/*
953 			 * Note: The compare with zero above has to be done the way shown,
954 			 * otherwise the Linux driver will have a problem.
955 			 */
956 			/*
957 			 * We received a bunch of frames or no CRC error occured on the
958 			 * network -> ok.
959 			 */
960 			pPrt->PPrevRx = RxCts;
961 			pPrt->PPrevFcs = FcsErrCts;
962 			pPrt->PPrevShorts = Shorts;
963 
964 			return(SK_HW_PS_NONE);
965 		}
966 
967 		pPrt->PPrevFcs = FcsErrCts;
968 	}
969 
970 
971 	if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
972 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
973 			("Short Event Count Restart Port %d \n", Port));
974 		Rtv = SK_HW_PS_RESTART;
975 	}
976 
977 	pPrt->PPrevShorts = Shorts;
978 	pPrt->PPrevRx = RxCts;
979 
980 	return(Rtv);
981 }	/* SkGePortCheckShorts */
982 #endif /* GENESIS */
983 
984 
985 /******************************************************************************
986  *
987  * SkGePortCheckUp() - Check if the link is up
988  *
989  * return:
990  *	0	o.k. nothing needed
991  *	1	Restart needed on this port
992  *	2	Link came up
993  */
SkGePortCheckUp(SK_AC * pAC,SK_IOC IoC,int Port)994 static int SkGePortCheckUp(
995 SK_AC	*pAC,		/* Adapter Context */
996 SK_IOC	IoC,		/* IO Context */
997 int		Port)		/* Which port should be checked */
998 {
999 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
1000 	SK_BOOL		AutoNeg;	/* Is Auto-negotiation used ? */
1001 	int			Rtv;		/* Return value */
1002 
1003 	Rtv = SK_HW_PS_NONE;
1004 
1005 	pPrt = &pAC->GIni.GP[Port];
1006 
1007 	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1008 		AutoNeg = SK_FALSE;
1009 	}
1010 	else {
1011 		AutoNeg = SK_TRUE;
1012 	}
1013 
1014 #ifdef GENESIS
1015 	if (pAC->GIni.GIGenesis) {
1016 
1017 		switch (pPrt->PhyType) {
1018 
1019 		case SK_PHY_XMAC:
1020 			Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
1021 			break;
1022 		case SK_PHY_BCOM:
1023 			Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
1024 			break;
1025 #ifdef OTHER_PHY
1026 		case SK_PHY_LONE:
1027 			Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
1028 			break;
1029 		case SK_PHY_NAT:
1030 			Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
1031 			break;
1032 #endif /* OTHER_PHY */
1033 		}
1034 	}
1035 #endif /* GENESIS */
1036 
1037 #ifdef YUKON
1038 	if (pAC->GIni.GIYukon) {
1039 
1040 		Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
1041 	}
1042 #endif /* YUKON */
1043 
1044 	return(Rtv);
1045 }	/* SkGePortCheckUp */
1046 
1047 
1048 #ifdef GENESIS
1049 /******************************************************************************
1050  *
1051  * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1052  *
1053  * return:
1054  *	0	o.k. nothing needed
1055  *	1	Restart needed on this port
1056  *	2	Link came up
1057  */
SkGePortCheckUpXmac(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL AutoNeg)1058 static int SkGePortCheckUpXmac(
1059 SK_AC	*pAC,		/* Adapter Context */
1060 SK_IOC	IoC,		/* IO Context */
1061 int		Port,		/* Which port should be checked */
1062 SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
1063 {
1064 	SK_U32		Shorts;		/* Short Event Counter */
1065 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
1066 	int			Done;
1067 	SK_U32		GpReg;		/* General Purpose register value */
1068 	SK_U16		Isrc;		/* Interrupt source register */
1069 	SK_U16		IsrcSum;	/* Interrupt source register sum */
1070 	SK_U16		LpAb;		/* Link Partner Ability */
1071 	SK_U16		ResAb;		/* Resolved Ability */
1072 	SK_U16		ExtStat;	/* Extended Status Register */
1073 	SK_U8		NextMode;	/* Next AutoSensing Mode */
1074 
1075 	pPrt = &pAC->GIni.GP[Port];
1076 
1077 	if (pPrt->PHWLinkUp) {
1078 		if (pPrt->PhyType != SK_PHY_XMAC) {
1079 			return(SK_HW_PS_NONE);
1080 		}
1081 		else {
1082 			return(SkGePortCheckShorts(pAC, IoC, Port));
1083 		}
1084 	}
1085 
1086 	IsrcSum = pPrt->PIsave;
1087 	pPrt->PIsave = 0;
1088 
1089 	/* Now wait for each port's link */
1090 	if (pPrt->PLinkBroken) {
1091 		/* Link was broken */
1092 		XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1093 
1094 		if ((GpReg & XM_GP_INP_ASS) == 0) {
1095 			/* The Link is in sync */
1096 			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1097 			IsrcSum |= Isrc;
1098 			SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1099 
1100 			if ((Isrc & XM_IS_INP_ASS) == 0) {
1101 				/* It has been in sync since last time */
1102 				/* Restart the PORT */
1103 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1104 					("Link in sync Restart Port %d\n", Port));
1105 
1106 				(void)SkXmUpdateStats(pAC, IoC, Port);
1107 
1108 				/* We now need to reinitialize the PrevShorts counter */
1109 				(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
1110 				pPrt->PPrevShorts = Shorts;
1111 
1112 				pPrt->PLinkBroken = SK_FALSE;
1113 
1114 				/*
1115 				 * Link Restart Workaround:
1116 				 *  it may be possible that the other Link side
1117 				 *  restarts its link as well an we detect
1118 				 *  another LinkBroken. To prevent this
1119 				 *  happening we check for a maximum number
1120 				 *  of consecutive restart. If those happens,
1121 				 *  we do NOT restart the active link and
1122 				 *  check whether the link is now o.k.
1123 				 */
1124 				pPrt->PLinkResCt++;
1125 
1126 				pPrt->PAutoNegTimeOut = 0;
1127 
1128 				if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
1129 					return(SK_HW_PS_RESTART);
1130 				}
1131 
1132 				pPrt->PLinkResCt = 0;
1133 
1134 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1135 					("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
1136 			}
1137 			else {
1138 				pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1139 
1140 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1141 					("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
1142 
1143 				/* Do nothing more if link is broken */
1144 				return(SK_HW_PS_NONE);
1145 			}
1146 		}
1147 		else {
1148 			/* Do nothing more if link is broken */
1149 			return(SK_HW_PS_NONE);
1150 		}
1151 
1152 	}
1153 	else {
1154 		/* Link was not broken, check if it is */
1155 		XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1156 		IsrcSum |= Isrc;
1157 		if ((Isrc & XM_IS_INP_ASS) != 0) {
1158 			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1159 			IsrcSum |= Isrc;
1160 			if ((Isrc & XM_IS_INP_ASS) != 0) {
1161 				XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1162 				IsrcSum |= Isrc;
1163 				if ((Isrc & XM_IS_INP_ASS) != 0) {
1164 					pPrt->PLinkBroken = SK_TRUE;
1165 					/* Re-Init Link partner Autoneg flag */
1166 					pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1167 					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1168 						("Link broken Port %d\n", Port));
1169 
1170 					/* Cable removed-> reinit sense mode */
1171 					SkHWInitDefSense(pAC, IoC, Port);
1172 
1173 					return(SK_HW_PS_RESTART);
1174 				}
1175 			}
1176 		}
1177 		else {
1178 			SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
1179 
1180 			if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
1181 				return(SK_HW_PS_RESTART);
1182 			}
1183 		}
1184 	}
1185 
1186 	/*
1187 	 * here we usually can check whether the link is in sync and
1188 	 * auto-negotiation is done.
1189 	 */
1190 	XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1191 	XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1192 	IsrcSum |= Isrc;
1193 
1194 	SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1195 
1196 	if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
1197 		if ((GpReg & XM_GP_INP_ASS) == 0) {
1198 			/* Save Auto-negotiation Done interrupt only if link is in sync */
1199 			pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1200 		}
1201 #ifdef DEBUG
1202 		if ((pPrt->PIsave & XM_IS_AND) != 0) {
1203 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1204 				("AutoNeg done rescheduled Port %d\n", Port));
1205 		}
1206 #endif /* DEBUG */
1207 		return(SK_HW_PS_NONE);
1208 	}
1209 
1210 	if (AutoNeg) {
1211 		if ((IsrcSum & XM_IS_AND) != 0) {
1212 			SkHWLinkUp(pAC, IoC, Port);
1213 			Done = SkMacAutoNegDone(pAC, IoC, Port);
1214 			if (Done != SK_AND_OK) {
1215 				/* Get PHY parameters, for debugging only */
1216 				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
1217 				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
1218 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1219 					("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
1220 					 Port, LpAb, ResAb));
1221 
1222 				/* Try next possible mode */
1223 				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1224 				SkHWLinkDown(pAC, IoC, Port);
1225 				if (Done == SK_AND_DUP_CAP) {
1226 					/* GoTo next mode */
1227 					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1228 				}
1229 
1230 				return(SK_HW_PS_RESTART);
1231 			}
1232 			/*
1233 			 * Dummy Read extended status to prevent extra link down/ups
1234 			 * (clear Page Received bit if set)
1235 			 */
1236 			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
1237 
1238 			return(SK_HW_PS_LINK);
1239 		}
1240 
1241 		/* AutoNeg not done, but HW link is up. Check for timeouts */
1242 		pPrt->PAutoNegTimeOut++;
1243 		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1244 			/* Increase the Timeout counter */
1245 			pPrt->PAutoNegTOCt++;
1246 
1247 			/* Timeout occured */
1248 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1249 				("AutoNeg timeout Port %d\n", Port));
1250 			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1251 				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1252 				/* Set Link manually up */
1253 				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1254 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1255 					("Set manual full duplex Port %d\n", Port));
1256 			}
1257 
1258 			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1259 				pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
1260 				pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
1261 				/*
1262 				 * This is rather complicated.
1263 				 * we need to check here whether the LIPA_AUTO
1264 				 * we saw before is false alert. We saw at one
1265 				 * switch ( SR8800) that on boot time it sends
1266 				 * just one auto-neg packet and does no further
1267 				 * auto-negotiation.
1268 				 * Solution: we restart the autosensing after
1269 				 * a few timeouts.
1270 				 */
1271 				pPrt->PAutoNegTOCt = 0;
1272 				pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1273 				SkHWInitDefSense(pAC, IoC, Port);
1274 			}
1275 
1276 			/* Do the restart */
1277 			return(SK_HW_PS_RESTART);
1278 		}
1279 	}
1280 	else {
1281 		/* Link is up and we don't need more */
1282 #ifdef DEBUG
1283 		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1284 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1285 				("ERROR: Lipa auto detected on port %d\n", Port));
1286 		}
1287 #endif /* DEBUG */
1288 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1289 			("Link sync(GP), Port %d\n", Port));
1290 		SkHWLinkUp(pAC, IoC, Port);
1291 
1292 		/*
1293 		 * Link sync (GP) and so assume a good connection. But if not received
1294 		 * a bunch of frames received in a time slot (maybe broken tx cable)
1295 		 * the port is restart.
1296 		 */
1297 		return(SK_HW_PS_LINK);
1298 	}
1299 
1300 	return(SK_HW_PS_NONE);
1301 }	/* SkGePortCheckUpXmac */
1302 
1303 
1304 /******************************************************************************
1305  *
1306  * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
1307  *
1308  * return:
1309  *	0	o.k. nothing needed
1310  *	1	Restart needed on this port
1311  *	2	Link came up
1312  */
SkGePortCheckUpBcom(SK_AC * pAC,SK_IOC IoC,int Port,SK_BOOL AutoNeg)1313 static int SkGePortCheckUpBcom(
1314 SK_AC	*pAC,		/* Adapter Context */
1315 SK_IOC	IoC,		/* IO Context */
1316 int		Port,		/* Which port should be checked */
1317 SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
1318 {
1319 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
1320 	int			Done;
1321 	SK_U16		Isrc;		/* Interrupt source register */
1322 	SK_U16		PhyStat;	/* Phy Status Register */
1323 	SK_U16		ResAb;		/* Master/Slave resolution */
1324 	SK_U16		Ctrl;		/* Broadcom control flags */
1325 #ifdef DEBUG
1326 	SK_U16		LpAb;
1327 	SK_U16		ExtStat;
1328 #endif /* DEBUG */
1329 
1330 	pPrt = &pAC->GIni.GP[Port];
1331 
1332 	/* Check for No HCD Link events (#10523) */
1333 	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
1334 
1335 #ifdef xDEBUG
1336 	if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) ==
1337 		(PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
1338 
1339 		SK_U32	Stat1, Stat2, Stat3;
1340 
1341 		Stat1 = 0;
1342 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1343 		CMSMPrintString(
1344 			pAC->pConfigTable,
1345 			MSG_TYPE_RUNTIME_INFO,
1346 			"CheckUp1 - Stat: %x, Mask: %x",
1347 			(void *)Isrc,
1348 			(void *)Stat1);
1349 
1350 		Stat1 = 0;
1351 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1352 		Stat2 = 0;
1353 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
1354 		Stat1 = Stat1 << 16 | Stat2;
1355 		Stat2 = 0;
1356 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1357 		Stat3 = 0;
1358 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1359 		Stat2 = Stat2 << 16 | Stat3;
1360 		CMSMPrintString(
1361 			pAC->pConfigTable,
1362 			MSG_TYPE_RUNTIME_INFO,
1363 			"Ctrl/Stat: %x, AN Adv/LP: %x",
1364 			(void *)Stat1,
1365 			(void *)Stat2);
1366 
1367 		Stat1 = 0;
1368 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1369 		Stat2 = 0;
1370 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1371 		Stat1 = Stat1 << 16 | Stat2;
1372 		Stat2 = 0;
1373 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1374 		Stat3 = 0;
1375 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
1376 		Stat2 = Stat2 << 16 | Stat3;
1377 		CMSMPrintString(
1378 			pAC->pConfigTable,
1379 			MSG_TYPE_RUNTIME_INFO,
1380 			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1381 			(void *)Stat1,
1382 			(void *)Stat2);
1383 
1384 		Stat1 = 0;
1385 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1386 		Stat2 = 0;
1387 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1388 		Stat1 = Stat1 << 16 | Stat2;
1389 		Stat2 = 0;
1390 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1391 		Stat3 = 0;
1392 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1393 		Stat2 = Stat2 << 16 | Stat3;
1394 		CMSMPrintString(
1395 			pAC->pConfigTable,
1396 			MSG_TYPE_RUNTIME_INFO,
1397 			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1398 			(void *)Stat1,
1399 			(void *)Stat2);
1400 	}
1401 #endif /* DEBUG */
1402 
1403 	if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
1404 		/*
1405 		 * Workaround BCom Errata:
1406 		 *	enable and disable loopback mode if "NO HCD" occurs.
1407 		 */
1408 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
1409 		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1410 			(SK_U16)(Ctrl | PHY_CT_LOOP));
1411 		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1412 			(SK_U16)(Ctrl & ~PHY_CT_LOOP));
1413 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1414 			("No HCD Link event, Port %d\n", Port));
1415 #ifdef xDEBUG
1416 		CMSMPrintString(
1417 			pAC->pConfigTable,
1418 			MSG_TYPE_RUNTIME_INFO,
1419 			"No HCD link event, port %d.",
1420 			(void *)Port,
1421 			(void *)NULL);
1422 #endif /* DEBUG */
1423 	}
1424 
1425 	/* Not obsolete: link status bit is latched to 0 and autoclearing! */
1426 	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1427 
1428 	if (pPrt->PHWLinkUp) {
1429 		return(SK_HW_PS_NONE);
1430 	}
1431 
1432 #ifdef xDEBUG
1433 	{
1434 		SK_U32	Stat1, Stat2, Stat3;
1435 
1436 		Stat1 = 0;
1437 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1438 		CMSMPrintString(
1439 			pAC->pConfigTable,
1440 			MSG_TYPE_RUNTIME_INFO,
1441 			"CheckUp1a - Stat: %x, Mask: %x",
1442 			(void *)Isrc,
1443 			(void *)Stat1);
1444 
1445 		Stat1 = 0;
1446 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1447 		Stat2 = 0;
1448 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1449 		Stat1 = Stat1 << 16 | PhyStat;
1450 		Stat2 = 0;
1451 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1452 		Stat3 = 0;
1453 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1454 		Stat2 = Stat2 << 16 | Stat3;
1455 		CMSMPrintString(
1456 			pAC->pConfigTable,
1457 			MSG_TYPE_RUNTIME_INFO,
1458 			"Ctrl/Stat: %x, AN Adv/LP: %x",
1459 			(void *)Stat1,
1460 			(void *)Stat2);
1461 
1462 		Stat1 = 0;
1463 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1464 		Stat2 = 0;
1465 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1466 		Stat1 = Stat1 << 16 | Stat2;
1467 		Stat2 = 0;
1468 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1469 		Stat3 = 0;
1470 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1471 		Stat2 = Stat2 << 16 | ResAb;
1472 		CMSMPrintString(
1473 			pAC->pConfigTable,
1474 			MSG_TYPE_RUNTIME_INFO,
1475 			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1476 			(void *)Stat1,
1477 			(void *)Stat2);
1478 
1479 		Stat1 = 0;
1480 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1481 		Stat2 = 0;
1482 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1483 		Stat1 = Stat1 << 16 | Stat2;
1484 		Stat2 = 0;
1485 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1486 		Stat3 = 0;
1487 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1488 		Stat2 = Stat2 << 16 | Stat3;
1489 		CMSMPrintString(
1490 			pAC->pConfigTable,
1491 			MSG_TYPE_RUNTIME_INFO,
1492 			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1493 			(void *)Stat1,
1494 			(void *)Stat2);
1495 	}
1496 #endif /* DEBUG */
1497 
1498 	/*
1499 	 * Here we usually can check whether the link is in sync and
1500 	 * auto-negotiation is done.
1501 	 */
1502 
1503 	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1504 
1505 	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1506 
1507 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1508 		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1509 
1510 	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1511 
1512 	if ((ResAb & PHY_B_1000S_MSF) != 0) {
1513 		/* Error */
1514 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1515 			("Master/Slave Fault port %d\n", Port));
1516 
1517 		pPrt->PAutoNegFail = SK_TRUE;
1518 		pPrt->PMSStatus = SK_MS_STAT_FAULT;
1519 
1520 		return(SK_HW_PS_RESTART);
1521 	}
1522 
1523 	if ((PhyStat & PHY_ST_LSYNC) == 0) {
1524 		return(SK_HW_PS_NONE);
1525 	}
1526 
1527 	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1528 		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1529 
1530 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1531 		("Port %d, ResAb: 0x%04X\n", Port, ResAb));
1532 
1533 	if (AutoNeg) {
1534 		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1535 
1536 			SkHWLinkUp(pAC, IoC, Port);
1537 
1538 			Done = SkMacAutoNegDone(pAC, IoC, Port);
1539 
1540 			if (Done != SK_AND_OK) {
1541 #ifdef DEBUG
1542 				/* Get PHY parameters, for debugging only */
1543 				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
1544 				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
1545 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1546 					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1547 					Port, LpAb, ExtStat));
1548 #endif /* DEBUG */
1549 				return(SK_HW_PS_RESTART);
1550 			}
1551 			else {
1552 #ifdef xDEBUG
1553 				/* Dummy read ISR to prevent extra link downs/ups */
1554 				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1555 
1556 				if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1557 					CMSMPrintString(
1558 						pAC->pConfigTable,
1559 						MSG_TYPE_RUNTIME_INFO,
1560 						"CheckUp2 - Stat: %x",
1561 						(void *)ExtStat,
1562 						(void *)NULL);
1563 				}
1564 #endif /* DEBUG */
1565 				return(SK_HW_PS_LINK);
1566 			}
1567 		}
1568 	}
1569 	else {	/* !AutoNeg */
1570 		/* Link is up and we don't need more. */
1571 #ifdef DEBUG
1572 		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1573 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1574 				("ERROR: Lipa auto detected on port %d\n", Port));
1575 		}
1576 #endif /* DEBUG */
1577 
1578 #ifdef xDEBUG
1579 		/* Dummy read ISR to prevent extra link downs/ups */
1580 		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1581 
1582 		if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1583 			CMSMPrintString(
1584 				pAC->pConfigTable,
1585 				MSG_TYPE_RUNTIME_INFO,
1586 				"CheckUp3 - Stat: %x",
1587 				(void *)ExtStat,
1588 				(void *)NULL);
1589 		}
1590 #endif /* DEBUG */
1591 
1592 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1593 			("Link sync(GP), Port %d\n", Port));
1594 		SkHWLinkUp(pAC, IoC, Port);
1595 
1596 		return(SK_HW_PS_LINK);
1597 	}
1598 
1599 	return(SK_HW_PS_NONE);
1600 }	/* SkGePortCheckUpBcom */
1601 #endif /* GENESIS */
1602 
1603 
1604 #ifdef YUKON
1605 /******************************************************************************
1606  *
1607  * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1608  *
1609  * return:
1610  *	0	o.k. nothing needed
1611  *	1	Restart needed on this port
1612  *	2	Link came up
1613  */
1614 static int SkGePortCheckUpGmac(
1615 SK_AC	*pAC,		/* Adapter Context */
1616 SK_IOC	IoC,		/* IO Context */
1617 int		Port,		/* Which port should be checked */
1618 SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
1619 {
1620 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
1621 	int			Done;
1622 	SK_U16		PhyIsrc;	/* PHY Interrupt source */
1623 	SK_U16		PhyStat;	/* PPY Status */
1624 	SK_U16		PhySpecStat;/* PHY Specific Status */
1625 	SK_U16		ResAb;		/* Master/Slave resolution */
1626 	SK_EVPARA	Para;
1627 #ifdef DEBUG
1628 	SK_U16		Word;		/* I/O helper */
1629 #endif /* DEBUG */
1630 
1631 	pPrt = &pAC->GIni.GP[Port];
1632 
1633 	if (pPrt->PHWLinkUp) {
1634 		return(SK_HW_PS_NONE);
1635 	}
1636 
1637 	/* Read PHY Status */
1638 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
1639 
1640 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1641 		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1642 
1643 	/* Read PHY Interrupt Status */
1644 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
1645 
1646 	if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
1647 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1648 			("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
1649 	}
1650 
1651 	if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
1652 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1653 			("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
1654 	}
1655 
1656 	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1657 
1658 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
1659 
1660 	if ((ResAb & PHY_B_1000S_MSF) != 0) {
1661 		/* Error */
1662 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1663 			("Master/Slave Fault port %d\n", Port));
1664 
1665 		pPrt->PAutoNegFail = SK_TRUE;
1666 		pPrt->PMSStatus = SK_MS_STAT_FAULT;
1667 
1668 		return(SK_HW_PS_RESTART);
1669 	}
1670 
1671 	/* Read PHY Specific Status */
1672 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
1673 
1674 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1675 		("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
1676 
1677 #ifdef DEBUG
1678 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
1679 
1680 	if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
1681 		(PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  {
1682 		/* Read PHY Next Page Link Partner */
1683 		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
1684 
1685 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1686 			("Page Received, NextPage: 0x%04X\n", Word));
1687 	}
1688 #endif /* DEBUG */
1689 
1690 	if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
1691 		return(SK_HW_PS_NONE);
1692 	}
1693 
1694 	if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
1695 		(PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
1696 		/* Downshift detected */
1697 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
1698 
1699 		Para.Para64 = Port;
1700 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
1701 
1702 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1703 			("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
1704 	}
1705 
1706 	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1707 		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1708 
1709 	pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
1710 
1711 	if (AutoNeg) {
1712 		/* Auto-Negotiation Over ? */
1713 		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1714 
1715 			SkHWLinkUp(pAC, IoC, Port);
1716 
1717 			Done = SkMacAutoNegDone(pAC, IoC, Port);
1718 
1719 			if (Done != SK_AND_OK) {
1720 				return(SK_HW_PS_RESTART);
1721 			}
1722 
1723 			return(SK_HW_PS_LINK);
1724 		}
1725 	}
1726 	else {	/* !AutoNeg */
1727 		/* Link is up and we don't need more */
1728 #ifdef DEBUG
1729 		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1730 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1731 				("ERROR: Lipa auto detected on port %d\n", Port));
1732 		}
1733 #endif /* DEBUG */
1734 
1735 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1736 			("Link sync, Port %d\n", Port));
1737 		SkHWLinkUp(pAC, IoC, Port);
1738 
1739 		return(SK_HW_PS_LINK);
1740 	}
1741 
1742 	return(SK_HW_PS_NONE);
1743 }	/* SkGePortCheckUpGmac */
1744 #endif /* YUKON */
1745 
1746 
1747 #ifdef OTHER_PHY
1748 /******************************************************************************
1749  *
1750  * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1751  *
1752  * return:
1753  *	0	o.k. nothing needed
1754  *	1	Restart needed on this port
1755  *	2	Link came up
1756  */
1757 static int SkGePortCheckUpLone(
1758 SK_AC	*pAC,		/* Adapter Context */
1759 SK_IOC	IoC,		/* IO Context */
1760 int		Port,		/* Which port should be checked */
1761 SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
1762 {
1763 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
1764 	int			Done;
1765 	SK_U16		Isrc;		/* Interrupt source register */
1766 	SK_U16		LpAb;		/* Link Partner Ability */
1767 	SK_U16		ExtStat;	/* Extended Status Register */
1768 	SK_U16		PhyStat;	/* Phy Status Register */
1769 	SK_U16		StatSum;
1770 	SK_U8		NextMode;	/* Next AutoSensing Mode */
1771 
1772 	pPrt = &pAC->GIni.GP[Port];
1773 
1774 	if (pPrt->PHWLinkUp) {
1775 		return(SK_HW_PS_NONE);
1776 	}
1777 
1778 	StatSum = pPrt->PIsave;
1779 	pPrt->PIsave = 0;
1780 
1781 	/*
1782 	 * here we usually can check whether the link is in sync and
1783 	 * auto-negotiation is done.
1784 	 */
1785 	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
1786 	StatSum |= PhyStat;
1787 
1788 	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1789 
1790 	if ((PhyStat & PHY_ST_LSYNC) == 0) {
1791 		/* Save Auto-negotiation Done bit */
1792 		pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
1793 #ifdef DEBUG
1794 		if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
1795 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1796 				("AutoNeg done rescheduled Port %d\n", Port));
1797 		}
1798 #endif /* DEBUG */
1799 		return(SK_HW_PS_NONE);
1800 	}
1801 
1802 	if (AutoNeg) {
1803 		if ((StatSum & PHY_ST_AN_OVER) != 0) {
1804 			SkHWLinkUp(pAC, IoC, Port);
1805 			Done = SkMacAutoNegDone(pAC, IoC, Port);
1806 			if (Done != SK_AND_OK) {
1807 				/* Get PHY parameters, for debugging only */
1808 				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
1809 				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
1810 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1811 					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1812 					 Port, LpAb, ExtStat));
1813 
1814 				/* Try next possible mode */
1815 				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1816 				SkHWLinkDown(pAC, IoC, Port);
1817 				if (Done == SK_AND_DUP_CAP) {
1818 					/* GoTo next mode */
1819 					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1820 				}
1821 
1822 				return(SK_HW_PS_RESTART);
1823 
1824 			}
1825 			else {
1826 				/*
1827 				 * Dummy Read interrupt status to prevent
1828 				 * extra link down/ups
1829 				 */
1830 				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1831 				return(SK_HW_PS_LINK);
1832 			}
1833 		}
1834 
1835 		/* AutoNeg not done, but HW link is up. Check for timeouts */
1836 		pPrt->PAutoNegTimeOut++;
1837 		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1838 			/* Timeout occured */
1839 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1840 				("AutoNeg timeout Port %d\n", Port));
1841 			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1842 				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1843 				/* Set Link manually up */
1844 				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1845 				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1846 					("Set manual full duplex Port %d\n", Port));
1847 			}
1848 
1849 			/* Do the restart */
1850 			return(SK_HW_PS_RESTART);
1851 		}
1852 	}
1853 	else {
1854 		/* Link is up and we don't need more */
1855 #ifdef DEBUG
1856 		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1857 			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1858 				("ERROR: Lipa auto detected on port %d\n", Port));
1859 		}
1860 #endif /* DEBUG */
1861 
1862 		/*
1863 		 * Dummy Read interrupt status to prevent
1864 		 * extra link down/ups
1865 		 */
1866 		SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1867 
1868 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1869 			("Link sync(GP), Port %d\n", Port));
1870 		SkHWLinkUp(pAC, IoC, Port);
1871 
1872 		return(SK_HW_PS_LINK);
1873 	}
1874 
1875 	return(SK_HW_PS_NONE);
1876 }	/* SkGePortCheckUpLone */
1877 
1878 
1879 /******************************************************************************
1880  *
1881  * SkGePortCheckUpNat() - Check if the link is up on National PHY
1882  *
1883  * return:
1884  *	0	o.k. nothing needed
1885  *	1	Restart needed on this port
1886  *	2	Link came up
1887  */
1888 static int SkGePortCheckUpNat(
1889 SK_AC	*pAC,		/* Adapter Context */
1890 SK_IOC	IoC,		/* IO Context */
1891 int		Port,		/* Which port should be checked */
1892 SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
1893 {
1894 	/* todo: National */
1895 	return(SK_HW_PS_NONE);
1896 }	/* SkGePortCheckUpNat */
1897 #endif /* OTHER_PHY */
1898 
1899 
1900 /******************************************************************************
1901  *
1902  *	SkGeSirqEvent() - Event Service Routine
1903  *
1904  * Description:
1905  *
1906  * Notes:
1907  */
1908 int	SkGeSirqEvent(
1909 SK_AC		*pAC,		/* Adapter Context */
1910 SK_IOC		IoC,		/* Io Context */
1911 SK_U32		Event,		/* Module specific Event */
1912 SK_EVPARA	Para)		/* Event specific Parameter */
1913 {
1914 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
1915 	SK_U32		Port;
1916 	SK_U32		Val32;
1917 	int			PortStat;
1918 	SK_U8		Val8;
1919 #ifdef GENESIS
1920 	SK_U64		Octets;
1921 #endif /* GENESIS */
1922 
1923 	Port = Para.Para32[0];
1924 	pPrt = &pAC->GIni.GP[Port];
1925 
1926 	switch (Event) {
1927 	case SK_HWEV_WATIM:
1928 		if (pPrt->PState == SK_PRT_RESET) {
1929 
1930 			PortStat = SK_HW_PS_NONE;
1931 		}
1932 		else {
1933 			/* Check whether port came up */
1934 			PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
1935 		}
1936 
1937 		switch (PortStat) {
1938 		case SK_HW_PS_RESTART:
1939 			if (pPrt->PHWLinkUp) {
1940 				/* Set Link to down */
1941 				SkHWLinkDown(pAC, IoC, (int)Port);
1942 
1943 				/*
1944 				 * Signal directly to RLMT to ensure correct
1945 				 * sequence of SWITCH and RESET event.
1946 				 */
1947 				SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1948 			}
1949 
1950 			/* Restart needed */
1951 			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1952 			break;
1953 
1954 		case SK_HW_PS_LINK:
1955 			/* Signal to RLMT */
1956 			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
1957 			break;
1958 		}
1959 
1960 		/* Start again the check Timer */
1961 		if (pPrt->PHWLinkUp) {
1962 			Val32 = SK_WA_ACT_TIME;
1963 		}
1964 		else {
1965 			Val32 = SK_WA_INA_TIME;
1966 		}
1967 
1968 		/* Todo: still needed for non-XMAC PHYs??? */
1969 		/* Start workaround Errata #2 timer */
1970 		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
1971 			SKGE_HWAC, SK_HWEV_WATIM, Para);
1972 		break;
1973 
1974 	case SK_HWEV_PORT_START:
1975 		if (pPrt->PHWLinkUp) {
1976 			/*
1977 			 * Signal directly to RLMT to ensure correct
1978 			 * sequence of SWITCH and RESET event.
1979 			 */
1980 			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1981 		}
1982 
1983 		SkHWLinkDown(pAC, IoC, (int)Port);
1984 
1985 		/* Schedule Port RESET */
1986 		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1987 
1988 		/* Start workaround Errata #2 timer */
1989 		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
1990 			SKGE_HWAC, SK_HWEV_WATIM, Para);
1991 		break;
1992 
1993 	case SK_HWEV_PORT_STOP:
1994 		if (pPrt->PHWLinkUp) {
1995 			/*
1996 			 * Signal directly to RLMT to ensure correct
1997 			 * sequence of SWITCH and RESET event.
1998 			 */
1999 			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2000 		}
2001 
2002 		/* Stop Workaround Timer */
2003 		SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
2004 
2005 		SkHWLinkDown(pAC, IoC, (int)Port);
2006 		break;
2007 
2008 	case SK_HWEV_UPDATE_STAT:
2009 		/* We do NOT need to update any statistics */
2010 		break;
2011 
2012 	case SK_HWEV_CLEAR_STAT:
2013 		/* We do NOT need to clear any statistics */
2014 		for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
2015 			pPrt->PPrevRx = 0;
2016 			pPrt->PPrevFcs = 0;
2017 			pPrt->PPrevShorts = 0;
2018 		}
2019 		break;
2020 
2021 	case SK_HWEV_SET_LMODE:
2022 		Val8 = (SK_U8)Para.Para32[1];
2023 		if (pPrt->PLinkModeConf != Val8) {
2024 			/* Set New link mode */
2025 			pPrt->PLinkModeConf = Val8;
2026 
2027 			/* Restart Port */
2028 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2029 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2030 		}
2031 		break;
2032 
2033 	case SK_HWEV_SET_FLOWMODE:
2034 		Val8 = (SK_U8)Para.Para32[1];
2035 		if (pPrt->PFlowCtrlMode != Val8) {
2036 			/* Set New Flow Control mode */
2037 			pPrt->PFlowCtrlMode = Val8;
2038 
2039 			/* Restart Port */
2040 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2041 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2042 		}
2043 		break;
2044 
2045 	case SK_HWEV_SET_ROLE:
2046 		/* not possible for fiber */
2047 		if (!pAC->GIni.GICopperType) {
2048 			break;
2049 		}
2050 		Val8 = (SK_U8)Para.Para32[1];
2051 		if (pPrt->PMSMode != Val8) {
2052 			/* Set New Role (Master/Slave) mode */
2053 			pPrt->PMSMode = Val8;
2054 
2055 			/* Restart Port */
2056 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2057 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2058 		}
2059 		break;
2060 
2061 	case SK_HWEV_SET_SPEED:
2062 		if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
2063 			break;
2064 		}
2065 		Val8 = (SK_U8)Para.Para32[1];
2066 		if (pPrt->PLinkSpeed != Val8) {
2067 			/* Set New Speed parameter */
2068 			pPrt->PLinkSpeed = Val8;
2069 
2070 			/* Restart Port */
2071 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2072 			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2073 		}
2074 		break;
2075 
2076 #ifdef GENESIS
2077 	case SK_HWEV_HALFDUP_CHK:
2078 		if (pAC->GIni.GIGenesis) {
2079 			/*
2080 			 * half duplex hangup workaround.
2081 			 * See packet arbiter timeout interrupt for description
2082 			 */
2083 			pPrt->HalfDupTimerActive = SK_FALSE;
2084 			if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
2085 				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
2086 #ifdef XXX
2087 				Len = sizeof(SK_U64);
2088 				SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
2089 					&Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
2090 					pAC->Rlmt.Port[Port].Net->NetNumber);
2091 #endif /* XXX */
2092 				/* Snap statistic counters */
2093 				(void)SkXmUpdateStats(pAC, IoC, Port);
2094 
2095 				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
2096 
2097 				Octets = (SK_U64)Val32 << 32;
2098 
2099 				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
2100 
2101 				Octets += Val32;
2102 
2103 				if (pPrt->LastOctets == Octets) {
2104 					/* Tx hanging, a FIFO flush restarts it */
2105 					SkMacFlushTxFifo(pAC, IoC, Port);
2106 				}
2107 			}
2108 		}
2109 		break;
2110 #endif /* GENESIS */
2111 
2112 	default:
2113 		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
2114 		break;
2115 	}
2116 
2117 	return(0);
2118 }	/* SkGeSirqEvent */
2119 
2120 
2121 #ifdef GENESIS
2122 /******************************************************************************
2123  *
2124  *	SkPhyIsrBcom() - PHY interrupt service routine
2125  *
2126  * Description: handles all interrupts from BCom PHY
2127  *
2128  * Returns: N/A
2129  */
2130 static void SkPhyIsrBcom(
2131 SK_AC		*pAC,		/* Adapter Context */
2132 SK_IOC		IoC,		/* Io Context */
2133 int			Port,		/* Port Num = PHY Num */
2134 SK_U16		IStatus)	/* Interrupt Status */
2135 {
2136 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
2137 	SK_EVPARA	Para;
2138 
2139 	pPrt = &pAC->GIni.GP[Port];
2140 
2141 	if ((IStatus & PHY_B_IS_PSE) != 0) {
2142 		/* Incorrectable pair swap error */
2143 		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
2144 			SKERR_SIRQ_E022MSG);
2145 	}
2146 
2147 	if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
2148 
2149 		SkHWLinkDown(pAC, IoC, Port);
2150 
2151 		Para.Para32[0] = (SK_U32)Port;
2152 		/* Signal to RLMT */
2153 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2154 
2155 		/* Start workaround Errata #2 timer */
2156 		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
2157 			SKGE_HWAC, SK_HWEV_WATIM, Para);
2158 	}
2159 
2160 }	/* SkPhyIsrBcom */
2161 #endif /* GENESIS */
2162 
2163 
2164 #ifdef YUKON
2165 /******************************************************************************
2166  *
2167  *	SkPhyIsrGmac() - PHY interrupt service routine
2168  *
2169  * Description: handles all interrupts from Marvell PHY
2170  *
2171  * Returns: N/A
2172  */
2173 static void SkPhyIsrGmac(
2174 SK_AC		*pAC,		/* Adapter Context */
2175 SK_IOC		IoC,		/* Io Context */
2176 int			Port,		/* Port Num = PHY Num */
2177 SK_U16		IStatus)	/* Interrupt Status */
2178 {
2179 	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
2180 	SK_EVPARA	Para;
2181 	SK_U16		Word;
2182 
2183 	pPrt = &pAC->GIni.GP[Port];
2184 
2185 	if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
2186 
2187 		SkHWLinkDown(pAC, IoC, Port);
2188 
2189 		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
2190 
2191 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2192 			("AutoNeg.Adv: 0x%04X\n", Word));
2193 
2194 		/* Set Auto-negotiation advertisement */
2195 		if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
2196 			/* restore Asymmetric Pause bit */
2197 			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
2198 				(SK_U16)(Word | PHY_M_AN_ASP));
2199 		}
2200 
2201 		Para.Para32[0] = (SK_U32)Port;
2202 		/* Signal to RLMT */
2203 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2204 	}
2205 
2206 	if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
2207 		/* Auto-Negotiation Error */
2208 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
2209 	}
2210 
2211 	if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
2212 		/* FIFO Overflow/Underrun Error */
2213 		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
2214 	}
2215 
2216 }	/* SkPhyIsrGmac */
2217 #endif /* YUKON */
2218 
2219 
2220 #ifdef OTHER_PHY
2221 /******************************************************************************
2222  *
2223  *	SkPhyIsrLone() - PHY interrupt service routine
2224  *
2225  * Description: handles all interrupts from LONE PHY
2226  *
2227  * Returns: N/A
2228  */
2229 static void SkPhyIsrLone(
2230 SK_AC	*pAC,		/* Adapter Context */
2231 SK_IOC	IoC,		/* Io Context */
2232 int		Port,		/* Port Num = PHY Num */
2233 SK_U16	IStatus)	/* Interrupt Status */
2234 {
2235 	SK_EVPARA	Para;
2236 
2237 	if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
2238 
2239 		SkHWLinkDown(pAC, IoC, Port);
2240 
2241 		Para.Para32[0] = (SK_U32)Port;
2242 		/* Signal to RLMT */
2243 		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2244 	}
2245 
2246 }	/* SkPhyIsrLone */
2247 #endif /* OTHER_PHY */
2248 
2249 /* End of File */
2250