[TG3]: Add tagged status support.
[linux-2.6/verdex.git] / drivers / net / sk98lin / skgesirq.c
blob87520f0057d7fbba64f74528ad79540701ba4cd0
1 /******************************************************************************
3 * Name: skgesirq.c
4 * Project: Gigabit Ethernet Adapters, Common Modules
5 * Version: $Revision: 1.92 $
6 * Date: $Date: 2003/09/16 14:37:07 $
7 * Purpose: Special IRQ module
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect.
14 * (C)Copyright 2002-2003 Marvell.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
26 * Special Interrupt handler
28 * The following abstract should show how this module is included
29 * in the driver path:
31 * In the ISR of the driver the bits for frame transmission complete and
32 * for receive complete are checked and handled by the driver itself.
33 * The bits of the slow path mask are checked after that and then the
34 * entry into the so-called "slow path" is prepared. It is an implementors
35 * decision whether this is executed directly or just scheduled by
36 * disabling the mask. In the interrupt service routine some events may be
37 * generated, so it would be a good idea to call the EventDispatcher
38 * right after this ISR.
40 * The Interrupt source register of the adapter is NOT read by this module.
41 * SO if the drivers implementor needs a while loop around the
42 * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
43 * each loop entered.
45 * However, the MAC Interrupt status registers are read in a while loop.
49 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
50 static const char SysKonnectFileId[] =
51 "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
52 #endif
54 #include "h/skdrv1st.h" /* Driver Specific Definitions */
55 #ifndef SK_SLIM
56 #include "h/skgepnmi.h" /* PNMI Definitions */
57 #include "h/skrlmt.h" /* RLMT Definitions */
58 #endif
59 #include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
61 /* local function prototypes */
62 #ifdef GENESIS
63 static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
64 static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
65 static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
66 #endif /* GENESIS */
67 #ifdef YUKON
68 static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
69 static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
70 #endif /* YUKON */
71 #ifdef OTHER_PHY
72 static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
73 static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
74 static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
75 #endif /* OTHER_PHY */
77 #ifdef GENESIS
79 * array of Rx counter from XMAC which are checked
80 * in AutoSense mode to check whether a link is not able to auto-negotiate.
82 static const SK_U16 SkGeRxRegs[]= {
83 XM_RXF_64B,
84 XM_RXF_127B,
85 XM_RXF_255B,
86 XM_RXF_511B,
87 XM_RXF_1023B,
88 XM_RXF_MAX_SZ
89 } ;
90 #endif /* GENESIS */
92 #ifdef __C2MAN__
94 * Special IRQ function
96 * General Description:
99 intro()
101 #endif
103 /******************************************************************************
105 * SkHWInitDefSense() - Default Autosensing mode initialization
107 * Description: sets the PLinkMode for HWInit
109 * Returns: N/A
111 static void SkHWInitDefSense(
112 SK_AC *pAC, /* adapter context */
113 SK_IOC IoC, /* IO context */
114 int Port) /* Port Index (MAC_1 + n) */
116 SK_GEPORT *pPrt; /* GIni Port struct pointer */
118 pPrt = &pAC->GIni.GP[Port];
120 pPrt->PAutoNegTimeOut = 0;
122 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
123 pPrt->PLinkMode = pPrt->PLinkModeConf;
124 return;
127 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
128 ("AutoSensing: First mode %d on Port %d\n",
129 (int)SK_LMODE_AUTOFULL, Port));
131 pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
133 return;
134 } /* SkHWInitDefSense */
137 #ifdef GENESIS
138 /******************************************************************************
140 * SkHWSenseGetNext() - Get Next Autosensing Mode
142 * Description: gets the appropriate next mode
144 * Note:
147 static SK_U8 SkHWSenseGetNext(
148 SK_AC *pAC, /* adapter context */
149 SK_IOC IoC, /* IO context */
150 int Port) /* Port Index (MAC_1 + n) */
152 SK_GEPORT *pPrt; /* GIni Port struct pointer */
154 pPrt = &pAC->GIni.GP[Port];
156 pPrt->PAutoNegTimeOut = 0;
158 if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
159 /* Leave all as configured */
160 return(pPrt->PLinkModeConf);
163 if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
164 /* Return next mode AUTOBOTH */
165 return ((SK_U8)SK_LMODE_AUTOBOTH);
168 /* Return default autofull */
169 return ((SK_U8)SK_LMODE_AUTOFULL);
170 } /* SkHWSenseGetNext */
173 /******************************************************************************
175 * SkHWSenseSetNext() - Autosensing Set next mode
177 * Description: sets the appropriate next mode
179 * Returns: N/A
181 static void SkHWSenseSetNext(
182 SK_AC *pAC, /* adapter context */
183 SK_IOC IoC, /* IO context */
184 int Port, /* Port Index (MAC_1 + n) */
185 SK_U8 NewMode) /* New Mode to be written in sense mode */
187 SK_GEPORT *pPrt; /* GIni Port struct pointer */
189 pPrt = &pAC->GIni.GP[Port];
191 pPrt->PAutoNegTimeOut = 0;
193 if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
194 return;
197 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
198 ("AutoSensing: next mode %d on Port %d\n",
199 (int)NewMode, Port));
201 pPrt->PLinkMode = NewMode;
203 return;
204 } /* SkHWSenseSetNext */
205 #endif /* GENESIS */
208 /******************************************************************************
210 * SkHWLinkDown() - Link Down handling
212 * Description: handles the hardware link down signal
214 * Returns: N/A
216 void SkHWLinkDown(
217 SK_AC *pAC, /* adapter context */
218 SK_IOC IoC, /* IO context */
219 int Port) /* Port Index (MAC_1 + n) */
221 SK_GEPORT *pPrt; /* GIni Port struct pointer */
223 pPrt = &pAC->GIni.GP[Port];
225 /* Disable all MAC interrupts */
226 SkMacIrqDisable(pAC, IoC, Port);
228 /* Disable Receiver and Transmitter */
229 SkMacRxTxDisable(pAC, IoC, Port);
231 /* Init default sense mode */
232 SkHWInitDefSense(pAC, IoC, Port);
234 if (pPrt->PHWLinkUp == SK_FALSE) {
235 return;
238 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
239 ("Link down Port %d\n", Port));
241 /* Set Link to DOWN */
242 pPrt->PHWLinkUp = SK_FALSE;
244 /* Reset Port stati */
245 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
246 pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
247 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
249 /* Re-init Phy especially when the AutoSense default is set now */
250 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
252 /* GP0: used for workaround of Rev. C Errata 2 */
254 /* Do NOT signal to RLMT */
256 /* Do NOT start the timer here */
257 } /* SkHWLinkDown */
260 /******************************************************************************
262 * SkHWLinkUp() - Link Up handling
264 * Description: handles the hardware link up signal
266 * Returns: N/A
268 void SkHWLinkUp(
269 SK_AC *pAC, /* adapter context */
270 SK_IOC IoC, /* IO context */
271 int Port) /* Port Index (MAC_1 + n) */
273 SK_GEPORT *pPrt; /* GIni Port struct pointer */
275 pPrt = &pAC->GIni.GP[Port];
277 if (pPrt->PHWLinkUp) {
278 /* We do NOT need to proceed on active link */
279 return;
282 pPrt->PHWLinkUp = SK_TRUE;
283 pPrt->PAutoNegFail = SK_FALSE;
284 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
286 if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
287 pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
288 pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
289 /* Link is up and no Auto-negotiation should be done */
291 /* Link speed should be the configured one */
292 switch (pPrt->PLinkSpeed) {
293 case SK_LSPEED_AUTO:
294 /* default is 1000 Mbps */
295 case SK_LSPEED_1000MBPS:
296 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
297 break;
298 case SK_LSPEED_100MBPS:
299 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
300 break;
301 case SK_LSPEED_10MBPS:
302 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
303 break;
306 /* Set Link Mode Status */
307 if (pPrt->PLinkMode == SK_LMODE_FULL) {
308 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
310 else {
311 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
314 /* No flow control without auto-negotiation */
315 pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
317 /* enable Rx/Tx */
318 (void)SkMacRxTxEnable(pAC, IoC, Port);
320 } /* SkHWLinkUp */
323 /******************************************************************************
325 * SkMacParity() - MAC parity workaround
327 * Description: handles MAC parity errors correctly
329 * Returns: N/A
331 static void SkMacParity(
332 SK_AC *pAC, /* adapter context */
333 SK_IOC IoC, /* IO context */
334 int Port) /* Port Index of the port failed */
336 SK_EVPARA Para;
337 SK_GEPORT *pPrt; /* GIni Port struct pointer */
338 SK_U32 TxMax; /* Tx Max Size Counter */
340 pPrt = &pAC->GIni.GP[Port];
342 /* Clear IRQ Tx Parity Error */
343 #ifdef GENESIS
344 if (pAC->GIni.GIGenesis) {
346 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
348 #endif /* GENESIS */
350 #ifdef YUKON
351 if (pAC->GIni.GIYukon) {
352 /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
353 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
354 (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
355 pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
357 #endif /* YUKON */
359 if (pPrt->PCheckPar) {
361 if (Port == MAC_1) {
362 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
364 else {
365 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
367 Para.Para64 = Port;
368 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
370 Para.Para32[0] = Port;
371 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
373 return;
376 /* Check whether frames with a size of 1k were sent */
377 #ifdef GENESIS
378 if (pAC->GIni.GIGenesis) {
379 /* Snap statistic counters */
380 (void)SkXmUpdateStats(pAC, IoC, Port);
382 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
384 #endif /* GENESIS */
386 #ifdef YUKON
387 if (pAC->GIni.GIYukon) {
389 (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
391 #endif /* YUKON */
393 if (TxMax > 0) {
394 /* From now on check the parity */
395 pPrt->PCheckPar = SK_TRUE;
397 } /* SkMacParity */
400 /******************************************************************************
402 * SkGeHwErr() - Hardware Error service routine
404 * Description: handles all HW Error interrupts
406 * Returns: N/A
408 static void SkGeHwErr(
409 SK_AC *pAC, /* adapter context */
410 SK_IOC IoC, /* IO context */
411 SK_U32 HwStatus) /* Interrupt status word */
413 SK_EVPARA Para;
414 SK_U16 Word;
416 if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
417 /* PCI Errors occured */
418 if ((HwStatus & IS_IRQ_STAT) != 0) {
419 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
421 else {
422 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
425 /* Reset all bits in the PCI STATUS register */
426 SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
428 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
429 SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
430 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
432 Para.Para64 = 0;
433 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
436 #ifdef GENESIS
437 if (pAC->GIni.GIGenesis) {
439 if ((HwStatus & IS_NO_STAT_M1) != 0) {
440 /* Ignore it */
441 /* This situation is also indicated in the descriptor */
442 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
445 if ((HwStatus & IS_NO_STAT_M2) != 0) {
446 /* Ignore it */
447 /* This situation is also indicated in the descriptor */
448 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
451 if ((HwStatus & IS_NO_TIST_M1) != 0) {
452 /* Ignore it */
453 /* This situation is also indicated in the descriptor */
454 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
457 if ((HwStatus & IS_NO_TIST_M2) != 0) {
458 /* Ignore it */
459 /* This situation is also indicated in the descriptor */
460 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
463 #endif /* GENESIS */
465 #ifdef YUKON
466 if (pAC->GIni.GIYukon) {
467 /* This is necessary only for Rx timing measurements */
468 if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
469 /* increment Time Stamp Timer counter (high) */
470 pAC->GIni.GITimeStampCnt++;
472 /* Clear Time Stamp Timer IRQ */
473 SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
476 if ((HwStatus & IS_IRQ_SENSOR) != 0) {
477 /* no sensors on 32-bit Yukon */
478 if (pAC->GIni.GIYukon32Bit) {
479 /* disable HW Error IRQ */
480 pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
484 #endif /* YUKON */
486 if ((HwStatus & IS_RAM_RD_PAR) != 0) {
487 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
488 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
489 Para.Para64 = 0;
490 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
493 if ((HwStatus & IS_RAM_WR_PAR) != 0) {
494 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
495 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
496 Para.Para64 = 0;
497 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
500 if ((HwStatus & IS_M1_PAR_ERR) != 0) {
501 SkMacParity(pAC, IoC, MAC_1);
504 if ((HwStatus & IS_M2_PAR_ERR) != 0) {
505 SkMacParity(pAC, IoC, MAC_2);
508 if ((HwStatus & IS_R1_PAR_ERR) != 0) {
509 /* Clear IRQ */
510 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
512 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
513 Para.Para64 = MAC_1;
514 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
516 Para.Para32[0] = MAC_1;
517 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
520 if ((HwStatus & IS_R2_PAR_ERR) != 0) {
521 /* Clear IRQ */
522 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
524 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
525 Para.Para64 = MAC_2;
526 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
528 Para.Para32[0] = MAC_2;
529 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
531 } /* SkGeHwErr */
534 /******************************************************************************
536 * SkGeSirqIsr() - Special Interrupt Service Routine
538 * Description: handles all non data transfer specific interrupts (slow path)
540 * Returns: N/A
542 void SkGeSirqIsr(
543 SK_AC *pAC, /* adapter context */
544 SK_IOC IoC, /* IO context */
545 SK_U32 Istatus) /* Interrupt status word */
547 SK_EVPARA Para;
548 SK_U32 RegVal32; /* Read register value */
549 SK_GEPORT *pPrt; /* GIni Port struct pointer */
550 SK_U16 PhyInt;
551 int i;
553 if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
554 /* read the HW Error Interrupt source */
555 SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
557 SkGeHwErr(pAC, IoC, RegVal32);
561 * Packet Timeout interrupts
563 /* Check whether MACs are correctly initialized */
564 if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
565 pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
566 /* MAC 1 was not initialized but Packet timeout occured */
567 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
568 SKERR_SIRQ_E004MSG);
571 if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
572 pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
573 /* MAC 2 was not initialized but Packet timeout occured */
574 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
575 SKERR_SIRQ_E005MSG);
578 if ((Istatus & IS_PA_TO_RX1) != 0) {
579 /* Means network is filling us up */
580 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
581 SKERR_SIRQ_E002MSG);
582 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
585 if ((Istatus & IS_PA_TO_RX2) != 0) {
586 /* Means network is filling us up */
587 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
588 SKERR_SIRQ_E003MSG);
589 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
592 if ((Istatus & IS_PA_TO_TX1) != 0) {
594 pPrt = &pAC->GIni.GP[0];
596 /* May be a normal situation in a server with a slow network */
597 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
599 #ifdef GENESIS
600 if (pAC->GIni.GIGenesis) {
602 * workaround: if in half duplex mode, check for Tx hangup.
603 * Read number of TX'ed bytes, wait for 10 ms, then compare
604 * the number with current value. If nothing changed, we assume
605 * that Tx is hanging and do a FIFO flush (see event routine).
607 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
608 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
609 !pPrt->HalfDupTimerActive) {
611 * many more pack. arb. timeouts may come in between,
612 * we ignore those
614 pPrt->HalfDupTimerActive = SK_TRUE;
615 #ifdef XXX
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;
622 #endif /* XXX */
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;
634 Para.Para32[0] = 0;
635 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
636 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
639 #endif /* GENESIS */
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);
649 #ifdef GENESIS
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;
656 #ifdef XXX
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;
663 #endif /* XXX */
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;
675 Para.Para32[0] = 1;
676 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
677 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
680 #endif /* GENESIS */
683 /* Check interrupts of the particular queues */
684 if ((Istatus & IS_R1_C) != 0) {
685 /* Clear IRQ */
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,
688 SKERR_SIRQ_E006MSG);
689 Para.Para64 = MAC_1;
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) {
696 /* Clear IRQ */
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,
699 SKERR_SIRQ_E007MSG);
700 Para.Para64 = MAC_2;
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) {
707 /* Clear IRQ */
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,
710 SKERR_SIRQ_E008MSG);
711 Para.Para64 = MAC_1;
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) {
718 /* Clear IRQ */
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,
721 SKERR_SIRQ_E009MSG);
722 Para.Para64 = MAC_1;
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) {
729 /* Clear IRQ */
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,
732 SKERR_SIRQ_E010MSG);
733 Para.Para64 = MAC_2;
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) {
740 /* Clear IRQ */
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,
743 SKERR_SIRQ_E011MSG);
744 Para.Para64 = MAC_2;
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) {
758 continue;
761 #ifdef GENESIS
762 if (pAC->GIni.GIGenesis) {
764 switch (pPrt->PhyType) {
766 case SK_PHY_XMAC:
767 break;
769 case SK_PHY_BCOM:
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",
775 i, PhyInt));
776 SkPhyIsrBcom(pAC, IoC, i, PhyInt);
778 break;
779 #ifdef OTHER_PHY
780 case SK_PHY_LONE:
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",
786 i, PhyInt));
787 SkPhyIsrLone(pAC, IoC, i, PhyInt);
789 break;
790 #endif /* OTHER_PHY */
793 #endif /* GENESIS */
795 #ifdef YUKON
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",
803 i, PhyInt));
804 SkPhyIsrGmac(pAC, IoC, i, PhyInt);
807 #endif /* YUKON */
811 /* I2C Ready interrupt */
812 if ((Istatus & IS_I2C_READY) != 0) {
813 #ifdef SK_SLIM
814 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
815 #else
816 SkI2cIsr(pAC, IoC);
817 #endif
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) {
837 /* IRQ from MAC 1 */
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) {
852 /* IRQ from MAC 2 */
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);
866 SkHwtIsr(pAC, IoC);
869 } /* SkGeSirqIsr */
872 #ifdef GENESIS
873 /******************************************************************************
875 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
877 * return:
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 */
893 int i;
895 pPrt = &pAC->GIni.GP[Port];
897 /* Default: no action */
898 Rtv = SK_HW_PS_NONE;
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
907 * really received.
909 RxCts = 0;
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 */
919 CheckShorts = 0;
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 */
928 CheckShorts = 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);
947 else {
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
960 * network -> ok.
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;
982 return(Rtv);
983 } /* SkGePortCheckShorts */
984 #endif /* GENESIS */
987 /******************************************************************************
989 * SkGePortCheckUp() - Check if the link is up
991 * return:
992 * 0 o.k. nothing needed
993 * 1 Restart needed on this port
994 * 2 Link came up
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) {
1010 AutoNeg = SK_FALSE;
1012 else {
1013 AutoNeg = SK_TRUE;
1016 #ifdef GENESIS
1017 if (pAC->GIni.GIGenesis) {
1019 switch (pPrt->PhyType) {
1021 case SK_PHY_XMAC:
1022 Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
1023 break;
1024 case SK_PHY_BCOM:
1025 Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
1026 break;
1027 #ifdef OTHER_PHY
1028 case SK_PHY_LONE:
1029 Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
1030 break;
1031 case SK_PHY_NAT:
1032 Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
1033 break;
1034 #endif /* OTHER_PHY */
1037 #endif /* GENESIS */
1039 #ifdef YUKON
1040 if (pAC->GIni.GIYukon) {
1042 Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
1044 #endif /* YUKON */
1046 return(Rtv);
1047 } /* SkGePortCheckUp */
1050 #ifdef GENESIS
1051 /******************************************************************************
1053 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1055 * return:
1056 * 0 o.k. nothing needed
1057 * 1 Restart needed on this port
1058 * 2 Link came up
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 */
1068 int Done;
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);
1083 else {
1084 return(SkGePortCheckShorts(pAC, IoC, Port));
1088 IsrcSum = pPrt->PIsave;
1089 pPrt->PIsave = 0;
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);
1099 IsrcSum |= 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.
1126 pPrt->PLinkResCt++;
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));
1139 else {
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);
1149 else {
1150 /* Do nothing more if link is broken */
1151 return(SK_HW_PS_NONE);
1155 else {
1156 /* Link was not broken, check if it is */
1157 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1158 IsrcSum |= Isrc;
1159 if ((Isrc & XM_IS_INP_ASS) != 0) {
1160 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1161 IsrcSum |= Isrc;
1162 if ((Isrc & XM_IS_INP_ASS) != 0) {
1163 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1164 IsrcSum |= 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);
1179 else {
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);
1194 IsrcSum |= 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);
1203 #ifdef DEBUG
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));
1208 #endif /* DEBUG */
1209 return(SK_HW_PS_NONE);
1212 if (AutoNeg) {
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
1269 * auto-negotiation.
1270 * Solution: we restart the autosensing after
1271 * a few timeouts.
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);
1282 else {
1283 /* Link is up and we don't need more */
1284 #ifdef DEBUG
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));
1289 #endif /* DEBUG */
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
1310 * return:
1311 * 0 o.k. nothing needed
1312 * 1 Restart needed on this port
1313 * 2 Link came up
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 */
1322 int Done;
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 */
1327 #ifdef DEBUG
1328 SK_U16 LpAb;
1329 SK_U16 ExtStat;
1330 #endif /* DEBUG */
1332 pPrt = &pAC->GIni.GP[Port];
1334 /* Check for No HCD Link events (#10523) */
1335 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
1337 #ifdef xDEBUG
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;
1343 Stat1 = 0;
1344 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1345 CMSMPrintString(
1346 pAC->pConfigTable,
1347 MSG_TYPE_RUNTIME_INFO,
1348 "CheckUp1 - Stat: %x, Mask: %x",
1349 (void *)Isrc,
1350 (void *)Stat1);
1352 Stat1 = 0;
1353 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1354 Stat2 = 0;
1355 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
1356 Stat1 = Stat1 << 16 | Stat2;
1357 Stat2 = 0;
1358 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1359 Stat3 = 0;
1360 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1361 Stat2 = Stat2 << 16 | Stat3;
1362 CMSMPrintString(
1363 pAC->pConfigTable,
1364 MSG_TYPE_RUNTIME_INFO,
1365 "Ctrl/Stat: %x, AN Adv/LP: %x",
1366 (void *)Stat1,
1367 (void *)Stat2);
1369 Stat1 = 0;
1370 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1371 Stat2 = 0;
1372 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1373 Stat1 = Stat1 << 16 | Stat2;
1374 Stat2 = 0;
1375 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1376 Stat3 = 0;
1377 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
1378 Stat2 = Stat2 << 16 | Stat3;
1379 CMSMPrintString(
1380 pAC->pConfigTable,
1381 MSG_TYPE_RUNTIME_INFO,
1382 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1383 (void *)Stat1,
1384 (void *)Stat2);
1386 Stat1 = 0;
1387 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1388 Stat2 = 0;
1389 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1390 Stat1 = Stat1 << 16 | Stat2;
1391 Stat2 = 0;
1392 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1393 Stat3 = 0;
1394 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1395 Stat2 = Stat2 << 16 | Stat3;
1396 CMSMPrintString(
1397 pAC->pConfigTable,
1398 MSG_TYPE_RUNTIME_INFO,
1399 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1400 (void *)Stat1,
1401 (void *)Stat2);
1403 #endif /* DEBUG */
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));
1417 #ifdef xDEBUG
1418 CMSMPrintString(
1419 pAC->pConfigTable,
1420 MSG_TYPE_RUNTIME_INFO,
1421 "No HCD link event, port %d.",
1422 (void *)Port,
1423 (void *)NULL);
1424 #endif /* DEBUG */
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);
1434 #ifdef xDEBUG
1436 SK_U32 Stat1, Stat2, Stat3;
1438 Stat1 = 0;
1439 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1440 CMSMPrintString(
1441 pAC->pConfigTable,
1442 MSG_TYPE_RUNTIME_INFO,
1443 "CheckUp1a - Stat: %x, Mask: %x",
1444 (void *)Isrc,
1445 (void *)Stat1);
1447 Stat1 = 0;
1448 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1449 Stat2 = 0;
1450 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1451 Stat1 = Stat1 << 16 | PhyStat;
1452 Stat2 = 0;
1453 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1454 Stat3 = 0;
1455 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1456 Stat2 = Stat2 << 16 | Stat3;
1457 CMSMPrintString(
1458 pAC->pConfigTable,
1459 MSG_TYPE_RUNTIME_INFO,
1460 "Ctrl/Stat: %x, AN Adv/LP: %x",
1461 (void *)Stat1,
1462 (void *)Stat2);
1464 Stat1 = 0;
1465 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1466 Stat2 = 0;
1467 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1468 Stat1 = Stat1 << 16 | Stat2;
1469 Stat2 = 0;
1470 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1471 Stat3 = 0;
1472 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1473 Stat2 = Stat2 << 16 | ResAb;
1474 CMSMPrintString(
1475 pAC->pConfigTable,
1476 MSG_TYPE_RUNTIME_INFO,
1477 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1478 (void *)Stat1,
1479 (void *)Stat2);
1481 Stat1 = 0;
1482 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1483 Stat2 = 0;
1484 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1485 Stat1 = Stat1 << 16 | Stat2;
1486 Stat2 = 0;
1487 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1488 Stat3 = 0;
1489 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1490 Stat2 = Stat2 << 16 | Stat3;
1491 CMSMPrintString(
1492 pAC->pConfigTable,
1493 MSG_TYPE_RUNTIME_INFO,
1494 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1495 (void *)Stat1,
1496 (void *)Stat2);
1498 #endif /* DEBUG */
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) {
1515 /* Error */
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));
1535 if (AutoNeg) {
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) {
1543 #ifdef DEBUG
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));
1550 #endif /* DEBUG */
1551 return(SK_HW_PS_RESTART);
1553 else {
1554 #ifdef xDEBUG
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) {
1559 CMSMPrintString(
1560 pAC->pConfigTable,
1561 MSG_TYPE_RUNTIME_INFO,
1562 "CheckUp2 - Stat: %x",
1563 (void *)ExtStat,
1564 (void *)NULL);
1566 #endif /* DEBUG */
1567 return(SK_HW_PS_LINK);
1571 else { /* !AutoNeg */
1572 /* Link is up and we don't need more. */
1573 #ifdef DEBUG
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));
1578 #endif /* DEBUG */
1580 #ifdef xDEBUG
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) {
1585 CMSMPrintString(
1586 pAC->pConfigTable,
1587 MSG_TYPE_RUNTIME_INFO,
1588 "CheckUp3 - Stat: %x",
1589 (void *)ExtStat,
1590 (void *)NULL);
1592 #endif /* DEBUG */
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 */
1606 #ifdef YUKON
1607 /******************************************************************************
1609 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1611 * return:
1612 * 0 o.k. nothing needed
1613 * 1 Restart needed on this port
1614 * 2 Link came up
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 */
1623 int Done;
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 */
1628 SK_EVPARA Para;
1629 #ifdef DEBUG
1630 SK_U16 Word; /* I/O helper */
1631 #endif /* DEBUG */
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) {
1663 /* Error */
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));
1679 #ifdef DEBUG
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));
1690 #endif /* DEBUG */
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);
1701 Para.Para64 = Port;
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);
1713 if (AutoNeg) {
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 */
1730 #ifdef DEBUG
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));
1735 #endif /* DEBUG */
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 */
1746 #endif /* YUKON */
1749 #ifdef OTHER_PHY
1750 /******************************************************************************
1752 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1754 * return:
1755 * 0 o.k. nothing needed
1756 * 1 Restart needed on this port
1757 * 2 Link came up
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 */
1766 int Done;
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 */
1771 SK_U16 StatSum;
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;
1781 pPrt->PIsave = 0;
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);
1788 StatSum |= 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);
1795 #ifdef DEBUG
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));
1800 #endif /* DEBUG */
1801 return(SK_HW_PS_NONE);
1804 if (AutoNeg) {
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);
1827 else {
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);
1855 else {
1856 /* Link is up and we don't need more */
1857 #ifdef DEBUG
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));
1862 #endif /* DEBUG */
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
1885 * return:
1886 * 0 o.k. nothing needed
1887 * 1 Restart needed on this port
1888 * 2 Link came up
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
1906 * Description:
1908 * Notes:
1910 int SkGeSirqEvent(
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 */
1917 SK_U32 Port;
1918 SK_U32 Val32;
1919 int PortStat;
1920 SK_U8 Val8;
1921 #ifdef GENESIS
1922 SK_U64 Octets;
1923 #endif /* GENESIS */
1925 Port = Para.Para32[0];
1926 pPrt = &pAC->GIni.GP[Port];
1928 switch (Event) {
1929 case SK_HWEV_WATIM:
1930 if (pPrt->PState == SK_PRT_RESET) {
1932 PortStat = SK_HW_PS_NONE;
1934 else {
1935 /* Check whether port came up */
1936 PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
1939 switch (PortStat) {
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);
1954 break;
1956 case SK_HW_PS_LINK:
1957 /* Signal to RLMT */
1958 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
1959 break;
1962 /* Start again the check Timer */
1963 if (pPrt->PHWLinkUp) {
1964 Val32 = SK_WA_ACT_TIME;
1966 else {
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);
1974 break;
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);
1993 break;
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);
2008 break;
2010 case SK_HWEV_UPDATE_STAT:
2011 /* We do NOT need to update any statistics */
2012 break;
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++) {
2017 pPrt->PPrevRx = 0;
2018 pPrt->PPrevFcs = 0;
2019 pPrt->PPrevShorts = 0;
2021 break;
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;
2029 /* Restart Port */
2030 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2031 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2033 break;
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;
2041 /* Restart Port */
2042 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2043 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2045 break;
2047 case SK_HWEV_SET_ROLE:
2048 /* not possible for fiber */
2049 if (!pAC->GIni.GICopperType) {
2050 break;
2052 Val8 = (SK_U8)Para.Para32[1];
2053 if (pPrt->PMSMode != Val8) {
2054 /* Set New Role (Master/Slave) mode */
2055 pPrt->PMSMode = Val8;
2057 /* Restart Port */
2058 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2059 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2061 break;
2063 case SK_HWEV_SET_SPEED:
2064 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
2065 break;
2067 Val8 = (SK_U8)Para.Para32[1];
2068 if (pPrt->PLinkSpeed != Val8) {
2069 /* Set New Speed parameter */
2070 pPrt->PLinkSpeed = Val8;
2072 /* Restart Port */
2073 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2074 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2076 break;
2078 #ifdef GENESIS
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) {
2088 #ifdef XXX
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);
2093 #endif /* XXX */
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);
2103 Octets += Val32;
2105 if (pPrt->LastOctets == Octets) {
2106 /* Tx hanging, a FIFO flush restarts it */
2107 SkMacFlushTxFifo(pAC, IoC, Port);
2111 break;
2112 #endif /* GENESIS */
2114 default:
2115 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
2116 break;
2119 return(0);
2120 } /* SkGeSirqEvent */
2123 #ifdef GENESIS
2124 /******************************************************************************
2126 * SkPhyIsrBcom() - PHY interrupt service routine
2128 * Description: handles all interrupts from BCom PHY
2130 * Returns: N/A
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 */
2139 SK_EVPARA Para;
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 */
2166 #ifdef YUKON
2167 /******************************************************************************
2169 * SkPhyIsrGmac() - PHY interrupt service routine
2171 * Description: handles all interrupts from Marvell PHY
2173 * Returns: N/A
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 */
2182 SK_EVPARA Para;
2183 SK_U16 Word;
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 */
2219 #endif /* YUKON */
2222 #ifdef OTHER_PHY
2223 /******************************************************************************
2225 * SkPhyIsrLone() - PHY interrupt service routine
2227 * Description: handles all interrupts from LONE PHY
2229 * Returns: N/A
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 */
2237 SK_EVPARA Para;
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 */
2251 /* End of File */