1 /******************************************************************************
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.65 $
6 * Date: $Date: 2001/02/23 13:41:51 $
7 * Purpose: Special IRQ module
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2000 SysKonnect GmbH.
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * The information in this file is provided "AS IS" without warranty.
22 ******************************************************************************/
24 /******************************************************************************
28 * $Log: skgesirq.c,v $
29 * Revision 1.65 2001/02/23 13:41:51 gklug
30 * fix: PHYS2INST should be used correctly for Dual Net operation
31 * chg: do no longer work with older PNMI
33 * Revision 1.64 2001/02/15 11:27:04 rassmann
34 * Working with RLMT v1 if SK_MAX_NETS undefined.
36 * Revision 1.63 2001/02/06 10:44:23 mkunz
37 * - NetIndex added to interface functions of pnmi V4 with dual net support
39 * Revision 1.62 2001/01/31 15:31:41 gklug
40 * fix: problem with autosensing an SR8800 switch
42 * Revision 1.61 2000/11/09 11:30:09 rassmann
43 * WA: Waiting after releasing reset until BCom chip is accessible.
45 * Revision 1.60 2000/10/18 12:37:48 cgoos
46 * Reinserted the comment for version 1.56.
48 * Revision 1.59 2000/10/18 12:22:20 cgoos
49 * Added workaround for half duplex hangup.
51 * Revision 1.58 2000/09/28 13:06:04 gklug
52 * fix: BCOM may NOT be touched if XMAC is in RESET state
54 * Revision 1.57 2000/09/08 12:38:39 cgoos
55 * Added forgotten variable declaration.
57 * Revision 1.56 2000/09/08 08:12:13 cgoos
58 * Changed handling of parity errors in SkGeHwErr (correct reset of error).
60 * Revision 1.55 2000/06/19 08:36:25 cgoos
63 * Revision 1.54 2000/05/22 08:45:57 malthoff
64 * Fix: #10523 is valid for all BCom PHYs.
66 * Revision 1.53 2000/05/19 10:20:30 cgoos
67 * Removed Solaris debug output code.
69 * Revision 1.52 2000/05/19 10:19:37 cgoos
70 * Added PHY state check in HWLinkDown.
71 * Move PHY interrupt code to IS_EXT_REG case in SkGeSirqIsr.
73 * Revision 1.51 2000/05/18 05:56:20 cgoos
76 * Revision 1.50 2000/05/17 12:49:49 malthoff
77 * Fixes BCom link bugs (#10523).
79 * Revision 1.49 1999/12/17 11:02:50 gklug
80 * fix: read PHY_STAT of Broadcom chip more often to assure good status
82 * Revision 1.48 1999/12/06 10:01:17 cgoos
83 * Added SET function for Role.
85 * Revision 1.47 1999/11/22 13:34:24 cgoos
86 * Changed license header to GPL.
88 * Revision 1.46 1999/09/16 10:30:07 cgoos
89 * Removed debugging output statement from Linux.
91 * Revision 1.45 1999/09/16 07:32:55 cgoos
92 * Fixed dual-port copperfield bug (PHY_READ from resetted port).
93 * Removed some unused variables.
95 * Revision 1.44 1999/08/03 15:25:04 cgoos
96 * Removed workaround for disabled interrupts in half duplex mode.
98 * Revision 1.43 1999/08/03 14:27:58 cgoos
99 * Removed SENSE mode code from SkGePortCheckUpBcom.
101 * Revision 1.42 1999/07/26 09:16:54 cgoos
102 * Added some typecasts to avoid compiler warnings.
104 * Revision 1.41 1999/05/19 07:28:59 cgoos
105 * Changes for 1000Base-T.
107 * Revision 1.40 1999/04/08 13:59:39 gklug
108 * fix: problem with 3Com switches endless RESTARTs
110 * Revision 1.39 1999/03/08 10:10:52 gklug
111 * fix: AutoSensing did switch to next mode even if LiPa indicated offline
113 * Revision 1.38 1999/03/08 09:49:03 gklug
114 * fix: Bug using pAC instead of IoC, causing AIX problems
115 * fix: change compare for Linux compiler bug workaround
117 * Revision 1.37 1999/01/28 14:51:33 gklug
118 * fix: monitor for autosensing and extra RESETS the RX on wire counters
120 * Revision 1.36 1999/01/22 09:19:55 gklug
121 * fix: Init DupMode and InitPauseMd are now called in RxTxEnable
123 * Revision 1.35 1998/12/11 15:22:59 gklug
124 * chg: autosensing: check for receive if manual mode was guessed
125 * chg: simplified workaround for XMAC errata
126 * chg: wait additional 100 ms before link goes up.
127 * chg: autoneg timeout to 600 ms
128 * chg: restart autoneg even if configured to autonegotiation
130 * Revision 1.34 1998/12/10 10:33:14 gklug
131 * add: more debug messages
132 * fix: do a new InitPhy if link went down (AutoSensing problem)
133 * chg: Check for zero shorts if link is NOT up
134 * chg: reset Port if link goes down
135 * chg: wait additional 100 ms when link comes up to check shorts
136 * fix: dummy read extended autoneg status to prevent link going down immediately
138 * Revision 1.33 1998/12/07 12:18:29 gklug
139 * add: refinement of autosense mode: take into account the autoneg cap of LiPa
141 * Revision 1.32 1998/12/07 07:11:21 gklug
142 * fix: compiler warning
144 * Revision 1.31 1998/12/02 09:29:05 gklug
145 * fix: WA XMAC Errata: FCSCt check was not correct.
146 * fix: WA XMAC Errata: Prec Counter were NOT updated in case of short checks.
147 * fix: Clear Stat : now clears the Prev counters of all known Ports
149 * Revision 1.30 1998/12/01 10:54:15 gklug
150 * dd: workaround for XMAC errata changed. Check RX count and CRC err Count, too.
152 * Revision 1.29 1998/12/01 10:01:53 gklug
153 * fix: if MAC IRQ occurs during port down, this will be handled correctly
155 * Revision 1.28 1998/11/26 16:22:11 gklug
156 * fix: bug in autosense if manual modes are used
158 * Revision 1.27 1998/11/26 15:50:06 gklug
159 * fix: PNMI needs to set PLinkModeConf
161 * Revision 1.26 1998/11/26 14:51:58 gklug
162 * add: AutoSensing functionalty
164 * Revision 1.25 1998/11/26 07:34:37 gklug
165 * fix: Init PrevShorts when restarting port due to Link connection
167 * Revision 1.24 1998/11/25 10:57:32 gklug
168 * fix: remove unreferenced local vars
170 * Revision 1.23 1998/11/25 08:26:40 gklug
171 * fix: don't do a RESET on a starting or stopping port
173 * Revision 1.22 1998/11/24 13:29:44 gklug
174 * add: Workaround for MAC parity errata
176 * Revision 1.21 1998/11/18 15:31:06 gklug
179 * Revision 1.20 1998/11/18 12:58:54 gklug
180 * fix: use PNMI query instead of hardware access
182 * Revision 1.19 1998/11/18 12:54:55 gklug
183 * chg: add new workaround for XMAC Errata
184 * add: short event counter monitoring on active link too
186 * Revision 1.18 1998/11/13 14:27:41 malthoff
187 * Bug Fix: Packet Arbiter Timeout was not cleared correctly
188 * for timeout on TX1 and TX2.
190 * Revision 1.17 1998/11/04 07:01:59 cgoos
191 * Moved HW link poll sequence.
192 * Added call to SkXmRxTxEnable.
194 * Revision 1.16 1998/11/03 13:46:03 gklug
195 * add: functionality of SET_LMODE and SET_FLOW_MODE
196 * fix: send RLMT LinkDown event when Port stop is given with LinkUp
198 * Revision 1.15 1998/11/03 12:56:47 gklug
199 * fix: Needs more events
201 * Revision 1.14 1998/10/30 07:36:35 gklug
202 * rmv: unnecessary code
204 * Revision 1.13 1998/10/29 15:21:57 gklug
205 * add: Poll link feature for activating HW link
206 * fix: Deactivate HWLink when Port STOP is given
208 * Revision 1.12 1998/10/28 07:38:57 cgoos
209 * Checking link status at begin of SkHWLinkUp.
211 * Revision 1.11 1998/10/22 09:46:50 gklug
212 * fix SysKonnectFileId typo
214 * Revision 1.10 1998/10/14 13:57:47 gklug
215 * add: Port start/stop event
217 * Revision 1.9 1998/10/14 05:48:29 cgoos
218 * Added definition for Para.
220 * Revision 1.8 1998/10/14 05:40:09 gklug
221 * add: Hardware Linkup signal used
223 * Revision 1.7 1998/10/09 06:50:20 malthoff
224 * Remove ID_sccs by SysKonnectFileId.
226 * Revision 1.6 1998/10/08 09:11:49 gklug
227 * add: clear IRQ commands
229 * Revision 1.5 1998/10/02 14:27:35 cgoos
230 * Fixed some typos and wrong event names.
232 * Revision 1.4 1998/10/02 06:24:17 gklug
233 * add: HW error function
236 * Revision 1.3 1998/10/01 07:03:00 gklug
237 * add: ISR for the usual interrupt source register
239 * Revision 1.2 1998/09/03 13:50:33 gklug
240 * add: function prototypes
242 * Revision 1.1 1998/08/27 11:50:21 gklug
247 ******************************************************************************/
250 * Special Interrupt handler
252 * The following abstract should show how this module is included
253 * in the driver path:
255 * In the ISR of the driver the bits for frame transmission complete and
256 * for receive complete are checked and handled by the driver itself.
257 * The bits of the slow path mask are checked after this and then the
258 * entry into the so-called "slow path" is prepared. It is an implemetors
259 * decision whether this is executed directly or just scheduled by
260 * disabling the mask. In the interrupt service routine events may be
261 * generated, so it would be a good idea to call the EventDispatcher
262 * right after this ISR.
264 * The Interrupt service register of the adapter is NOT read by this
265 * module. SO if the drivers implemetor needs a while loop around the
266 * slow data paths Interrupt bits, he needs to call the SkGeIsr() for
269 * However, the XMAC Interrupt status registers are read in a while loop.
273 static const char SysKonnectFileId[] =
274 "$Id: skgesirq.c,v 1.65 2001/02/23 13:41:51 gklug Exp $" ;
276 #include "h/skdrv1st.h" /* Driver Specific Definitions */
277 #include "h/skgepnmi.h" /* PNMI Definitions */
278 #include "h/skrlmt.h" /* RLMT Definitions */
279 #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
281 /* local function prototypes */
282 static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int);
283 static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int);
284 static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int);
285 static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int);
286 static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
287 static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
290 * Define an array of RX counter which are checked
291 * in AutoSense mode to check whether a link is not able to autonegotiate.
293 static const SK_U32 SkGeRxOids[]= {
295 OID_SKGE_STAT_RX_127,
296 OID_SKGE_STAT_RX_255,
297 OID_SKGE_STAT_RX_511,
298 OID_SKGE_STAT_RX_1023,
299 OID_SKGE_STAT_RX_MAX,
304 * Special IRQ function
306 * General Description:
313 /* Define return codes of SkGePortCheckUp and CheckShort. */
314 #define SK_HW_PS_NONE 0 /* No action needed */
315 #define SK_HW_PS_RESTART 1 /* Restart needed */
316 #define SK_HW_PS_LINK 2 /* Link Up actions needed */
318 /******************************************************************************
320 * SkHWInitDefSense() - Default Autosensing mode initialization
323 * This function handles the Hardware link down signal
328 void SkHWInitDefSense(
329 SK_AC *pAC, /* adapter context */
330 SK_IOC IoC, /* IO context */
331 int Port) /* Port Index (MAC_1 + n) */
335 pPrt = &pAC->GIni.GP[Port];
337 pPrt->PAutoNegTimeOut = 0;
339 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
340 pPrt->PLinkMode = pPrt->PLinkModeConf;
344 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
345 ("AutoSensing: First mode %d on Port %d\n",
346 (int)SK_LMODE_AUTOFULL,
349 pPrt->PLinkMode = SK_LMODE_AUTOFULL;
352 } /* SkHWInitDefSense */
355 /******************************************************************************
357 * SkHWSenseGetNext() - GetNextAutosensing Mode
360 * This function handles the AutoSensing
365 SK_U8 SkHWSenseGetNext(
366 SK_AC *pAC, /* adapter context */
367 SK_IOC IoC, /* IO context */
368 int Port) /* Port Index (MAC_1 + n) */
372 pPrt = &pAC->GIni.GP[Port];
374 pPrt->PAutoNegTimeOut = 0;
376 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
377 /* Leave all as configured */
378 return (pPrt->PLinkModeConf);
381 if (pPrt->PLinkMode == SK_LMODE_AUTOFULL) {
382 /* Return next mode AUTOBOTH */
383 return (SK_LMODE_AUTOBOTH);
386 /* Return default autofull */
387 return (SK_LMODE_AUTOFULL);
388 } /* SkHWSenseGetNext */
391 /******************************************************************************
393 * SkHWSenseSetNext() - Autosensing Set next mode
396 * This function sets the appropriate next mode.
401 void SkHWSenseSetNext(
402 SK_AC *pAC, /* adapter context */
403 SK_IOC IoC, /* IO context */
404 int Port, /* Port Index (MAC_1 + n) */
405 SK_U8 NewMode) /* New Mode to be written in sense mode */
409 pPrt = &pAC->GIni.GP[Port];
411 pPrt->PAutoNegTimeOut = 0;
413 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
417 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
418 ("AutoSensing: next mode %d on Port %d\n", (int)NewMode, Port));
419 pPrt->PLinkMode = NewMode;
422 } /* SkHWSenseSetNext */
425 /******************************************************************************
427 * SkHWLinkDown() - Link Down handling
430 * This function handles the Hardware link down signal
436 SK_AC *pAC, /* adapter context */
437 SK_IOC IoC, /* IO context */
438 int Port) /* Port Index (MAC_1 + n) */
443 pPrt = &pAC->GIni.GP[Port];
445 /* Disable all XMAC interrupts. */
446 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
448 /* Disable Receiver and Transmitter. */
449 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
450 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
452 /* Disable all PHY interrupts. */
453 switch (pPrt->PhyType) {
455 /* Make sure that PHY is initialized. */
456 if (pAC->GIni.GP[Port].PState) {
457 /* NOT allowed if BCOM is in RESET state */
458 /* Workaround BCOM Errata (#10523) all BCom. */
459 /* Disable Power Management if link is down. */
460 PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, &Word);
461 PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL,
462 Word | PHY_B_AC_DIS_PM);
463 PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_INT_MASK, 0xffff);
467 PHY_WRITE(IoC, pPrt, Port, PHY_LONE_INT_ENAB, 0x0);
471 PHY_WRITE(IoC, pPrt, Port, PHY_NAT_INT_MASK, 0xffff); */
475 /* Init default sense mode. */
476 SkHWInitDefSense(pAC, IoC, Port);
478 if (!pPrt->PHWLinkUp) {
482 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_IRQ,
483 ("Link down Port %d\n", Port));
485 /* Set Link to DOWN. */
486 pPrt->PHWLinkUp = SK_FALSE;
488 /* Reset Port stati */
489 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
490 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
493 * Reinit Phy especially when the AutoSense default is set now.
495 SkXmInitPhy(pAC, IoC, Port, SK_FALSE);
497 /* GP0: used for workaround of Rev. C Errata 2. */
499 /* Do NOT signal to RLMT. */
501 /* Do NOT start the timer here. */
505 /******************************************************************************
507 * SkHWLinkUp() - Link Up handling
510 * This function handles the Hardware link up signal
516 SK_AC *pAC, /* adapter context */
517 SK_IOC IoC, /* IO context */
518 int Port) /* Port Index (MAC_1 + n) */
522 pPrt = &pAC->GIni.GP[Port];
524 if (pPrt->PHWLinkUp) {
525 /* We do NOT need to proceed on active link */
529 pPrt->PHWLinkUp = SK_TRUE;
530 pPrt->PAutoNegFail = SK_FALSE;
531 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
533 if (pPrt->PLinkMode != SK_LMODE_AUTOHALF &&
534 pPrt->PLinkMode != SK_LMODE_AUTOFULL &&
535 pPrt->PLinkMode != SK_LMODE_AUTOBOTH) {
536 /* Link is up and no Autonegotiation should be done */
541 if (pPrt->PLinkMode == SK_LMODE_FULL) {
542 pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL;
545 pPrt->PLinkModeStatus = SK_LMODE_STAT_HALF;
548 /* No flow control without autonegotiation */
549 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
552 SkXmRxTxEnable(pAC, IoC, Port);
557 /******************************************************************************
559 * SkMacParity - does everything to handle MAC parity errors correctly
562 static void SkMacParity(
563 SK_AC *pAC, /* adapter context */
564 SK_IOC IoC, /* IO context */
565 int Port) /* Port Index of the port failed */
568 SK_GEPORT *pPrt; /* GIni Port struct pointer */
569 SK_U64 TxMax; /* TxMax Counter */
572 pPrt = &pAC->GIni.GP[Port];
575 SK_OUT16(IoC, MR_ADDR(Port,TX_MFF_CTRL1), MFF_CLR_PERR);
577 if (pPrt->PCheckPar) {
579 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E016,
583 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E017,
587 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
588 Para.Para32[0] = Port;
589 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
594 /* Check whether frames with a size of 1k were sent */
595 Len = sizeof(SK_U64);
596 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_MAX, (char *)&TxMax,
597 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
598 pAC->Rlmt.Port[Port].Net->NetNumber);
601 /* From now on check the parity */
602 pPrt->PCheckPar = SK_TRUE;
607 /******************************************************************************
609 * Hardware Error service routine
615 static void SkGeHwErr(
616 SK_AC *pAC, /* adapter context */
617 SK_IOC IoC, /* IO context */
618 SK_U32 HwStatus) /* Interrupt status word */
623 if ((HwStatus & IS_IRQ_MST_ERR) || (HwStatus & IS_IRQ_STAT)) {
624 if (HwStatus & IS_IRQ_STAT) {
625 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
628 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
631 /* Reset all bits in the PCI STATUS register */
632 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
633 SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
634 SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS);
635 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
638 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
641 if (HwStatus & IS_NO_STAT_M1) {
643 /* This situation is also indicated in the descriptor */
644 SK_OUT16(IoC, MR_ADDR(MAC_1,RX_MFF_CTRL1), MFF_CLR_INSTAT);
647 if (HwStatus & IS_NO_STAT_M2) {
649 /* This situation is also indicated in the descriptor */
650 SK_OUT16(IoC, MR_ADDR(MAC_2,RX_MFF_CTRL1), MFF_CLR_INSTAT);
653 if (HwStatus & IS_NO_TIST_M1) {
655 /* This situation is also indicated in the descriptor */
656 SK_OUT16(IoC, MR_ADDR(MAC_1,RX_MFF_CTRL1), MFF_CLR_INTIST);
659 if (HwStatus & IS_NO_TIST_M2) {
661 /* This situation is also indicated in the descriptor */
662 SK_OUT16(IoC, MR_ADDR(MAC_2,RX_MFF_CTRL1), MFF_CLR_INTIST);
665 if (HwStatus & IS_RAM_RD_PAR) {
666 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
667 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
669 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
672 if (HwStatus & IS_RAM_WR_PAR) {
673 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
674 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
676 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
679 if (HwStatus & IS_M1_PAR_ERR) {
680 SkMacParity(pAC, IoC, MAC_1);
683 if (HwStatus & IS_M2_PAR_ERR) {
684 SkMacParity(pAC, IoC, MAC_2);
687 if (HwStatus & IS_R1_PAR_ERR) {
689 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
691 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
693 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
694 Para.Para32[0] = MAC_1;
695 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
698 if (HwStatus & IS_R2_PAR_ERR) {
700 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
702 SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
704 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
705 Para.Para32[0] = MAC_2;
706 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
711 /******************************************************************************
713 * Interrupt service routine
720 SK_AC *pAC, /* adapter context */
721 SK_IOC IoC, /* IO context */
722 SK_U32 Istatus) /* Interrupt status word */
725 SK_U32 RegVal32; /* Read register Value */
728 if (Istatus & IS_HW_ERR) {
729 SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
730 SkGeHwErr(pAC, IoC, RegVal32);
734 * Packet Timeout interrupts
736 /* Check whether XMACs are correctly initialized */
737 if ((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) &&
738 !pAC->GIni.GP[MAC_1].PState) {
739 /* XMAC was not initialized but Packet timeout occurred */
740 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
744 if ((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) &&
745 !pAC->GIni.GP[MAC_2].PState) {
746 /* XMAC was not initialized but Packet timeout occurred */
747 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
751 if (Istatus & IS_PA_TO_RX1) {
752 /* Means network is filling us up */
753 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
755 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
758 if (Istatus & IS_PA_TO_RX2) {
759 /* Means network is filling us up */
760 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
762 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
765 if (Istatus & IS_PA_TO_TX1) {
768 SK_GEPORT *pPrt = &pAC->GIni.GP[0];
770 /* May be a normal situation in a server with a slow network */
771 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
774 * workaround: if in half duplex mode, check for tx hangup.
775 * Read number of TX'ed bytes, wait for 10 ms, then compare
776 * the number with current value. If nothing changed, we
777 * assume that tx is hanging and do a FIFO flush (see event
780 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
781 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
782 !pPrt->HalfDupTimerActive) {
784 * many more pack. arb. timeouts may come in between,
787 pPrt->HalfDupTimerActive = SK_TRUE;
789 Len = sizeof(SK_U64);
790 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *) &Octets,
791 &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 0),
792 pAC->Rlmt.Port[0].Net->NetNumber);
793 pPrt->LastOctets = Octets;
795 SkTimerStart(pAC, IoC,
796 &pPrt->HalfDupChkTimer,
804 if (Istatus & IS_PA_TO_TX2) {
807 SK_GEPORT *pPrt = &pAC->GIni.GP[1];
809 /* May be a normal situation in a server with a slow network */
810 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
813 * workaround: see above
815 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
816 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
817 !pPrt->HalfDupTimerActive) {
818 pPrt->HalfDupTimerActive = SK_TRUE;
820 Len = sizeof(SK_U64);
821 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *) &Octets,
822 &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 1),
823 pAC->Rlmt.Port[1].Net->NetNumber);
824 pPrt->LastOctets = Octets;
826 SkTimerStart(pAC, IoC,
827 &pPrt->HalfDupChkTimer,
836 * Check interrupts of the particular queues.
838 if (Istatus & IS_R1_C) {
840 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
841 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
844 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
845 Para.Para32[0] = MAC_1;
846 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
849 if (Istatus & IS_R2_C) {
851 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
852 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
855 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
856 Para.Para32[0] = MAC_2;
857 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
860 if (Istatus & IS_XS1_C) {
862 SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
863 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
866 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
867 Para.Para32[0] = MAC_1;
868 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
871 if (Istatus & IS_XA1_C) {
873 SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
874 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
877 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
878 Para.Para32[0] = MAC_1;
879 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
882 if (Istatus & IS_XS2_C) {
884 SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
885 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
888 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
889 Para.Para32[0] = MAC_2;
890 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
893 if (Istatus & IS_XA2_C) {
895 SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
896 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
899 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
900 Para.Para32[0] = MAC_2;
901 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
905 * External reg interrupt.
907 if (Istatus & IS_EXT_REG) {
911 SK_GEPORT *pPrt; /* GIni Port struct pointer */
913 /* Test IRQs from PHY. */
914 for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
915 pPrt = &pAC->GIni.GP[i];
916 switch (pPrt->PhyType) {
921 PHY_READ(IoC, pPrt, i, PHY_BCOM_INT_STAT, &PhyInt);
922 PHY_READ(IoC, pPrt, i, PHY_BCOM_INT_MASK, &PhyIMsk);
925 if (PhyInt & PhyIMsk) {
928 MSG_TYPE_RUNTIME_INFO,
929 "SirqIsr - Stat: %x",
935 if (PhyInt & ~PhyIMsk) {
940 ("Port %d Bcom Int: %x Mask: %x\n",
941 i, PhyInt, PhyIMsk));
942 SkPhyIsrBcom(pAC, IoC, i, PhyInt);
947 PHY_READ(IoC, pPrt, i, PHY_LONE_INT_STAT, &PhyInt);
948 PHY_READ(IoC, pPrt, i, PHY_LONE_INT_ENAB, &PhyIMsk);
950 if (PhyInt & PhyIMsk) {
955 ("Port %d Lone Int: %x Mask: %x\n",
956 i, PhyInt, PhyIMsk));
957 SkPhyIsrLone(pAC, IoC, i, PhyInt);
968 * I2C Ready interrupt
970 if (Istatus & IS_I2C_READY) {
974 if (Istatus & IS_LNK_SYNC_M1) {
976 * We do NOT need the Link Sync interrupt, because it shows
977 * us only a link going down.
979 /* clear interrupt */
980 SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
983 /* Check MAC after link sync counter */
984 if (Istatus & IS_MAC1) {
985 XM_IN16(IoC, MAC_1, XM_ISRC, &XmIsr);
986 SkXmIrq(pAC, IoC, MAC_1, XmIsr);
989 if (Istatus & IS_LNK_SYNC_M2) {
991 * We do NOT need the Link Sync interrupt, because it shows
992 * us only a link going down.
994 /* clear interrupt */
995 SK_OUT8(IoC, MR_ADDR(MAC_2,LNK_SYNC_CTRL), LED_CLR_IRQ);
998 /* Check MAC after link sync counter */
999 if (Istatus & IS_MAC2) {
1000 XM_IN16(IoC, MAC_2, XM_ISRC, &XmIsr);
1001 SkXmIrq(pAC, IoC, MAC_2, XmIsr);
1008 if (Istatus & IS_TIMINT) {
1014 /******************************************************************************
1016 * SkGePortCheckShorts - Implementing of the Workaround Errata # 2
1019 * 0 o.k. nothing needed
1020 * 1 Restart needed on this port
1022 int SkGePortCheckShorts(
1023 SK_AC *pAC, /* Adapter Context */
1024 SK_IOC IoC, /* IO Context */
1025 int Port) /* Which port should be checked */
1027 SK_U64 Shorts; /* Short Event Counter */
1028 SK_U64 CheckShorts; /* Check value for Short Event Counter */
1029 SK_U64 RxCts; /* RX Counter (packets on network) */
1030 SK_U64 RxTmp; /* RX temp. Counter */
1031 SK_U64 FcsErrCts; /* FCS Error Counter */
1032 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1034 int Rtv; /* Return value */
1037 pPrt = &pAC->GIni.GP[Port];
1039 /* Default: no action */
1040 Rtv = SK_HW_PS_NONE;
1043 * Extra precaution: check for short Event counter
1045 Len = sizeof(SK_U64);
1046 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_RX_SHORTS, (char *)&Shorts,
1047 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
1048 pAC->Rlmt.Port[Port].Net->NetNumber);
1051 * Read RX counter (packets seen on the network and not neccesarily
1054 Len = sizeof(SK_U64);
1057 for (i = 0; i < sizeof(SkGeRxOids)/sizeof(SK_U32); i++) {
1058 SkPnmiGetVar(pAC, IoC, SkGeRxOids[i], (char *)&RxTmp,
1059 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
1060 pAC->Rlmt.Port[Port].Net->NetNumber);
1064 /* On default: check shorts against zero */
1068 * Extra extra precaution on active links:
1070 if (pPrt->PHWLinkUp) {
1072 * Reset Link Restart counter
1074 pPrt->PLinkResCt = 0;
1075 pPrt->PAutoNegTOCt = 0;
1077 /* If link is up check for 2 */
1080 Len = sizeof(SK_U64);
1081 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_RX_FCS,
1082 (char *)&FcsErrCts, &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
1083 pAC->Rlmt.Port[Port].Net->NetNumber);
1085 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1086 pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
1087 (pPrt->PLinkMode == SK_LMODE_HALF ||
1088 pPrt->PLinkMode == SK_LMODE_FULL)) {
1090 * This is autosensing and we are in the fallback
1091 * manual full/half duplex mode.
1093 if (RxCts == pPrt->PPrevRx) {
1098 pPrt->PPrevFcs = FcsErrCts;
1099 pPrt->PPrevShorts = Shorts;
1100 return (SK_HW_PS_RESTART);
1103 pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
1107 if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
1108 (!(FcsErrCts - pPrt->PPrevFcs))) {
1110 * Note: The compare with zero above has to be done the way shown,
1111 * otherwise the Linux driver will have a problem.
1114 * We received a bunch of frames or no CRC error occurred on the
1117 pPrt->PPrevRx = RxCts;
1118 pPrt->PPrevFcs = FcsErrCts;
1119 pPrt->PPrevShorts = Shorts;
1121 return (SK_HW_PS_NONE);
1124 pPrt->PPrevFcs = FcsErrCts;
1128 if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
1129 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1130 ("Short Event Count Restart Port %d \n", Port));
1131 Rtv = SK_HW_PS_RESTART;
1134 pPrt->PPrevShorts = Shorts;
1135 pPrt->PPrevRx = RxCts;
1138 } /* SkGePortCheckShorts*/
1141 /******************************************************************************
1143 * SkGePortCheckUp - Implementation of the Workaround for Errata #2
1146 * 0 o.k. nothing needed
1147 * 1 Restart needed on this port
1150 int SkGePortCheckUp(
1151 SK_AC *pAC, /* Adapter Context */
1152 SK_IOC IoC, /* IO Context */
1153 int Port) /* Which port should be checked */
1155 switch (pAC->GIni.GP[Port].PhyType) {
1157 return (SkGePortCheckUpXmac(pAC, IoC, Port));
1159 return (SkGePortCheckUpBcom(pAC, IoC, Port));
1161 return (SkGePortCheckUpLone(pAC, IoC, Port));
1163 return (SkGePortCheckUpNat(pAC, IoC, Port));
1165 return (SK_HW_PS_NONE);
1166 } /* SkGePortCheckUp */
1169 /******************************************************************************
1171 * SkGePortCheckUpXmac - Implementing of the Workaround Errata # 2
1174 * 0 o.k. nothing needed
1175 * 1 Restart needed on this port
1178 static int SkGePortCheckUpXmac(
1179 SK_AC *pAC, /* Adapter Context */
1180 SK_IOC IoC, /* IO Context */
1181 int Port) /* Which port should be checked */
1183 SK_U64 Shorts; /* Short Event Counter */
1184 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1187 SK_U32 GpReg; /* General Purpose register value */
1188 SK_U16 Isrc; /* Interrupt source register */
1189 SK_U16 IsrcSum; /* Interrupt source register sum */
1190 SK_U16 LpAb; /* Link Partner Ability */
1191 SK_U16 ResAb; /* Resolved Ability */
1192 SK_U16 ExtStat; /* Extended Status Register */
1193 SK_BOOL AutoNeg; /* Is Autonegotiation used ? */
1194 SK_U8 NextMode; /* Next AutoSensing Mode */
1196 pPrt = &pAC->GIni.GP[Port];
1198 if (pPrt->PHWLinkUp) {
1199 if (pPrt->PhyType != SK_PHY_XMAC) {
1200 return (SK_HW_PS_NONE);
1203 return (SkGePortCheckShorts(pAC, IoC, Port));
1207 IsrcSum = pPrt->PIsave;
1210 /* Now wait for each port's link. */
1211 if (pPrt->PLinkMode == SK_LMODE_HALF ||
1212 pPrt->PLinkMode == SK_LMODE_FULL) {
1219 if (pPrt->PLinkBroken) {
1220 /* Link was broken */
1221 XM_IN32(IoC,Port,XM_GP_PORT, &GpReg);
1223 if ((GpReg & XM_GP_INP_ASS) == 0) {
1224 /* The Link is in sync */
1225 XM_IN16(IoC,Port,XM_ISRC, &Isrc);
1227 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1228 if ((Isrc & XM_IS_INP_ASS) == 0) {
1229 /* It has been in sync since last Time */
1230 /* Restart the PORT */
1231 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1232 ("Link in sync Restart Port %d\n", Port));
1234 /* We now need to reinitialize the PrevShorts counter. */
1235 Len = sizeof(SK_U64);
1236 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_RX_SHORTS, (char *)&Shorts,
1237 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
1238 pAC->Rlmt.Port[Port].Net->NetNumber);
1239 pPrt->PPrevShorts = Shorts;
1241 pAC->GIni.GP[Port].PLinkBroken = SK_FALSE;
1244 * Link Restart Workaround:
1245 * it may be possible that the other Link side
1246 * restarts its link as well an we detect
1247 * another LinkBroken. To prevent this
1248 * happening we check for a maximum number
1249 * of consecutive restart. If those happens,
1250 * we do NOT restart the active link and
1251 * check whether the lionk is now o.k.
1253 pAC->GIni.GP[Port].PLinkResCt ++;
1254 pPrt->PAutoNegTimeOut = 0;
1256 if (pAC->GIni.GP[Port].PLinkResCt < SK_MAX_LRESTART) {
1257 return (SK_HW_PS_RESTART);
1260 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
1261 ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
1262 pAC->GIni.GP[Port].PLinkResCt = 0;
1265 pPrt->PIsave = (SK_U16)(IsrcSum & (XM_IS_AND));
1266 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
1267 ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
1269 /* Do nothing more if link is broken */
1270 return (SK_HW_PS_NONE);
1274 /* Do nothing more if link is broken */
1275 return (SK_HW_PS_NONE);
1280 /* Link was not broken, check if it is */
1281 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1283 if ((Isrc & XM_IS_INP_ASS) == XM_IS_INP_ASS) {
1284 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1286 if ((Isrc & XM_IS_INP_ASS) == XM_IS_INP_ASS) {
1287 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1289 if ((Isrc & XM_IS_INP_ASS) == XM_IS_INP_ASS) {
1290 pPrt->PLinkBroken = SK_TRUE;
1292 * Re-Init Link partner Autoneg flag
1294 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1295 SK_DBG_MSG(pAC,SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1296 ("Link broken Port %d\n", Port));
1298 /* Cable removed-> reinit sense mode. */
1299 /* Init default sense mode. */
1300 SkHWInitDefSense(pAC, IoC, Port);
1302 return (SK_HW_PS_RESTART);
1307 SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
1308 if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
1309 return (SK_HW_PS_RESTART);
1315 * here we usually can check whether the link is in sync and
1316 * autonegotiation is done.
1318 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1319 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1322 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1323 if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
1324 if ((GpReg & XM_GP_INP_ASS) == 0) {
1325 /* Save Autonegotiation Done interrupt only if link is in sync. */
1326 pPrt->PIsave = (SK_U16)(IsrcSum & (XM_IS_AND));
1329 if (pPrt->PIsave & (XM_IS_AND)) {
1330 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
1331 ("AutoNeg done rescheduled Port %d\n", Port));
1334 return (SK_HW_PS_NONE);
1338 if (IsrcSum & XM_IS_AND) {
1339 SkHWLinkUp(pAC, IoC, Port);
1340 Done = SkXmAutoNegDone(pAC,IoC,Port);
1341 if (Done != SK_AND_OK) {
1342 /* Get PHY parameters, for debuging only */
1343 PHY_READ(IoC, pPrt, Port, PHY_XMAC_AUNE_LP, &LpAb);
1344 PHY_READ(IoC, pPrt, Port, PHY_XMAC_RES_ABI, &ResAb);
1345 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
1346 ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
1347 Port, LpAb, ResAb));
1349 /* Try next possible mode */
1350 NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1351 SkHWLinkDown(pAC, IoC, Port);
1352 if (Done == SK_AND_DUP_CAP) {
1353 /* GoTo next mode */
1354 SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1357 return (SK_HW_PS_RESTART);
1361 * Dummy Read extended status to prevent extra link down/ups
1362 * (clear Page Received bit if set)
1364 PHY_READ(IoC, pPrt, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
1365 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
1366 ("AutoNeg done Port %d\n", Port));
1367 return (SK_HW_PS_LINK);
1372 * AutoNeg not done, but HW link is up. Check for timeouts
1374 pPrt->PAutoNegTimeOut ++;
1375 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1377 * Increase the Timeout counter.
1379 pPrt->PAutoNegTOCt ++;
1383 * What do we need now?
1385 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,
1387 ("AutoNeg timeout Port %d\n",
1389 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1390 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1393 * Set Link manually up.
1395 SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1396 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1397 ("Set manual full duplex Port %d\n", Port));
1400 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1401 pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
1402 pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
1404 * This is rather complicated.
1405 * we need to check here whether the LIPA_AUTO
1406 * we saw before is false alert. We saw at one
1407 * switch ( SR8800) that on boot time it sends
1408 * just one autoneg packet and does no further
1410 * Solution: we restart the autosensing after
1413 pPrt->PAutoNegTOCt = 0;
1414 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1415 SkHWInitDefSense(pAC, IoC, Port);
1421 return (SK_HW_PS_RESTART);
1426 * Link is up and we don't need more.
1429 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1430 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1431 ("ERROR: Lipa auto detected on port %d\n", Port));
1435 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_IRQ,
1436 ("Link sync(GP), Port %d\n", Port));
1437 SkHWLinkUp(pAC, IoC, Port);
1438 return (SK_HW_PS_LINK);
1441 return (SK_HW_PS_NONE);
1442 } /* SkGePortCheckUpXmac */
1445 /******************************************************************************
1447 * SkGePortCheckUpBcom - Check, if the link is up
1450 * 0 o.k. nothing needed
1451 * 1 Restart needed on this port
1454 static int SkGePortCheckUpBcom(
1455 SK_AC *pAC, /* Adapter Context */
1456 SK_IOC IoC, /* IO Context */
1457 int Port) /* Which port should be checked */
1459 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1461 SK_U16 Isrc; /* Interrupt source register */
1462 SK_U16 PhyStat; /* Phy Status Register */
1463 SK_U16 ResAb; /* Master/Slave resolution */
1464 SK_U16 Ctrl; /* Broadcom control flags */
1469 SK_BOOL AutoNeg; /* Is Autonegotiation used ? */
1471 pPrt = &pAC->GIni.GP[Port];
1473 /* Check for No HCD Link events (#10523) */
1474 PHY_READ(IoC, pPrt, Port, PHY_BCOM_INT_STAT, &Isrc);
1477 if ((Isrc & ~0x1800) == 0x70) {
1478 SK_U32 Stat1, Stat2, Stat3;
1481 PHY_READ(pAC, pPrt, Port, PHY_BCOM_INT_MASK, &Stat1);
1484 MSG_TYPE_RUNTIME_INFO,
1485 "CheckUp1 - Stat: %x, Mask: %x",
1490 PHY_READ(pAC, pPrt, Port, PHY_BCOM_CTRL, &Stat1);
1492 PHY_READ(pAC, pPrt, Port, PHY_BCOM_STAT, &Stat2);
1493 Stat1 = Stat1 << 16 | Stat2;
1495 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1497 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_LP, &Stat3);
1498 Stat2 = Stat2 << 16 | Stat3;
1501 MSG_TYPE_RUNTIME_INFO,
1502 "Ctrl/Stat: %x, AN Adv/LP: %x",
1507 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1509 PHY_READ(pAC, pPrt, Port, PHY_BCOM_EXT_STAT, &Stat2);
1510 Stat1 = Stat1 << 16 | Stat2;
1512 PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1514 PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_STAT, &Stat3);
1515 Stat2 = Stat2 << 16 | Stat3;
1518 MSG_TYPE_RUNTIME_INFO,
1519 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1524 PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1526 PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1527 Stat1 = Stat1 << 16 | Stat2;
1529 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1531 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_STAT, &Stat3);
1532 Stat2 = Stat2 << 16 | Stat3;
1535 MSG_TYPE_RUNTIME_INFO,
1536 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1542 if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
1544 * Workaround BCOM Errata:
1545 * enable and disable loopback mode if "NO HCD" occurs.
1547 PHY_READ(IoC, pPrt, Port, PHY_BCOM_CTRL, &Ctrl);
1548 PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_CTRL, Ctrl | PHY_CT_LOOP);
1549 PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_CTRL, Ctrl & ~PHY_CT_LOOP);
1550 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1551 ("No HCD Link event, Port %d\n", Port));
1555 MSG_TYPE_RUNTIME_INFO,
1556 "No HCD link event, port %d.",
1562 /* Not obsolete: link status bit is latched to 0 and autoclearing! */
1563 PHY_READ(IoC, pPrt, Port, PHY_BCOM_STAT, &PhyStat);
1565 if (pPrt->PHWLinkUp) {
1566 return (SK_HW_PS_NONE);
1571 SK_U32 Stat1, Stat2, Stat3;
1574 PHY_READ(pAC, pPrt, Port, PHY_BCOM_INT_MASK, &Stat1);
1577 MSG_TYPE_RUNTIME_INFO,
1578 "CheckUp1a - Stat: %x, Mask: %x",
1583 PHY_READ(pAC, pPrt, Port, PHY_BCOM_CTRL, &Stat1);
1585 PHY_READ(pAC, pPrt, Port, PHY_BCOM_STAT, &PhyStat);
1586 Stat1 = Stat1 << 16 | PhyStat;
1588 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1590 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_LP, &Stat3);
1591 Stat2 = Stat2 << 16 | Stat3;
1594 MSG_TYPE_RUNTIME_INFO,
1595 "Ctrl/Stat: %x, AN Adv/LP: %x",
1600 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1602 PHY_READ(pAC, pPrt, Port, PHY_BCOM_EXT_STAT, &Stat2);
1603 Stat1 = Stat1 << 16 | Stat2;
1605 PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1607 PHY_READ(pAC, pPrt, Port, PHY_BCOM_1000T_STAT, &ResAb);
1608 Stat2 = Stat2 << 16 | ResAb;
1611 MSG_TYPE_RUNTIME_INFO,
1612 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1617 PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1619 PHY_READ(pAC, pPrt, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1620 Stat1 = Stat1 << 16 | Stat2;
1622 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1624 PHY_READ(pAC, pPrt, Port, PHY_BCOM_AUX_STAT, &Stat3);
1625 Stat2 = Stat2 << 16 | Stat3;
1628 MSG_TYPE_RUNTIME_INFO,
1629 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1635 /* Now wait for each port's link. */
1636 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1644 * Here we usually can check whether the link is in sync and
1645 * autonegotiation is done.
1648 /* RA;:;: obsolete */
1649 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1652 PHY_READ(IoC, pPrt, Port, PHY_BCOM_STAT, &PhyStat);
1655 if ((PhyStat & PHY_ST_LSYNC) >> 2 != (ExtStat & PHY_B_PES_LS) >> 8) {
1658 MSG_TYPE_RUNTIME_INFO,
1659 "PhyStat != ExtStat: %x %x",
1665 SkXmAutoNegLipaBcom(pAC, IoC, Port, PhyStat);
1667 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1668 ("AutoNeg:%d, PhyStat: %Xh.\n", AutoNeg, PhyStat));
1670 PHY_READ(IoC, pPrt, Port, PHY_BCOM_1000T_STAT, &ResAb);
1672 if (ResAb & PHY_B_1000S_MSF) {
1674 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1675 ("Master/Slave Fault port %d\n", Port));
1676 pPrt->PAutoNegFail = SK_TRUE;
1677 pPrt->PMSStatus = SK_MS_STAT_FAULT;
1678 return (SK_HW_PS_RESTART);
1681 if ((PhyStat & PHY_ST_LSYNC) == 0) {
1682 return (SK_HW_PS_NONE);
1684 else if (ResAb & PHY_B_1000S_MSR) {
1685 pPrt->PMSStatus = SK_MS_STAT_MASTER;
1688 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
1691 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1692 ("AutoNeg:%d, PhyStat: %Xh.\n", AutoNeg, PhyStat));
1695 if (PhyStat & PHY_ST_AN_OVER) {
1696 SkHWLinkUp(pAC, IoC, Port);
1697 Done = SkXmAutoNegDone(pAC, IoC, Port);
1698 if (Done != SK_AND_OK) {
1700 /* Get PHY parameters, for debugging only. */
1701 PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUNE_LP, &LpAb);
1702 PHY_READ(IoC, pPrt, Port, PHY_BCOM_1000T_STAT, &ExtStat);
1703 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1704 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1705 Port, LpAb, ExtStat));
1707 return (SK_HW_PS_RESTART);
1711 /* Dummy read ISR to prevent extra link downs/ups. */
1712 PHY_READ(IoC, pPrt, Port, PHY_BCOM_INT_STAT, &ExtStat);
1714 if ((ExtStat & ~0x1800) != 0) {
1717 MSG_TYPE_RUNTIME_INFO,
1718 "CheckUp2 - Stat: %x",
1724 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1725 ("AutoNeg done Port %d\n", Port));
1726 return (SK_HW_PS_LINK);
1730 else { /* !AutoNeg */
1732 * Link is up and we don't need more.
1735 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1736 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1737 ("ERROR: Lipa auto detected on port %d\n", Port));
1742 /* Dummy read ISR to prevent extra link downs/ups. */
1743 PHY_READ(IoC, pPrt, Port, PHY_BCOM_INT_STAT, &ExtStat);
1745 if ((ExtStat & ~0x1800) != 0) {
1748 MSG_TYPE_RUNTIME_INFO,
1749 "CheckUp3 - Stat: %x",
1755 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1756 ("Link sync(GP), Port %d\n", Port));
1757 SkHWLinkUp(pAC, IoC, Port);
1758 return (SK_HW_PS_LINK);
1761 return (SK_HW_PS_NONE);
1762 } /* SkGePortCheckUpBcom */
1765 /******************************************************************************
1767 * SkGePortCheckUpLone - Check if the link is up
1770 * 0 o.k. nothing needed
1771 * 1 Restart needed on this port
1774 static int SkGePortCheckUpLone(
1775 SK_AC *pAC, /* Adapter Context */
1776 SK_IOC IoC, /* IO Context */
1777 int Port) /* Which port should be checked */
1779 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1781 SK_U16 Isrc; /* Interrupt source register */
1782 SK_U16 LpAb; /* Link Partner Ability */
1783 SK_U16 ExtStat; /* Extended Status Register */
1784 SK_U16 PhyStat; /* Phy Status Register */
1786 SK_BOOL AutoNeg; /* Is Autonegotiation used ? */
1787 SK_U8 NextMode; /* Next AutoSensing Mode */
1789 pPrt = &pAC->GIni.GP[Port];
1791 if (pPrt->PHWLinkUp) {
1792 return (SK_HW_PS_NONE);
1795 StatSum = pPrt->PIsave;
1798 /* Now wait for each ports link */
1799 if (pPrt->PLinkMode == SK_LMODE_HALF ||
1800 pPrt->PLinkMode == SK_LMODE_FULL) {
1808 * here we usually can check whether the link is in sync and
1809 * autonegotiation is done.
1811 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1812 PHY_READ(IoC, pPrt, Port, PHY_LONE_STAT, &PhyStat);
1815 SkXmAutoNegLipaLone(pAC, IoC, Port, PhyStat);
1816 if ((PhyStat & PHY_ST_LSYNC) == 0){
1818 * Save Autonegotiation Done bit
1820 pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
1822 if (pPrt->PIsave & PHY_ST_AN_OVER) {
1823 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
1824 ("AutoNeg done rescheduled Port %d\n", Port));
1827 return (SK_HW_PS_NONE);
1831 if (StatSum & PHY_ST_AN_OVER) {
1832 SkHWLinkUp(pAC, IoC, Port);
1833 Done = SkXmAutoNegDone(pAC,IoC,Port);
1834 if (Done != SK_AND_OK) {
1835 /* Get PHY parameters, for debuging only */
1836 PHY_READ(IoC, pPrt, Port,
1839 PHY_READ(IoC, pPrt, Port,
1840 PHY_LONE_1000T_STAT,
1842 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1843 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1844 Port, LpAb, ExtStat));
1846 /* Try next possible mode */
1847 NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1848 SkHWLinkDown(pAC, IoC, Port);
1849 if (Done == SK_AND_DUP_CAP) {
1850 /* GoTo next mode */
1851 SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1854 return (SK_HW_PS_RESTART);
1859 * Dummy Read interrupt status to prevent
1860 * extra link down/ups
1862 PHY_READ(IoC, pPrt, Port, PHY_LONE_INT_STAT, &ExtStat);
1863 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1864 ("AutoNeg done Port %d\n", Port));
1865 return (SK_HW_PS_LINK);
1870 * AutoNeg not done, but HW link is up. Check for timeouts
1872 pPrt->PAutoNegTimeOut ++;
1873 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1876 * What do we need now?
1878 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,
1880 ("AutoNeg timeout Port %d\n",
1882 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1883 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1886 * Set Link manually up.
1888 SkHWSenseSetNext(pAC, IoC, Port,
1890 SK_DBG_MSG(pAC,SK_DBGMOD_HWM,
1892 ("Set manual full duplex Port %d\n",
1899 return (SK_HW_PS_RESTART);
1904 * Link is up and we don't need more.
1907 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1908 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1909 ("ERROR: Lipa auto detected on port %d\n", Port));
1914 * Dummy Read interrupt status to prevent
1915 * extra link down/ups
1917 PHY_READ(IoC, pPrt, Port, PHY_LONE_INT_STAT, &ExtStat);
1919 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1920 ("Link sync(GP), Port %d\n", Port));
1921 SkHWLinkUp(pAC, IoC, Port);
1922 return (SK_HW_PS_LINK);
1925 return (SK_HW_PS_NONE);
1926 } /* SkGePortCheckUpLone*/
1929 /******************************************************************************
1931 * SkGePortCheckUpNat - Check if the link is up
1934 * 0 o.k. nothing needed
1935 * 1 Restart needed on this port
1938 static int SkGePortCheckUpNat(
1939 SK_AC *pAC, /* Adapter Context */
1940 SK_IOC IoC, /* IO Context */
1941 int Port) /* Which port should be checked */
1943 /* todo: National */
1944 return (SK_HW_PS_NONE);
1945 } /* SkGePortCheckUpNat */
1948 /******************************************************************************
1950 * Event service routine
1957 SK_AC *pAC, /* Adapter Context */
1958 SK_IOC IoC, /* Io Context */
1959 SK_U32 Event, /* Module specific Event */
1960 SK_EVPARA Para) /* Event specific Parameter */
1963 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1970 Port = Para.Para32[0];
1971 pPrt = & pAC->GIni.GP[Port];
1975 /* Check whether port came up */
1976 PortStat = SkGePortCheckUp(pAC, IoC, Port);
1979 case SK_HW_PS_RESTART:
1980 if (pPrt->PHWLinkUp) {
1984 SkHWLinkDown(pAC, IoC, Port);
1987 * Signal directly to RLMT to ensure correct
1988 * sequence of SWITCH and RESET event.
1990 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1993 /* Restart needed */
1994 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1998 /* Signal to RLMT */
1999 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
2004 /* Start again the check Timer */
2005 if (pPrt->PHWLinkUp) {
2006 Time = SK_WA_ACT_TIME;
2009 Time = SK_WA_INA_TIME;
2012 /* Todo: still needed for non-XMAC PHYs??? */
2013 /* Start workaround Errata #2 timer. */
2014 SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer,
2015 Time, SKGE_HWAC, SK_HWEV_WATIM, Para);
2018 case SK_HWEV_PORT_START:
2019 if (pPrt->PHWLinkUp) {
2021 * Signal directly to RLMT to ensure correct
2022 * sequence of SWITCH and RESET event.
2024 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2027 SkHWLinkDown(pAC, IoC, Port);
2029 /* Schedule Port RESET */
2030 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
2032 /* Start workaround Errata #2 timer */
2033 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
2034 SKGE_HWAC, SK_HWEV_WATIM, Para);
2037 case SK_HWEV_PORT_STOP:
2038 if (pAC->GIni.GP[Port].PHWLinkUp) {
2040 * Signal directly to RLMT to ensure correct
2041 * sequence of SWITCH and RESET event.
2043 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2046 /* Stop Workaround Timer */
2047 SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
2049 SkHWLinkDown(pAC, IoC, Port);
2052 case SK_HWEV_UPDATE_STAT:
2053 /* We do NOT need to update any statistics */
2056 case SK_HWEV_CLEAR_STAT:
2057 /* We do NOT need to clear any statistics */
2058 for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
2061 pPrt->PPrevShorts = 0;
2065 case SK_HWEV_SET_LMODE:
2066 Val8 = (SK_U8)Para.Para32[1];
2067 if (pPrt->PLinkModeConf != Val8) {
2068 /* Set New link mode */
2069 pPrt->PLinkModeConf = Val8;
2072 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2073 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2077 case SK_HWEV_SET_FLOWMODE:
2078 Val8 = (SK_U8)Para.Para32[1];
2079 if (pPrt->PFlowCtrlMode != Val8) {
2080 /* Set New Flow Control mode */
2081 pPrt->PFlowCtrlMode = Val8;
2084 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2085 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2089 case SK_HWEV_SET_ROLE:
2090 Val8 = (SK_U8)Para.Para32[1];
2091 if (pPrt->PMSMode != Val8) {
2092 /* Set New link mode */
2093 pPrt->PMSMode = Val8;
2096 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2097 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2101 case SK_HWEV_HALFDUP_CHK:
2103 * half duplex hangup workaround. See packet arbiter timeout
2104 * interrupt for description
2106 pPrt->HalfDupTimerActive = SK_FALSE;
2107 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
2108 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
2109 Len = sizeof(SK_U64);
2110 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
2111 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
2112 pAC->Rlmt.Port[Port].Net->NetNumber);
2113 if (pPrt->LastOctets == Octets) {
2114 /* TX hanging, do a FIFO flush restarts it. */
2115 SkXmFlushTxFifo(pAC, IoC, Port);
2120 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
2125 } /* SkGeSirqEvent */
2128 /******************************************************************************
2130 * SkPhyIsrBcom - PHY interrupt service routine
2132 * Description: handle all interrupts from BCOM PHY
2136 static void SkPhyIsrBcom(
2137 SK_AC *pAC, /* Adapter Context */
2138 SK_IOC IoC, /* Io Context */
2139 int Port, /* Port Num = PHY Num */
2140 SK_U16 IStatus) /* Interrupt Status */
2142 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2145 pPrt = &pAC->GIni.GP[Port];
2147 if (IStatus & PHY_B_IS_PSE) {
2148 /* Incorrectable pair swap error. */
2149 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
2150 SKERR_SIRQ_E022MSG);
2153 if (IStatus & PHY_B_IS_MDXI_SC) {
2157 if (IStatus & PHY_B_IS_HCT) {
2161 if (IStatus & PHY_B_IS_LCT) {
2165 if (IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) {
2166 Para.Para32[0] = (SK_U32)Port;
2168 SkHWLinkDown(pAC, IoC, Port);
2170 /* Signal to RLMT */
2171 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2173 /* Start workaround Errata #2 timer */
2174 SkTimerStart(pAC, IoC, &pPrt->PWaTimer,
2175 SK_WA_INA_TIME, SKGE_HWAC, SK_HWEV_WATIM, Para);
2178 if (IStatus & PHY_B_IS_NO_HDCL) {
2181 if (IStatus & PHY_B_IS_NO_HDC) {
2185 if (IStatus & PHY_B_IS_NEG_USHDC) {
2189 if (IStatus & PHY_B_IS_SCR_S_ER) {
2193 if (IStatus & PHY_B_IS_RRS_CHANGE) {
2197 if (IStatus & PHY_B_IS_LRS_CHANGE) {
2201 if (IStatus & PHY_B_IS_DUP_CHANGE) {
2205 if (IStatus & PHY_B_IS_LSP_CHANGE) {
2209 if (IStatus & PHY_B_IS_CRC_ER) {
2212 } /* SkPhyIsrBcom */
2215 /******************************************************************************
2217 * SkPhyIsrLone - PHY interrupt service routine
2219 * Description: handle all interrupts from LONE PHY
2223 static void SkPhyIsrLone(
2224 SK_AC *pAC, /* Adapter Context */
2225 SK_IOC IoC, /* Io Context */
2226 int Port, /* Port Num = PHY Num */
2227 SK_U16 IStatus) /* Interrupt Status */
2231 if (IStatus & PHY_L_IS_CROSS) {
2235 if (IStatus & PHY_L_IS_POL) {
2239 if (IStatus & PHY_L_IS_SS) {
2243 if (IStatus & PHY_L_IS_CFULL) {
2247 if (IStatus & PHY_L_IS_AN_C) {
2251 if (IStatus & PHY_L_IS_SPEED) {
2255 if (IStatus & PHY_L_IS_CFULL) {
2259 if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
2260 SkHWLinkDown(pAC, IoC, Port);
2262 /* Signal to RLMT */
2263 Para.Para32[0] = (SK_U32)Port;
2264 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2266 /* Start workaround Errata #2 timer */
2267 SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer,
2268 SK_WA_INA_TIME, SKGE_HWAC, SK_HWEV_WATIM, Para);
2271 if (IStatus & PHY_L_IS_MDINT) {
2274 } /* SkPhyIsrLone */