1 /******************************************************************************
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.83 $
6 * Date: $Date: 2003/02/05 15:10:59 $
7 * Purpose: Special IRQ module
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2003 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.83 2003/02/05 15:10:59 rschmidt
30 * Fixed setting of PLinkSpeedUsed in SkHWLinkUp() when
31 * auto-negotiation is disabled.
34 * Revision 1.82 2003/01/29 13:34:33 rschmidt
35 * Added some typecasts to avoid compiler warnings.
37 * Revision 1.81 2002/12/05 10:49:51 rschmidt
38 * Fixed missing Link Down Event for fiber (Bug Id #10768)
39 * Added reading of cable length when link is up
40 * Removed testing of unused error bits in PHY ISR
43 * Revision 1.80 2002/11/12 17:15:21 rschmidt
44 * Replaced SkPnmiGetVar() by ...MacStatistic() in SkMacParity().
47 * Revision 1.79 2002/10/14 15:14:51 rschmidt
48 * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in
49 * SkMacParity() depending on GIChipRev (HW-Bug #8).
50 * Added error messages for GPHY Auto-Negotiation Error and
51 * FIFO Overflow/Underrun in SkPhyIsrGmac().
54 * Revision 1.78 2002/10/10 15:54:29 mkarl
55 * changes for PLinkSpeedUsed
57 * Revision 1.77 2002/09/12 08:58:51 rwahl
58 * Retrieve counters needed for XMAC errata workarounds directly because
59 * PNMI returns corrected counter values (e.g. #10620).
61 * Revision 1.76 2002/08/16 15:21:54 rschmidt
62 * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
63 * Replaced wrong 1st para pAC with IoC in SK_IN/OUT macros.
66 * Revision 1.75 2002/08/12 13:50:47 rschmidt
67 * Changed clearing of IS_M1_PAR_ERR (MAC 1 Parity Error) in
68 * SkMacParity() by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE (HW-Bug #8).
69 * Added clearing of IS_IRQ_TIST_OV and IS_IRQ_SENSOR in SkGeHwErr().
70 * Corrected handling of Link Up and Auto-Negotiation Over for GPHY.
71 * in SkGePortCheckUpGmac().
74 * Revision 1.74 2002/08/08 16:17:04 rschmidt
75 * Added PhyType check for SK_HWEV_SET_ROLE event (copper only)
76 * Changed Link Up check reading PHY Specific Status (YUKON)
79 * Revision 1.73 2002/07/15 18:36:53 rwahl
82 * Revision 1.72 2002/07/15 15:46:26 rschmidt
83 * Added new event: SK_HWEV_SET_SPEED
86 * Revision 1.71 2002/06/10 09:34:19 rschmidt
89 * Revision 1.70 2002/06/05 08:29:18 rschmidt
90 * SkXmRxTxEnable() replaced by SkMacRxTxEnable().
93 * Revision 1.69 2002/04/25 13:03:49 rschmidt
94 * Changes for handling YUKON.
95 * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types.
96 * Replaced all XMAC-access macros by functions: SkMacRxTxDisable(),
98 * Added handling for GMAC FIFO in SkMacParity().
99 * Replaced all SkXm...() functions with SkMac...() to handle also
101 * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced
102 * by functions SkXmPhyRead(), SkXmPhyWrite().
103 * Disabling all PHY interrupts moved to SkMacIrqDisable().
104 * Added handling for GPHY IRQ in SkGeSirqIsr().
105 * Removed status parameter from MAC IRQ handler SkMacIrq().
106 * Added SkGePortCheckUpGmac(), SkPhyIsrGmac() for GMAC.
109 * Revision 1.68 2002/02/26 15:24:53 rwahl
110 * Fix: no link with manual configuration (#10673). The previous fix for
111 * #10639 was removed. So for RLMT mode = CLS the RLMT may switch to
112 * misconfigured port. It should not occur for the other RLMT modes.
114 * Revision 1.67 2001/11/20 09:19:58 rwahl
115 * Reworked bugfix #10639 (no dependency to RLMT mode).
117 * Revision 1.66 2001/10/26 07:52:53 afischer
118 * Port switching bug in `check local link` mode
120 * Revision 1.65 2001/02/23 13:41:51 gklug
121 * fix: PHYS2INST should be used correctly for Dual Net operation
122 * chg: do no longer work with older PNMI
124 * Revision 1.64 2001/02/15 11:27:04 rassmann
125 * Working with RLMT v1 if SK_MAX_NETS undefined.
127 * Revision 1.63 2001/02/06 10:44:23 mkunz
128 * - NetIndex added to interface functions of pnmi V4 with dual net support
130 * Revision 1.62 2001/01/31 15:31:41 gklug
131 * fix: problem with autosensing an SR8800 switch
133 * Revision 1.61 2000/11/09 11:30:09 rassmann
134 * WA: Waiting after releasing reset until BCom chip is accessible.
136 * Revision 1.60 2000/10/18 12:37:48 cgoos
137 * Reinserted the comment for version 1.56.
139 * Revision 1.59 2000/10/18 12:22:20 cgoos
140 * Added workaround for half duplex hangup.
142 * Revision 1.58 2000/09/28 13:06:04 gklug
143 * fix: BCom may NOT be touched if XMAC is in RESET state
145 * Revision 1.57 2000/09/08 12:38:39 cgoos
146 * Added forgotten variable declaration.
148 * Revision 1.56 2000/09/08 08:12:13 cgoos
149 * Changed handling of parity errors in SkGeHwErr (correct reset of error).
151 * Revision 1.55 2000/06/19 08:36:25 cgoos
154 * Revision 1.54 2000/05/22 08:45:57 malthoff
155 * Fix: #10523 is valid for all BCom PHYs.
157 * Revision 1.53 2000/05/19 10:20:30 cgoos
158 * Removed Solaris debug output code.
160 * Revision 1.52 2000/05/19 10:19:37 cgoos
161 * Added PHY state check in HWLinkDown.
162 * Move PHY interrupt code to IS_EXT_REG case in SkGeSirqIsr.
164 * Revision 1.51 2000/05/18 05:56:20 cgoos
167 * Revision 1.50 2000/05/17 12:49:49 malthoff
168 * Fixes BCom link bugs (#10523).
170 * Revision 1.49 1999/12/17 11:02:50 gklug
171 * fix: read PHY_STAT of Broadcom chip more often to assure good status
173 * Revision 1.48 1999/12/06 10:01:17 cgoos
174 * Added SET function for Role.
176 * Revision 1.47 1999/11/22 13:34:24 cgoos
177 * Changed license header to GPL.
179 * Revision 1.46 1999/09/16 10:30:07 cgoos
180 * Removed debugging output statement from Linux.
182 * Revision 1.45 1999/09/16 07:32:55 cgoos
183 * Fixed dual-port copperfield bug (PHY_READ from resetted port).
184 * Removed some unused variables.
186 * Revision 1.44 1999/08/03 15:25:04 cgoos
187 * Removed workaround for disabled interrupts in half duplex mode.
189 * Revision 1.43 1999/08/03 14:27:58 cgoos
190 * Removed SENSE mode code from SkGePortCheckUpBcom.
192 * Revision 1.42 1999/07/26 09:16:54 cgoos
193 * Added some typecasts to avoid compiler warnings.
195 * Revision 1.41 1999/05/19 07:28:59 cgoos
196 * Changes for 1000Base-T.
198 * Revision 1.40 1999/04/08 13:59:39 gklug
199 * fix: problem with 3Com switches endless RESTARTs
201 * Revision 1.39 1999/03/08 10:10:52 gklug
202 * fix: AutoSensing did switch to next mode even if LiPa indicated offline
204 * Revision 1.38 1999/03/08 09:49:03 gklug
205 * fix: Bug using pAC instead of IoC, causing AIX problems
206 * fix: change compare for Linux compiler bug workaround
208 * Revision 1.37 1999/01/28 14:51:33 gklug
209 * fix: monitor for autosensing and extra RESETS the RX on wire counters
211 * Revision 1.36 1999/01/22 09:19:55 gklug
212 * fix: Init DupMode and InitPauseMd are now called in RxTxEnable
214 * Revision 1.35 1998/12/11 15:22:59 gklug
215 * chg: autosensing: check for receive if manual mode was guessed
216 * chg: simplified workaround for XMAC errata
217 * chg: wait additional 100 ms before link goes up.
218 * chg: autoneg timeout to 600 ms
219 * chg: restart autoneg even if configured to autonegotiation
221 * Revision 1.34 1998/12/10 10:33:14 gklug
222 * add: more debug messages
223 * fix: do a new InitPhy if link went down (AutoSensing problem)
224 * chg: Check for zero shorts if link is NOT up
225 * chg: reset Port if link goes down
226 * chg: wait additional 100 ms when link comes up to check shorts
227 * fix: dummy read extended autoneg status to prevent link going down immediately
229 * Revision 1.33 1998/12/07 12:18:29 gklug
230 * add: refinement of autosense mode: take into account the autoneg cap of LiPa
232 * Revision 1.32 1998/12/07 07:11:21 gklug
233 * fix: compiler warning
235 * Revision 1.31 1998/12/02 09:29:05 gklug
236 * fix: WA XMAC Errata: FCSCt check was not correct.
237 * fix: WA XMAC Errata: Prec Counter were NOT updated in case of short checks.
238 * fix: Clear Stat : now clears the Prev counters of all known Ports
240 * Revision 1.30 1998/12/01 10:54:15 gklug
241 * dd: workaround for XMAC errata changed. Check RX count and CRC err Count, too.
243 * Revision 1.29 1998/12/01 10:01:53 gklug
244 * fix: if MAC IRQ occurs during port down, this will be handled correctly
246 * Revision 1.28 1998/11/26 16:22:11 gklug
247 * fix: bug in autosense if manual modes are used
249 * Revision 1.27 1998/11/26 15:50:06 gklug
250 * fix: PNMI needs to set PLinkModeConf
252 * Revision 1.26 1998/11/26 14:51:58 gklug
253 * add: AutoSensing functionalty
255 * Revision 1.25 1998/11/26 07:34:37 gklug
256 * fix: Init PrevShorts when restarting port due to Link connection
258 * Revision 1.24 1998/11/25 10:57:32 gklug
259 * fix: remove unreferenced local vars
261 * Revision 1.23 1998/11/25 08:26:40 gklug
262 * fix: don't do a RESET on a starting or stopping port
264 * Revision 1.22 1998/11/24 13:29:44 gklug
265 * add: Workaround for MAC parity errata
267 * Revision 1.21 1998/11/18 15:31:06 gklug
270 * Revision 1.20 1998/11/18 12:58:54 gklug
271 * fix: use PNMI query instead of hardware access
273 * Revision 1.19 1998/11/18 12:54:55 gklug
274 * chg: add new workaround for XMAC Errata
275 * add: short event counter monitoring on active link too
277 * Revision 1.18 1998/11/13 14:27:41 malthoff
278 * Bug Fix: Packet Arbiter Timeout was not cleared correctly
279 * for timeout on TX1 and TX2.
281 * Revision 1.17 1998/11/04 07:01:59 cgoos
282 * Moved HW link poll sequence.
283 * Added call to SkXmRxTxEnable.
285 * Revision 1.16 1998/11/03 13:46:03 gklug
286 * add: functionality of SET_LMODE and SET_FLOW_MODE
287 * fix: send RLMT LinkDown event when Port stop is given with LinkUp
289 * Revision 1.15 1998/11/03 12:56:47 gklug
290 * fix: Needs more events
292 * Revision 1.14 1998/10/30 07:36:35 gklug
293 * rmv: unnecessary code
295 * Revision 1.13 1998/10/29 15:21:57 gklug
296 * add: Poll link feature for activating HW link
297 * fix: Deactivate HWLink when Port STOP is given
299 * Revision 1.12 1998/10/28 07:38:57 cgoos
300 * Checking link status at begin of SkHWLinkUp.
302 * Revision 1.11 1998/10/22 09:46:50 gklug
303 * fix SysKonnectFileId typo
305 * Revision 1.10 1998/10/14 13:57:47 gklug
306 * add: Port start/stop event
308 * Revision 1.9 1998/10/14 05:48:29 cgoos
309 * Added definition for Para.
311 * Revision 1.8 1998/10/14 05:40:09 gklug
312 * add: Hardware Linkup signal used
314 * Revision 1.7 1998/10/09 06:50:20 malthoff
315 * Remove ID_sccs by SysKonnectFileId.
317 * Revision 1.6 1998/10/08 09:11:49 gklug
318 * add: clear IRQ commands
320 * Revision 1.5 1998/10/02 14:27:35 cgoos
321 * Fixed some typos and wrong event names.
323 * Revision 1.4 1998/10/02 06:24:17 gklug
324 * add: HW error function
327 * Revision 1.3 1998/10/01 07:03:00 gklug
328 * add: ISR for the usual interrupt source register
330 * Revision 1.2 1998/09/03 13:50:33 gklug
331 * add: function prototypes
333 * Revision 1.1 1998/08/27 11:50:21 gklug
338 ******************************************************************************/
341 * Special Interrupt handler
343 * The following abstract should show how this module is included
344 * in the driver path:
346 * In the ISR of the driver the bits for frame transmission complete and
347 * for receive complete are checked and handled by the driver itself.
348 * The bits of the slow path mask are checked after that and then the
349 * entry into the so-called "slow path" is prepared. It is an implementors
350 * decision whether this is executed directly or just scheduled by
351 * disabling the mask. In the interrupt service routine some events may be
352 * generated, so it would be a good idea to call the EventDispatcher
353 * right after this ISR.
355 * The Interrupt source register of the adapter is NOT read by this module.
356 * SO if the drivers implementor needs a while loop around the
357 * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
360 * However, the MAC Interrupt status registers are read in a while loop.
364 static const char SysKonnectFileId[] =
365 "$Id: skgesirq.c,v 1.83 2003/02/05 15:10:59 rschmidt Exp $" ;
367 #include "h/skdrv1st.h" /* Driver Specific Definitions */
368 #include "h/skgepnmi.h" /* PNMI Definitions */
369 #include "h/skrlmt.h" /* RLMT Definitions */
370 #include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
372 /* local function prototypes */
373 static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int);
374 static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int);
375 static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int);
376 static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
377 static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
379 static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int);
380 static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int);
381 static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
382 #endif /* OTHER_PHY */
385 * array of Rx counter from XMAC which are checked
386 * in AutoSense mode to check whether a link is not able to auto-negotiate.
388 static const SK_U16 SkGeRxRegs[]= {
399 * Special IRQ function
401 * General Description:
408 /* Define return codes of SkGePortCheckUp and CheckShort */
409 #define SK_HW_PS_NONE 0 /* No action needed */
410 #define SK_HW_PS_RESTART 1 /* Restart needed */
411 #define SK_HW_PS_LINK 2 /* Link Up actions needed */
413 /******************************************************************************
415 * SkHWInitDefSense() - Default Autosensing mode initialization
417 * Description: sets the PLinkMode for HWInit
421 static void SkHWInitDefSense(
422 SK_AC *pAC, /* adapter context */
423 SK_IOC IoC, /* IO context */
424 int Port) /* Port Index (MAC_1 + n) */
426 SK_GEPORT *pPrt; /* GIni Port struct pointer */
428 pPrt = &pAC->GIni.GP[Port];
430 pPrt->PAutoNegTimeOut = 0;
432 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
433 pPrt->PLinkMode = pPrt->PLinkModeConf;
437 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
438 ("AutoSensing: First mode %d on Port %d\n",
439 (int)SK_LMODE_AUTOFULL, Port));
441 pPrt->PLinkMode = SK_LMODE_AUTOFULL;
444 } /* SkHWInitDefSense */
447 /******************************************************************************
449 * SkHWSenseGetNext() - Get Next Autosensing Mode
451 * Description: gets the appropriate next mode
456 SK_U8 SkHWSenseGetNext(
457 SK_AC *pAC, /* adapter context */
458 SK_IOC IoC, /* IO context */
459 int Port) /* Port Index (MAC_1 + n) */
461 SK_GEPORT *pPrt; /* GIni Port struct pointer */
463 pPrt = &pAC->GIni.GP[Port];
465 pPrt->PAutoNegTimeOut = 0;
467 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
468 /* Leave all as configured */
469 return(pPrt->PLinkModeConf);
472 if (pPrt->PLinkMode == SK_LMODE_AUTOFULL) {
473 /* Return next mode AUTOBOTH */
474 return(SK_LMODE_AUTOBOTH);
477 /* Return default autofull */
478 return(SK_LMODE_AUTOFULL);
479 } /* SkHWSenseGetNext */
482 /******************************************************************************
484 * SkHWSenseSetNext() - Autosensing Set next mode
486 * Description: sets the appropriate next mode
490 void SkHWSenseSetNext(
491 SK_AC *pAC, /* adapter context */
492 SK_IOC IoC, /* IO context */
493 int Port, /* Port Index (MAC_1 + n) */
494 SK_U8 NewMode) /* New Mode to be written in sense mode */
496 SK_GEPORT *pPrt; /* GIni Port struct pointer */
498 pPrt = &pAC->GIni.GP[Port];
500 pPrt->PAutoNegTimeOut = 0;
502 if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
506 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
507 ("AutoSensing: next mode %d on Port %d\n",
508 (int)NewMode, Port));
510 pPrt->PLinkMode = NewMode;
513 } /* SkHWSenseSetNext */
516 /******************************************************************************
518 * SkHWLinkDown() - Link Down handling
520 * Description: handles the hardware link down signal
525 SK_AC *pAC, /* adapter context */
526 SK_IOC IoC, /* IO context */
527 int Port) /* Port Index (MAC_1 + n) */
529 SK_GEPORT *pPrt; /* GIni Port struct pointer */
531 pPrt = &pAC->GIni.GP[Port];
533 /* Disable all MAC interrupts */
534 SkMacIrqDisable(pAC, IoC, Port);
536 /* Disable Receiver and Transmitter */
537 SkMacRxTxDisable(pAC, IoC, Port);
539 /* Init default sense mode */
540 SkHWInitDefSense(pAC, IoC, Port);
542 if (!pPrt->PHWLinkUp) {
546 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
547 ("Link down Port %d\n", Port));
549 /* Set Link to DOWN */
550 pPrt->PHWLinkUp = SK_FALSE;
552 /* Reset Port stati */
553 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
554 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
555 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_INDETERMINATED;
557 /* Re-init Phy especially when the AutoSense default is set now */
558 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
560 /* GP0: used for workaround of Rev. C Errata 2 */
562 /* Do NOT signal to RLMT */
564 /* Do NOT start the timer here */
568 /******************************************************************************
570 * SkHWLinkUp() - Link Up handling
572 * Description: handles the hardware link up signal
577 SK_AC *pAC, /* adapter context */
578 SK_IOC IoC, /* IO context */
579 int Port) /* Port Index (MAC_1 + n) */
581 SK_GEPORT *pPrt; /* GIni Port struct pointer */
583 pPrt = &pAC->GIni.GP[Port];
585 if (pPrt->PHWLinkUp) {
586 /* We do NOT need to proceed on active link */
590 pPrt->PHWLinkUp = SK_TRUE;
591 pPrt->PAutoNegFail = SK_FALSE;
592 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
594 if (pPrt->PLinkMode != SK_LMODE_AUTOHALF &&
595 pPrt->PLinkMode != SK_LMODE_AUTOFULL &&
596 pPrt->PLinkMode != SK_LMODE_AUTOBOTH) {
597 /* Link is up and no Auto-negotiation should be done */
599 /* Link speed should be the configured one */
600 switch (pPrt->PLinkSpeed) {
602 /* default is 1000 Mbps */
603 case SK_LSPEED_1000MBPS:
604 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
606 case SK_LSPEED_100MBPS:
607 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
609 case SK_LSPEED_10MBPS:
610 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
614 /* Set Link Mode Status */
615 if (pPrt->PLinkMode == SK_LMODE_FULL) {
616 pPrt->PLinkModeStatus = SK_LMODE_STAT_FULL;
619 pPrt->PLinkModeStatus = SK_LMODE_STAT_HALF;
622 /* No flow control without auto-negotiation */
623 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
626 SkMacRxTxEnable(pAC, IoC, Port);
631 /******************************************************************************
633 * SkMacParity() - MAC parity workaround
635 * Description: handles MAC parity errors correctly
639 static void SkMacParity(
640 SK_AC *pAC, /* adapter context */
641 SK_IOC IoC, /* IO context */
642 int Port) /* Port Index of the port failed */
645 SK_GEPORT *pPrt; /* GIni Port struct pointer */
646 SK_U32 TxMax; /* TxMax Counter */
648 pPrt = &pAC->GIni.GP[Port];
650 /* Clear IRQ Tx Parity Error */
651 if (pAC->GIni.GIGenesis) {
652 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
655 /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
656 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
657 (SK_U8)((pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
660 if (pPrt->PCheckPar) {
662 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
665 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
668 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
669 Para.Para32[0] = Port;
670 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
675 /* Check whether frames with a size of 1k were sent */
676 if (pAC->GIni.GIGenesis) {
677 /* Snap statistic counters */
678 (void)SkXmUpdateStats(pAC, IoC, Port);
680 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
683 (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
687 /* From now on check the parity */
688 pPrt->PCheckPar = SK_TRUE;
693 /******************************************************************************
695 * SkGeHwErr() - Hardware Error service routine
697 * Description: handles all HW Error interrupts
701 static void SkGeHwErr(
702 SK_AC *pAC, /* adapter context */
703 SK_IOC IoC, /* IO context */
704 SK_U32 HwStatus) /* Interrupt status word */
709 if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
710 /* PCI Errors occured */
711 if ((HwStatus & IS_IRQ_STAT) != 0) {
712 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
715 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
718 /* Reset all bits in the PCI STATUS register */
719 SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
721 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
722 SK_OUT16(IoC, PCI_C(PCI_STATUS), Word | PCI_ERRBITS);
723 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
726 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
729 if (pAC->GIni.GIGenesis) {
730 if ((HwStatus & IS_NO_STAT_M1) != 0) {
732 /* This situation is also indicated in the descriptor */
733 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
736 if ((HwStatus & IS_NO_STAT_M2) != 0) {
738 /* This situation is also indicated in the descriptor */
739 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
742 if ((HwStatus & IS_NO_TIST_M1) != 0) {
744 /* This situation is also indicated in the descriptor */
745 SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
748 if ((HwStatus & IS_NO_TIST_M2) != 0) {
750 /* This situation is also indicated in the descriptor */
751 SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
755 /* This is necessary only for Rx timing measurements */
756 if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
757 /* Clear Time Stamp Timer IRQ */
758 SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
761 if ((HwStatus & IS_IRQ_SENSOR) != 0) {
763 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
767 if ((HwStatus & IS_RAM_RD_PAR) != 0) {
768 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
769 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
771 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
774 if ((HwStatus & IS_RAM_WR_PAR) != 0) {
775 SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
776 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
778 SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
781 if ((HwStatus & IS_M1_PAR_ERR) != 0) {
782 SkMacParity(pAC, IoC, MAC_1);
785 if ((HwStatus & IS_M2_PAR_ERR) != 0) {
786 SkMacParity(pAC, IoC, MAC_2);
789 if ((HwStatus & IS_R1_PAR_ERR) != 0) {
791 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
793 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
795 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
796 Para.Para32[0] = MAC_1;
797 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
800 if ((HwStatus & IS_R2_PAR_ERR) != 0) {
802 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
804 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
806 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
807 Para.Para32[0] = MAC_2;
808 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
813 /******************************************************************************
815 * SkGeSirqIsr() - Special Interrupt Service Routine
817 * Description: handles all non data transfer specific interrupts (slow path)
822 SK_AC *pAC, /* adapter context */
823 SK_IOC IoC, /* IO context */
824 SK_U32 Istatus) /* Interrupt status word */
827 SK_U32 RegVal32; /* Read register value */
828 SK_GEPORT *pPrt; /* GIni Port struct pointer */
835 if ((Istatus & IS_HW_ERR) != 0) {
836 /* read the HW Error Interrupt source */
837 SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
839 SkGeHwErr(pAC, IoC, RegVal32);
843 * Packet Timeout interrupts
845 /* Check whether MACs are correctly initialized */
846 if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
847 pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
848 /* MAC 1 was not initialized but Packet timeout occured */
849 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
853 if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
854 pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
855 /* MAC 2 was not initialized but Packet timeout occured */
856 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
860 if ((Istatus & IS_PA_TO_RX1) != 0) {
861 /* Means network is filling us up */
862 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
864 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
867 if ((Istatus & IS_PA_TO_RX2) != 0) {
868 /* Means network is filling us up */
869 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
871 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
874 if ((Istatus & IS_PA_TO_TX1) != 0) {
876 pPrt = &pAC->GIni.GP[0];
878 /* May be a normal situation in a server with a slow network */
879 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
882 * workaround: if in half duplex mode, check for Tx hangup.
883 * Read number of TX'ed bytes, wait for 10 ms, then compare
884 * the number with current value. If nothing changed, we assume
885 * that Tx is hanging and do a FIFO flush (see event routine).
887 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
888 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
889 !pPrt->HalfDupTimerActive) {
891 * many more pack. arb. timeouts may come in between,
894 pPrt->HalfDupTimerActive = SK_TRUE;
896 Len = sizeof(SK_U64);
897 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
898 &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 0),
899 pAC->Rlmt.Port[0].Net->NetNumber);
901 pPrt->LastOctets = Octets;
904 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
905 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
909 if ((Istatus & IS_PA_TO_TX2) != 0) {
911 pPrt = &pAC->GIni.GP[1];
913 /* May be a normal situation in a server with a slow network */
914 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
916 /* workaround: see above */
917 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
918 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
919 !pPrt->HalfDupTimerActive) {
920 pPrt->HalfDupTimerActive = SK_TRUE;
922 Len = sizeof(SK_U64);
923 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
924 &Len, (SK_U32) SK_PNMI_PORT_PHYS2INST(pAC, 1),
925 pAC->Rlmt.Port[1].Net->NetNumber);
927 pPrt->LastOctets = Octets;
930 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
931 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
935 /* Check interrupts of the particular queues */
936 if ((Istatus & IS_R1_C) != 0) {
938 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
939 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
942 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
943 Para.Para32[0] = MAC_1;
944 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
947 if ((Istatus & IS_R2_C) != 0) {
949 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
950 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
953 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
954 Para.Para32[0] = MAC_2;
955 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
958 if ((Istatus & IS_XS1_C) != 0) {
960 SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
961 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
964 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
965 Para.Para32[0] = MAC_1;
966 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
969 if ((Istatus & IS_XA1_C) != 0) {
971 SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
972 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
975 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
976 Para.Para32[0] = MAC_1;
977 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
980 if ((Istatus & IS_XS2_C) != 0) {
982 SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
983 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
986 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
987 Para.Para32[0] = MAC_2;
988 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
991 if ((Istatus & IS_XA2_C) != 0) {
993 SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
994 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
997 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
998 Para.Para32[0] = MAC_2;
999 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
1002 /* External reg interrupt */
1003 if ((Istatus & IS_EXT_REG) != 0) {
1004 /* Test IRQs from PHY */
1005 for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
1007 pPrt = &pAC->GIni.GP[i];
1009 if (pPrt->PState == SK_PRT_RESET) {
1013 switch (pPrt->PhyType) {
1019 SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
1020 SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_MASK, &PhyIMsk);
1022 if ((PhyInt & ~PhyIMsk) != 0) {
1023 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1024 ("Port %d Bcom Int: 0x%04X Mask: 0x%04X\n",
1025 i, PhyInt, PhyIMsk));
1026 SkPhyIsrBcom(pAC, IoC, i, PhyInt);
1030 case SK_PHY_MARV_COPPER:
1031 case SK_PHY_MARV_FIBER:
1032 SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
1033 SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_MASK, &PhyIMsk);
1035 if ((PhyInt & PhyIMsk) != 0) {
1036 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1037 ("Port %d Marv Int: 0x%04X Mask: 0x%04X\n",
1038 i, PhyInt, PhyIMsk));
1039 SkPhyIsrGmac(pAC, IoC, i, PhyInt);
1045 SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
1046 SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_ENAB, &PhyIMsk);
1048 if ((PhyInt & PhyIMsk) != 0) {
1049 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1050 ("Port %d Lone Int: %x Mask: %x\n",
1051 i, PhyInt, PhyIMsk));
1052 SkPhyIsrLone(pAC, IoC, i, PhyInt);
1056 /* todo: National */
1058 #endif /* OTHER_PHY */
1063 /* I2C Ready interrupt */
1064 if ((Istatus & IS_I2C_READY) != 0) {
1068 if ((Istatus & IS_LNK_SYNC_M1) != 0) {
1070 * We do NOT need the Link Sync interrupt, because it shows
1071 * us only a link going down.
1073 /* clear interrupt */
1074 SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
1077 /* Check MAC after link sync counter */
1078 if ((Istatus & IS_MAC1) != 0) {
1079 /* IRQ from MAC 1 */
1080 SkMacIrq(pAC, IoC, MAC_1);
1083 if ((Istatus & IS_LNK_SYNC_M2) != 0) {
1085 * We do NOT need the Link Sync interrupt, because it shows
1086 * us only a link going down.
1088 /* clear interrupt */
1089 SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
1092 /* Check MAC after link sync counter */
1093 if ((Istatus & IS_MAC2) != 0) {
1094 /* IRQ from MAC 2 */
1095 SkMacIrq(pAC, IoC, MAC_2);
1098 /* Timer interrupt (served last) */
1099 if ((Istatus & IS_TIMINT) != 0) {
1105 /******************************************************************************
1107 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
1110 * 0 o.k. nothing needed
1111 * 1 Restart needed on this port
1113 static int SkGePortCheckShorts(
1114 SK_AC *pAC, /* Adapter Context */
1115 SK_IOC IoC, /* IO Context */
1116 int Port) /* Which port should be checked */
1118 SK_U32 Shorts; /* Short Event Counter */
1119 SK_U32 CheckShorts; /* Check value for Short Event Counter */
1120 SK_U64 RxCts; /* Rx Counter (packets on network) */
1121 SK_U32 RxTmp; /* Rx temp. Counter */
1122 SK_U32 FcsErrCts; /* FCS Error Counter */
1123 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1124 int Rtv; /* Return value */
1127 pPrt = &pAC->GIni.GP[Port];
1129 /* Default: no action */
1130 Rtv = SK_HW_PS_NONE;
1132 (void)SkXmUpdateStats(pAC, IoC, Port);
1134 /* Extra precaution: check for short Event counter */
1135 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
1138 * Read Rx counter (packets seen on the network and not necessarily
1143 for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
1144 (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
1145 RxCts += (SK_U64)RxTmp;
1148 /* On default: check shorts against zero */
1151 /* Extra precaution on active links */
1152 if (pPrt->PHWLinkUp) {
1153 /* Reset Link Restart counter */
1154 pPrt->PLinkResCt = 0;
1155 pPrt->PAutoNegTOCt = 0;
1157 /* If link is up check for 2 */
1160 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
1162 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1163 pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
1164 (pPrt->PLinkMode == SK_LMODE_HALF ||
1165 pPrt->PLinkMode == SK_LMODE_FULL)) {
1167 * This is autosensing and we are in the fallback
1168 * manual full/half duplex mode.
1170 if (RxCts == pPrt->PPrevRx) {
1171 /* Nothing received, restart link */
1172 pPrt->PPrevFcs = FcsErrCts;
1173 pPrt->PPrevShorts = Shorts;
1175 return(SK_HW_PS_RESTART);
1178 pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
1182 if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
1183 (!(FcsErrCts - pPrt->PPrevFcs))) {
1185 * Note: The compare with zero above has to be done the way shown,
1186 * otherwise the Linux driver will have a problem.
1189 * We received a bunch of frames or no CRC error occured on the
1192 pPrt->PPrevRx = RxCts;
1193 pPrt->PPrevFcs = FcsErrCts;
1194 pPrt->PPrevShorts = Shorts;
1196 return(SK_HW_PS_NONE);
1199 pPrt->PPrevFcs = FcsErrCts;
1203 if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
1204 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1205 ("Short Event Count Restart Port %d \n", Port));
1206 Rtv = SK_HW_PS_RESTART;
1209 pPrt->PPrevShorts = Shorts;
1210 pPrt->PPrevRx = RxCts;
1213 } /* SkGePortCheckShorts */
1216 /******************************************************************************
1218 * SkGePortCheckUp() - Check if the link is up
1221 * 0 o.k. nothing needed
1222 * 1 Restart needed on this port
1225 static int SkGePortCheckUp(
1226 SK_AC *pAC, /* Adapter Context */
1227 SK_IOC IoC, /* IO Context */
1228 int Port) /* Which port should be checked */
1230 switch (pAC->GIni.GP[Port].PhyType) {
1232 return(SkGePortCheckUpXmac(pAC, IoC, Port));
1234 return(SkGePortCheckUpBcom(pAC, IoC, Port));
1235 case SK_PHY_MARV_COPPER:
1236 case SK_PHY_MARV_FIBER:
1237 return(SkGePortCheckUpGmac(pAC, IoC, Port));
1240 return(SkGePortCheckUpLone(pAC, IoC, Port));
1242 return(SkGePortCheckUpNat(pAC, IoC, Port));
1243 #endif /* OTHER_PHY */
1245 return(SK_HW_PS_NONE);
1246 } /* SkGePortCheckUp */
1249 /******************************************************************************
1251 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1254 * 0 o.k. nothing needed
1255 * 1 Restart needed on this port
1258 static int SkGePortCheckUpXmac(
1259 SK_AC *pAC, /* Adapter Context */
1260 SK_IOC IoC, /* IO Context */
1261 int Port) /* Which port should be checked */
1263 SK_U32 Shorts; /* Short Event Counter */
1264 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1266 SK_U32 GpReg; /* General Purpose register value */
1267 SK_U16 Isrc; /* Interrupt source register */
1268 SK_U16 IsrcSum; /* Interrupt source register sum */
1269 SK_U16 LpAb; /* Link Partner Ability */
1270 SK_U16 ResAb; /* Resolved Ability */
1271 SK_U16 ExtStat; /* Extended Status Register */
1272 SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
1273 SK_U8 NextMode; /* Next AutoSensing Mode */
1275 pPrt = &pAC->GIni.GP[Port];
1277 if (pPrt->PHWLinkUp) {
1278 if (pPrt->PhyType != SK_PHY_XMAC) {
1279 return(SK_HW_PS_NONE);
1282 return(SkGePortCheckShorts(pAC, IoC, Port));
1286 IsrcSum = pPrt->PIsave;
1289 /* Now wait for each port's link */
1290 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1297 if (pPrt->PLinkBroken) {
1298 /* Link was broken */
1299 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1301 if ((GpReg & XM_GP_INP_ASS) == 0) {
1302 /* The Link is in sync */
1303 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1305 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1307 if ((Isrc & XM_IS_INP_ASS) == 0) {
1308 /* It has been in sync since last time */
1309 /* Restart the PORT */
1310 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1311 ("Link in sync Restart Port %d\n", Port));
1313 (void)SkXmUpdateStats(pAC, IoC, Port);
1315 /* We now need to reinitialize the PrevShorts counter */
1316 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
1317 pPrt->PPrevShorts = Shorts;
1319 pPrt->PLinkBroken = SK_FALSE;
1322 * Link Restart Workaround:
1323 * it may be possible that the other Link side
1324 * restarts its link as well an we detect
1325 * another LinkBroken. To prevent this
1326 * happening we check for a maximum number
1327 * of consecutive restart. If those happens,
1328 * we do NOT restart the active link and
1329 * check whether the link is now o.k.
1333 pPrt->PAutoNegTimeOut = 0;
1335 if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
1336 return(SK_HW_PS_RESTART);
1339 pPrt->PLinkResCt = 0;
1341 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1342 ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
1345 pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1347 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1348 ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
1350 /* Do nothing more if link is broken */
1351 return(SK_HW_PS_NONE);
1355 /* Do nothing more if link is broken */
1356 return(SK_HW_PS_NONE);
1361 /* Link was not broken, check if it is */
1362 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1364 if ((Isrc & XM_IS_INP_ASS) != 0) {
1365 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1367 if ((Isrc & XM_IS_INP_ASS) != 0) {
1368 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1370 if ((Isrc & XM_IS_INP_ASS) != 0) {
1371 pPrt->PLinkBroken = SK_TRUE;
1372 /* Re-Init Link partner Autoneg flag */
1373 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1374 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1375 ("Link broken Port %d\n", Port));
1377 /* Cable removed-> reinit sense mode */
1378 SkHWInitDefSense(pAC, IoC, Port);
1380 return(SK_HW_PS_RESTART);
1385 SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
1386 if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
1387 return(SK_HW_PS_RESTART);
1393 * here we usually can check whether the link is in sync and
1394 * auto-negotiation is done.
1396 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1397 XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1400 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1402 if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
1403 if ((GpReg & XM_GP_INP_ASS) == 0) {
1404 /* Save Auto-negotiation Done interrupt only if link is in sync */
1405 pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1408 if ((pPrt->PIsave & XM_IS_AND) != 0) {
1409 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1410 ("AutoNeg done rescheduled Port %d\n", Port));
1413 return(SK_HW_PS_NONE);
1417 if ((IsrcSum & XM_IS_AND) != 0) {
1418 SkHWLinkUp(pAC, IoC, Port);
1419 Done = SkMacAutoNegDone(pAC, IoC, Port);
1420 if (Done != SK_AND_OK) {
1421 /* Get PHY parameters, for debugging only */
1422 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
1423 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
1424 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1425 ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
1426 Port, LpAb, ResAb));
1428 /* Try next possible mode */
1429 NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1430 SkHWLinkDown(pAC, IoC, Port);
1431 if (Done == SK_AND_DUP_CAP) {
1432 /* GoTo next mode */
1433 SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1436 return(SK_HW_PS_RESTART);
1439 * Dummy Read extended status to prevent extra link down/ups
1440 * (clear Page Received bit if set)
1442 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
1443 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1444 ("AutoNeg done Port %d\n", Port));
1445 return(SK_HW_PS_LINK);
1448 /* AutoNeg not done, but HW link is up. Check for timeouts */
1449 pPrt->PAutoNegTimeOut++;
1450 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1451 /* Increase the Timeout counter */
1452 pPrt->PAutoNegTOCt++;
1454 /* Timeout occured */
1455 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1456 ("AutoNeg timeout Port %d\n", Port));
1457 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1458 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1459 /* Set Link manually up */
1460 SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1461 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1462 ("Set manual full duplex Port %d\n", Port));
1465 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1466 pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
1467 pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
1469 * This is rather complicated.
1470 * we need to check here whether the LIPA_AUTO
1471 * we saw before is false alert. We saw at one
1472 * switch ( SR8800) that on boot time it sends
1473 * just one auto-neg packet and does no further
1475 * Solution: we restart the autosensing after
1478 pPrt->PAutoNegTOCt = 0;
1479 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1480 SkHWInitDefSense(pAC, IoC, Port);
1483 /* Do the restart */
1484 return(SK_HW_PS_RESTART);
1488 /* Link is up and we don't need more */
1490 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1491 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1492 ("ERROR: Lipa auto detected on port %d\n", Port));
1495 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1496 ("Link sync(GP), Port %d\n", Port));
1497 SkHWLinkUp(pAC, IoC, Port);
1500 * Link sync (GP) and so assume a good connection. But if not received
1501 * a bunch of frames received in a time slot (maybe broken tx cable)
1502 * the port is restart.
1504 return(SK_HW_PS_LINK);
1507 return(SK_HW_PS_NONE);
1508 } /* SkGePortCheckUpXmac */
1511 /******************************************************************************
1513 * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
1516 * 0 o.k. nothing needed
1517 * 1 Restart needed on this port
1520 static int SkGePortCheckUpBcom(
1521 SK_AC *pAC, /* Adapter Context */
1522 SK_IOC IoC, /* IO Context */
1523 int Port) /* Which port should be checked */
1525 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1527 SK_U16 Isrc; /* Interrupt source register */
1528 SK_U16 PhyStat; /* Phy Status Register */
1529 SK_U16 ResAb; /* Master/Slave resolution */
1530 SK_U16 Ctrl; /* Broadcom control flags */
1535 SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
1537 pPrt = &pAC->GIni.GP[Port];
1539 /* Check for No HCD Link events (#10523) */
1540 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
1543 if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) ==
1544 (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
1546 SK_U32 Stat1, Stat2, Stat3;
1549 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1552 MSG_TYPE_RUNTIME_INFO,
1553 "CheckUp1 - Stat: %x, Mask: %x",
1558 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1560 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
1561 Stat1 = Stat1 << 16 | Stat2;
1563 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1565 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1566 Stat2 = Stat2 << 16 | Stat3;
1569 MSG_TYPE_RUNTIME_INFO,
1570 "Ctrl/Stat: %x, AN Adv/LP: %x",
1575 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1577 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1578 Stat1 = Stat1 << 16 | Stat2;
1580 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1582 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
1583 Stat2 = Stat2 << 16 | Stat3;
1586 MSG_TYPE_RUNTIME_INFO,
1587 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1592 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1594 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1595 Stat1 = Stat1 << 16 | Stat2;
1597 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1599 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1600 Stat2 = Stat2 << 16 | Stat3;
1603 MSG_TYPE_RUNTIME_INFO,
1604 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1610 if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
1612 * Workaround BCom Errata:
1613 * enable and disable loopback mode if "NO HCD" occurs.
1615 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
1616 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1617 (SK_U16)(Ctrl | PHY_CT_LOOP));
1618 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1619 (SK_U16)(Ctrl & ~PHY_CT_LOOP));
1620 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1621 ("No HCD Link event, Port %d\n", Port));
1625 MSG_TYPE_RUNTIME_INFO,
1626 "No HCD link event, port %d.",
1632 /* Not obsolete: link status bit is latched to 0 and autoclearing! */
1633 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1635 if (pPrt->PHWLinkUp) {
1636 return(SK_HW_PS_NONE);
1641 SK_U32 Stat1, Stat2, Stat3;
1644 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1647 MSG_TYPE_RUNTIME_INFO,
1648 "CheckUp1a - Stat: %x, Mask: %x",
1653 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1655 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1656 Stat1 = Stat1 << 16 | PhyStat;
1658 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1660 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1661 Stat2 = Stat2 << 16 | Stat3;
1664 MSG_TYPE_RUNTIME_INFO,
1665 "Ctrl/Stat: %x, AN Adv/LP: %x",
1670 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1672 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1673 Stat1 = Stat1 << 16 | Stat2;
1675 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1677 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1678 Stat2 = Stat2 << 16 | ResAb;
1681 MSG_TYPE_RUNTIME_INFO,
1682 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1687 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1689 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1690 Stat1 = Stat1 << 16 | Stat2;
1692 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1694 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1695 Stat2 = Stat2 << 16 | Stat3;
1698 MSG_TYPE_RUNTIME_INFO,
1699 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1705 /* Now wait for each port's link */
1706 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1714 * Here we usually can check whether the link is in sync and
1715 * auto-negotiation is done.
1718 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1720 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1722 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1723 ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat));
1725 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1727 if ((ResAb & PHY_B_1000S_MSF) != 0) {
1729 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1730 ("Master/Slave Fault port %d\n", Port));
1731 pPrt->PAutoNegFail = SK_TRUE;
1732 pPrt->PMSStatus = SK_MS_STAT_FAULT;
1734 return(SK_HW_PS_RESTART);
1737 if ((PhyStat & PHY_ST_LSYNC) == 0) {
1738 return(SK_HW_PS_NONE);
1741 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1742 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1744 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1745 ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat));
1748 if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1749 SkHWLinkUp(pAC, IoC, Port);
1750 Done = SkMacAutoNegDone(pAC, IoC, Port);
1751 if (Done != SK_AND_OK) {
1753 /* Get PHY parameters, for debugging only */
1754 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
1755 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
1756 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1757 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1758 Port, LpAb, ExtStat));
1760 return(SK_HW_PS_RESTART);
1764 /* Dummy read ISR to prevent extra link downs/ups */
1765 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1767 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1770 MSG_TYPE_RUNTIME_INFO,
1771 "CheckUp2 - Stat: %x",
1777 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1778 ("AutoNeg done Port %d\n", Port));
1779 return(SK_HW_PS_LINK);
1783 else { /* !AutoNeg */
1784 /* Link is up and we don't need more. */
1786 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1787 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1788 ("ERROR: Lipa auto detected on port %d\n", Port));
1793 /* Dummy read ISR to prevent extra link downs/ups */
1794 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1796 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1799 MSG_TYPE_RUNTIME_INFO,
1800 "CheckUp3 - Stat: %x",
1806 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1807 ("Link sync(GP), Port %d\n", Port));
1808 SkHWLinkUp(pAC, IoC, Port);
1809 return(SK_HW_PS_LINK);
1812 return(SK_HW_PS_NONE);
1813 } /* SkGePortCheckUpBcom */
1816 /******************************************************************************
1818 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1821 * 0 o.k. nothing needed
1822 * 1 Restart needed on this port
1825 static int SkGePortCheckUpGmac(
1826 SK_AC *pAC, /* Adapter Context */
1827 SK_IOC IoC, /* IO Context */
1828 int Port) /* Which port should be checked */
1830 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1832 SK_U16 Isrc; /* Interrupt source */
1833 SK_U16 PhyStat; /* Phy Status */
1834 SK_U16 PhySpecStat;/* Phy Specific Status */
1835 SK_U16 ResAb; /* Master/Slave resolution */
1836 SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
1838 pPrt = &pAC->GIni.GP[Port];
1840 /* Read PHY Interrupt Status */
1841 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &Isrc);
1843 if ((Isrc & PHY_M_IS_AN_COMPL) != 0) {
1847 if ((Isrc & PHY_M_IS_DOWNSH_DET) != 0) {
1851 if (pPrt->PHWLinkUp) {
1852 return(SK_HW_PS_NONE);
1855 /* Now wait for each port's link */
1856 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1863 /* Read PHY Status */
1864 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
1866 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1867 ("AutoNeg: %d, PhyStat: 0x%04x\n", AutoNeg, PhyStat));
1869 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1871 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
1873 if ((ResAb & PHY_B_1000S_MSF) != 0) {
1875 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1876 ("Master/Slave Fault port %d\n", Port));
1877 pPrt->PAutoNegFail = SK_TRUE;
1878 pPrt->PMSStatus = SK_MS_STAT_FAULT;
1880 return(SK_HW_PS_RESTART);
1883 /* Read PHY Specific Status */
1884 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
1886 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1887 ("AutoNeg: %d, PhySpecStat: 0x%04x\n", AutoNeg, PhySpecStat));
1889 if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
1890 return(SK_HW_PS_NONE);
1893 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1894 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1896 pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
1899 /* Auto-Negotiation Over ? */
1900 if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1902 SkHWLinkUp(pAC, IoC, Port);
1904 Done = SkMacAutoNegDone(pAC, IoC, Port);
1906 if (Done != SK_AND_OK) {
1907 return(SK_HW_PS_RESTART);
1910 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1911 ("AutoNeg done Port %d\n", Port));
1912 return(SK_HW_PS_LINK);
1915 else { /* !AutoNeg */
1916 /* Link is up and we don't need more */
1918 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1919 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1920 ("ERROR: Lipa auto detected on port %d\n", Port));
1924 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1925 ("Link sync, Port %d\n", Port));
1926 SkHWLinkUp(pAC, IoC, Port);
1928 return(SK_HW_PS_LINK);
1931 return(SK_HW_PS_NONE);
1932 } /* SkGePortCheckUpGmac */
1936 /******************************************************************************
1938 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1941 * 0 o.k. nothing needed
1942 * 1 Restart needed on this port
1945 static int SkGePortCheckUpLone(
1946 SK_AC *pAC, /* Adapter Context */
1947 SK_IOC IoC, /* IO Context */
1948 int Port) /* Which port should be checked */
1950 SK_GEPORT *pPrt; /* GIni Port struct pointer */
1952 SK_U16 Isrc; /* Interrupt source register */
1953 SK_U16 LpAb; /* Link Partner Ability */
1954 SK_U16 ExtStat; /* Extended Status Register */
1955 SK_U16 PhyStat; /* Phy Status Register */
1957 SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
1958 SK_U8 NextMode; /* Next AutoSensing Mode */
1960 pPrt = &pAC->GIni.GP[Port];
1962 if (pPrt->PHWLinkUp) {
1963 return(SK_HW_PS_NONE);
1966 StatSum = pPrt->PIsave;
1969 /* Now wait for each ports link */
1970 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1978 * here we usually can check whether the link is in sync and
1979 * auto-negotiation is done.
1981 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
1984 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1986 if ((PhyStat & PHY_ST_LSYNC) == 0) {
1987 /* Save Auto-negotiation Done bit */
1988 pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
1990 if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
1991 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1992 ("AutoNeg done rescheduled Port %d\n", Port));
1995 return(SK_HW_PS_NONE);
1999 if ((StatSum & PHY_ST_AN_OVER) != 0) {
2000 SkHWLinkUp(pAC, IoC, Port);
2001 Done = SkMacAutoNegDone(pAC, IoC, Port);
2002 if (Done != SK_AND_OK) {
2003 /* Get PHY parameters, for debugging only */
2004 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
2005 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
2006 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2007 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
2008 Port, LpAb, ExtStat));
2010 /* Try next possible mode */
2011 NextMode = SkHWSenseGetNext(pAC, IoC, Port);
2012 SkHWLinkDown(pAC, IoC, Port);
2013 if (Done == SK_AND_DUP_CAP) {
2014 /* GoTo next mode */
2015 SkHWSenseSetNext(pAC, IoC, Port, NextMode);
2018 return(SK_HW_PS_RESTART);
2023 * Dummy Read interrupt status to prevent
2024 * extra link down/ups
2026 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
2027 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2028 ("AutoNeg done Port %d\n", Port));
2029 return(SK_HW_PS_LINK);
2033 /* AutoNeg not done, but HW link is up. Check for timeouts */
2034 pPrt->PAutoNegTimeOut++;
2035 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
2036 /* Timeout occured */
2037 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
2038 ("AutoNeg timeout Port %d\n", Port));
2039 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
2040 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
2041 /* Set Link manually up */
2042 SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
2043 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
2044 ("Set manual full duplex Port %d\n", Port));
2047 /* Do the restart */
2048 return(SK_HW_PS_RESTART);
2052 /* Link is up and we don't need more */
2054 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
2055 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2056 ("ERROR: Lipa auto detected on port %d\n", Port));
2061 * Dummy Read interrupt status to prevent
2062 * extra link down/ups
2064 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
2066 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
2067 ("Link sync(GP), Port %d\n", Port));
2068 SkHWLinkUp(pAC, IoC, Port);
2069 return(SK_HW_PS_LINK);
2072 return(SK_HW_PS_NONE);
2073 } /* SkGePortCheckUpLone */
2076 /******************************************************************************
2078 * SkGePortCheckUpNat() - Check if the link is up on National PHY
2081 * 0 o.k. nothing needed
2082 * 1 Restart needed on this port
2085 static int SkGePortCheckUpNat(
2086 SK_AC *pAC, /* Adapter Context */
2087 SK_IOC IoC, /* IO Context */
2088 int Port) /* Which port should be checked */
2090 /* todo: National */
2091 return(SK_HW_PS_NONE);
2092 } /* SkGePortCheckUpNat */
2093 #endif /* OTHER_PHY */
2096 /******************************************************************************
2098 * SkGeSirqEvent() - Event Service Routine
2105 SK_AC *pAC, /* Adapter Context */
2106 SK_IOC IoC, /* Io Context */
2107 SK_U32 Event, /* Module specific Event */
2108 SK_EVPARA Para) /* Event specific Parameter */
2111 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2118 Port = Para.Para32[0];
2119 pPrt = &pAC->GIni.GP[Port];
2123 /* Check whether port came up */
2124 PortStat = SkGePortCheckUp(pAC, IoC, Port);
2127 case SK_HW_PS_RESTART:
2128 if (pPrt->PHWLinkUp) {
2132 SkHWLinkDown(pAC, IoC, Port);
2135 * Signal directly to RLMT to ensure correct
2136 * sequence of SWITCH and RESET event.
2138 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2141 /* Restart needed */
2142 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
2146 /* Signal to RLMT */
2147 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
2152 /* Start again the check Timer */
2153 if (pPrt->PHWLinkUp) {
2154 Time = SK_WA_ACT_TIME;
2157 Time = SK_WA_INA_TIME;
2160 /* Todo: still needed for non-XMAC PHYs??? */
2161 /* Start workaround Errata #2 timer */
2162 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Time,
2163 SKGE_HWAC, SK_HWEV_WATIM, Para);
2166 case SK_HWEV_PORT_START:
2167 if (pPrt->PHWLinkUp) {
2169 * Signal directly to RLMT to ensure correct
2170 * sequence of SWITCH and RESET event.
2172 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2175 SkHWLinkDown(pAC, IoC, Port);
2177 /* Schedule Port RESET */
2178 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
2180 /* Start workaround Errata #2 timer */
2181 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
2182 SKGE_HWAC, SK_HWEV_WATIM, Para);
2185 case SK_HWEV_PORT_STOP:
2186 if (pPrt->PHWLinkUp) {
2188 * Signal directly to RLMT to ensure correct
2189 * sequence of SWITCH and RESET event.
2191 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2194 /* Stop Workaround Timer */
2195 SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
2197 SkHWLinkDown(pAC, IoC, Port);
2200 case SK_HWEV_UPDATE_STAT:
2201 /* We do NOT need to update any statistics */
2204 case SK_HWEV_CLEAR_STAT:
2205 /* We do NOT need to clear any statistics */
2206 for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
2209 pPrt->PPrevShorts = 0;
2213 case SK_HWEV_SET_LMODE:
2214 Val8 = (SK_U8)Para.Para32[1];
2215 if (pPrt->PLinkModeConf != Val8) {
2216 /* Set New link mode */
2217 pPrt->PLinkModeConf = Val8;
2220 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2221 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2225 case SK_HWEV_SET_FLOWMODE:
2226 Val8 = (SK_U8)Para.Para32[1];
2227 if (pPrt->PFlowCtrlMode != Val8) {
2228 /* Set New Flow Control mode */
2229 pPrt->PFlowCtrlMode = Val8;
2232 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2233 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2237 case SK_HWEV_SET_ROLE:
2238 /* not possible for fiber */
2239 if (!pAC->GIni.GICopperType) {
2242 Val8 = (SK_U8)Para.Para32[1];
2243 if (pPrt->PMSMode != Val8) {
2244 /* Set New link mode */
2245 pPrt->PMSMode = Val8;
2248 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2249 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2253 case SK_HWEV_SET_SPEED:
2254 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
2257 Val8 = (SK_U8)Para.Para32[1];
2258 if (pPrt->PLinkSpeed != Val8) {
2259 /* Set New Speed parameter */
2260 pPrt->PLinkSpeed = Val8;
2263 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2264 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2268 case SK_HWEV_HALFDUP_CHK:
2270 * half duplex hangup workaround.
2271 * See packet arbiter timeout interrupt for description
2273 pPrt->HalfDupTimerActive = SK_FALSE;
2274 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
2275 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
2277 Len = sizeof(SK_U64);
2278 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
2279 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
2280 pAC->Rlmt.Port[Port].Net->NetNumber);
2282 if (pPrt->LastOctets == Octets) {
2283 /* Tx hanging, a FIFO flush restarts it */
2284 SkMacFlushTxFifo(pAC, IoC, Port);
2290 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
2295 } /* SkGeSirqEvent */
2298 /******************************************************************************
2300 * SkPhyIsrBcom() - PHY interrupt service routine
2302 * Description: handles all interrupts from BCom PHY
2306 static void SkPhyIsrBcom(
2307 SK_AC *pAC, /* Adapter Context */
2308 SK_IOC IoC, /* Io Context */
2309 int Port, /* Port Num = PHY Num */
2310 SK_U16 IStatus) /* Interrupt Status */
2312 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2315 pPrt = &pAC->GIni.GP[Port];
2317 if ((IStatus & PHY_B_IS_PSE) != 0) {
2318 /* Incorrectable pair swap error */
2319 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
2320 SKERR_SIRQ_E022MSG);
2323 if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
2324 Para.Para32[0] = (SK_U32)Port;
2326 SkHWLinkDown(pAC, IoC, Port);
2328 /* Signal to RLMT */
2329 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2331 /* Start workaround Errata #2 timer */
2332 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
2333 SKGE_HWAC, SK_HWEV_WATIM, Para);
2336 } /* SkPhyIsrBcom */
2339 /******************************************************************************
2341 * SkPhyIsrGmac() - PHY interrupt service routine
2343 * Description: handles all interrupts from Marvell PHY
2347 static void SkPhyIsrGmac(
2348 SK_AC *pAC, /* Adapter Context */
2349 SK_IOC IoC, /* Io Context */
2350 int Port, /* Port Num = PHY Num */
2351 SK_U16 IStatus) /* Interrupt Status */
2353 SK_GEPORT *pPrt; /* GIni Port struct pointer */
2356 pPrt = &pAC->GIni.GP[Port];
2358 if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
2359 Para.Para32[0] = (SK_U32)Port;
2361 SkHWLinkDown(pAC, IoC, Port);
2363 /* Signal to RLMT */
2364 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2367 if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
2368 /* Auto-Negotiation Error */
2369 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
2372 if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) {
2376 if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
2377 /* FIFO Overflow/Underrun Error */
2378 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
2380 } /* SkPhyIsrGmac */
2384 /******************************************************************************
2386 * SkPhyIsrLone() - PHY interrupt service routine
2388 * Description: handles all interrupts from LONE PHY
2392 static void SkPhyIsrLone(
2393 SK_AC *pAC, /* Adapter Context */
2394 SK_IOC IoC, /* Io Context */
2395 int Port, /* Port Num = PHY Num */
2396 SK_U16 IStatus) /* Interrupt Status */
2400 if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
2401 SkHWLinkDown(pAC, IoC, Port);
2403 /* Signal to RLMT */
2404 Para.Para32[0] = (SK_U32)Port;
2405 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2408 } /* SkPhyIsrLone */
2409 #endif /* OTHER_PHY */