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
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
;
616 Len
= sizeof(SK_U64
);
617 SkPnmiGetVar(pAC
, IoC
, OID_SKGE_STAT_TX_OCTETS
, (char *)&Octets
,
618 &Len
, (SK_U32
)SK_PNMI_PORT_PHYS2INST(pAC
, 0),
619 pAC
->Rlmt
.Port
[0].Net
->NetNumber
);
621 pPrt
->LastOctets
= Octets
;
623 /* Snap statistic counters */
624 (void)SkXmUpdateStats(pAC
, IoC
, 0);
626 (void)SkXmMacStatistic(pAC
, IoC
, 0, XM_TXO_OK_HI
, &RegVal32
);
628 pPrt
->LastOctets
= (SK_U64
)RegVal32
<< 32;
630 (void)SkXmMacStatistic(pAC
, IoC
, 0, XM_TXO_OK_LO
, &RegVal32
);
632 pPrt
->LastOctets
+= RegVal32
;
635 SkTimerStart(pAC
, IoC
, &pPrt
->HalfDupChkTimer
, SK_HALFDUP_CHK_TIME
,
636 SKGE_HWAC
, SK_HWEV_HALFDUP_CHK
, Para
);
642 if ((Istatus
& IS_PA_TO_TX2
) != 0) {
644 pPrt
= &pAC
->GIni
.GP
[1];
646 /* May be a normal situation in a server with a slow network */
647 SK_OUT16(IoC
, B3_PA_CTRL
, PA_CLR_TO_TX2
);
650 if (pAC
->GIni
.GIGenesis
) {
651 /* workaround: see above */
652 if ((pPrt
->PLinkModeStatus
== SK_LMODE_STAT_HALF
||
653 pPrt
->PLinkModeStatus
== SK_LMODE_STAT_AUTOHALF
) &&
654 !pPrt
->HalfDupTimerActive
) {
655 pPrt
->HalfDupTimerActive
= SK_TRUE
;
657 Len
= sizeof(SK_U64
);
658 SkPnmiGetVar(pAC
, IoC
, OID_SKGE_STAT_TX_OCTETS
, (char *)&Octets
,
659 &Len
, (SK_U32
)SK_PNMI_PORT_PHYS2INST(pAC
, 1),
660 pAC
->Rlmt
.Port
[1].Net
->NetNumber
);
662 pPrt
->LastOctets
= Octets
;
664 /* Snap statistic counters */
665 (void)SkXmUpdateStats(pAC
, IoC
, 1);
667 (void)SkXmMacStatistic(pAC
, IoC
, 1, XM_TXO_OK_HI
, &RegVal32
);
669 pPrt
->LastOctets
= (SK_U64
)RegVal32
<< 32;
671 (void)SkXmMacStatistic(pAC
, IoC
, 1, XM_TXO_OK_LO
, &RegVal32
);
673 pPrt
->LastOctets
+= RegVal32
;
676 SkTimerStart(pAC
, IoC
, &pPrt
->HalfDupChkTimer
, SK_HALFDUP_CHK_TIME
,
677 SKGE_HWAC
, SK_HWEV_HALFDUP_CHK
, Para
);
683 /* Check interrupts of the particular queues */
684 if ((Istatus
& IS_R1_C
) != 0) {
686 SK_OUT32(IoC
, B0_R1_CSR
, CSR_IRQ_CL_C
);
687 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_SIRQ_E006
,
690 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_FAIL
, Para
);
691 Para
.Para32
[0] = MAC_1
;
692 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
695 if ((Istatus
& IS_R2_C
) != 0) {
697 SK_OUT32(IoC
, B0_R2_CSR
, CSR_IRQ_CL_C
);
698 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_SIRQ_E007
,
701 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_FAIL
, Para
);
702 Para
.Para32
[0] = MAC_2
;
703 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
706 if ((Istatus
& IS_XS1_C
) != 0) {
708 SK_OUT32(IoC
, B0_XS1_CSR
, CSR_IRQ_CL_C
);
709 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_SIRQ_E008
,
712 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_FAIL
, Para
);
713 Para
.Para32
[0] = MAC_1
;
714 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
717 if ((Istatus
& IS_XA1_C
) != 0) {
719 SK_OUT32(IoC
, B0_XA1_CSR
, CSR_IRQ_CL_C
);
720 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_SIRQ_E009
,
723 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_FAIL
, Para
);
724 Para
.Para32
[0] = MAC_1
;
725 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
728 if ((Istatus
& IS_XS2_C
) != 0) {
730 SK_OUT32(IoC
, B0_XS2_CSR
, CSR_IRQ_CL_C
);
731 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_SIRQ_E010
,
734 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_FAIL
, Para
);
735 Para
.Para32
[0] = MAC_2
;
736 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
739 if ((Istatus
& IS_XA2_C
) != 0) {
741 SK_OUT32(IoC
, B0_XA2_CSR
, CSR_IRQ_CL_C
);
742 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_SIRQ_E011
,
745 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_FAIL
, Para
);
746 Para
.Para32
[0] = MAC_2
;
747 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
750 /* External reg interrupt */
751 if ((Istatus
& IS_EXT_REG
) != 0) {
752 /* Test IRQs from PHY */
753 for (i
= 0; i
< pAC
->GIni
.GIMacsFound
; i
++) {
755 pPrt
= &pAC
->GIni
.GP
[i
];
757 if (pPrt
->PState
== SK_PRT_RESET
) {
762 if (pAC
->GIni
.GIGenesis
) {
764 switch (pPrt
->PhyType
) {
770 SkXmPhyRead(pAC
, IoC
, i
, PHY_BCOM_INT_STAT
, &PhyInt
);
772 if ((PhyInt
& ~PHY_B_DEF_MSK
) != 0) {
773 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
774 ("Port %d Bcom Int: 0x%04X\n",
776 SkPhyIsrBcom(pAC
, IoC
, i
, PhyInt
);
781 SkXmPhyRead(pAC
, IoC
, i
, PHY_LONE_INT_STAT
, &PhyInt
);
783 if ((PhyInt
& PHY_L_DEF_MSK
) != 0) {
784 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
785 ("Port %d Lone Int: %x\n",
787 SkPhyIsrLone(pAC
, IoC
, i
, PhyInt
);
790 #endif /* OTHER_PHY */
796 if (pAC
->GIni
.GIYukon
) {
797 /* Read PHY Interrupt Status */
798 SkGmPhyRead(pAC
, IoC
, i
, PHY_MARV_INT_STAT
, &PhyInt
);
800 if ((PhyInt
& PHY_M_DEF_MSK
) != 0) {
801 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
802 ("Port %d Marv Int: 0x%04X\n",
804 SkPhyIsrGmac(pAC
, IoC
, i
, PhyInt
);
811 /* I2C Ready interrupt */
812 if ((Istatus
& IS_I2C_READY
) != 0) {
814 SK_OUT32(IoC
, B2_I2C_IRQ
, I2C_CLR_IRQ
);
820 /* SW forced interrupt */
821 if ((Istatus
& IS_IRQ_SW
) != 0) {
822 /* clear the software IRQ */
823 SK_OUT8(IoC
, B0_CTST
, CS_CL_SW_IRQ
);
826 if ((Istatus
& IS_LNK_SYNC_M1
) != 0) {
828 * We do NOT need the Link Sync interrupt, because it shows
829 * us only a link going down.
831 /* clear interrupt */
832 SK_OUT8(IoC
, MR_ADDR(MAC_1
, LNK_SYNC_CTRL
), LED_CLR_IRQ
);
835 /* Check MAC after link sync counter */
836 if ((Istatus
& IS_MAC1
) != 0) {
838 SkMacIrq(pAC
, IoC
, MAC_1
);
841 if ((Istatus
& IS_LNK_SYNC_M2
) != 0) {
843 * We do NOT need the Link Sync interrupt, because it shows
844 * us only a link going down.
846 /* clear interrupt */
847 SK_OUT8(IoC
, MR_ADDR(MAC_2
, LNK_SYNC_CTRL
), LED_CLR_IRQ
);
850 /* Check MAC after link sync counter */
851 if ((Istatus
& IS_MAC2
) != 0) {
853 SkMacIrq(pAC
, IoC
, MAC_2
);
856 /* Timer interrupt (served last) */
857 if ((Istatus
& IS_TIMINT
) != 0) {
858 /* check for HW Errors */
859 if (((Istatus
& IS_HW_ERR
) & ~pAC
->GIni
.GIValIrqMask
) != 0) {
860 /* read the HW Error Interrupt source */
861 SK_IN32(IoC
, B0_HWE_ISRC
, &RegVal32
);
863 SkGeHwErr(pAC
, IoC
, RegVal32
);
873 /******************************************************************************
875 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
878 * 0 o.k. nothing needed
879 * 1 Restart needed on this port
881 static int SkGePortCheckShorts(
882 SK_AC
*pAC
, /* Adapter Context */
883 SK_IOC IoC
, /* IO Context */
884 int Port
) /* Which port should be checked */
886 SK_U32 Shorts
; /* Short Event Counter */
887 SK_U32 CheckShorts
; /* Check value for Short Event Counter */
888 SK_U64 RxCts
; /* Rx Counter (packets on network) */
889 SK_U32 RxTmp
; /* Rx temp. Counter */
890 SK_U32 FcsErrCts
; /* FCS Error Counter */
891 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
892 int Rtv
; /* Return value */
895 pPrt
= &pAC
->GIni
.GP
[Port
];
897 /* Default: no action */
900 (void)SkXmUpdateStats(pAC
, IoC
, Port
);
902 /* Extra precaution: check for short Event counter */
903 (void)SkXmMacStatistic(pAC
, IoC
, Port
, XM_RXE_SHT_ERR
, &Shorts
);
906 * Read Rx counters (packets seen on the network and not necessarily
911 for (i
= 0; i
< sizeof(SkGeRxRegs
)/sizeof(SkGeRxRegs
[0]); i
++) {
913 (void)SkXmMacStatistic(pAC
, IoC
, Port
, SkGeRxRegs
[i
], &RxTmp
);
915 RxCts
+= (SK_U64
)RxTmp
;
918 /* On default: check shorts against zero */
921 /* Extra precaution on active links */
922 if (pPrt
->PHWLinkUp
) {
923 /* Reset Link Restart counter */
924 pPrt
->PLinkResCt
= 0;
925 pPrt
->PAutoNegTOCt
= 0;
927 /* If link is up check for 2 */
930 (void)SkXmMacStatistic(pAC
, IoC
, Port
, XM_RXF_FCS_ERR
, &FcsErrCts
);
932 if (pPrt
->PLinkModeConf
== SK_LMODE_AUTOSENSE
&&
933 pPrt
->PLipaAutoNeg
== SK_LIPA_UNKNOWN
&&
934 (pPrt
->PLinkMode
== SK_LMODE_HALF
||
935 pPrt
->PLinkMode
== SK_LMODE_FULL
)) {
937 * This is autosensing and we are in the fallback
938 * manual full/half duplex mode.
940 if (RxCts
== pPrt
->PPrevRx
) {
941 /* Nothing received, restart link */
942 pPrt
->PPrevFcs
= FcsErrCts
;
943 pPrt
->PPrevShorts
= Shorts
;
945 return(SK_HW_PS_RESTART
);
948 pPrt
->PLipaAutoNeg
= SK_LIPA_MANUAL
;
952 if (((RxCts
- pPrt
->PPrevRx
) > pPrt
->PRxLim
) ||
953 (!(FcsErrCts
- pPrt
->PPrevFcs
))) {
955 * Note: The compare with zero above has to be done the way shown,
956 * otherwise the Linux driver will have a problem.
959 * We received a bunch of frames or no CRC error occured on the
962 pPrt
->PPrevRx
= RxCts
;
963 pPrt
->PPrevFcs
= FcsErrCts
;
964 pPrt
->PPrevShorts
= Shorts
;
966 return(SK_HW_PS_NONE
);
969 pPrt
->PPrevFcs
= FcsErrCts
;
973 if ((Shorts
- pPrt
->PPrevShorts
) > CheckShorts
) {
974 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
975 ("Short Event Count Restart Port %d \n", Port
));
976 Rtv
= SK_HW_PS_RESTART
;
979 pPrt
->PPrevShorts
= Shorts
;
980 pPrt
->PPrevRx
= RxCts
;
983 } /* SkGePortCheckShorts */
987 /******************************************************************************
989 * SkGePortCheckUp() - Check if the link is up
992 * 0 o.k. nothing needed
993 * 1 Restart needed on this port
996 static int SkGePortCheckUp(
997 SK_AC
*pAC
, /* Adapter Context */
998 SK_IOC IoC
, /* IO Context */
999 int Port
) /* Which port should be checked */
1001 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
1002 SK_BOOL AutoNeg
; /* Is Auto-negotiation used ? */
1003 int Rtv
; /* Return value */
1005 Rtv
= SK_HW_PS_NONE
;
1007 pPrt
= &pAC
->GIni
.GP
[Port
];
1009 if (pPrt
->PLinkMode
== SK_LMODE_HALF
|| pPrt
->PLinkMode
== SK_LMODE_FULL
) {
1017 if (pAC
->GIni
.GIGenesis
) {
1019 switch (pPrt
->PhyType
) {
1022 Rtv
= SkGePortCheckUpXmac(pAC
, IoC
, Port
, AutoNeg
);
1025 Rtv
= SkGePortCheckUpBcom(pAC
, IoC
, Port
, AutoNeg
);
1029 Rtv
= SkGePortCheckUpLone(pAC
, IoC
, Port
, AutoNeg
);
1032 Rtv
= SkGePortCheckUpNat(pAC
, IoC
, Port
, AutoNeg
);
1034 #endif /* OTHER_PHY */
1037 #endif /* GENESIS */
1040 if (pAC
->GIni
.GIYukon
) {
1042 Rtv
= SkGePortCheckUpGmac(pAC
, IoC
, Port
, AutoNeg
);
1047 } /* SkGePortCheckUp */
1051 /******************************************************************************
1053 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1056 * 0 o.k. nothing needed
1057 * 1 Restart needed on this port
1060 static int SkGePortCheckUpXmac(
1061 SK_AC
*pAC
, /* Adapter Context */
1062 SK_IOC IoC
, /* IO Context */
1063 int Port
, /* Which port should be checked */
1064 SK_BOOL AutoNeg
) /* Is Auto-negotiation used ? */
1066 SK_U32 Shorts
; /* Short Event Counter */
1067 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
1069 SK_U32 GpReg
; /* General Purpose register value */
1070 SK_U16 Isrc
; /* Interrupt source register */
1071 SK_U16 IsrcSum
; /* Interrupt source register sum */
1072 SK_U16 LpAb
; /* Link Partner Ability */
1073 SK_U16 ResAb
; /* Resolved Ability */
1074 SK_U16 ExtStat
; /* Extended Status Register */
1075 SK_U8 NextMode
; /* Next AutoSensing Mode */
1077 pPrt
= &pAC
->GIni
.GP
[Port
];
1079 if (pPrt
->PHWLinkUp
) {
1080 if (pPrt
->PhyType
!= SK_PHY_XMAC
) {
1081 return(SK_HW_PS_NONE
);
1084 return(SkGePortCheckShorts(pAC
, IoC
, Port
));
1088 IsrcSum
= pPrt
->PIsave
;
1091 /* Now wait for each port's link */
1092 if (pPrt
->PLinkBroken
) {
1093 /* Link was broken */
1094 XM_IN32(IoC
, Port
, XM_GP_PORT
, &GpReg
);
1096 if ((GpReg
& XM_GP_INP_ASS
) == 0) {
1097 /* The Link is in sync */
1098 XM_IN16(IoC
, Port
, XM_ISRC
, &Isrc
);
1100 SkXmAutoNegLipaXmac(pAC
, IoC
, Port
, IsrcSum
);
1102 if ((Isrc
& XM_IS_INP_ASS
) == 0) {
1103 /* It has been in sync since last time */
1104 /* Restart the PORT */
1105 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1106 ("Link in sync Restart Port %d\n", Port
));
1108 (void)SkXmUpdateStats(pAC
, IoC
, Port
);
1110 /* We now need to reinitialize the PrevShorts counter */
1111 (void)SkXmMacStatistic(pAC
, IoC
, Port
, XM_RXE_SHT_ERR
, &Shorts
);
1112 pPrt
->PPrevShorts
= Shorts
;
1114 pPrt
->PLinkBroken
= SK_FALSE
;
1117 * Link Restart Workaround:
1118 * it may be possible that the other Link side
1119 * restarts its link as well an we detect
1120 * another LinkBroken. To prevent this
1121 * happening we check for a maximum number
1122 * of consecutive restart. If those happens,
1123 * we do NOT restart the active link and
1124 * check whether the link is now o.k.
1128 pPrt
->PAutoNegTimeOut
= 0;
1130 if (pPrt
->PLinkResCt
< SK_MAX_LRESTART
) {
1131 return(SK_HW_PS_RESTART
);
1134 pPrt
->PLinkResCt
= 0;
1136 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1137 ("Do NOT restart on Port %d %x %x\n", Port
, Isrc
, IsrcSum
));
1140 pPrt
->PIsave
= (SK_U16
)(IsrcSum
& XM_IS_AND
);
1142 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1143 ("Save Sync/nosync Port %d %x %x\n", Port
, Isrc
, IsrcSum
));
1145 /* Do nothing more if link is broken */
1146 return(SK_HW_PS_NONE
);
1150 /* Do nothing more if link is broken */
1151 return(SK_HW_PS_NONE
);
1156 /* Link was not broken, check if it is */
1157 XM_IN16(IoC
, Port
, XM_ISRC
, &Isrc
);
1159 if ((Isrc
& XM_IS_INP_ASS
) != 0) {
1160 XM_IN16(IoC
, Port
, XM_ISRC
, &Isrc
);
1162 if ((Isrc
& XM_IS_INP_ASS
) != 0) {
1163 XM_IN16(IoC
, Port
, XM_ISRC
, &Isrc
);
1165 if ((Isrc
& XM_IS_INP_ASS
) != 0) {
1166 pPrt
->PLinkBroken
= SK_TRUE
;
1167 /* Re-Init Link partner Autoneg flag */
1168 pPrt
->PLipaAutoNeg
= SK_LIPA_UNKNOWN
;
1169 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1170 ("Link broken Port %d\n", Port
));
1172 /* Cable removed-> reinit sense mode */
1173 SkHWInitDefSense(pAC
, IoC
, Port
);
1175 return(SK_HW_PS_RESTART
);
1180 SkXmAutoNegLipaXmac(pAC
, IoC
, Port
, Isrc
);
1182 if (SkGePortCheckShorts(pAC
, IoC
, Port
) == SK_HW_PS_RESTART
) {
1183 return(SK_HW_PS_RESTART
);
1189 * here we usually can check whether the link is in sync and
1190 * auto-negotiation is done.
1192 XM_IN32(IoC
, Port
, XM_GP_PORT
, &GpReg
);
1193 XM_IN16(IoC
, Port
, XM_ISRC
, &Isrc
);
1196 SkXmAutoNegLipaXmac(pAC
, IoC
, Port
, IsrcSum
);
1198 if ((GpReg
& XM_GP_INP_ASS
) != 0 || (IsrcSum
& XM_IS_INP_ASS
) != 0) {
1199 if ((GpReg
& XM_GP_INP_ASS
) == 0) {
1200 /* Save Auto-negotiation Done interrupt only if link is in sync */
1201 pPrt
->PIsave
= (SK_U16
)(IsrcSum
& XM_IS_AND
);
1204 if ((pPrt
->PIsave
& XM_IS_AND
) != 0) {
1205 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1206 ("AutoNeg done rescheduled Port %d\n", Port
));
1209 return(SK_HW_PS_NONE
);
1213 if ((IsrcSum
& XM_IS_AND
) != 0) {
1214 SkHWLinkUp(pAC
, IoC
, Port
);
1215 Done
= SkMacAutoNegDone(pAC
, IoC
, Port
);
1216 if (Done
!= SK_AND_OK
) {
1217 /* Get PHY parameters, for debugging only */
1218 SkXmPhyRead(pAC
, IoC
, Port
, PHY_XMAC_AUNE_LP
, &LpAb
);
1219 SkXmPhyRead(pAC
, IoC
, Port
, PHY_XMAC_RES_ABI
, &ResAb
);
1220 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1221 ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
1222 Port
, LpAb
, ResAb
));
1224 /* Try next possible mode */
1225 NextMode
= SkHWSenseGetNext(pAC
, IoC
, Port
);
1226 SkHWLinkDown(pAC
, IoC
, Port
);
1227 if (Done
== SK_AND_DUP_CAP
) {
1228 /* GoTo next mode */
1229 SkHWSenseSetNext(pAC
, IoC
, Port
, NextMode
);
1232 return(SK_HW_PS_RESTART
);
1235 * Dummy Read extended status to prevent extra link down/ups
1236 * (clear Page Received bit if set)
1238 SkXmPhyRead(pAC
, IoC
, Port
, PHY_XMAC_AUNE_EXP
, &ExtStat
);
1240 return(SK_HW_PS_LINK
);
1243 /* AutoNeg not done, but HW link is up. Check for timeouts */
1244 pPrt
->PAutoNegTimeOut
++;
1245 if (pPrt
->PAutoNegTimeOut
>= SK_AND_MAX_TO
) {
1246 /* Increase the Timeout counter */
1247 pPrt
->PAutoNegTOCt
++;
1249 /* Timeout occured */
1250 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1251 ("AutoNeg timeout Port %d\n", Port
));
1252 if (pPrt
->PLinkModeConf
== SK_LMODE_AUTOSENSE
&&
1253 pPrt
->PLipaAutoNeg
!= SK_LIPA_AUTO
) {
1254 /* Set Link manually up */
1255 SkHWSenseSetNext(pAC
, IoC
, Port
, SK_LMODE_FULL
);
1256 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1257 ("Set manual full duplex Port %d\n", Port
));
1260 if (pPrt
->PLinkModeConf
== SK_LMODE_AUTOSENSE
&&
1261 pPrt
->PLipaAutoNeg
== SK_LIPA_AUTO
&&
1262 pPrt
->PAutoNegTOCt
>= SK_MAX_ANEG_TO
) {
1264 * This is rather complicated.
1265 * we need to check here whether the LIPA_AUTO
1266 * we saw before is false alert. We saw at one
1267 * switch ( SR8800) that on boot time it sends
1268 * just one auto-neg packet and does no further
1270 * Solution: we restart the autosensing after
1273 pPrt
->PAutoNegTOCt
= 0;
1274 pPrt
->PLipaAutoNeg
= SK_LIPA_UNKNOWN
;
1275 SkHWInitDefSense(pAC
, IoC
, Port
);
1278 /* Do the restart */
1279 return(SK_HW_PS_RESTART
);
1283 /* Link is up and we don't need more */
1285 if (pPrt
->PLipaAutoNeg
== SK_LIPA_AUTO
) {
1286 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1287 ("ERROR: Lipa auto detected on port %d\n", Port
));
1290 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1291 ("Link sync(GP), Port %d\n", Port
));
1292 SkHWLinkUp(pAC
, IoC
, Port
);
1295 * Link sync (GP) and so assume a good connection. But if not received
1296 * a bunch of frames received in a time slot (maybe broken tx cable)
1297 * the port is restart.
1299 return(SK_HW_PS_LINK
);
1302 return(SK_HW_PS_NONE
);
1303 } /* SkGePortCheckUpXmac */
1306 /******************************************************************************
1308 * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
1311 * 0 o.k. nothing needed
1312 * 1 Restart needed on this port
1315 static int SkGePortCheckUpBcom(
1316 SK_AC
*pAC
, /* Adapter Context */
1317 SK_IOC IoC
, /* IO Context */
1318 int Port
, /* Which port should be checked */
1319 SK_BOOL AutoNeg
) /* Is Auto-negotiation used ? */
1321 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
1323 SK_U16 Isrc
; /* Interrupt source register */
1324 SK_U16 PhyStat
; /* Phy Status Register */
1325 SK_U16 ResAb
; /* Master/Slave resolution */
1326 SK_U16 Ctrl
; /* Broadcom control flags */
1332 pPrt
= &pAC
->GIni
.GP
[Port
];
1334 /* Check for No HCD Link events (#10523) */
1335 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_STAT
, &Isrc
);
1338 if ((Isrc
& ~(PHY_B_IS_HCT
| PHY_B_IS_LCT
) ==
1339 (PHY_B_IS_SCR_S_ER
| PHY_B_IS_RRS_CHANGE
| PHY_B_IS_LRS_CHANGE
)) {
1341 SK_U32 Stat1
, Stat2
, Stat3
;
1344 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_MASK
, &Stat1
);
1347 MSG_TYPE_RUNTIME_INFO
,
1348 "CheckUp1 - Stat: %x, Mask: %x",
1353 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_CTRL
, &Stat1
);
1355 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_STAT
, &Stat2
);
1356 Stat1
= Stat1
<< 16 | Stat2
;
1358 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_ADV
, &Stat2
);
1360 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_LP
, &Stat3
);
1361 Stat2
= Stat2
<< 16 | Stat3
;
1364 MSG_TYPE_RUNTIME_INFO
,
1365 "Ctrl/Stat: %x, AN Adv/LP: %x",
1370 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_EXP
, &Stat1
);
1372 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_EXT_STAT
, &Stat2
);
1373 Stat1
= Stat1
<< 16 | Stat2
;
1375 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_CTRL
, &Stat2
);
1377 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_STAT
, &Stat3
);
1378 Stat2
= Stat2
<< 16 | Stat3
;
1381 MSG_TYPE_RUNTIME_INFO
,
1382 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1387 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_CTRL
, &Stat1
);
1389 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_STAT
, &Stat2
);
1390 Stat1
= Stat1
<< 16 | Stat2
;
1392 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, &Stat2
);
1394 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_STAT
, &Stat3
);
1395 Stat2
= Stat2
<< 16 | Stat3
;
1398 MSG_TYPE_RUNTIME_INFO
,
1399 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1405 if ((Isrc
& (PHY_B_IS_NO_HDCL
/* | PHY_B_IS_NO_HDC */)) != 0) {
1407 * Workaround BCom Errata:
1408 * enable and disable loopback mode if "NO HCD" occurs.
1410 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_CTRL
, &Ctrl
);
1411 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_CTRL
,
1412 (SK_U16
)(Ctrl
| PHY_CT_LOOP
));
1413 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_CTRL
,
1414 (SK_U16
)(Ctrl
& ~PHY_CT_LOOP
));
1415 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1416 ("No HCD Link event, Port %d\n", Port
));
1420 MSG_TYPE_RUNTIME_INFO
,
1421 "No HCD link event, port %d.",
1427 /* Not obsolete: link status bit is latched to 0 and autoclearing! */
1428 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_STAT
, &PhyStat
);
1430 if (pPrt
->PHWLinkUp
) {
1431 return(SK_HW_PS_NONE
);
1436 SK_U32 Stat1
, Stat2
, Stat3
;
1439 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_MASK
, &Stat1
);
1442 MSG_TYPE_RUNTIME_INFO
,
1443 "CheckUp1a - Stat: %x, Mask: %x",
1448 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_CTRL
, &Stat1
);
1450 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_STAT
, &PhyStat
);
1451 Stat1
= Stat1
<< 16 | PhyStat
;
1453 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_ADV
, &Stat2
);
1455 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_LP
, &Stat3
);
1456 Stat2
= Stat2
<< 16 | Stat3
;
1459 MSG_TYPE_RUNTIME_INFO
,
1460 "Ctrl/Stat: %x, AN Adv/LP: %x",
1465 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_EXP
, &Stat1
);
1467 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_EXT_STAT
, &Stat2
);
1468 Stat1
= Stat1
<< 16 | Stat2
;
1470 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_CTRL
, &Stat2
);
1472 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_STAT
, &ResAb
);
1473 Stat2
= Stat2
<< 16 | ResAb
;
1476 MSG_TYPE_RUNTIME_INFO
,
1477 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1482 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_CTRL
, &Stat1
);
1484 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_STAT
, &Stat2
);
1485 Stat1
= Stat1
<< 16 | Stat2
;
1487 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, &Stat2
);
1489 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_STAT
, &Stat3
);
1490 Stat2
= Stat2
<< 16 | Stat3
;
1493 MSG_TYPE_RUNTIME_INFO
,
1494 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1501 * Here we usually can check whether the link is in sync and
1502 * auto-negotiation is done.
1505 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_STAT
, &PhyStat
);
1507 SkMacAutoNegLipaPhy(pAC
, IoC
, Port
, PhyStat
);
1509 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1510 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port
, PhyStat
));
1512 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_STAT
, &ResAb
);
1514 if ((ResAb
& PHY_B_1000S_MSF
) != 0) {
1516 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1517 ("Master/Slave Fault port %d\n", Port
));
1519 pPrt
->PAutoNegFail
= SK_TRUE
;
1520 pPrt
->PMSStatus
= SK_MS_STAT_FAULT
;
1522 return(SK_HW_PS_RESTART
);
1525 if ((PhyStat
& PHY_ST_LSYNC
) == 0) {
1526 return(SK_HW_PS_NONE
);
1529 pPrt
->PMSStatus
= ((ResAb
& PHY_B_1000S_MSR
) != 0) ?
1530 SK_MS_STAT_MASTER
: SK_MS_STAT_SLAVE
;
1532 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1533 ("Port %d, ResAb: 0x%04X\n", Port
, ResAb
));
1536 if ((PhyStat
& PHY_ST_AN_OVER
) != 0) {
1538 SkHWLinkUp(pAC
, IoC
, Port
);
1540 Done
= SkMacAutoNegDone(pAC
, IoC
, Port
);
1542 if (Done
!= SK_AND_OK
) {
1544 /* Get PHY parameters, for debugging only */
1545 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_LP
, &LpAb
);
1546 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_STAT
, &ExtStat
);
1547 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1548 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1549 Port
, LpAb
, ExtStat
));
1551 return(SK_HW_PS_RESTART
);
1555 /* Dummy read ISR to prevent extra link downs/ups */
1556 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_STAT
, &ExtStat
);
1558 if ((ExtStat
& ~(PHY_B_IS_HCT
| PHY_B_IS_LCT
)) != 0) {
1561 MSG_TYPE_RUNTIME_INFO
,
1562 "CheckUp2 - Stat: %x",
1567 return(SK_HW_PS_LINK
);
1571 else { /* !AutoNeg */
1572 /* Link is up and we don't need more. */
1574 if (pPrt
->PLipaAutoNeg
== SK_LIPA_AUTO
) {
1575 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1576 ("ERROR: Lipa auto detected on port %d\n", Port
));
1581 /* Dummy read ISR to prevent extra link downs/ups */
1582 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_INT_STAT
, &ExtStat
);
1584 if ((ExtStat
& ~(PHY_B_IS_HCT
| PHY_B_IS_LCT
)) != 0) {
1587 MSG_TYPE_RUNTIME_INFO
,
1588 "CheckUp3 - Stat: %x",
1594 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1595 ("Link sync(GP), Port %d\n", Port
));
1596 SkHWLinkUp(pAC
, IoC
, Port
);
1598 return(SK_HW_PS_LINK
);
1601 return(SK_HW_PS_NONE
);
1602 } /* SkGePortCheckUpBcom */
1603 #endif /* GENESIS */
1607 /******************************************************************************
1609 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1612 * 0 o.k. nothing needed
1613 * 1 Restart needed on this port
1616 static int SkGePortCheckUpGmac(
1617 SK_AC
*pAC
, /* Adapter Context */
1618 SK_IOC IoC
, /* IO Context */
1619 int Port
, /* Which port should be checked */
1620 SK_BOOL AutoNeg
) /* Is Auto-negotiation used ? */
1622 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
1624 SK_U16 PhyIsrc
; /* PHY Interrupt source */
1625 SK_U16 PhyStat
; /* PPY Status */
1626 SK_U16 PhySpecStat
;/* PHY Specific Status */
1627 SK_U16 ResAb
; /* Master/Slave resolution */
1630 SK_U16 Word
; /* I/O helper */
1633 pPrt
= &pAC
->GIni
.GP
[Port
];
1635 if (pPrt
->PHWLinkUp
) {
1636 return(SK_HW_PS_NONE
);
1639 /* Read PHY Status */
1640 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_STAT
, &PhyStat
);
1642 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1643 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port
, PhyStat
));
1645 /* Read PHY Interrupt Status */
1646 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_INT_STAT
, &PhyIsrc
);
1648 if ((PhyIsrc
& PHY_M_IS_AN_COMPL
) != 0) {
1649 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1650 ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc
));
1653 if ((PhyIsrc
& PHY_M_IS_LSP_CHANGE
) != 0) {
1654 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1655 ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc
));
1658 SkMacAutoNegLipaPhy(pAC
, IoC
, Port
, PhyStat
);
1660 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_1000T_STAT
, &ResAb
);
1662 if ((ResAb
& PHY_B_1000S_MSF
) != 0) {
1664 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1665 ("Master/Slave Fault port %d\n", Port
));
1667 pPrt
->PAutoNegFail
= SK_TRUE
;
1668 pPrt
->PMSStatus
= SK_MS_STAT_FAULT
;
1670 return(SK_HW_PS_RESTART
);
1673 /* Read PHY Specific Status */
1674 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_STAT
, &PhySpecStat
);
1676 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1677 ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb
, PhySpecStat
));
1680 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_AUNE_EXP
, &Word
);
1682 if ((PhyIsrc
& PHY_M_IS_AN_PR
) != 0 || (Word
& PHY_ANE_RX_PG
) != 0 ||
1683 (PhySpecStat
& PHY_M_PS_PAGE_REC
) != 0) {
1684 /* Read PHY Next Page Link Partner */
1685 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_NEPG_LP
, &Word
);
1687 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1688 ("Page Received, NextPage: 0x%04X\n", Word
));
1692 if ((PhySpecStat
& PHY_M_PS_LINK_UP
) == 0) {
1693 return(SK_HW_PS_NONE
);
1696 if ((PhySpecStat
& PHY_M_PS_DOWNS_STAT
) != 0 ||
1697 (PhyIsrc
& PHY_M_IS_DOWNSH_DET
) != 0) {
1698 /* Downshift detected */
1699 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_SIRQ_E025
, SKERR_SIRQ_E025MSG
);
1702 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_DOWNSHIFT_DET
, Para
);
1704 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1705 ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc
));
1708 pPrt
->PMSStatus
= ((ResAb
& PHY_B_1000S_MSR
) != 0) ?
1709 SK_MS_STAT_MASTER
: SK_MS_STAT_SLAVE
;
1711 pPrt
->PCableLen
= (SK_U8
)((PhySpecStat
& PHY_M_PS_CABLE_MSK
) >> 7);
1714 /* Auto-Negotiation Over ? */
1715 if ((PhyStat
& PHY_ST_AN_OVER
) != 0) {
1717 SkHWLinkUp(pAC
, IoC
, Port
);
1719 Done
= SkMacAutoNegDone(pAC
, IoC
, Port
);
1721 if (Done
!= SK_AND_OK
) {
1722 return(SK_HW_PS_RESTART
);
1725 return(SK_HW_PS_LINK
);
1728 else { /* !AutoNeg */
1729 /* Link is up and we don't need more */
1731 if (pPrt
->PLipaAutoNeg
== SK_LIPA_AUTO
) {
1732 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1733 ("ERROR: Lipa auto detected on port %d\n", Port
));
1737 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1738 ("Link sync, Port %d\n", Port
));
1739 SkHWLinkUp(pAC
, IoC
, Port
);
1741 return(SK_HW_PS_LINK
);
1744 return(SK_HW_PS_NONE
);
1745 } /* SkGePortCheckUpGmac */
1750 /******************************************************************************
1752 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1755 * 0 o.k. nothing needed
1756 * 1 Restart needed on this port
1759 static int SkGePortCheckUpLone(
1760 SK_AC
*pAC
, /* Adapter Context */
1761 SK_IOC IoC
, /* IO Context */
1762 int Port
, /* Which port should be checked */
1763 SK_BOOL AutoNeg
) /* Is Auto-negotiation used ? */
1765 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
1767 SK_U16 Isrc
; /* Interrupt source register */
1768 SK_U16 LpAb
; /* Link Partner Ability */
1769 SK_U16 ExtStat
; /* Extended Status Register */
1770 SK_U16 PhyStat
; /* Phy Status Register */
1772 SK_U8 NextMode
; /* Next AutoSensing Mode */
1774 pPrt
= &pAC
->GIni
.GP
[Port
];
1776 if (pPrt
->PHWLinkUp
) {
1777 return(SK_HW_PS_NONE
);
1780 StatSum
= pPrt
->PIsave
;
1784 * here we usually can check whether the link is in sync and
1785 * auto-negotiation is done.
1787 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_STAT
, &PhyStat
);
1790 SkMacAutoNegLipaPhy(pAC
, IoC
, Port
, PhyStat
);
1792 if ((PhyStat
& PHY_ST_LSYNC
) == 0) {
1793 /* Save Auto-negotiation Done bit */
1794 pPrt
->PIsave
= (SK_U16
)(StatSum
& PHY_ST_AN_OVER
);
1796 if ((pPrt
->PIsave
& PHY_ST_AN_OVER
) != 0) {
1797 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1798 ("AutoNeg done rescheduled Port %d\n", Port
));
1801 return(SK_HW_PS_NONE
);
1805 if ((StatSum
& PHY_ST_AN_OVER
) != 0) {
1806 SkHWLinkUp(pAC
, IoC
, Port
);
1807 Done
= SkMacAutoNegDone(pAC
, IoC
, Port
);
1808 if (Done
!= SK_AND_OK
) {
1809 /* Get PHY parameters, for debugging only */
1810 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_AUNE_LP
, &LpAb
);
1811 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_1000T_STAT
, &ExtStat
);
1812 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1813 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1814 Port
, LpAb
, ExtStat
));
1816 /* Try next possible mode */
1817 NextMode
= SkHWSenseGetNext(pAC
, IoC
, Port
);
1818 SkHWLinkDown(pAC
, IoC
, Port
);
1819 if (Done
== SK_AND_DUP_CAP
) {
1820 /* GoTo next mode */
1821 SkHWSenseSetNext(pAC
, IoC
, Port
, NextMode
);
1824 return(SK_HW_PS_RESTART
);
1829 * Dummy Read interrupt status to prevent
1830 * extra link down/ups
1832 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_INT_STAT
, &ExtStat
);
1833 return(SK_HW_PS_LINK
);
1837 /* AutoNeg not done, but HW link is up. Check for timeouts */
1838 pPrt
->PAutoNegTimeOut
++;
1839 if (pPrt
->PAutoNegTimeOut
>= SK_AND_MAX_TO
) {
1840 /* Timeout occured */
1841 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1842 ("AutoNeg timeout Port %d\n", Port
));
1843 if (pPrt
->PLinkModeConf
== SK_LMODE_AUTOSENSE
&&
1844 pPrt
->PLipaAutoNeg
!= SK_LIPA_AUTO
) {
1845 /* Set Link manually up */
1846 SkHWSenseSetNext(pAC
, IoC
, Port
, SK_LMODE_FULL
);
1847 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1848 ("Set manual full duplex Port %d\n", Port
));
1851 /* Do the restart */
1852 return(SK_HW_PS_RESTART
);
1856 /* Link is up and we don't need more */
1858 if (pPrt
->PLipaAutoNeg
== SK_LIPA_AUTO
) {
1859 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1860 ("ERROR: Lipa auto detected on port %d\n", Port
));
1865 * Dummy Read interrupt status to prevent
1866 * extra link down/ups
1868 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_INT_STAT
, &ExtStat
);
1870 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
1871 ("Link sync(GP), Port %d\n", Port
));
1872 SkHWLinkUp(pAC
, IoC
, Port
);
1874 return(SK_HW_PS_LINK
);
1877 return(SK_HW_PS_NONE
);
1878 } /* SkGePortCheckUpLone */
1881 /******************************************************************************
1883 * SkGePortCheckUpNat() - Check if the link is up on National PHY
1886 * 0 o.k. nothing needed
1887 * 1 Restart needed on this port
1890 static int SkGePortCheckUpNat(
1891 SK_AC
*pAC
, /* Adapter Context */
1892 SK_IOC IoC
, /* IO Context */
1893 int Port
, /* Which port should be checked */
1894 SK_BOOL AutoNeg
) /* Is Auto-negotiation used ? */
1896 /* todo: National */
1897 return(SK_HW_PS_NONE
);
1898 } /* SkGePortCheckUpNat */
1899 #endif /* OTHER_PHY */
1902 /******************************************************************************
1904 * SkGeSirqEvent() - Event Service Routine
1911 SK_AC
*pAC
, /* Adapter Context */
1912 SK_IOC IoC
, /* Io Context */
1913 SK_U32 Event
, /* Module specific Event */
1914 SK_EVPARA Para
) /* Event specific Parameter */
1916 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
1923 #endif /* GENESIS */
1925 Port
= Para
.Para32
[0];
1926 pPrt
= &pAC
->GIni
.GP
[Port
];
1930 if (pPrt
->PState
== SK_PRT_RESET
) {
1932 PortStat
= SK_HW_PS_NONE
;
1935 /* Check whether port came up */
1936 PortStat
= SkGePortCheckUp(pAC
, IoC
, (int)Port
);
1940 case SK_HW_PS_RESTART
:
1941 if (pPrt
->PHWLinkUp
) {
1942 /* Set Link to down */
1943 SkHWLinkDown(pAC
, IoC
, (int)Port
);
1946 * Signal directly to RLMT to ensure correct
1947 * sequence of SWITCH and RESET event.
1949 SkRlmtEvent(pAC
, IoC
, SK_RLMT_LINK_DOWN
, Para
);
1952 /* Restart needed */
1953 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_RESET
, Para
);
1957 /* Signal to RLMT */
1958 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_UP
, Para
);
1962 /* Start again the check Timer */
1963 if (pPrt
->PHWLinkUp
) {
1964 Val32
= SK_WA_ACT_TIME
;
1967 Val32
= SK_WA_INA_TIME
;
1970 /* Todo: still needed for non-XMAC PHYs??? */
1971 /* Start workaround Errata #2 timer */
1972 SkTimerStart(pAC
, IoC
, &pPrt
->PWaTimer
, Val32
,
1973 SKGE_HWAC
, SK_HWEV_WATIM
, Para
);
1976 case SK_HWEV_PORT_START
:
1977 if (pPrt
->PHWLinkUp
) {
1979 * Signal directly to RLMT to ensure correct
1980 * sequence of SWITCH and RESET event.
1982 SkRlmtEvent(pAC
, IoC
, SK_RLMT_LINK_DOWN
, Para
);
1985 SkHWLinkDown(pAC
, IoC
, (int)Port
);
1987 /* Schedule Port RESET */
1988 SkEventQueue(pAC
, SKGE_DRV
, SK_DRV_PORT_RESET
, Para
);
1990 /* Start workaround Errata #2 timer */
1991 SkTimerStart(pAC
, IoC
, &pPrt
->PWaTimer
, SK_WA_INA_TIME
,
1992 SKGE_HWAC
, SK_HWEV_WATIM
, Para
);
1995 case SK_HWEV_PORT_STOP
:
1996 if (pPrt
->PHWLinkUp
) {
1998 * Signal directly to RLMT to ensure correct
1999 * sequence of SWITCH and RESET event.
2001 SkRlmtEvent(pAC
, IoC
, SK_RLMT_LINK_DOWN
, Para
);
2004 /* Stop Workaround Timer */
2005 SkTimerStop(pAC
, IoC
, &pPrt
->PWaTimer
);
2007 SkHWLinkDown(pAC
, IoC
, (int)Port
);
2010 case SK_HWEV_UPDATE_STAT
:
2011 /* We do NOT need to update any statistics */
2014 case SK_HWEV_CLEAR_STAT
:
2015 /* We do NOT need to clear any statistics */
2016 for (Port
= 0; Port
< (SK_U32
)pAC
->GIni
.GIMacsFound
; Port
++) {
2019 pPrt
->PPrevShorts
= 0;
2023 case SK_HWEV_SET_LMODE
:
2024 Val8
= (SK_U8
)Para
.Para32
[1];
2025 if (pPrt
->PLinkModeConf
!= Val8
) {
2026 /* Set New link mode */
2027 pPrt
->PLinkModeConf
= Val8
;
2030 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para
);
2031 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
2035 case SK_HWEV_SET_FLOWMODE
:
2036 Val8
= (SK_U8
)Para
.Para32
[1];
2037 if (pPrt
->PFlowCtrlMode
!= Val8
) {
2038 /* Set New Flow Control mode */
2039 pPrt
->PFlowCtrlMode
= 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_ROLE
:
2048 /* not possible for fiber */
2049 if (!pAC
->GIni
.GICopperType
) {
2052 Val8
= (SK_U8
)Para
.Para32
[1];
2053 if (pPrt
->PMSMode
!= Val8
) {
2054 /* Set New Role (Master/Slave) mode */
2055 pPrt
->PMSMode
= Val8
;
2058 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para
);
2059 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
2063 case SK_HWEV_SET_SPEED
:
2064 if (pPrt
->PhyType
!= SK_PHY_MARV_COPPER
) {
2067 Val8
= (SK_U8
)Para
.Para32
[1];
2068 if (pPrt
->PLinkSpeed
!= Val8
) {
2069 /* Set New Speed parameter */
2070 pPrt
->PLinkSpeed
= Val8
;
2073 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_STOP
, Para
);
2074 SkEventQueue(pAC
, SKGE_HWAC
, SK_HWEV_PORT_START
, Para
);
2079 case SK_HWEV_HALFDUP_CHK
:
2080 if (pAC
->GIni
.GIGenesis
) {
2082 * half duplex hangup workaround.
2083 * See packet arbiter timeout interrupt for description
2085 pPrt
->HalfDupTimerActive
= SK_FALSE
;
2086 if (pPrt
->PLinkModeStatus
== SK_LMODE_STAT_HALF
||
2087 pPrt
->PLinkModeStatus
== SK_LMODE_STAT_AUTOHALF
) {
2089 Len
= sizeof(SK_U64
);
2090 SkPnmiGetVar(pAC
, IoC
, OID_SKGE_STAT_TX_OCTETS
, (char *)&Octets
,
2091 &Len
, (SK_U32
)SK_PNMI_PORT_PHYS2INST(pAC
, Port
),
2092 pAC
->Rlmt
.Port
[Port
].Net
->NetNumber
);
2094 /* Snap statistic counters */
2095 (void)SkXmUpdateStats(pAC
, IoC
, Port
);
2097 (void)SkXmMacStatistic(pAC
, IoC
, Port
, XM_TXO_OK_HI
, &Val32
);
2099 Octets
= (SK_U64
)Val32
<< 32;
2101 (void)SkXmMacStatistic(pAC
, IoC
, Port
, XM_TXO_OK_LO
, &Val32
);
2105 if (pPrt
->LastOctets
== Octets
) {
2106 /* Tx hanging, a FIFO flush restarts it */
2107 SkMacFlushTxFifo(pAC
, IoC
, Port
);
2112 #endif /* GENESIS */
2115 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_SIRQ_E001
, SKERR_SIRQ_E001MSG
);
2120 } /* SkGeSirqEvent */
2124 /******************************************************************************
2126 * SkPhyIsrBcom() - PHY interrupt service routine
2128 * Description: handles all interrupts from BCom PHY
2132 static void SkPhyIsrBcom(
2133 SK_AC
*pAC
, /* Adapter Context */
2134 SK_IOC IoC
, /* Io Context */
2135 int Port
, /* Port Num = PHY Num */
2136 SK_U16 IStatus
) /* Interrupt Status */
2138 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
2141 pPrt
= &pAC
->GIni
.GP
[Port
];
2143 if ((IStatus
& PHY_B_IS_PSE
) != 0) {
2144 /* Incorrectable pair swap error */
2145 SK_ERR_LOG(pAC
, SK_ERRCL_HW
| SK_ERRCL_INIT
, SKERR_SIRQ_E022
,
2146 SKERR_SIRQ_E022MSG
);
2149 if ((IStatus
& (PHY_B_IS_AN_PR
| PHY_B_IS_LST_CHANGE
)) != 0) {
2151 SkHWLinkDown(pAC
, IoC
, Port
);
2153 Para
.Para32
[0] = (SK_U32
)Port
;
2154 /* Signal to RLMT */
2155 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
2157 /* Start workaround Errata #2 timer */
2158 SkTimerStart(pAC
, IoC
, &pPrt
->PWaTimer
, SK_WA_INA_TIME
,
2159 SKGE_HWAC
, SK_HWEV_WATIM
, Para
);
2162 } /* SkPhyIsrBcom */
2163 #endif /* GENESIS */
2167 /******************************************************************************
2169 * SkPhyIsrGmac() - PHY interrupt service routine
2171 * Description: handles all interrupts from Marvell PHY
2175 static void SkPhyIsrGmac(
2176 SK_AC
*pAC
, /* Adapter Context */
2177 SK_IOC IoC
, /* Io Context */
2178 int Port
, /* Port Num = PHY Num */
2179 SK_U16 IStatus
) /* Interrupt Status */
2181 SK_GEPORT
*pPrt
; /* GIni Port struct pointer */
2185 pPrt
= &pAC
->GIni
.GP
[Port
];
2187 if ((IStatus
& (PHY_M_IS_AN_PR
| PHY_M_IS_LST_CHANGE
)) != 0) {
2189 SkHWLinkDown(pAC
, IoC
, Port
);
2191 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_AUNE_ADV
, &Word
);
2193 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2194 ("AutoNeg.Adv: 0x%04X\n", Word
));
2196 /* Set Auto-negotiation advertisement */
2197 if (pPrt
->PFlowCtrlMode
== SK_FLOW_MODE_SYM_OR_REM
) {
2198 /* restore Asymmetric Pause bit */
2199 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_AUNE_ADV
,
2200 (SK_U16
)(Word
| PHY_M_AN_ASP
));
2203 Para
.Para32
[0] = (SK_U32
)Port
;
2204 /* Signal to RLMT */
2205 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
2208 if ((IStatus
& PHY_M_IS_AN_ERROR
) != 0) {
2209 /* Auto-Negotiation Error */
2210 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_SIRQ_E023
, SKERR_SIRQ_E023MSG
);
2213 if ((IStatus
& PHY_M_IS_FIFO_ERROR
) != 0) {
2214 /* FIFO Overflow/Underrun Error */
2215 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_SIRQ_E024
, SKERR_SIRQ_E024MSG
);
2218 } /* SkPhyIsrGmac */
2223 /******************************************************************************
2225 * SkPhyIsrLone() - PHY interrupt service routine
2227 * Description: handles all interrupts from LONE PHY
2231 static void SkPhyIsrLone(
2232 SK_AC
*pAC
, /* Adapter Context */
2233 SK_IOC IoC
, /* Io Context */
2234 int Port
, /* Port Num = PHY Num */
2235 SK_U16 IStatus
) /* Interrupt Status */
2239 if (IStatus
& (PHY_L_IS_DUP
| PHY_L_IS_ISOL
)) {
2241 SkHWLinkDown(pAC
, IoC
, Port
);
2243 Para
.Para32
[0] = (SK_U32
)Port
;
2244 /* Signal to RLMT */
2245 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
2248 } /* SkPhyIsrLone */
2249 #endif /* OTHER_PHY */