1 /******************************************************************************
4 * Project: Gigabit Ethernet Adapters, Common Modules
5 * Purpose: Special IRQ module
7 ******************************************************************************/
9 /******************************************************************************
11 * (C)Copyright 1998-2002 SysKonnect.
12 * (C)Copyright 2002-2003 Marvell.
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.
19 * The information in this file is provided "AS IS" without warranty.
21 ******************************************************************************/
24 * Special Interrupt handler
26 * The following abstract should show how this module is included
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.
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
43 * However, the MAC Interrupt status registers are read in a while loop.
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.";
52 #include "h/skdrv1st.h" /* Driver Specific Definitions */
54 #include "h/skgepnmi.h" /* PNMI Definitions */
55 #include "h/skrlmt.h" /* RLMT Definitions */
57 #include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
59 /* local function prototypes */
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);
66 static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
67 static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
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 */
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.
80 static const SK_U16 SkGeRxRegs[]= {
92 * Special IRQ function
94 * General Description:
101 /******************************************************************************
103 * SkHWInitDefSense() - Default Autosensing mode initialization
105 * Description: sets the PLinkMode for HWInit
109 static void SkHWInitDefSense(
110 SK_AC *pAC, /* adapter context */
111 SK_IOC IoC, /* IO context */
112 int Port) /* Port Index (MAC_1 + n) */
114 SK_GEPORT *pPrt; /* GIni Port struct pointer */
116 pPrt = &pAC->GIni.GP[Port];
118 pPrt->PAutoNegTimeOut = 0;
120 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
121 pPrt->PLinkMode = pPrt->PLinkModeConf;
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));
129 pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
132 } /* SkHWInitDefSense */
136 /******************************************************************************
138 * SkHWSenseGetNext() - Get Next Autosensing Mode
140 * Description: gets the appropriate next mode
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) */
150 SK_GEPORT *pPrt; /* GIni Port struct pointer */
152 pPrt = &pAC->GIni.GP[Port];
154 pPrt->PAutoNegTimeOut = 0;
156 if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
157 /* Leave all as configured */
158 return(pPrt->PLinkModeConf);
161 if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
162 /* Return next mode AUTOBOTH */
163 return ((SK_U8)SK_LMODE_AUTOBOTH);
166 /* Return default autofull */
167 return ((SK_U8)SK_LMODE_AUTOFULL);
168 } /* SkHWSenseGetNext */
171 /******************************************************************************
173 * SkHWSenseSetNext() - Autosensing Set next mode
175 * Description: sets the appropriate next mode
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 */
185 SK_GEPORT *pPrt; /* GIni Port struct pointer */
187 pPrt = &pAC->GIni.GP[Port];
189 pPrt->PAutoNegTimeOut = 0;
191 if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
195 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
196 ("AutoSensing: next mode %d on Port %d\n",
197 (int)NewMode, Port));
199 pPrt->PLinkMode = NewMode;
202 } /* SkHWSenseSetNext */
206 /******************************************************************************
208 * SkHWLinkDown() - Link Down handling
210 * Description: handles the hardware link down signal
215 SK_AC *pAC, /* adapter context */
216 SK_IOC IoC, /* IO context */
217 int Port) /* Port Index (MAC_1 + n) */
219 SK_GEPORT *pPrt; /* GIni Port struct pointer */
221 pPrt = &pAC->GIni.GP[Port];
223 /* Disable all MAC interrupts */
224 SkMacIrqDisable(pAC, IoC, Port);
226 /* Disable Receiver and Transmitter */
227 SkMacRxTxDisable(pAC, IoC, Port);
229 /* Init default sense mode */
230 SkHWInitDefSense(pAC, IoC, Port);
232 if (pPrt->PHWLinkUp == SK_FALSE) {
236 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
237 ("Link down Port %d\n", Port));
239 /* Set Link to DOWN */
240 pPrt->PHWLinkUp = SK_FALSE;
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;
247 /* Re-init Phy especially when the AutoSense default is set now */
248 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
250 /* GP0: used for workaround of Rev. C Errata 2 */
252 /* Do NOT signal to RLMT */
254 /* Do NOT start the timer here */
258 /******************************************************************************
260 * SkHWLinkUp() - Link Up handling
262 * Description: handles the hardware link up signal
267 SK_AC *pAC, /* adapter context */
268 SK_IOC IoC, /* IO context */
269 int Port) /* Port Index (MAC_1 + n) */
271 SK_GEPORT *pPrt; /* GIni Port struct pointer */
273 pPrt = &pAC->GIni.GP[Port];
275 if (pPrt->PHWLinkUp) {
276 /* We do NOT need to proceed on active link */
280 pPrt->PHWLinkUp = SK_TRUE;
281 pPrt->PAutoNegFail = SK_FALSE;
282 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
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 */
289 /* Link speed should be the configured one */
290 switch (pPrt->PLinkSpeed) {
292 /* default is 1000 Mbps */
293 case SK_LSPEED_1000MBPS:
294 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
296 case SK_LSPEED_100MBPS:
297 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
299 case SK_LSPEED_10MBPS:
300 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
304 /* Set Link Mode Status */
305 if (pPrt->PLinkMode == SK_LMODE_FULL) {
306 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
309 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
312 /* No flow control without auto-negotiation */
313 pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
316 (void)SkMacRxTxEnable(pAC, IoC, Port);
321 /******************************************************************************
323 * SkMacParity() - MAC parity workaround
325 * Description: handles MAC parity errors correctly
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 */
335 SK_GEPORT *pPrt; /* GIni Port struct pointer */
336 SK_U32 TxMax; /* Tx Max Size Counter */
338 pPrt = &pAC->GIni.GP[Port];
340 /* Clear IRQ Tx Parity Error */
342 if (pAC->GIni.GIGenesis) {
344 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
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));
357 if (pPrt->PCheckPar) {
360 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
363 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
366 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
368 Para.Para32[0] = Port;
369 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
374 /* Check whether frames with a size of 1k were sent */
376 if (pAC->GIni.GIGenesis) {
377 /* Snap statistic counters */
378 (void)SkXmUpdateStats(pAC, IoC, Port);
380 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
385 if (pAC->GIni.GIYukon) {
387 (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
392 /* From now on check the parity */
393 pPrt->PCheckPar = SK_TRUE;
398 /******************************************************************************
400 * SkGeHwErr() - Hardware Error service routine
402 * Description: handles all HW Error interrupts
406 static void SkGeHwErr(
407 SK_AC *pAC, /* adapter context */
408 SK_IOC IoC, /* IO context */
409 SK_U32 HwStatus) /* Interrupt status word */
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);
420 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
423 /* Reset all bits in the PCI STATUS register */
424 SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
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);
431 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
435 if (pAC->GIni.GIGenesis) {
437 if ((HwStatus & IS_NO_STAT_M1) != 0) {
439 /* This situation is also indicated in the descriptor */
440 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
443 if ((HwStatus & IS_NO_STAT_M2) != 0) {
445 /* This situation is also indicated in the descriptor */
446 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
449 if ((HwStatus & IS_NO_TIST_M1) != 0) {
451 /* This situation is also indicated in the descriptor */
452 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
455 if ((HwStatus & IS_NO_TIST_M2) != 0) {
457 /* This situation is also indicated in the descriptor */
458 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
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++;
470 /* Clear Time Stamp Timer IRQ */
471 SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
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;
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);
488 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
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);
495 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
498 if ((HwStatus & IS_M1_PAR_ERR) != 0) {
499 SkMacParity(pAC, IoC, MAC_1);
502 if ((HwStatus & IS_M2_PAR_ERR) != 0) {
503 SkMacParity(pAC, IoC, MAC_2);
506 if ((HwStatus & IS_R1_PAR_ERR) != 0) {
508 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
510 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
512 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
514 Para.Para32[0] = MAC_1;
515 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
518 if ((HwStatus & IS_R2_PAR_ERR) != 0) {
520 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
522 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
524 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
526 Para.Para32[0] = MAC_2;
527 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
532 /******************************************************************************
534 * SkGeSirqIsr() - Special Interrupt Service Routine
536 * Description: handles all non data transfer specific interrupts (slow path)
541 SK_AC *pAC, /* adapter context */
542 SK_IOC IoC, /* IO context */
543 SK_U32 Istatus) /* Interrupt status word */
546 SK_U32 RegVal32; /* Read register value */
547 SK_GEPORT *pPrt; /* GIni Port struct pointer */
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);
555 SkGeHwErr(pAC, IoC, RegVal32);
559 * Packet Timeout interrupts
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,
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,
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,
580 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
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,
587 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
590 if ((Istatus & IS_PA_TO_TX1) != 0) {
592 pPrt = &pAC->GIni.GP[0];
594 /* May be a normal situation in a server with a slow network */
595 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
598 if (pAC->GIni.GIGenesis) {
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).
605 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
606 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
607 !pPrt->HalfDupTimerActive) {
609 * many more pack. arb. timeouts may come in between,
612 pPrt->HalfDupTimerActive = SK_TRUE;
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);
619 pPrt->LastOctets = Octets;
621 /* Snap statistic counters */
622 (void)SkXmUpdateStats(pAC, IoC, 0);
624 (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
626 pPrt->LastOctets = (SK_U64)RegVal32 << 32;
628 (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
630 pPrt->LastOctets += RegVal32;
633 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
634 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
640 if ((Istatus & IS_PA_TO_TX2) != 0) {
642 pPrt = &pAC->GIni.GP[1];
644 /* May be a normal situation in a server with a slow network */
645 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
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;
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);
660 pPrt->LastOctets = Octets;
662 /* Snap statistic counters */
663 (void)SkXmUpdateStats(pAC, IoC, 1);
665 (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
667 pPrt->LastOctets = (SK_U64)RegVal32 << 32;
669 (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
671 pPrt->LastOctets += RegVal32;
674 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
675 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
681 /* Check interrupts of the particular queues */
682 if ((Istatus & IS_R1_C) != 0) {
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,
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);
693 if ((Istatus & IS_R2_C) != 0) {
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,
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);
704 if ((Istatus & IS_XS1_C) != 0) {
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,
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);
715 if ((Istatus & IS_XA1_C) != 0) {
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,
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);
726 if ((Istatus & IS_XS2_C) != 0) {
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,
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);
737 if ((Istatus & IS_XA2_C) != 0) {
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,
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);
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++) {
753 pPrt = &pAC->GIni.GP[i];
755 if (pPrt->PState == SK_PRT_RESET) {
760 if (pAC->GIni.GIGenesis) {
762 switch (pPrt->PhyType) {
768 SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
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",
774 SkPhyIsrBcom(pAC, IoC, i, PhyInt);
779 SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
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",
785 SkPhyIsrLone(pAC, IoC, i, PhyInt);
788 #endif /* OTHER_PHY */
794 if (pAC->GIni.GIYukon) {
795 /* Read PHY Interrupt Status */
796 SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
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",
802 SkPhyIsrGmac(pAC, IoC, i, PhyInt);
809 /* I2C Ready interrupt */
810 if ((Istatus & IS_I2C_READY) != 0) {
812 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
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);
824 if ((Istatus & IS_LNK_SYNC_M1) != 0) {
826 * We do NOT need the Link Sync interrupt, because it shows
827 * us only a link going down.
829 /* clear interrupt */
830 SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
833 /* Check MAC after link sync counter */
834 if ((Istatus & IS_MAC1) != 0) {
836 SkMacIrq(pAC, IoC, MAC_1);
839 if ((Istatus & IS_LNK_SYNC_M2) != 0) {
841 * We do NOT need the Link Sync interrupt, because it shows
842 * us only a link going down.
844 /* clear interrupt */
845 SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
848 /* Check MAC after link sync counter */
849 if ((Istatus & IS_MAC2) != 0) {
851 SkMacIrq(pAC, IoC, MAC_2);
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);
861 SkGeHwErr(pAC, IoC, RegVal32);
871 /******************************************************************************
873 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
876 * 0 o.k. nothing needed
877 * 1 Restart needed on this 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 */
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 */
893 pPrt = &pAC->GIni.GP[Port];
895 /* Default: no action */
898 (void)SkXmUpdateStats(pAC, IoC, Port);
900 /* Extra precaution: check for short Event counter */
901 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
904 * Read Rx counters (packets seen on the network and not necessarily
909 for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
911 (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
913 RxCts += (SK_U64)RxTmp;
916 /* On default: check shorts against zero */
919 /* Extra precaution on active links */
920 if (pPrt->PHWLinkUp) {
921 /* Reset Link Restart counter */
922 pPrt->PLinkResCt = 0;
923 pPrt->PAutoNegTOCt = 0;
925 /* If link is up check for 2 */
928 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
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)) {
935 * This is autosensing and we are in the fallback
936 * manual full/half duplex mode.
938 if (RxCts == pPrt->PPrevRx) {
939 /* Nothing received, restart link */
940 pPrt->PPrevFcs = FcsErrCts;
941 pPrt->PPrevShorts = Shorts;
943 return(SK_HW_PS_RESTART);
946 pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
950 if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
951 (!(FcsErrCts - pPrt->PPrevFcs))) {
953 * Note: The compare with zero above has to be done the way shown,
954 * otherwise the Linux driver will have a problem.
957 * We received a bunch of frames or no CRC error occured on the
960 pPrt->PPrevRx = RxCts;
961 pPrt->PPrevFcs = FcsErrCts;
962 pPrt->PPrevShorts = Shorts;
964 return(SK_HW_PS_NONE);
967 pPrt->PPrevFcs = FcsErrCts;
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;
977 pPrt->PPrevShorts = Shorts;
978 pPrt->PPrevRx = RxCts;
981 } /* SkGePortCheckShorts */
985 /******************************************************************************
987 * SkGePortCheckUp() - Check if the link is up
990 * 0 o.k. nothing needed
991 * 1 Restart needed on this 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 */
999 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1000 SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
1001 int Rtv; /* Return value */
1003 Rtv = SK_HW_PS_NONE;
1005 pPrt = &pAC->GIni.GP[Port];
1007 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1015 if (pAC->GIni.GIGenesis) {
1017 switch (pPrt->PhyType) {
1020 Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
1023 Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
1027 Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
1030 Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
1032 #endif /* OTHER_PHY */
1035 #endif /* GENESIS */
1038 if (pAC->GIni.GIYukon) {
1040 Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
1045 } /* SkGePortCheckUp */
1049 /******************************************************************************
1051 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1054 * 0 o.k. nothing needed
1055 * 1 Restart needed on this port
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 ? */
1064 SK_U32 Shorts; /* Short Event Counter */
1065 SK_GEPORT *pPrt; /* GIni Port struct pointer */
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 */
1075 pPrt = &pAC->GIni.GP[Port];
1077 if (pPrt->PHWLinkUp) {
1078 if (pPrt->PhyType != SK_PHY_XMAC) {
1079 return(SK_HW_PS_NONE);
1082 return(SkGePortCheckShorts(pAC, IoC, Port));
1086 IsrcSum = pPrt->PIsave;
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);
1094 if ((GpReg & XM_GP_INP_ASS) == 0) {
1095 /* The Link is in sync */
1096 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1098 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
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));
1106 (void)SkXmUpdateStats(pAC, IoC, Port);
1108 /* We now need to reinitialize the PrevShorts counter */
1109 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
1110 pPrt->PPrevShorts = Shorts;
1112 pPrt->PLinkBroken = SK_FALSE;
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.
1126 pPrt->PAutoNegTimeOut = 0;
1128 if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
1129 return(SK_HW_PS_RESTART);
1132 pPrt->PLinkResCt = 0;
1134 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1135 ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
1138 pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1140 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1141 ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
1143 /* Do nothing more if link is broken */
1144 return(SK_HW_PS_NONE);
1148 /* Do nothing more if link is broken */
1149 return(SK_HW_PS_NONE);
1154 /* Link was not broken, check if it is */
1155 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1157 if ((Isrc & XM_IS_INP_ASS) != 0) {
1158 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1160 if ((Isrc & XM_IS_INP_ASS) != 0) {
1161 XM_IN16(IoC, Port, XM_ISRC, &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));
1170 /* Cable removed-> reinit sense mode */
1171 SkHWInitDefSense(pAC, IoC, Port);
1173 return(SK_HW_PS_RESTART);
1178 SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
1180 if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
1181 return(SK_HW_PS_RESTART);
1187 * here we usually can check whether the link is in sync and
1188 * auto-negotiation is done.
1190 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1191 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1194 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
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);
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));
1207 return(SK_HW_PS_NONE);
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));
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);
1230 return(SK_HW_PS_RESTART);
1233 * Dummy Read extended status to prevent extra link down/ups
1234 * (clear Page Received bit if set)
1236 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
1238 return(SK_HW_PS_LINK);
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++;
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));
1258 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1259 pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
1260 pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
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
1268 * Solution: we restart the autosensing after
1271 pPrt->PAutoNegTOCt = 0;
1272 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1273 SkHWInitDefSense(pAC, IoC, Port);
1276 /* Do the restart */
1277 return(SK_HW_PS_RESTART);
1281 /* Link is up and we don't need more */
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));
1288 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1289 ("Link sync(GP), Port %d\n", Port));
1290 SkHWLinkUp(pAC, IoC, Port);
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.
1297 return(SK_HW_PS_LINK);
1300 return(SK_HW_PS_NONE);
1301 } /* SkGePortCheckUpXmac */
1304 /******************************************************************************
1306 * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
1309 * 0 o.k. nothing needed
1310 * 1 Restart needed on this port
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 ? */
1319 SK_GEPORT *pPrt; /* GIni Port struct pointer */
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 */
1330 pPrt = &pAC->GIni.GP[Port];
1332 /* Check for No HCD Link events (#10523) */
1333 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
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)) {
1339 SK_U32 Stat1, Stat2, Stat3;
1342 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1345 MSG_TYPE_RUNTIME_INFO,
1346 "CheckUp1 - Stat: %x, Mask: %x",
1351 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1353 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
1354 Stat1 = Stat1 << 16 | Stat2;
1356 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1358 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1359 Stat2 = Stat2 << 16 | Stat3;
1362 MSG_TYPE_RUNTIME_INFO,
1363 "Ctrl/Stat: %x, AN Adv/LP: %x",
1368 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1370 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1371 Stat1 = Stat1 << 16 | Stat2;
1373 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1375 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
1376 Stat2 = Stat2 << 16 | Stat3;
1379 MSG_TYPE_RUNTIME_INFO,
1380 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1385 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1387 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1388 Stat1 = Stat1 << 16 | Stat2;
1390 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1392 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1393 Stat2 = Stat2 << 16 | Stat3;
1396 MSG_TYPE_RUNTIME_INFO,
1397 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1403 if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
1405 * Workaround BCom Errata:
1406 * enable and disable loopback mode if "NO HCD" occurs.
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));
1418 MSG_TYPE_RUNTIME_INFO,
1419 "No HCD link event, port %d.",
1425 /* Not obsolete: link status bit is latched to 0 and autoclearing! */
1426 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1428 if (pPrt->PHWLinkUp) {
1429 return(SK_HW_PS_NONE);
1434 SK_U32 Stat1, Stat2, Stat3;
1437 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1440 MSG_TYPE_RUNTIME_INFO,
1441 "CheckUp1a - Stat: %x, Mask: %x",
1446 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1448 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1449 Stat1 = Stat1 << 16 | PhyStat;
1451 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1453 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1454 Stat2 = Stat2 << 16 | Stat3;
1457 MSG_TYPE_RUNTIME_INFO,
1458 "Ctrl/Stat: %x, AN Adv/LP: %x",
1463 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1465 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1466 Stat1 = Stat1 << 16 | Stat2;
1468 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1470 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1471 Stat2 = Stat2 << 16 | ResAb;
1474 MSG_TYPE_RUNTIME_INFO,
1475 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1480 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1482 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1483 Stat1 = Stat1 << 16 | Stat2;
1485 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1487 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1488 Stat2 = Stat2 << 16 | Stat3;
1491 MSG_TYPE_RUNTIME_INFO,
1492 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1499 * Here we usually can check whether the link is in sync and
1500 * auto-negotiation is done.
1503 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1505 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1507 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1508 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1510 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1512 if ((ResAb & PHY_B_1000S_MSF) != 0) {
1514 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1515 ("Master/Slave Fault port %d\n", Port));
1517 pPrt->PAutoNegFail = SK_TRUE;
1518 pPrt->PMSStatus = SK_MS_STAT_FAULT;
1520 return(SK_HW_PS_RESTART);
1523 if ((PhyStat & PHY_ST_LSYNC) == 0) {
1524 return(SK_HW_PS_NONE);
1527 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1528 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1530 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1531 ("Port %d, ResAb: 0x%04X\n", Port, ResAb));
1534 if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1536 SkHWLinkUp(pAC, IoC, Port);
1538 Done = SkMacAutoNegDone(pAC, IoC, Port);
1540 if (Done != SK_AND_OK) {
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));
1549 return(SK_HW_PS_RESTART);
1553 /* Dummy read ISR to prevent extra link downs/ups */
1554 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1556 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1559 MSG_TYPE_RUNTIME_INFO,
1560 "CheckUp2 - Stat: %x",
1565 return(SK_HW_PS_LINK);
1569 else { /* !AutoNeg */
1570 /* Link is up and we don't need more. */
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));
1579 /* Dummy read ISR to prevent extra link downs/ups */
1580 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1582 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1585 MSG_TYPE_RUNTIME_INFO,
1586 "CheckUp3 - Stat: %x",
1592 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1593 ("Link sync(GP), Port %d\n", Port));
1594 SkHWLinkUp(pAC, IoC, Port);
1596 return(SK_HW_PS_LINK);
1599 return(SK_HW_PS_NONE);
1600 } /* SkGePortCheckUpBcom */
1601 #endif /* GENESIS */
1605 /******************************************************************************
1607 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1610 * 0 o.k. nothing needed
1611 * 1 Restart needed on this port
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 ? */
1620 SK_GEPORT *pPrt; /* GIni Port struct pointer */
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 */
1628 SK_U16 Word; /* I/O helper */
1631 pPrt = &pAC->GIni.GP[Port];
1633 if (pPrt->PHWLinkUp) {
1634 return(SK_HW_PS_NONE);
1637 /* Read PHY Status */
1638 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
1640 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1641 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1643 /* Read PHY Interrupt Status */
1644 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
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));
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));
1656 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1658 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
1660 if ((ResAb & PHY_B_1000S_MSF) != 0) {
1662 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1663 ("Master/Slave Fault port %d\n", Port));
1665 pPrt->PAutoNegFail = SK_TRUE;
1666 pPrt->PMSStatus = SK_MS_STAT_FAULT;
1668 return(SK_HW_PS_RESTART);
1671 /* Read PHY Specific Status */
1672 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
1674 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1675 ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
1678 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
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);
1685 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1686 ("Page Received, NextPage: 0x%04X\n", Word));
1690 if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
1691 return(SK_HW_PS_NONE);
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);
1700 SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
1702 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1703 ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
1706 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1707 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1709 pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
1712 /* Auto-Negotiation Over ? */
1713 if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1715 SkHWLinkUp(pAC, IoC, Port);
1717 Done = SkMacAutoNegDone(pAC, IoC, Port);
1719 if (Done != SK_AND_OK) {
1720 return(SK_HW_PS_RESTART);
1723 return(SK_HW_PS_LINK);
1726 else { /* !AutoNeg */
1727 /* Link is up and we don't need more */
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));
1735 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1736 ("Link sync, Port %d\n", Port));
1737 SkHWLinkUp(pAC, IoC, Port);
1739 return(SK_HW_PS_LINK);
1742 return(SK_HW_PS_NONE);
1743 } /* SkGePortCheckUpGmac */
1748 /******************************************************************************
1750 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1753 * 0 o.k. nothing needed
1754 * 1 Restart needed on this port
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 ? */
1763 SK_GEPORT *pPrt; /* GIni Port struct pointer */
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 */
1770 SK_U8 NextMode; /* Next AutoSensing Mode */
1772 pPrt = &pAC->GIni.GP[Port];
1774 if (pPrt->PHWLinkUp) {
1775 return(SK_HW_PS_NONE);
1778 StatSum = pPrt->PIsave;
1782 * here we usually can check whether the link is in sync and
1783 * auto-negotiation is done.
1785 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
1788 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1790 if ((PhyStat & PHY_ST_LSYNC) == 0) {
1791 /* Save Auto-negotiation Done bit */
1792 pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
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));
1799 return(SK_HW_PS_NONE);
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));
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);
1822 return(SK_HW_PS_RESTART);
1827 * Dummy Read interrupt status to prevent
1828 * extra link down/ups
1830 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1831 return(SK_HW_PS_LINK);
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));
1849 /* Do the restart */
1850 return(SK_HW_PS_RESTART);
1854 /* Link is up and we don't need more */
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));
1863 * Dummy Read interrupt status to prevent
1864 * extra link down/ups
1866 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1868 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1869 ("Link sync(GP), Port %d\n", Port));
1870 SkHWLinkUp(pAC, IoC, Port);
1872 return(SK_HW_PS_LINK);
1875 return(SK_HW_PS_NONE);
1876 } /* SkGePortCheckUpLone */
1879 /******************************************************************************
1881 * SkGePortCheckUpNat() - Check if the link is up on National PHY
1884 * 0 o.k. nothing needed
1885 * 1 Restart needed on this port
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 ? */
1894 /* todo: National */
1895 return(SK_HW_PS_NONE);
1896 } /* SkGePortCheckUpNat */
1897 #endif /* OTHER_PHY */
1900 /******************************************************************************
1902 * SkGeSirqEvent() - Event Service Routine
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 */
1914 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1921 #endif /* GENESIS */
1923 Port = Para.Para32[0];
1924 pPrt = &pAC->GIni.GP[Port];
1928 if (pPrt->PState == SK_PRT_RESET) {
1930 PortStat = SK_HW_PS_NONE;
1933 /* Check whether port came up */
1934 PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
1938 case SK_HW_PS_RESTART:
1939 if (pPrt->PHWLinkUp) {
1940 /* Set Link to down */
1941 SkHWLinkDown(pAC, IoC, (int)Port);
1944 * Signal directly to RLMT to ensure correct
1945 * sequence of SWITCH and RESET event.
1947 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1950 /* Restart needed */
1951 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1955 /* Signal to RLMT */
1956 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
1960 /* Start again the check Timer */
1961 if (pPrt->PHWLinkUp) {
1962 Val32 = SK_WA_ACT_TIME;
1965 Val32 = SK_WA_INA_TIME;
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);
1974 case SK_HWEV_PORT_START:
1975 if (pPrt->PHWLinkUp) {
1977 * Signal directly to RLMT to ensure correct
1978 * sequence of SWITCH and RESET event.
1980 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1983 SkHWLinkDown(pAC, IoC, (int)Port);
1985 /* Schedule Port RESET */
1986 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1988 /* Start workaround Errata #2 timer */
1989 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
1990 SKGE_HWAC, SK_HWEV_WATIM, Para);
1993 case SK_HWEV_PORT_STOP:
1994 if (pPrt->PHWLinkUp) {
1996 * Signal directly to RLMT to ensure correct
1997 * sequence of SWITCH and RESET event.
1999 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2002 /* Stop Workaround Timer */
2003 SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
2005 SkHWLinkDown(pAC, IoC, (int)Port);
2008 case SK_HWEV_UPDATE_STAT:
2009 /* We do NOT need to update any statistics */
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++) {
2017 pPrt->PPrevShorts = 0;
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;
2028 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2029 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
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;
2040 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2041 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2045 case SK_HWEV_SET_ROLE:
2046 /* not possible for fiber */
2047 if (!pAC->GIni.GICopperType) {
2050 Val8 = (SK_U8)Para.Para32[1];
2051 if (pPrt->PMSMode != Val8) {
2052 /* Set New Role (Master/Slave) mode */
2053 pPrt->PMSMode = Val8;
2056 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2057 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2061 case SK_HWEV_SET_SPEED:
2062 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
2065 Val8 = (SK_U8)Para.Para32[1];
2066 if (pPrt->PLinkSpeed != Val8) {
2067 /* Set New Speed parameter */
2068 pPrt->PLinkSpeed = Val8;
2071 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2072 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2077 case SK_HWEV_HALFDUP_CHK:
2078 if (pAC->GIni.GIGenesis) {
2080 * half duplex hangup workaround.
2081 * See packet arbiter timeout interrupt for description
2083 pPrt->HalfDupTimerActive = SK_FALSE;
2084 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
2085 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
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);
2092 /* Snap statistic counters */
2093 (void)SkXmUpdateStats(pAC, IoC, Port);
2095 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
2097 Octets = (SK_U64)Val32 << 32;
2099 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
2103 if (pPrt->LastOctets == Octets) {
2104 /* Tx hanging, a FIFO flush restarts it */
2105 SkMacFlushTxFifo(pAC, IoC, Port);
2110 #endif /* GENESIS */
2113 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
2118 } /* SkGeSirqEvent */
2122 /******************************************************************************
2124 * SkPhyIsrBcom() - PHY interrupt service routine
2126 * Description: handles all interrupts from BCom PHY
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 */
2136 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2139 pPrt = &pAC->GIni.GP[Port];
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);
2147 if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
2149 SkHWLinkDown(pAC, IoC, Port);
2151 Para.Para32[0] = (SK_U32)Port;
2152 /* Signal to RLMT */
2153 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2155 /* Start workaround Errata #2 timer */
2156 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
2157 SKGE_HWAC, SK_HWEV_WATIM, Para);
2160 } /* SkPhyIsrBcom */
2161 #endif /* GENESIS */
2165 /******************************************************************************
2167 * SkPhyIsrGmac() - PHY interrupt service routine
2169 * Description: handles all interrupts from Marvell PHY
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 */
2179 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2183 pPrt = &pAC->GIni.GP[Port];
2185 if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
2187 SkHWLinkDown(pAC, IoC, Port);
2189 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
2191 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2192 ("AutoNeg.Adv: 0x%04X\n", Word));
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));
2201 Para.Para32[0] = (SK_U32)Port;
2202 /* Signal to RLMT */
2203 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
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);
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);
2216 } /* SkPhyIsrGmac */
2221 /******************************************************************************
2223 * SkPhyIsrLone() - PHY interrupt service routine
2225 * Description: handles all interrupts from LONE PHY
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 */
2237 if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
2239 SkHWLinkDown(pAC, IoC, Port);
2241 Para.Para32[0] = (SK_U32)Port;
2242 /* Signal to RLMT */
2243 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2246 } /* SkPhyIsrLone */
2247 #endif /* OTHER_PHY */