Linux 2.6.17.3
[linux/fpc-iii.git] / drivers / net / sk98lin / skgesirq.c
blobab66d80a4455896d8fe7084c1f3943d50df3567a
1 /******************************************************************************
3 * Name: skgesirq.c
4 * Project: Gigabit Ethernet Adapters, Common Modules
5 * Version: $Revision: 1.92 $
6 * Date: $Date: 2003/09/16 14:37:07 $
7 * Purpose: Special IRQ module
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect.
14 * (C)Copyright 2002-2003 Marvell.
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.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
26 * Special Interrupt handler
28 * The following abstract should show how this module is included
29 * in the driver path:
31 * In the ISR of the driver the bits for frame transmission complete and
32 * for receive complete are checked and handled by the driver itself.
33 * The bits of the slow path mask are checked after that and then the
34 * entry into the so-called "slow path" is prepared. It is an implementors
35 * decision whether this is executed directly or just scheduled by
36 * disabling the mask. In the interrupt service routine some events may be
37 * generated, so it would be a good idea to call the EventDispatcher
38 * right after this ISR.
40 * The Interrupt source register of the adapter is NOT read by this module.
41 * SO if the drivers implementor needs a while loop around the
42 * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
43 * each loop entered.
45 * However, the MAC Interrupt status registers are read in a while loop.
49 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
50 static const char SysKonnectFileId[] =
51 "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
52 #endif
54 #include "h/skdrv1st.h" /* Driver Specific Definitions */
55 #ifndef SK_SLIM
56 #include "h/skgepnmi.h" /* PNMI Definitions */
57 #include "h/skrlmt.h" /* RLMT Definitions */
58 #endif
59 #include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
61 /* local function prototypes */
62 #ifdef GENESIS
63 static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
64 static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
65 static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
66 #endif /* GENESIS */
67 #ifdef YUKON
68 static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
69 static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
70 #endif /* YUKON */
71 #ifdef OTHER_PHY
72 static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
73 static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
74 static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
75 #endif /* OTHER_PHY */
77 #ifdef GENESIS
79 * array of Rx counter from XMAC which are checked
80 * in AutoSense mode to check whether a link is not able to auto-negotiate.
82 static const SK_U16 SkGeRxRegs[]= {
83 XM_RXF_64B,
84 XM_RXF_127B,
85 XM_RXF_255B,
86 XM_RXF_511B,
87 XM_RXF_1023B,
88 XM_RXF_MAX_SZ
89 } ;
90 #endif /* GENESIS */
92 #ifdef __C2MAN__
94 * Special IRQ function
96 * General Description:
99 intro()
101 #endif
103 /******************************************************************************
105 * SkHWInitDefSense() - Default Autosensing mode initialization
107 * Description: sets the PLinkMode for HWInit
109 * Returns: N/A
111 static void SkHWInitDefSense(
112 SK_AC *pAC, /* adapter context */
113 SK_IOC IoC, /* IO context */
114 int Port) /* Port Index (MAC_1 + n) */
116 SK_GEPORT *pPrt; /* GIni Port struct pointer */
118 pPrt = &pAC->GIni.GP[Port];
120 pPrt->PAutoNegTimeOut = 0;
122 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
123 pPrt->PLinkMode = pPrt->PLinkModeConf;
124 return;
127 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
128 ("AutoSensing: First mode %d on Port %d\n",
129 (int)SK_LMODE_AUTOFULL, Port));
131 pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
133 return;
134 } /* SkHWInitDefSense */
137 #ifdef GENESIS
138 /******************************************************************************
140 * SkHWSenseGetNext() - Get Next Autosensing Mode
142 * Description: gets the appropriate next mode
144 * Note:
147 static SK_U8 SkHWSenseGetNext(
148 SK_AC *pAC, /* adapter context */
149 SK_IOC IoC, /* IO context */
150 int Port) /* Port Index (MAC_1 + n) */
152 SK_GEPORT *pPrt; /* GIni Port struct pointer */
154 pPrt = &pAC->GIni.GP[Port];
156 pPrt->PAutoNegTimeOut = 0;
158 if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
159 /* Leave all as configured */
160 return(pPrt->PLinkModeConf);
163 if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
164 /* Return next mode AUTOBOTH */
165 return ((SK_U8)SK_LMODE_AUTOBOTH);
168 /* Return default autofull */
169 return ((SK_U8)SK_LMODE_AUTOFULL);
170 } /* SkHWSenseGetNext */
173 /******************************************************************************
175 * SkHWSenseSetNext() - Autosensing Set next mode
177 * Description: sets the appropriate next mode
179 * Returns: N/A
181 static void SkHWSenseSetNext(
182 SK_AC *pAC, /* adapter context */
183 SK_IOC IoC, /* IO context */
184 int Port, /* Port Index (MAC_1 + n) */
185 SK_U8 NewMode) /* New Mode to be written in sense mode */
187 SK_GEPORT *pPrt; /* GIni Port struct pointer */
189 pPrt = &pAC->GIni.GP[Port];
191 pPrt->PAutoNegTimeOut = 0;
193 if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
194 return;
197 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
198 ("AutoSensing: next mode %d on Port %d\n",
199 (int)NewMode, Port));
201 pPrt->PLinkMode = NewMode;
203 return;
204 } /* SkHWSenseSetNext */
205 #endif /* GENESIS */
208 /******************************************************************************
210 * SkHWLinkDown() - Link Down handling
212 * Description: handles the hardware link down signal
214 * Returns: N/A
216 void SkHWLinkDown(
217 SK_AC *pAC, /* adapter context */
218 SK_IOC IoC, /* IO context */
219 int Port) /* Port Index (MAC_1 + n) */
221 SK_GEPORT *pPrt; /* GIni Port struct pointer */
223 pPrt = &pAC->GIni.GP[Port];
225 /* Disable all MAC interrupts */
226 SkMacIrqDisable(pAC, IoC, Port);
228 /* Disable Receiver and Transmitter */
229 SkMacRxTxDisable(pAC, IoC, Port);
231 /* Init default sense mode */
232 SkHWInitDefSense(pAC, IoC, Port);
234 if (pPrt->PHWLinkUp == SK_FALSE) {
235 return;
238 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
239 ("Link down Port %d\n", Port));
241 /* Set Link to DOWN */
242 pPrt->PHWLinkUp = SK_FALSE;
244 /* Reset Port stati */
245 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
246 pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
247 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
249 /* Re-init Phy especially when the AutoSense default is set now */
250 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
252 /* GP0: used for workaround of Rev. C Errata 2 */
254 /* Do NOT signal to RLMT */
256 /* Do NOT start the timer here */
257 } /* SkHWLinkDown */
260 /******************************************************************************
262 * SkHWLinkUp() - Link Up handling
264 * Description: handles the hardware link up signal
266 * Returns: N/A
268 static void SkHWLinkUp(
269 SK_AC *pAC, /* adapter context */
270 SK_IOC IoC, /* IO context */
271 int Port) /* Port Index (MAC_1 + n) */
273 SK_GEPORT *pPrt; /* GIni Port struct pointer */
275 pPrt = &pAC->GIni.GP[Port];
277 if (pPrt->PHWLinkUp) {
278 /* We do NOT need to proceed on active link */
279 return;
282 pPrt->PHWLinkUp = SK_TRUE;
283 pPrt->PAutoNegFail = SK_FALSE;
284 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
286 if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
287 pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
288 pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
289 /* Link is up and no Auto-negotiation should be done */
291 /* Link speed should be the configured one */
292 switch (pPrt->PLinkSpeed) {
293 case SK_LSPEED_AUTO:
294 /* default is 1000 Mbps */
295 case SK_LSPEED_1000MBPS:
296 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
297 break;
298 case SK_LSPEED_100MBPS:
299 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
300 break;
301 case SK_LSPEED_10MBPS:
302 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
303 break;
306 /* Set Link Mode Status */
307 if (pPrt->PLinkMode == SK_LMODE_FULL) {
308 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
310 else {
311 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
314 /* No flow control without auto-negotiation */
315 pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
317 /* enable Rx/Tx */
318 (void)SkMacRxTxEnable(pAC, IoC, Port);
320 } /* SkHWLinkUp */
323 /******************************************************************************
325 * SkMacParity() - MAC parity workaround
327 * Description: handles MAC parity errors correctly
329 * Returns: N/A
331 static void SkMacParity(
332 SK_AC *pAC, /* adapter context */
333 SK_IOC IoC, /* IO context */
334 int Port) /* Port Index of the port failed */
336 SK_EVPARA Para;
337 SK_GEPORT *pPrt; /* GIni Port struct pointer */
338 SK_U32 TxMax; /* Tx Max Size Counter */
340 pPrt = &pAC->GIni.GP[Port];
342 /* Clear IRQ Tx Parity Error */
343 #ifdef GENESIS
344 if (pAC->GIni.GIGenesis) {
346 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
348 #endif /* GENESIS */
350 #ifdef YUKON
351 if (pAC->GIni.GIYukon) {
352 /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
353 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
354 (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
355 pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
357 #endif /* YUKON */
359 if (pPrt->PCheckPar) {
361 if (Port == MAC_1) {
362 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
364 else {
365 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
367 Para.Para64 = Port;
368 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
370 Para.Para32[0] = Port;
371 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
373 return;
376 /* Check whether frames with a size of 1k were sent */
377 #ifdef GENESIS
378 if (pAC->GIni.GIGenesis) {
379 /* Snap statistic counters */
380 (void)SkXmUpdateStats(pAC, IoC, Port);
382 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
384 #endif /* GENESIS */
386 #ifdef YUKON
387 if (pAC->GIni.GIYukon) {
389 (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
391 #endif /* YUKON */
393 if (TxMax > 0) {
394 /* From now on check the parity */
395 pPrt->PCheckPar = SK_TRUE;
397 } /* SkMacParity */
400 /******************************************************************************
402 * SkGeHwErr() - Hardware Error service routine
404 * Description: handles all HW Error interrupts
406 * Returns: N/A
408 static void SkGeHwErr(
409 SK_AC *pAC, /* adapter context */
410 SK_IOC IoC, /* IO context */
411 SK_U32 HwStatus) /* Interrupt status word */
413 SK_EVPARA Para;
414 SK_U16 Word;
416 if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
417 /* PCI Errors occured */
418 if ((HwStatus & IS_IRQ_STAT) != 0) {
419 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
421 else {
422 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
425 /* Reset all bits in the PCI STATUS register */
426 SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
428 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
429 SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
430 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
432 Para.Para64 = 0;
433 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
436 #ifdef GENESIS
437 if (pAC->GIni.GIGenesis) {
439 if ((HwStatus & IS_NO_STAT_M1) != 0) {
440 /* Ignore it */
441 /* This situation is also indicated in the descriptor */
442 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
445 if ((HwStatus & IS_NO_STAT_M2) != 0) {
446 /* Ignore it */
447 /* This situation is also indicated in the descriptor */
448 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
451 if ((HwStatus & IS_NO_TIST_M1) != 0) {
452 /* Ignore it */
453 /* This situation is also indicated in the descriptor */
454 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
457 if ((HwStatus & IS_NO_TIST_M2) != 0) {
458 /* Ignore it */
459 /* This situation is also indicated in the descriptor */
460 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
463 #endif /* GENESIS */
465 #ifdef YUKON
466 if (pAC->GIni.GIYukon) {
467 /* This is necessary only for Rx timing measurements */
468 if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
469 /* increment Time Stamp Timer counter (high) */
470 pAC->GIni.GITimeStampCnt++;
472 /* Clear Time Stamp Timer IRQ */
473 SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
476 if ((HwStatus & IS_IRQ_SENSOR) != 0) {
477 /* no sensors on 32-bit Yukon */
478 if (pAC->GIni.GIYukon32Bit) {
479 /* disable HW Error IRQ */
480 pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
484 #endif /* YUKON */
486 if ((HwStatus & IS_RAM_RD_PAR) != 0) {
487 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
488 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
489 Para.Para64 = 0;
490 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
493 if ((HwStatus & IS_RAM_WR_PAR) != 0) {
494 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
495 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
496 Para.Para64 = 0;
497 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
500 if ((HwStatus & IS_M1_PAR_ERR) != 0) {
501 SkMacParity(pAC, IoC, MAC_1);
504 if ((HwStatus & IS_M2_PAR_ERR) != 0) {
505 SkMacParity(pAC, IoC, MAC_2);
508 if ((HwStatus & IS_R1_PAR_ERR) != 0) {
509 /* Clear IRQ */
510 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
512 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
513 Para.Para64 = MAC_1;
514 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
516 Para.Para32[0] = MAC_1;
517 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
520 if ((HwStatus & IS_R2_PAR_ERR) != 0) {
521 /* Clear IRQ */
522 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
524 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
525 Para.Para64 = MAC_2;
526 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
528 Para.Para32[0] = MAC_2;
529 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
531 } /* SkGeHwErr */
534 /******************************************************************************
536 * SkGeSirqIsr() - Special Interrupt Service Routine
538 * Description: handles all non data transfer specific interrupts (slow path)
540 * Returns: N/A
542 void SkGeSirqIsr(
543 SK_AC *pAC, /* adapter context */
544 SK_IOC IoC, /* IO context */
545 SK_U32 Istatus) /* Interrupt status word */
547 SK_EVPARA Para;
548 SK_U32 RegVal32; /* Read register value */
549 SK_GEPORT *pPrt; /* GIni Port struct pointer */
550 SK_U16 PhyInt;
551 int i;
553 if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
554 /* read the HW Error Interrupt source */
555 SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
557 SkGeHwErr(pAC, IoC, RegVal32);
561 * Packet Timeout interrupts
563 /* Check whether MACs are correctly initialized */
564 if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
565 pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
566 /* MAC 1 was not initialized but Packet timeout occured */
567 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
568 SKERR_SIRQ_E004MSG);
571 if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
572 pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
573 /* MAC 2 was not initialized but Packet timeout occured */
574 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
575 SKERR_SIRQ_E005MSG);
578 if ((Istatus & IS_PA_TO_RX1) != 0) {
579 /* Means network is filling us up */
580 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
581 SKERR_SIRQ_E002MSG);
582 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
585 if ((Istatus & IS_PA_TO_RX2) != 0) {
586 /* Means network is filling us up */
587 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
588 SKERR_SIRQ_E003MSG);
589 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
592 if ((Istatus & IS_PA_TO_TX1) != 0) {
594 pPrt = &pAC->GIni.GP[0];
596 /* May be a normal situation in a server with a slow network */
597 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
599 #ifdef GENESIS
600 if (pAC->GIni.GIGenesis) {
602 * workaround: if in half duplex mode, check for Tx hangup.
603 * Read number of TX'ed bytes, wait for 10 ms, then compare
604 * the number with current value. If nothing changed, we assume
605 * that Tx is hanging and do a FIFO flush (see event routine).
607 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
608 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
609 !pPrt->HalfDupTimerActive) {
611 * many more pack. arb. timeouts may come in between,
612 * we ignore those
614 pPrt->HalfDupTimerActive = SK_TRUE;
615 /* Snap statistic counters */
616 (void)SkXmUpdateStats(pAC, IoC, 0);
618 (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
620 pPrt->LastOctets = (SK_U64)RegVal32 << 32;
622 (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
624 pPrt->LastOctets += RegVal32;
626 Para.Para32[0] = 0;
627 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
628 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
631 #endif /* GENESIS */
634 if ((Istatus & IS_PA_TO_TX2) != 0) {
636 pPrt = &pAC->GIni.GP[1];
638 /* May be a normal situation in a server with a slow network */
639 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
641 #ifdef GENESIS
642 if (pAC->GIni.GIGenesis) {
643 /* workaround: see above */
644 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
645 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
646 !pPrt->HalfDupTimerActive) {
647 pPrt->HalfDupTimerActive = SK_TRUE;
648 /* Snap statistic counters */
649 (void)SkXmUpdateStats(pAC, IoC, 1);
651 (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
653 pPrt->LastOctets = (SK_U64)RegVal32 << 32;
655 (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
657 pPrt->LastOctets += RegVal32;
659 Para.Para32[0] = 1;
660 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
661 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
664 #endif /* GENESIS */
667 /* Check interrupts of the particular queues */
668 if ((Istatus & IS_R1_C) != 0) {
669 /* Clear IRQ */
670 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
671 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
672 SKERR_SIRQ_E006MSG);
673 Para.Para64 = MAC_1;
674 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
675 Para.Para32[0] = MAC_1;
676 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
679 if ((Istatus & IS_R2_C) != 0) {
680 /* Clear IRQ */
681 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
682 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
683 SKERR_SIRQ_E007MSG);
684 Para.Para64 = MAC_2;
685 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
686 Para.Para32[0] = MAC_2;
687 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
690 if ((Istatus & IS_XS1_C) != 0) {
691 /* Clear IRQ */
692 SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
693 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
694 SKERR_SIRQ_E008MSG);
695 Para.Para64 = MAC_1;
696 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
697 Para.Para32[0] = MAC_1;
698 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
701 if ((Istatus & IS_XA1_C) != 0) {
702 /* Clear IRQ */
703 SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
704 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
705 SKERR_SIRQ_E009MSG);
706 Para.Para64 = MAC_1;
707 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
708 Para.Para32[0] = MAC_1;
709 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
712 if ((Istatus & IS_XS2_C) != 0) {
713 /* Clear IRQ */
714 SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
715 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
716 SKERR_SIRQ_E010MSG);
717 Para.Para64 = MAC_2;
718 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
719 Para.Para32[0] = MAC_2;
720 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
723 if ((Istatus & IS_XA2_C) != 0) {
724 /* Clear IRQ */
725 SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
726 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
727 SKERR_SIRQ_E011MSG);
728 Para.Para64 = MAC_2;
729 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
730 Para.Para32[0] = MAC_2;
731 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
734 /* External reg interrupt */
735 if ((Istatus & IS_EXT_REG) != 0) {
736 /* Test IRQs from PHY */
737 for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
739 pPrt = &pAC->GIni.GP[i];
741 if (pPrt->PState == SK_PRT_RESET) {
742 continue;
745 #ifdef GENESIS
746 if (pAC->GIni.GIGenesis) {
748 switch (pPrt->PhyType) {
750 case SK_PHY_XMAC:
751 break;
753 case SK_PHY_BCOM:
754 SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
756 if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
757 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
758 ("Port %d Bcom Int: 0x%04X\n",
759 i, PhyInt));
760 SkPhyIsrBcom(pAC, IoC, i, PhyInt);
762 break;
763 #ifdef OTHER_PHY
764 case SK_PHY_LONE:
765 SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
767 if ((PhyInt & PHY_L_DEF_MSK) != 0) {
768 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
769 ("Port %d Lone Int: %x\n",
770 i, PhyInt));
771 SkPhyIsrLone(pAC, IoC, i, PhyInt);
773 break;
774 #endif /* OTHER_PHY */
777 #endif /* GENESIS */
779 #ifdef YUKON
780 if (pAC->GIni.GIYukon) {
781 /* Read PHY Interrupt Status */
782 SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
784 if ((PhyInt & PHY_M_DEF_MSK) != 0) {
785 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
786 ("Port %d Marv Int: 0x%04X\n",
787 i, PhyInt));
788 SkPhyIsrGmac(pAC, IoC, i, PhyInt);
791 #endif /* YUKON */
795 /* I2C Ready interrupt */
796 if ((Istatus & IS_I2C_READY) != 0) {
797 #ifdef SK_SLIM
798 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
799 #else
800 SkI2cIsr(pAC, IoC);
801 #endif
804 /* SW forced interrupt */
805 if ((Istatus & IS_IRQ_SW) != 0) {
806 /* clear the software IRQ */
807 SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
810 if ((Istatus & IS_LNK_SYNC_M1) != 0) {
812 * We do NOT need the Link Sync interrupt, because it shows
813 * us only a link going down.
815 /* clear interrupt */
816 SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
819 /* Check MAC after link sync counter */
820 if ((Istatus & IS_MAC1) != 0) {
821 /* IRQ from MAC 1 */
822 SkMacIrq(pAC, IoC, MAC_1);
825 if ((Istatus & IS_LNK_SYNC_M2) != 0) {
827 * We do NOT need the Link Sync interrupt, because it shows
828 * us only a link going down.
830 /* clear interrupt */
831 SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
834 /* Check MAC after link sync counter */
835 if ((Istatus & IS_MAC2) != 0) {
836 /* IRQ from MAC 2 */
837 SkMacIrq(pAC, IoC, MAC_2);
840 /* Timer interrupt (served last) */
841 if ((Istatus & IS_TIMINT) != 0) {
842 /* check for HW Errors */
843 if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
844 /* read the HW Error Interrupt source */
845 SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
847 SkGeHwErr(pAC, IoC, RegVal32);
850 SkHwtIsr(pAC, IoC);
853 } /* SkGeSirqIsr */
856 #ifdef GENESIS
857 /******************************************************************************
859 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
861 * return:
862 * 0 o.k. nothing needed
863 * 1 Restart needed on this port
865 static int SkGePortCheckShorts(
866 SK_AC *pAC, /* Adapter Context */
867 SK_IOC IoC, /* IO Context */
868 int Port) /* Which port should be checked */
870 SK_U32 Shorts; /* Short Event Counter */
871 SK_U32 CheckShorts; /* Check value for Short Event Counter */
872 SK_U64 RxCts; /* Rx Counter (packets on network) */
873 SK_U32 RxTmp; /* Rx temp. Counter */
874 SK_U32 FcsErrCts; /* FCS Error Counter */
875 SK_GEPORT *pPrt; /* GIni Port struct pointer */
876 int Rtv; /* Return value */
877 int i;
879 pPrt = &pAC->GIni.GP[Port];
881 /* Default: no action */
882 Rtv = SK_HW_PS_NONE;
884 (void)SkXmUpdateStats(pAC, IoC, Port);
886 /* Extra precaution: check for short Event counter */
887 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
890 * Read Rx counters (packets seen on the network and not necessarily
891 * really received.
893 RxCts = 0;
895 for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
897 (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
899 RxCts += (SK_U64)RxTmp;
902 /* On default: check shorts against zero */
903 CheckShorts = 0;
905 /* Extra precaution on active links */
906 if (pPrt->PHWLinkUp) {
907 /* Reset Link Restart counter */
908 pPrt->PLinkResCt = 0;
909 pPrt->PAutoNegTOCt = 0;
911 /* If link is up check for 2 */
912 CheckShorts = 2;
914 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
916 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
917 pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
918 (pPrt->PLinkMode == SK_LMODE_HALF ||
919 pPrt->PLinkMode == SK_LMODE_FULL)) {
921 * This is autosensing and we are in the fallback
922 * manual full/half duplex mode.
924 if (RxCts == pPrt->PPrevRx) {
925 /* Nothing received, restart link */
926 pPrt->PPrevFcs = FcsErrCts;
927 pPrt->PPrevShorts = Shorts;
929 return(SK_HW_PS_RESTART);
931 else {
932 pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
936 if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
937 (!(FcsErrCts - pPrt->PPrevFcs))) {
939 * Note: The compare with zero above has to be done the way shown,
940 * otherwise the Linux driver will have a problem.
943 * We received a bunch of frames or no CRC error occured on the
944 * network -> ok.
946 pPrt->PPrevRx = RxCts;
947 pPrt->PPrevFcs = FcsErrCts;
948 pPrt->PPrevShorts = Shorts;
950 return(SK_HW_PS_NONE);
953 pPrt->PPrevFcs = FcsErrCts;
957 if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
958 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
959 ("Short Event Count Restart Port %d \n", Port));
960 Rtv = SK_HW_PS_RESTART;
963 pPrt->PPrevShorts = Shorts;
964 pPrt->PPrevRx = RxCts;
966 return(Rtv);
967 } /* SkGePortCheckShorts */
968 #endif /* GENESIS */
971 /******************************************************************************
973 * SkGePortCheckUp() - Check if the link is up
975 * return:
976 * 0 o.k. nothing needed
977 * 1 Restart needed on this port
978 * 2 Link came up
980 static int SkGePortCheckUp(
981 SK_AC *pAC, /* Adapter Context */
982 SK_IOC IoC, /* IO Context */
983 int Port) /* Which port should be checked */
985 SK_GEPORT *pPrt; /* GIni Port struct pointer */
986 SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
987 int Rtv; /* Return value */
989 Rtv = SK_HW_PS_NONE;
991 pPrt = &pAC->GIni.GP[Port];
993 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
994 AutoNeg = SK_FALSE;
996 else {
997 AutoNeg = SK_TRUE;
1000 #ifdef GENESIS
1001 if (pAC->GIni.GIGenesis) {
1003 switch (pPrt->PhyType) {
1005 case SK_PHY_XMAC:
1006 Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
1007 break;
1008 case SK_PHY_BCOM:
1009 Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
1010 break;
1011 #ifdef OTHER_PHY
1012 case SK_PHY_LONE:
1013 Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
1014 break;
1015 case SK_PHY_NAT:
1016 Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
1017 break;
1018 #endif /* OTHER_PHY */
1021 #endif /* GENESIS */
1023 #ifdef YUKON
1024 if (pAC->GIni.GIYukon) {
1026 Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
1028 #endif /* YUKON */
1030 return(Rtv);
1031 } /* SkGePortCheckUp */
1034 #ifdef GENESIS
1035 /******************************************************************************
1037 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1039 * return:
1040 * 0 o.k. nothing needed
1041 * 1 Restart needed on this port
1042 * 2 Link came up
1044 static int SkGePortCheckUpXmac(
1045 SK_AC *pAC, /* Adapter Context */
1046 SK_IOC IoC, /* IO Context */
1047 int Port, /* Which port should be checked */
1048 SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
1050 SK_U32 Shorts; /* Short Event Counter */
1051 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1052 int Done;
1053 SK_U32 GpReg; /* General Purpose register value */
1054 SK_U16 Isrc; /* Interrupt source register */
1055 SK_U16 IsrcSum; /* Interrupt source register sum */
1056 SK_U16 LpAb; /* Link Partner Ability */
1057 SK_U16 ResAb; /* Resolved Ability */
1058 SK_U16 ExtStat; /* Extended Status Register */
1059 SK_U8 NextMode; /* Next AutoSensing Mode */
1061 pPrt = &pAC->GIni.GP[Port];
1063 if (pPrt->PHWLinkUp) {
1064 if (pPrt->PhyType != SK_PHY_XMAC) {
1065 return(SK_HW_PS_NONE);
1067 else {
1068 return(SkGePortCheckShorts(pAC, IoC, Port));
1072 IsrcSum = pPrt->PIsave;
1073 pPrt->PIsave = 0;
1075 /* Now wait for each port's link */
1076 if (pPrt->PLinkBroken) {
1077 /* Link was broken */
1078 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1080 if ((GpReg & XM_GP_INP_ASS) == 0) {
1081 /* The Link is in sync */
1082 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1083 IsrcSum |= Isrc;
1084 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1086 if ((Isrc & XM_IS_INP_ASS) == 0) {
1087 /* It has been in sync since last time */
1088 /* Restart the PORT */
1089 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1090 ("Link in sync Restart Port %d\n", Port));
1092 (void)SkXmUpdateStats(pAC, IoC, Port);
1094 /* We now need to reinitialize the PrevShorts counter */
1095 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
1096 pPrt->PPrevShorts = Shorts;
1098 pPrt->PLinkBroken = SK_FALSE;
1101 * Link Restart Workaround:
1102 * it may be possible that the other Link side
1103 * restarts its link as well an we detect
1104 * another LinkBroken. To prevent this
1105 * happening we check for a maximum number
1106 * of consecutive restart. If those happens,
1107 * we do NOT restart the active link and
1108 * check whether the link is now o.k.
1110 pPrt->PLinkResCt++;
1112 pPrt->PAutoNegTimeOut = 0;
1114 if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
1115 return(SK_HW_PS_RESTART);
1118 pPrt->PLinkResCt = 0;
1120 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1121 ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
1123 else {
1124 pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1126 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1127 ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
1129 /* Do nothing more if link is broken */
1130 return(SK_HW_PS_NONE);
1133 else {
1134 /* Do nothing more if link is broken */
1135 return(SK_HW_PS_NONE);
1139 else {
1140 /* Link was not broken, check if it is */
1141 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1142 IsrcSum |= Isrc;
1143 if ((Isrc & XM_IS_INP_ASS) != 0) {
1144 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1145 IsrcSum |= Isrc;
1146 if ((Isrc & XM_IS_INP_ASS) != 0) {
1147 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1148 IsrcSum |= Isrc;
1149 if ((Isrc & XM_IS_INP_ASS) != 0) {
1150 pPrt->PLinkBroken = SK_TRUE;
1151 /* Re-Init Link partner Autoneg flag */
1152 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1153 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1154 ("Link broken Port %d\n", Port));
1156 /* Cable removed-> reinit sense mode */
1157 SkHWInitDefSense(pAC, IoC, Port);
1159 return(SK_HW_PS_RESTART);
1163 else {
1164 SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
1166 if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
1167 return(SK_HW_PS_RESTART);
1173 * here we usually can check whether the link is in sync and
1174 * auto-negotiation is done.
1176 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1177 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1178 IsrcSum |= Isrc;
1180 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1182 if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
1183 if ((GpReg & XM_GP_INP_ASS) == 0) {
1184 /* Save Auto-negotiation Done interrupt only if link is in sync */
1185 pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1187 #ifdef DEBUG
1188 if ((pPrt->PIsave & XM_IS_AND) != 0) {
1189 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1190 ("AutoNeg done rescheduled Port %d\n", Port));
1192 #endif /* DEBUG */
1193 return(SK_HW_PS_NONE);
1196 if (AutoNeg) {
1197 if ((IsrcSum & XM_IS_AND) != 0) {
1198 SkHWLinkUp(pAC, IoC, Port);
1199 Done = SkMacAutoNegDone(pAC, IoC, Port);
1200 if (Done != SK_AND_OK) {
1201 /* Get PHY parameters, for debugging only */
1202 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
1203 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
1204 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1205 ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
1206 Port, LpAb, ResAb));
1208 /* Try next possible mode */
1209 NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1210 SkHWLinkDown(pAC, IoC, Port);
1211 if (Done == SK_AND_DUP_CAP) {
1212 /* GoTo next mode */
1213 SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1216 return(SK_HW_PS_RESTART);
1219 * Dummy Read extended status to prevent extra link down/ups
1220 * (clear Page Received bit if set)
1222 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
1224 return(SK_HW_PS_LINK);
1227 /* AutoNeg not done, but HW link is up. Check for timeouts */
1228 pPrt->PAutoNegTimeOut++;
1229 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1230 /* Increase the Timeout counter */
1231 pPrt->PAutoNegTOCt++;
1233 /* Timeout occured */
1234 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1235 ("AutoNeg timeout Port %d\n", Port));
1236 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1237 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1238 /* Set Link manually up */
1239 SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1240 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1241 ("Set manual full duplex Port %d\n", Port));
1244 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1245 pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
1246 pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
1248 * This is rather complicated.
1249 * we need to check here whether the LIPA_AUTO
1250 * we saw before is false alert. We saw at one
1251 * switch ( SR8800) that on boot time it sends
1252 * just one auto-neg packet and does no further
1253 * auto-negotiation.
1254 * Solution: we restart the autosensing after
1255 * a few timeouts.
1257 pPrt->PAutoNegTOCt = 0;
1258 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1259 SkHWInitDefSense(pAC, IoC, Port);
1262 /* Do the restart */
1263 return(SK_HW_PS_RESTART);
1266 else {
1267 /* Link is up and we don't need more */
1268 #ifdef DEBUG
1269 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1270 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1271 ("ERROR: Lipa auto detected on port %d\n", Port));
1273 #endif /* DEBUG */
1274 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1275 ("Link sync(GP), Port %d\n", Port));
1276 SkHWLinkUp(pAC, IoC, Port);
1279 * Link sync (GP) and so assume a good connection. But if not received
1280 * a bunch of frames received in a time slot (maybe broken tx cable)
1281 * the port is restart.
1283 return(SK_HW_PS_LINK);
1286 return(SK_HW_PS_NONE);
1287 } /* SkGePortCheckUpXmac */
1290 /******************************************************************************
1292 * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
1294 * return:
1295 * 0 o.k. nothing needed
1296 * 1 Restart needed on this port
1297 * 2 Link came up
1299 static int SkGePortCheckUpBcom(
1300 SK_AC *pAC, /* Adapter Context */
1301 SK_IOC IoC, /* IO Context */
1302 int Port, /* Which port should be checked */
1303 SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
1305 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1306 int Done;
1307 SK_U16 Isrc; /* Interrupt source register */
1308 SK_U16 PhyStat; /* Phy Status Register */
1309 SK_U16 ResAb; /* Master/Slave resolution */
1310 SK_U16 Ctrl; /* Broadcom control flags */
1311 #ifdef DEBUG
1312 SK_U16 LpAb;
1313 SK_U16 ExtStat;
1314 #endif /* DEBUG */
1316 pPrt = &pAC->GIni.GP[Port];
1318 /* Check for No HCD Link events (#10523) */
1319 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
1321 #ifdef xDEBUG
1322 if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) ==
1323 (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
1325 SK_U32 Stat1, Stat2, Stat3;
1327 Stat1 = 0;
1328 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1329 CMSMPrintString(
1330 pAC->pConfigTable,
1331 MSG_TYPE_RUNTIME_INFO,
1332 "CheckUp1 - Stat: %x, Mask: %x",
1333 (void *)Isrc,
1334 (void *)Stat1);
1336 Stat1 = 0;
1337 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1338 Stat2 = 0;
1339 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
1340 Stat1 = Stat1 << 16 | Stat2;
1341 Stat2 = 0;
1342 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1343 Stat3 = 0;
1344 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1345 Stat2 = Stat2 << 16 | Stat3;
1346 CMSMPrintString(
1347 pAC->pConfigTable,
1348 MSG_TYPE_RUNTIME_INFO,
1349 "Ctrl/Stat: %x, AN Adv/LP: %x",
1350 (void *)Stat1,
1351 (void *)Stat2);
1353 Stat1 = 0;
1354 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1355 Stat2 = 0;
1356 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1357 Stat1 = Stat1 << 16 | Stat2;
1358 Stat2 = 0;
1359 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1360 Stat3 = 0;
1361 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
1362 Stat2 = Stat2 << 16 | Stat3;
1363 CMSMPrintString(
1364 pAC->pConfigTable,
1365 MSG_TYPE_RUNTIME_INFO,
1366 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1367 (void *)Stat1,
1368 (void *)Stat2);
1370 Stat1 = 0;
1371 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1372 Stat2 = 0;
1373 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1374 Stat1 = Stat1 << 16 | Stat2;
1375 Stat2 = 0;
1376 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1377 Stat3 = 0;
1378 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1379 Stat2 = Stat2 << 16 | Stat3;
1380 CMSMPrintString(
1381 pAC->pConfigTable,
1382 MSG_TYPE_RUNTIME_INFO,
1383 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1384 (void *)Stat1,
1385 (void *)Stat2);
1387 #endif /* DEBUG */
1389 if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
1391 * Workaround BCom Errata:
1392 * enable and disable loopback mode if "NO HCD" occurs.
1394 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
1395 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1396 (SK_U16)(Ctrl | PHY_CT_LOOP));
1397 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1398 (SK_U16)(Ctrl & ~PHY_CT_LOOP));
1399 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1400 ("No HCD Link event, Port %d\n", Port));
1401 #ifdef xDEBUG
1402 CMSMPrintString(
1403 pAC->pConfigTable,
1404 MSG_TYPE_RUNTIME_INFO,
1405 "No HCD link event, port %d.",
1406 (void *)Port,
1407 (void *)NULL);
1408 #endif /* DEBUG */
1411 /* Not obsolete: link status bit is latched to 0 and autoclearing! */
1412 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1414 if (pPrt->PHWLinkUp) {
1415 return(SK_HW_PS_NONE);
1418 #ifdef xDEBUG
1420 SK_U32 Stat1, Stat2, Stat3;
1422 Stat1 = 0;
1423 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1424 CMSMPrintString(
1425 pAC->pConfigTable,
1426 MSG_TYPE_RUNTIME_INFO,
1427 "CheckUp1a - Stat: %x, Mask: %x",
1428 (void *)Isrc,
1429 (void *)Stat1);
1431 Stat1 = 0;
1432 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1433 Stat2 = 0;
1434 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1435 Stat1 = Stat1 << 16 | PhyStat;
1436 Stat2 = 0;
1437 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1438 Stat3 = 0;
1439 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1440 Stat2 = Stat2 << 16 | Stat3;
1441 CMSMPrintString(
1442 pAC->pConfigTable,
1443 MSG_TYPE_RUNTIME_INFO,
1444 "Ctrl/Stat: %x, AN Adv/LP: %x",
1445 (void *)Stat1,
1446 (void *)Stat2);
1448 Stat1 = 0;
1449 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1450 Stat2 = 0;
1451 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1452 Stat1 = Stat1 << 16 | Stat2;
1453 Stat2 = 0;
1454 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1455 Stat3 = 0;
1456 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1457 Stat2 = Stat2 << 16 | ResAb;
1458 CMSMPrintString(
1459 pAC->pConfigTable,
1460 MSG_TYPE_RUNTIME_INFO,
1461 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1462 (void *)Stat1,
1463 (void *)Stat2);
1465 Stat1 = 0;
1466 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1467 Stat2 = 0;
1468 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1469 Stat1 = Stat1 << 16 | Stat2;
1470 Stat2 = 0;
1471 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1472 Stat3 = 0;
1473 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1474 Stat2 = Stat2 << 16 | Stat3;
1475 CMSMPrintString(
1476 pAC->pConfigTable,
1477 MSG_TYPE_RUNTIME_INFO,
1478 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1479 (void *)Stat1,
1480 (void *)Stat2);
1482 #endif /* DEBUG */
1485 * Here we usually can check whether the link is in sync and
1486 * auto-negotiation is done.
1489 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1491 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1493 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1494 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1496 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1498 if ((ResAb & PHY_B_1000S_MSF) != 0) {
1499 /* Error */
1500 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1501 ("Master/Slave Fault port %d\n", Port));
1503 pPrt->PAutoNegFail = SK_TRUE;
1504 pPrt->PMSStatus = SK_MS_STAT_FAULT;
1506 return(SK_HW_PS_RESTART);
1509 if ((PhyStat & PHY_ST_LSYNC) == 0) {
1510 return(SK_HW_PS_NONE);
1513 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1514 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1516 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1517 ("Port %d, ResAb: 0x%04X\n", Port, ResAb));
1519 if (AutoNeg) {
1520 if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1522 SkHWLinkUp(pAC, IoC, Port);
1524 Done = SkMacAutoNegDone(pAC, IoC, Port);
1526 if (Done != SK_AND_OK) {
1527 #ifdef DEBUG
1528 /* Get PHY parameters, for debugging only */
1529 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
1530 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
1531 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1532 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1533 Port, LpAb, ExtStat));
1534 #endif /* DEBUG */
1535 return(SK_HW_PS_RESTART);
1537 else {
1538 #ifdef xDEBUG
1539 /* Dummy read ISR to prevent extra link downs/ups */
1540 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1542 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1543 CMSMPrintString(
1544 pAC->pConfigTable,
1545 MSG_TYPE_RUNTIME_INFO,
1546 "CheckUp2 - Stat: %x",
1547 (void *)ExtStat,
1548 (void *)NULL);
1550 #endif /* DEBUG */
1551 return(SK_HW_PS_LINK);
1555 else { /* !AutoNeg */
1556 /* Link is up and we don't need more. */
1557 #ifdef DEBUG
1558 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1559 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1560 ("ERROR: Lipa auto detected on port %d\n", Port));
1562 #endif /* DEBUG */
1564 #ifdef xDEBUG
1565 /* Dummy read ISR to prevent extra link downs/ups */
1566 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1568 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1569 CMSMPrintString(
1570 pAC->pConfigTable,
1571 MSG_TYPE_RUNTIME_INFO,
1572 "CheckUp3 - Stat: %x",
1573 (void *)ExtStat,
1574 (void *)NULL);
1576 #endif /* DEBUG */
1578 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1579 ("Link sync(GP), Port %d\n", Port));
1580 SkHWLinkUp(pAC, IoC, Port);
1582 return(SK_HW_PS_LINK);
1585 return(SK_HW_PS_NONE);
1586 } /* SkGePortCheckUpBcom */
1587 #endif /* GENESIS */
1590 #ifdef YUKON
1591 /******************************************************************************
1593 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1595 * return:
1596 * 0 o.k. nothing needed
1597 * 1 Restart needed on this port
1598 * 2 Link came up
1600 static int SkGePortCheckUpGmac(
1601 SK_AC *pAC, /* Adapter Context */
1602 SK_IOC IoC, /* IO Context */
1603 int Port, /* Which port should be checked */
1604 SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
1606 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1607 int Done;
1608 SK_U16 PhyIsrc; /* PHY Interrupt source */
1609 SK_U16 PhyStat; /* PPY Status */
1610 SK_U16 PhySpecStat;/* PHY Specific Status */
1611 SK_U16 ResAb; /* Master/Slave resolution */
1612 SK_EVPARA Para;
1613 #ifdef DEBUG
1614 SK_U16 Word; /* I/O helper */
1615 #endif /* DEBUG */
1617 pPrt = &pAC->GIni.GP[Port];
1619 if (pPrt->PHWLinkUp) {
1620 return(SK_HW_PS_NONE);
1623 /* Read PHY Status */
1624 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
1626 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1627 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1629 /* Read PHY Interrupt Status */
1630 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
1632 if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
1633 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1634 ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
1637 if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
1638 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1639 ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
1642 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1644 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
1646 if ((ResAb & PHY_B_1000S_MSF) != 0) {
1647 /* Error */
1648 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1649 ("Master/Slave Fault port %d\n", Port));
1651 pPrt->PAutoNegFail = SK_TRUE;
1652 pPrt->PMSStatus = SK_MS_STAT_FAULT;
1654 return(SK_HW_PS_RESTART);
1657 /* Read PHY Specific Status */
1658 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
1660 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1661 ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
1663 #ifdef DEBUG
1664 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
1666 if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
1667 (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) {
1668 /* Read PHY Next Page Link Partner */
1669 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
1671 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1672 ("Page Received, NextPage: 0x%04X\n", Word));
1674 #endif /* DEBUG */
1676 if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
1677 return(SK_HW_PS_NONE);
1680 if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
1681 (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
1682 /* Downshift detected */
1683 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
1685 Para.Para64 = Port;
1686 SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
1688 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1689 ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
1692 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1693 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1695 pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
1697 if (AutoNeg) {
1698 /* Auto-Negotiation Over ? */
1699 if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1701 SkHWLinkUp(pAC, IoC, Port);
1703 Done = SkMacAutoNegDone(pAC, IoC, Port);
1705 if (Done != SK_AND_OK) {
1706 return(SK_HW_PS_RESTART);
1709 return(SK_HW_PS_LINK);
1712 else { /* !AutoNeg */
1713 /* Link is up and we don't need more */
1714 #ifdef DEBUG
1715 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1716 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1717 ("ERROR: Lipa auto detected on port %d\n", Port));
1719 #endif /* DEBUG */
1721 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1722 ("Link sync, Port %d\n", Port));
1723 SkHWLinkUp(pAC, IoC, Port);
1725 return(SK_HW_PS_LINK);
1728 return(SK_HW_PS_NONE);
1729 } /* SkGePortCheckUpGmac */
1730 #endif /* YUKON */
1733 #ifdef OTHER_PHY
1734 /******************************************************************************
1736 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1738 * return:
1739 * 0 o.k. nothing needed
1740 * 1 Restart needed on this port
1741 * 2 Link came up
1743 static int SkGePortCheckUpLone(
1744 SK_AC *pAC, /* Adapter Context */
1745 SK_IOC IoC, /* IO Context */
1746 int Port, /* Which port should be checked */
1747 SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
1749 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1750 int Done;
1751 SK_U16 Isrc; /* Interrupt source register */
1752 SK_U16 LpAb; /* Link Partner Ability */
1753 SK_U16 ExtStat; /* Extended Status Register */
1754 SK_U16 PhyStat; /* Phy Status Register */
1755 SK_U16 StatSum;
1756 SK_U8 NextMode; /* Next AutoSensing Mode */
1758 pPrt = &pAC->GIni.GP[Port];
1760 if (pPrt->PHWLinkUp) {
1761 return(SK_HW_PS_NONE);
1764 StatSum = pPrt->PIsave;
1765 pPrt->PIsave = 0;
1768 * here we usually can check whether the link is in sync and
1769 * auto-negotiation is done.
1771 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
1772 StatSum |= PhyStat;
1774 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1776 if ((PhyStat & PHY_ST_LSYNC) == 0) {
1777 /* Save Auto-negotiation Done bit */
1778 pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
1779 #ifdef DEBUG
1780 if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
1781 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1782 ("AutoNeg done rescheduled Port %d\n", Port));
1784 #endif /* DEBUG */
1785 return(SK_HW_PS_NONE);
1788 if (AutoNeg) {
1789 if ((StatSum & PHY_ST_AN_OVER) != 0) {
1790 SkHWLinkUp(pAC, IoC, Port);
1791 Done = SkMacAutoNegDone(pAC, IoC, Port);
1792 if (Done != SK_AND_OK) {
1793 /* Get PHY parameters, for debugging only */
1794 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
1795 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
1796 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1797 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1798 Port, LpAb, ExtStat));
1800 /* Try next possible mode */
1801 NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1802 SkHWLinkDown(pAC, IoC, Port);
1803 if (Done == SK_AND_DUP_CAP) {
1804 /* GoTo next mode */
1805 SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1808 return(SK_HW_PS_RESTART);
1811 else {
1813 * Dummy Read interrupt status to prevent
1814 * extra link down/ups
1816 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1817 return(SK_HW_PS_LINK);
1821 /* AutoNeg not done, but HW link is up. Check for timeouts */
1822 pPrt->PAutoNegTimeOut++;
1823 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1824 /* Timeout occured */
1825 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1826 ("AutoNeg timeout Port %d\n", Port));
1827 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1828 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1829 /* Set Link manually up */
1830 SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1831 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1832 ("Set manual full duplex Port %d\n", Port));
1835 /* Do the restart */
1836 return(SK_HW_PS_RESTART);
1839 else {
1840 /* Link is up and we don't need more */
1841 #ifdef DEBUG
1842 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1843 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1844 ("ERROR: Lipa auto detected on port %d\n", Port));
1846 #endif /* DEBUG */
1849 * Dummy Read interrupt status to prevent
1850 * extra link down/ups
1852 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1854 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1855 ("Link sync(GP), Port %d\n", Port));
1856 SkHWLinkUp(pAC, IoC, Port);
1858 return(SK_HW_PS_LINK);
1861 return(SK_HW_PS_NONE);
1862 } /* SkGePortCheckUpLone */
1865 /******************************************************************************
1867 * SkGePortCheckUpNat() - Check if the link is up on National PHY
1869 * return:
1870 * 0 o.k. nothing needed
1871 * 1 Restart needed on this port
1872 * 2 Link came up
1874 static int SkGePortCheckUpNat(
1875 SK_AC *pAC, /* Adapter Context */
1876 SK_IOC IoC, /* IO Context */
1877 int Port, /* Which port should be checked */
1878 SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
1880 /* todo: National */
1881 return(SK_HW_PS_NONE);
1882 } /* SkGePortCheckUpNat */
1883 #endif /* OTHER_PHY */
1886 /******************************************************************************
1888 * SkGeSirqEvent() - Event Service Routine
1890 * Description:
1892 * Notes:
1894 int SkGeSirqEvent(
1895 SK_AC *pAC, /* Adapter Context */
1896 SK_IOC IoC, /* Io Context */
1897 SK_U32 Event, /* Module specific Event */
1898 SK_EVPARA Para) /* Event specific Parameter */
1900 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1901 SK_U32 Port;
1902 SK_U32 Val32;
1903 int PortStat;
1904 SK_U8 Val8;
1905 #ifdef GENESIS
1906 SK_U64 Octets;
1907 #endif /* GENESIS */
1909 Port = Para.Para32[0];
1910 pPrt = &pAC->GIni.GP[Port];
1912 switch (Event) {
1913 case SK_HWEV_WATIM:
1914 if (pPrt->PState == SK_PRT_RESET) {
1916 PortStat = SK_HW_PS_NONE;
1918 else {
1919 /* Check whether port came up */
1920 PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
1923 switch (PortStat) {
1924 case SK_HW_PS_RESTART:
1925 if (pPrt->PHWLinkUp) {
1926 /* Set Link to down */
1927 SkHWLinkDown(pAC, IoC, (int)Port);
1930 * Signal directly to RLMT to ensure correct
1931 * sequence of SWITCH and RESET event.
1933 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1936 /* Restart needed */
1937 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1938 break;
1940 case SK_HW_PS_LINK:
1941 /* Signal to RLMT */
1942 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
1943 break;
1946 /* Start again the check Timer */
1947 if (pPrt->PHWLinkUp) {
1948 Val32 = SK_WA_ACT_TIME;
1950 else {
1951 Val32 = SK_WA_INA_TIME;
1954 /* Todo: still needed for non-XMAC PHYs??? */
1955 /* Start workaround Errata #2 timer */
1956 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
1957 SKGE_HWAC, SK_HWEV_WATIM, Para);
1958 break;
1960 case SK_HWEV_PORT_START:
1961 if (pPrt->PHWLinkUp) {
1963 * Signal directly to RLMT to ensure correct
1964 * sequence of SWITCH and RESET event.
1966 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1969 SkHWLinkDown(pAC, IoC, (int)Port);
1971 /* Schedule Port RESET */
1972 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1974 /* Start workaround Errata #2 timer */
1975 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
1976 SKGE_HWAC, SK_HWEV_WATIM, Para);
1977 break;
1979 case SK_HWEV_PORT_STOP:
1980 if (pPrt->PHWLinkUp) {
1982 * Signal directly to RLMT to ensure correct
1983 * sequence of SWITCH and RESET event.
1985 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1988 /* Stop Workaround Timer */
1989 SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
1991 SkHWLinkDown(pAC, IoC, (int)Port);
1992 break;
1994 case SK_HWEV_UPDATE_STAT:
1995 /* We do NOT need to update any statistics */
1996 break;
1998 case SK_HWEV_CLEAR_STAT:
1999 /* We do NOT need to clear any statistics */
2000 for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
2001 pPrt->PPrevRx = 0;
2002 pPrt->PPrevFcs = 0;
2003 pPrt->PPrevShorts = 0;
2005 break;
2007 case SK_HWEV_SET_LMODE:
2008 Val8 = (SK_U8)Para.Para32[1];
2009 if (pPrt->PLinkModeConf != Val8) {
2010 /* Set New link mode */
2011 pPrt->PLinkModeConf = Val8;
2013 /* Restart Port */
2014 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2015 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2017 break;
2019 case SK_HWEV_SET_FLOWMODE:
2020 Val8 = (SK_U8)Para.Para32[1];
2021 if (pPrt->PFlowCtrlMode != Val8) {
2022 /* Set New Flow Control mode */
2023 pPrt->PFlowCtrlMode = Val8;
2025 /* Restart Port */
2026 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2027 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2029 break;
2031 case SK_HWEV_SET_ROLE:
2032 /* not possible for fiber */
2033 if (!pAC->GIni.GICopperType) {
2034 break;
2036 Val8 = (SK_U8)Para.Para32[1];
2037 if (pPrt->PMSMode != Val8) {
2038 /* Set New Role (Master/Slave) mode */
2039 pPrt->PMSMode = Val8;
2041 /* Restart Port */
2042 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2043 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2045 break;
2047 case SK_HWEV_SET_SPEED:
2048 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
2049 break;
2051 Val8 = (SK_U8)Para.Para32[1];
2052 if (pPrt->PLinkSpeed != Val8) {
2053 /* Set New Speed parameter */
2054 pPrt->PLinkSpeed = Val8;
2056 /* Restart Port */
2057 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2058 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2060 break;
2062 #ifdef GENESIS
2063 case SK_HWEV_HALFDUP_CHK:
2064 if (pAC->GIni.GIGenesis) {
2066 * half duplex hangup workaround.
2067 * See packet arbiter timeout interrupt for description
2069 pPrt->HalfDupTimerActive = SK_FALSE;
2070 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
2071 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
2072 /* Snap statistic counters */
2073 (void)SkXmUpdateStats(pAC, IoC, Port);
2075 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
2077 Octets = (SK_U64)Val32 << 32;
2079 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
2081 Octets += Val32;
2083 if (pPrt->LastOctets == Octets) {
2084 /* Tx hanging, a FIFO flush restarts it */
2085 SkMacFlushTxFifo(pAC, IoC, Port);
2089 break;
2090 #endif /* GENESIS */
2092 default:
2093 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
2094 break;
2097 return(0);
2098 } /* SkGeSirqEvent */
2101 #ifdef GENESIS
2102 /******************************************************************************
2104 * SkPhyIsrBcom() - PHY interrupt service routine
2106 * Description: handles all interrupts from BCom PHY
2108 * Returns: N/A
2110 static void SkPhyIsrBcom(
2111 SK_AC *pAC, /* Adapter Context */
2112 SK_IOC IoC, /* Io Context */
2113 int Port, /* Port Num = PHY Num */
2114 SK_U16 IStatus) /* Interrupt Status */
2116 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2117 SK_EVPARA Para;
2119 pPrt = &pAC->GIni.GP[Port];
2121 if ((IStatus & PHY_B_IS_PSE) != 0) {
2122 /* Incorrectable pair swap error */
2123 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
2124 SKERR_SIRQ_E022MSG);
2127 if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
2129 SkHWLinkDown(pAC, IoC, Port);
2131 Para.Para32[0] = (SK_U32)Port;
2132 /* Signal to RLMT */
2133 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2135 /* Start workaround Errata #2 timer */
2136 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
2137 SKGE_HWAC, SK_HWEV_WATIM, Para);
2140 } /* SkPhyIsrBcom */
2141 #endif /* GENESIS */
2144 #ifdef YUKON
2145 /******************************************************************************
2147 * SkPhyIsrGmac() - PHY interrupt service routine
2149 * Description: handles all interrupts from Marvell PHY
2151 * Returns: N/A
2153 static void SkPhyIsrGmac(
2154 SK_AC *pAC, /* Adapter Context */
2155 SK_IOC IoC, /* Io Context */
2156 int Port, /* Port Num = PHY Num */
2157 SK_U16 IStatus) /* Interrupt Status */
2159 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2160 SK_EVPARA Para;
2161 SK_U16 Word;
2163 pPrt = &pAC->GIni.GP[Port];
2165 if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
2167 SkHWLinkDown(pAC, IoC, Port);
2169 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
2171 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2172 ("AutoNeg.Adv: 0x%04X\n", Word));
2174 /* Set Auto-negotiation advertisement */
2175 if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
2176 /* restore Asymmetric Pause bit */
2177 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
2178 (SK_U16)(Word | PHY_M_AN_ASP));
2181 Para.Para32[0] = (SK_U32)Port;
2182 /* Signal to RLMT */
2183 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2186 if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
2187 /* Auto-Negotiation Error */
2188 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
2191 if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
2192 /* FIFO Overflow/Underrun Error */
2193 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
2196 } /* SkPhyIsrGmac */
2197 #endif /* YUKON */
2200 #ifdef OTHER_PHY
2201 /******************************************************************************
2203 * SkPhyIsrLone() - PHY interrupt service routine
2205 * Description: handles all interrupts from LONE PHY
2207 * Returns: N/A
2209 static void SkPhyIsrLone(
2210 SK_AC *pAC, /* Adapter Context */
2211 SK_IOC IoC, /* Io Context */
2212 int Port, /* Port Num = PHY Num */
2213 SK_U16 IStatus) /* Interrupt Status */
2215 SK_EVPARA Para;
2217 if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
2219 SkHWLinkDown(pAC, IoC, Port);
2221 Para.Para32[0] = (SK_U32)Port;
2222 /* Signal to RLMT */
2223 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2226 } /* SkPhyIsrLone */
2227 #endif /* OTHER_PHY */
2229 /* End of File */