1 /******************************************************************************
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
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
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.";
54 #include "h/skdrv1st.h" /* Driver Specific Definitions */
56 #include "h/skgepnmi.h" /* PNMI Definitions */
57 #include "h/skrlmt.h" /* RLMT Definitions */
59 #include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
61 /* local function prototypes */
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
);
68 static int SkGePortCheckUpGmac(SK_AC
*, SK_IOC
, int, SK_BOOL
);
69 static void SkPhyIsrGmac(SK_AC
*, SK_IOC
, int, SK_U16
);
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 */
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
[]= {
94 * Special IRQ function
96 * General Description:
103 /******************************************************************************
105 * SkHWInitDefSense() - Default Autosensing mode initialization
107 * Description: sets the PLinkMode for HWInit
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
;
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
;
134 } /* SkHWInitDefSense */
138 /******************************************************************************
140 * SkHWSenseGetNext() - Get Next Autosensing Mode
142 * Description: gets the appropriate next mode
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
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
) {
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
;
204 } /* SkHWSenseSetNext */
208 /******************************************************************************
210 * SkHWLinkDown() - Link Down handling
212 * Description: handles the hardware link down signal
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
) {
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 */
260 /******************************************************************************
262 * SkHWLinkUp() - Link Up handling
264 * Description: handles the hardware link up signal
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 */
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
) {
294 /* default is 1000 Mbps */
295 case SK_LSPEED_1000MBPS
:
296 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_1000MBPS
;
298 case SK_LSPEED_100MBPS
:
299 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_100MBPS
;
301 case SK_LSPEED_10MBPS
:
302 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_10MBPS
;
306 /* Set Link Mode Status */
307 if (pPrt
->PLinkMode
== SK_LMODE_FULL
) {
308 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_FULL
;
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
;
318 (void)SkMacRxTxEnable(pAC
, IoC
, Port
);
323 /******************************************************************************
325 * SkMacParity() - MAC parity workaround
327 * Description: handles MAC parity errors correctly
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 */
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 */
344 if (pAC
->GIni
.GIGenesis
) {
346 SK_OUT16(IoC
, MR_ADDR(Port
, TX_MFF_CTRL1
), MFF_CLR_PERR
);
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
));
359 if (pPrt
->PCheckPar
) {
362 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_SIRQ_E016
, SKERR_SIRQ_E016MSG
);
365 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_SIRQ_E017
, SKERR_SIRQ_E017MSG
);
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
);
376 /* Check whether frames with a size of 1k were sent */
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
);
387 if (pAC
->GIni
.GIYukon
) {
389 (void)SkGmMacStatistic(pAC
, IoC
, Port
, GM_TXF_1518B
, &TxMax
);
394 /* From now on check the parity */
395 pPrt
->PCheckPar
= SK_TRUE
;
400 /******************************************************************************
402 * SkGeHwErr() - Hardware Error service routine
404 * Description: handles all HW Error interrupts
408 static void SkGeHwErr(
409 SK_AC
*pAC
, /* adapter context */
410 SK_IOC IoC
, /* IO context */
411 SK_U32 HwStatus
) /* Interrupt status 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
);
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
);
433 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_ADAP_FAIL
, Para
);
437 if (pAC
->GIni
.GIGenesis
) {
439 if ((HwStatus
& IS_NO_STAT_M1
) != 0) {
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) {
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) {
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) {
459 /* This situation is also indicated in the descriptor */
460 SK_OUT16(IoC
, MR_ADDR(MAC_2
, RX_MFF_CTRL1
), MFF_CLR_INTIST
);
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
;
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
);
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
);
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) {
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
);
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) {
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
);
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
);
534 /******************************************************************************
536 * SkGeSirqIsr() - Special Interrupt Service Routine
538 * Description: handles all non data transfer specific interrupts (slow path)
543 SK_AC
*pAC
, /* adapter context */
544 SK_IOC IoC
, /* IO context */
545 SK_U32 Istatus
) /* Interrupt status word */
548 SK_U32 RegVal32
; /* Read register value */
549 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
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
,
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
,
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
,
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
,
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
);
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,
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
;
627 SkTimerStart(pAC
, IoC
, &pPrt
->HalfDupChkTimer
, SK_HALFDUP_CHK_TIME
,
628 SKGE_HWAC
, SK_HWEV_HALFDUP_CHK
, Para
);
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
);
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
;
660 SkTimerStart(pAC
, IoC
, &pPrt
->HalfDupChkTimer
, SK_HALFDUP_CHK_TIME
,
661 SKGE_HWAC
, SK_HWEV_HALFDUP_CHK
, Para
);
667 /* Check interrupts of the particular queues */
668 if ((Istatus
& IS_R1_C
) != 0) {
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
,
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) {
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
,
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) {
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
,
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) {
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
,
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) {
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
,
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) {
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
,
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
) {
746 if (pAC
->GIni
.GIGenesis
) {
748 switch (pPrt
->PhyType
) {
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",
760 SkPhyIsrBcom(pAC
, IoC
, i
, PhyInt
);
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",
771 SkPhyIsrLone(pAC
, IoC
, i
, PhyInt
);
774 #endif /* OTHER_PHY */
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",
788 SkPhyIsrGmac(pAC
, IoC
, i
, PhyInt
);
795 /* I2C Ready interrupt */
796 if ((Istatus
& IS_I2C_READY
) != 0) {
798 SK_OUT32(IoC
, B2_I2C_IRQ
, I2C_CLR_IRQ
);
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) {
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) {
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
);
857 /******************************************************************************
859 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
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 */
879 pPrt
= &pAC
->GIni
.GP
[Port
];
881 /* Default: no action */
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
895 for (i
= 0; i
< ARRAY_SIZE(SkGeRxRegs
); i
++) {
897 (void)SkXmMacStatistic(pAC
, IoC
, Port
, SkGeRxRegs
[i
], &RxTmp
);
899 RxCts
+= (SK_U64
)RxTmp
;
902 /* On default: check shorts against zero */
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 */
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
);
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
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
;
967 } /* SkGePortCheckShorts */
971 /******************************************************************************
973 * SkGePortCheckUp() - Check if the link is up
976 * 0 o.k. nothing needed
977 * 1 Restart needed on this port
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 */
991 pPrt
= &pAC
->GIni
.GP
[Port
];
993 if (pPrt
->PLinkMode
== SK_LMODE_HALF
|| pPrt
->PLinkMode
== SK_LMODE_FULL
) {
1001 if (pAC
->GIni
.GIGenesis
) {
1003 switch (pPrt
->PhyType
) {
1006 Rtv
= SkGePortCheckUpXmac(pAC
, IoC
, Port
, AutoNeg
);
1009 Rtv
= SkGePortCheckUpBcom(pAC
, IoC
, Port
, AutoNeg
);
1013 Rtv
= SkGePortCheckUpLone(pAC
, IoC
, Port
, AutoNeg
);
1016 Rtv
= SkGePortCheckUpNat(pAC
, IoC
, Port
, AutoNeg
);
1018 #endif /* OTHER_PHY */
1021 #endif /* GENESIS */
1024 if (pAC
->GIni
.GIYukon
) {
1026 Rtv
= SkGePortCheckUpGmac(pAC
, IoC
, Port
, AutoNeg
);
1031 } /* SkGePortCheckUp */
1035 /******************************************************************************
1037 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1040 * 0 o.k. nothing needed
1041 * 1 Restart needed on this port
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 */
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
);
1068 return(SkGePortCheckShorts(pAC
, IoC
, Port
));
1072 IsrcSum
= pPrt
->PIsave
;
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
);
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.
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
));
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
);
1134 /* Do nothing more if link is broken */
1135 return(SK_HW_PS_NONE
);
1140 /* Link was not broken, check if it is */
1141 XM_IN16(IoC
, Port
, XM_ISRC
, &Isrc
);
1143 if ((Isrc
& XM_IS_INP_ASS
) != 0) {
1144 XM_IN16(IoC
, Port
, XM_ISRC
, &Isrc
);
1146 if ((Isrc
& XM_IS_INP_ASS
) != 0) {
1147 XM_IN16(IoC
, Port
, XM_ISRC
, &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
);
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
);
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
);
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
));
1193 return(SK_HW_PS_NONE
);
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
1254 * Solution: we restart the autosensing after
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
);
1267 /* Link is up and we don't need more */
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
));
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
1295 * 0 o.k. nothing needed
1296 * 1 Restart needed on this port
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 */
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 */
1316 pPrt
= &pAC
->GIni
.GP
[Port
];
1318 /* Check for No HCD Link events (#10523) */
1319 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_STAT
, &Isrc
);
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
;
1328 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_MASK
, &Stat1
);
1331 MSG_TYPE_RUNTIME_INFO
,
1332 "CheckUp1 - Stat: %x, Mask: %x",
1337 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_CTRL
, &Stat1
);
1339 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_STAT
, &Stat2
);
1340 Stat1
= Stat1
<< 16 | Stat2
;
1342 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_ADV
, &Stat2
);
1344 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_LP
, &Stat3
);
1345 Stat2
= Stat2
<< 16 | Stat3
;
1348 MSG_TYPE_RUNTIME_INFO
,
1349 "Ctrl/Stat: %x, AN Adv/LP: %x",
1354 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_EXP
, &Stat1
);
1356 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_EXT_STAT
, &Stat2
);
1357 Stat1
= Stat1
<< 16 | Stat2
;
1359 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_CTRL
, &Stat2
);
1361 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_STAT
, &Stat3
);
1362 Stat2
= Stat2
<< 16 | Stat3
;
1365 MSG_TYPE_RUNTIME_INFO
,
1366 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1371 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_CTRL
, &Stat1
);
1373 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_STAT
, &Stat2
);
1374 Stat1
= Stat1
<< 16 | Stat2
;
1376 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, &Stat2
);
1378 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_STAT
, &Stat3
);
1379 Stat2
= Stat2
<< 16 | Stat3
;
1382 MSG_TYPE_RUNTIME_INFO
,
1383 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
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
));
1404 MSG_TYPE_RUNTIME_INFO
,
1405 "No HCD link event, port %d.",
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
);
1420 SK_U32 Stat1
, Stat2
, Stat3
;
1423 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_MASK
, &Stat1
);
1426 MSG_TYPE_RUNTIME_INFO
,
1427 "CheckUp1a - Stat: %x, Mask: %x",
1432 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_CTRL
, &Stat1
);
1434 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_STAT
, &PhyStat
);
1435 Stat1
= Stat1
<< 16 | PhyStat
;
1437 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_ADV
, &Stat2
);
1439 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_LP
, &Stat3
);
1440 Stat2
= Stat2
<< 16 | Stat3
;
1443 MSG_TYPE_RUNTIME_INFO
,
1444 "Ctrl/Stat: %x, AN Adv/LP: %x",
1449 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_EXP
, &Stat1
);
1451 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_EXT_STAT
, &Stat2
);
1452 Stat1
= Stat1
<< 16 | Stat2
;
1454 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_CTRL
, &Stat2
);
1456 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_STAT
, &ResAb
);
1457 Stat2
= Stat2
<< 16 | ResAb
;
1460 MSG_TYPE_RUNTIME_INFO
,
1461 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1466 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_CTRL
, &Stat1
);
1468 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_STAT
, &Stat2
);
1469 Stat1
= Stat1
<< 16 | Stat2
;
1471 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, &Stat2
);
1473 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_STAT
, &Stat3
);
1474 Stat2
= Stat2
<< 16 | Stat3
;
1477 MSG_TYPE_RUNTIME_INFO
,
1478 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
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) {
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
));
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
) {
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
));
1535 return(SK_HW_PS_RESTART
);
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) {
1545 MSG_TYPE_RUNTIME_INFO
,
1546 "CheckUp2 - Stat: %x",
1551 return(SK_HW_PS_LINK
);
1555 else { /* !AutoNeg */
1556 /* Link is up and we don't need more. */
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
));
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) {
1571 MSG_TYPE_RUNTIME_INFO
,
1572 "CheckUp3 - Stat: %x",
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 */
1591 /******************************************************************************
1593 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1596 * 0 o.k. nothing needed
1597 * 1 Restart needed on this port
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 */
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 */
1614 SK_U16 Word
; /* I/O helper */
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) {
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
));
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
));
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
);
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);
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 */
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
));
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 */
1734 /******************************************************************************
1736 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1739 * 0 o.k. nothing needed
1740 * 1 Restart needed on this port
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 */
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 */
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
;
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
);
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
);
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
));
1785 return(SK_HW_PS_NONE
);
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
);
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
);
1840 /* Link is up and we don't need more */
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
));
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
1870 * 0 o.k. nothing needed
1871 * 1 Restart needed on this port
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
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 */
1907 #endif /* GENESIS */
1909 Port
= Para
.Para32
[0];
1910 pPrt
= &pAC
->GIni
.GP
[Port
];
1914 if (pPrt
->PState
== SK_PRT_RESET
) {
1916 PortStat
= SK_HW_PS_NONE
;
1919 /* Check whether port came up */
1920 PortStat
= SkGePortCheckUp(pAC
, IoC
, (int)Port
);
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
);
1941 /* Signal to RLMT */
1942 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_UP
, Para
);
1946 /* Start again the check Timer */
1947 if (pPrt
->PHWLinkUp
) {
1948 Val32
= SK_WA_ACT_TIME
;
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
);
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
);
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
);
1994 case SK_HWEV_UPDATE_STAT
:
1995 /* We do NOT need to update any statistics */
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
++) {
2003 pPrt
->PPrevShorts
= 0;
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
;
2014 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para
);
2015 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
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
;
2026 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para
);
2027 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
2031 case SK_HWEV_SET_ROLE
:
2032 /* not possible for fiber */
2033 if (!pAC
->GIni
.GICopperType
) {
2036 Val8
= (SK_U8
)Para
.Para32
[1];
2037 if (pPrt
->PMSMode
!= Val8
) {
2038 /* Set New Role (Master/Slave) mode */
2039 pPrt
->PMSMode
= Val8
;
2042 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para
);
2043 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
2047 case SK_HWEV_SET_SPEED
:
2048 if (pPrt
->PhyType
!= SK_PHY_MARV_COPPER
) {
2051 Val8
= (SK_U8
)Para
.Para32
[1];
2052 if (pPrt
->PLinkSpeed
!= Val8
) {
2053 /* Set New Speed parameter */
2054 pPrt
->PLinkSpeed
= Val8
;
2057 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para
);
2058 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
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
);
2083 if (pPrt
->LastOctets
== Octets
) {
2084 /* Tx hanging, a FIFO flush restarts it */
2085 SkMacFlushTxFifo(pAC
, IoC
, Port
);
2090 #endif /* GENESIS */
2093 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_SIRQ_E001
, SKERR_SIRQ_E001MSG
);
2098 } /* SkGeSirqEvent */
2102 /******************************************************************************
2104 * SkPhyIsrBcom() - PHY interrupt service routine
2106 * Description: handles all interrupts from BCom PHY
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 */
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 */
2145 /******************************************************************************
2147 * SkPhyIsrGmac() - PHY interrupt service routine
2149 * Description: handles all interrupts from Marvell PHY
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 */
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 */
2201 /******************************************************************************
2203 * SkPhyIsrLone() - PHY interrupt service routine
2205 * Description: handles all interrupts from LONE PHY
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 */
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 */