| Stephen Hemminger | 5ad887f | 2007-09-15 19:35:14 -0400 | [diff] [blame] | 1 | /****************************************************************************** | 
|  | 2 | * | 
|  | 3 | * Name:	skgesirq.c | 
|  | 4 | * Project:	Gigabit Ethernet Adapters, Common Modules | 
|  | 5 | * Version:	$Revision: 1.92 $ | 
|  | 6 | * Date:	$Date: 2003/09/16 14:37:07 $ | 
|  | 7 | * Purpose:	Special IRQ module | 
|  | 8 | * | 
|  | 9 | ******************************************************************************/ | 
|  | 10 |  | 
|  | 11 | /****************************************************************************** | 
|  | 12 | * | 
|  | 13 | *	(C)Copyright 1998-2002 SysKonnect. | 
|  | 14 | *	(C)Copyright 2002-2003 Marvell. | 
|  | 15 | * | 
|  | 16 | *	This program is free software; you can redistribute it and/or modify | 
|  | 17 | *	it under the terms of the GNU General Public License as published by | 
|  | 18 | *	the Free Software Foundation; either version 2 of the License, or | 
|  | 19 | *	(at your option) any later version. | 
|  | 20 | * | 
|  | 21 | *	The information in this file is provided "AS IS" without warranty. | 
|  | 22 | * | 
|  | 23 | ******************************************************************************/ | 
|  | 24 |  | 
|  | 25 | /* | 
|  | 26 | *	Special Interrupt handler | 
|  | 27 | * | 
|  | 28 | *	The following abstract should show how this module is included | 
|  | 29 | *	in the driver path: | 
|  | 30 | * | 
|  | 31 | *	In the ISR of the driver the bits for frame transmission complete and | 
|  | 32 | *	for receive complete are checked and handled by the driver itself. | 
|  | 33 | *	The bits of the slow path mask are checked after that and then the | 
|  | 34 | *	entry into the so-called "slow path" is prepared. It is an implementors | 
|  | 35 | *	decision whether this is executed directly or just scheduled by | 
|  | 36 | *	disabling the mask. In the interrupt service routine some events may be | 
|  | 37 | *	generated, so it would be a good idea to call the EventDispatcher | 
|  | 38 | *	right after this ISR. | 
|  | 39 | * | 
|  | 40 | *	The Interrupt source register of the adapter is NOT read by this module. | 
|  | 41 | *  SO if the drivers implementor needs a while loop around the | 
|  | 42 | *	slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for | 
|  | 43 | *	each loop entered. | 
|  | 44 | * | 
|  | 45 | *	However, the MAC Interrupt status registers are read in a while loop. | 
|  | 46 | * | 
|  | 47 | */ | 
|  | 48 |  | 
|  | 49 | #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) | 
|  | 50 | static const char SysKonnectFileId[] = | 
|  | 51 | "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell."; | 
|  | 52 | #endif | 
|  | 53 |  | 
|  | 54 | #include "h/skdrv1st.h"		/* Driver Specific Definitions */ | 
|  | 55 | #ifndef SK_SLIM | 
|  | 56 | #include "h/skgepnmi.h"		/* PNMI Definitions */ | 
|  | 57 | #include "h/skrlmt.h"		/* RLMT Definitions */ | 
|  | 58 | #endif | 
|  | 59 | #include "h/skdrv2nd.h"		/* Adapter Control and Driver specific Def. */ | 
|  | 60 |  | 
|  | 61 | /* local function prototypes */ | 
|  | 62 | #ifdef GENESIS | 
|  | 63 | static int	SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL); | 
|  | 64 | static int	SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL); | 
|  | 65 | static void	SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16); | 
|  | 66 | #endif /* GENESIS */ | 
|  | 67 | #ifdef YUKON | 
|  | 68 | static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL); | 
|  | 69 | static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16); | 
|  | 70 | #endif /* YUKON */ | 
|  | 71 | #ifdef OTHER_PHY | 
|  | 72 | static int	SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL); | 
|  | 73 | static int	SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL); | 
|  | 74 | static void	SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16); | 
|  | 75 | #endif /* OTHER_PHY */ | 
|  | 76 |  | 
|  | 77 | #ifdef GENESIS | 
|  | 78 | /* | 
|  | 79 | * array of Rx counter from XMAC which are checked | 
|  | 80 | * in AutoSense mode to check whether a link is not able to auto-negotiate. | 
|  | 81 | */ | 
|  | 82 | static const SK_U16 SkGeRxRegs[]= { | 
|  | 83 | XM_RXF_64B, | 
|  | 84 | XM_RXF_127B, | 
|  | 85 | XM_RXF_255B, | 
|  | 86 | XM_RXF_511B, | 
|  | 87 | XM_RXF_1023B, | 
|  | 88 | XM_RXF_MAX_SZ | 
|  | 89 | } ; | 
|  | 90 | #endif /* GENESIS */ | 
|  | 91 |  | 
|  | 92 | #ifdef __C2MAN__ | 
|  | 93 | /* | 
|  | 94 | *	Special IRQ function | 
|  | 95 | * | 
|  | 96 | *	General Description: | 
|  | 97 | * | 
|  | 98 | */ | 
|  | 99 | intro() | 
|  | 100 | {} | 
|  | 101 | #endif | 
|  | 102 |  | 
|  | 103 | /****************************************************************************** | 
|  | 104 | * | 
|  | 105 | *	SkHWInitDefSense() - Default Autosensing mode initialization | 
|  | 106 | * | 
|  | 107 | * Description: sets the PLinkMode for HWInit | 
|  | 108 | * | 
|  | 109 | * Returns: N/A | 
|  | 110 | */ | 
|  | 111 | static void SkHWInitDefSense( | 
|  | 112 | SK_AC	*pAC,	/* adapter context */ | 
|  | 113 | SK_IOC	IoC,	/* IO context */ | 
|  | 114 | int		Port)	/* Port Index (MAC_1 + n) */ | 
|  | 115 | { | 
|  | 116 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 117 |  | 
|  | 118 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 119 |  | 
|  | 120 | pPrt->PAutoNegTimeOut = 0; | 
|  | 121 |  | 
|  | 122 | if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { | 
|  | 123 | pPrt->PLinkMode = pPrt->PLinkModeConf; | 
|  | 124 | return; | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 128 | ("AutoSensing: First mode %d on Port %d\n", | 
|  | 129 | (int)SK_LMODE_AUTOFULL, Port)); | 
|  | 130 |  | 
|  | 131 | pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; | 
|  | 132 |  | 
|  | 133 | return; | 
|  | 134 | }	/* SkHWInitDefSense */ | 
|  | 135 |  | 
|  | 136 |  | 
|  | 137 | #ifdef GENESIS | 
|  | 138 | /****************************************************************************** | 
|  | 139 | * | 
|  | 140 | *	SkHWSenseGetNext() - Get Next Autosensing Mode | 
|  | 141 | * | 
|  | 142 | * Description: gets the appropriate next mode | 
|  | 143 | * | 
|  | 144 | * Note: | 
|  | 145 | * | 
|  | 146 | */ | 
|  | 147 | static SK_U8 SkHWSenseGetNext( | 
|  | 148 | SK_AC	*pAC,	/* adapter context */ | 
|  | 149 | SK_IOC	IoC,	/* IO context */ | 
|  | 150 | int		Port)	/* Port Index (MAC_1 + n) */ | 
|  | 151 | { | 
|  | 152 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 153 |  | 
|  | 154 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 155 |  | 
|  | 156 | pPrt->PAutoNegTimeOut = 0; | 
|  | 157 |  | 
|  | 158 | if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { | 
|  | 159 | /* Leave all as configured */ | 
|  | 160 | return(pPrt->PLinkModeConf); | 
|  | 161 | } | 
|  | 162 |  | 
|  | 163 | if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) { | 
|  | 164 | /* Return next mode AUTOBOTH */ | 
|  | 165 | return ((SK_U8)SK_LMODE_AUTOBOTH); | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | /* Return default autofull */ | 
|  | 169 | return ((SK_U8)SK_LMODE_AUTOFULL); | 
|  | 170 | }	/* SkHWSenseGetNext */ | 
|  | 171 |  | 
|  | 172 |  | 
|  | 173 | /****************************************************************************** | 
|  | 174 | * | 
|  | 175 | *	SkHWSenseSetNext() - Autosensing Set next mode | 
|  | 176 | * | 
|  | 177 | * Description:	sets the appropriate next mode | 
|  | 178 | * | 
|  | 179 | * Returns: N/A | 
|  | 180 | */ | 
|  | 181 | static void SkHWSenseSetNext( | 
|  | 182 | SK_AC	*pAC,		/* adapter context */ | 
|  | 183 | SK_IOC	IoC,		/* IO context */ | 
|  | 184 | int		Port,		/* Port Index (MAC_1 + n) */ | 
|  | 185 | SK_U8	NewMode)	/* New Mode to be written in sense mode */ | 
|  | 186 | { | 
|  | 187 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 188 |  | 
|  | 189 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 190 |  | 
|  | 191 | pPrt->PAutoNegTimeOut = 0; | 
|  | 192 |  | 
|  | 193 | if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { | 
|  | 194 | return; | 
|  | 195 | } | 
|  | 196 |  | 
|  | 197 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 198 | ("AutoSensing: next mode %d on Port %d\n", | 
|  | 199 | (int)NewMode, Port)); | 
|  | 200 |  | 
|  | 201 | pPrt->PLinkMode = NewMode; | 
|  | 202 |  | 
|  | 203 | return; | 
|  | 204 | }	/* SkHWSenseSetNext */ | 
|  | 205 | #endif /* GENESIS */ | 
|  | 206 |  | 
|  | 207 |  | 
|  | 208 | /****************************************************************************** | 
|  | 209 | * | 
|  | 210 | *	SkHWLinkDown() - Link Down handling | 
|  | 211 | * | 
|  | 212 | * Description: handles the hardware link down signal | 
|  | 213 | * | 
|  | 214 | * Returns: N/A | 
|  | 215 | */ | 
|  | 216 | void SkHWLinkDown( | 
|  | 217 | SK_AC	*pAC,		/* adapter context */ | 
|  | 218 | SK_IOC	IoC,		/* IO context */ | 
|  | 219 | int		Port)		/* Port Index (MAC_1 + n) */ | 
|  | 220 | { | 
|  | 221 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 222 |  | 
|  | 223 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 224 |  | 
|  | 225 | /* Disable all MAC interrupts */ | 
|  | 226 | SkMacIrqDisable(pAC, IoC, Port); | 
|  | 227 |  | 
|  | 228 | /* Disable Receiver and Transmitter */ | 
|  | 229 | SkMacRxTxDisable(pAC, IoC, Port); | 
|  | 230 |  | 
|  | 231 | /* Init default sense mode */ | 
|  | 232 | SkHWInitDefSense(pAC, IoC, Port); | 
|  | 233 |  | 
|  | 234 | if (pPrt->PHWLinkUp == SK_FALSE) { | 
|  | 235 | return; | 
|  | 236 | } | 
|  | 237 |  | 
|  | 238 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 239 | ("Link down Port %d\n", Port)); | 
|  | 240 |  | 
|  | 241 | /* Set Link to DOWN */ | 
|  | 242 | pPrt->PHWLinkUp = SK_FALSE; | 
|  | 243 |  | 
|  | 244 | /* Reset Port stati */ | 
|  | 245 | pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; | 
|  | 246 | pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; | 
|  | 247 | pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED; | 
|  | 248 |  | 
|  | 249 | /* Re-init Phy especially when the AutoSense default is set now */ | 
|  | 250 | SkMacInitPhy(pAC, IoC, Port, SK_FALSE); | 
|  | 251 |  | 
|  | 252 | /* GP0: used for workaround of Rev. C Errata 2 */ | 
|  | 253 |  | 
|  | 254 | /* Do NOT signal to RLMT */ | 
|  | 255 |  | 
|  | 256 | /* Do NOT start the timer here */ | 
|  | 257 | }	/* SkHWLinkDown */ | 
|  | 258 |  | 
|  | 259 |  | 
|  | 260 | /****************************************************************************** | 
|  | 261 | * | 
|  | 262 | *	SkHWLinkUp() - Link Up handling | 
|  | 263 | * | 
|  | 264 | * Description: handles the hardware link up signal | 
|  | 265 | * | 
|  | 266 | * Returns: N/A | 
|  | 267 | */ | 
|  | 268 | static void SkHWLinkUp( | 
|  | 269 | SK_AC	*pAC,	/* adapter context */ | 
|  | 270 | SK_IOC	IoC,	/* IO context */ | 
|  | 271 | int		Port)	/* Port Index (MAC_1 + n) */ | 
|  | 272 | { | 
|  | 273 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 274 |  | 
|  | 275 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 276 |  | 
|  | 277 | if (pPrt->PHWLinkUp) { | 
|  | 278 | /* We do NOT need to proceed on active link */ | 
|  | 279 | return; | 
|  | 280 | } | 
|  | 281 |  | 
|  | 282 | pPrt->PHWLinkUp = SK_TRUE; | 
|  | 283 | pPrt->PAutoNegFail = SK_FALSE; | 
|  | 284 | pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; | 
|  | 285 |  | 
|  | 286 | if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF && | 
|  | 287 | pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL && | 
|  | 288 | pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) { | 
|  | 289 | /* Link is up and no Auto-negotiation should be done */ | 
|  | 290 |  | 
|  | 291 | /* Link speed should be the configured one */ | 
|  | 292 | switch (pPrt->PLinkSpeed) { | 
|  | 293 | case SK_LSPEED_AUTO: | 
|  | 294 | /* default is 1000 Mbps */ | 
|  | 295 | case SK_LSPEED_1000MBPS: | 
|  | 296 | pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; | 
|  | 297 | break; | 
|  | 298 | case SK_LSPEED_100MBPS: | 
|  | 299 | pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; | 
|  | 300 | break; | 
|  | 301 | case SK_LSPEED_10MBPS: | 
|  | 302 | pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; | 
|  | 303 | break; | 
|  | 304 | } | 
|  | 305 |  | 
|  | 306 | /* Set Link Mode Status */ | 
|  | 307 | if (pPrt->PLinkMode == SK_LMODE_FULL) { | 
|  | 308 | pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL; | 
|  | 309 | } | 
|  | 310 | else { | 
|  | 311 | pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF; | 
|  | 312 | } | 
|  | 313 |  | 
|  | 314 | /* No flow control without auto-negotiation */ | 
|  | 315 | pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; | 
|  | 316 |  | 
|  | 317 | /* enable Rx/Tx */ | 
|  | 318 | (void)SkMacRxTxEnable(pAC, IoC, Port); | 
|  | 319 | } | 
|  | 320 | }	/* SkHWLinkUp */ | 
|  | 321 |  | 
|  | 322 |  | 
|  | 323 | /****************************************************************************** | 
|  | 324 | * | 
|  | 325 | *	SkMacParity() - MAC parity workaround | 
|  | 326 | * | 
|  | 327 | * Description: handles MAC parity errors correctly | 
|  | 328 | * | 
|  | 329 | * Returns: N/A | 
|  | 330 | */ | 
|  | 331 | static void SkMacParity( | 
|  | 332 | SK_AC	*pAC,	/* adapter context */ | 
|  | 333 | SK_IOC	IoC,	/* IO context */ | 
|  | 334 | int		Port)	/* Port Index of the port failed */ | 
|  | 335 | { | 
|  | 336 | SK_EVPARA	Para; | 
|  | 337 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 338 | SK_U32		TxMax;		/* Tx Max Size Counter */ | 
|  | 339 |  | 
|  | 340 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 341 |  | 
|  | 342 | /* Clear IRQ Tx Parity Error */ | 
|  | 343 | #ifdef GENESIS | 
|  | 344 | if (pAC->GIni.GIGenesis) { | 
|  | 345 |  | 
|  | 346 | SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); | 
|  | 347 | } | 
|  | 348 | #endif /* GENESIS */ | 
|  | 349 |  | 
|  | 350 | #ifdef YUKON | 
|  | 351 | if (pAC->GIni.GIYukon) { | 
|  | 352 | /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ | 
|  | 353 | SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), | 
|  | 354 | (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON && | 
|  | 355 | pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); | 
|  | 356 | } | 
|  | 357 | #endif /* YUKON */ | 
|  | 358 |  | 
|  | 359 | if (pPrt->PCheckPar) { | 
|  | 360 |  | 
|  | 361 | if (Port == MAC_1) { | 
|  | 362 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); | 
|  | 363 | } | 
|  | 364 | else { | 
|  | 365 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); | 
|  | 366 | } | 
|  | 367 | Para.Para64 = Port; | 
|  | 368 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 369 |  | 
|  | 370 | Para.Para32[0] = Port; | 
|  | 371 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 372 |  | 
|  | 373 | return; | 
|  | 374 | } | 
|  | 375 |  | 
|  | 376 | /* Check whether frames with a size of 1k were sent */ | 
|  | 377 | #ifdef GENESIS | 
|  | 378 | if (pAC->GIni.GIGenesis) { | 
|  | 379 | /* Snap statistic counters */ | 
|  | 380 | (void)SkXmUpdateStats(pAC, IoC, Port); | 
|  | 381 |  | 
|  | 382 | (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); | 
|  | 383 | } | 
|  | 384 | #endif /* GENESIS */ | 
|  | 385 |  | 
|  | 386 | #ifdef YUKON | 
|  | 387 | if (pAC->GIni.GIYukon) { | 
|  | 388 |  | 
|  | 389 | (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); | 
|  | 390 | } | 
|  | 391 | #endif /* YUKON */ | 
|  | 392 |  | 
|  | 393 | if (TxMax > 0) { | 
|  | 394 | /* From now on check the parity */ | 
|  | 395 | pPrt->PCheckPar = SK_TRUE; | 
|  | 396 | } | 
|  | 397 | }	/* SkMacParity */ | 
|  | 398 |  | 
|  | 399 |  | 
|  | 400 | /****************************************************************************** | 
|  | 401 | * | 
|  | 402 | *	SkGeHwErr() - Hardware Error service routine | 
|  | 403 | * | 
|  | 404 | * Description: handles all HW Error interrupts | 
|  | 405 | * | 
|  | 406 | * Returns: N/A | 
|  | 407 | */ | 
|  | 408 | static void SkGeHwErr( | 
|  | 409 | SK_AC	*pAC,		/* adapter context */ | 
|  | 410 | SK_IOC	IoC,		/* IO context */ | 
|  | 411 | SK_U32	HwStatus)	/* Interrupt status word */ | 
|  | 412 | { | 
|  | 413 | SK_EVPARA	Para; | 
|  | 414 | SK_U16		Word; | 
|  | 415 |  | 
|  | 416 | if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) { | 
|  | 417 | /* PCI Errors occured */ | 
|  | 418 | if ((HwStatus & IS_IRQ_STAT) != 0) { | 
|  | 419 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); | 
|  | 420 | } | 
|  | 421 | else { | 
|  | 422 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); | 
|  | 423 | } | 
|  | 424 |  | 
|  | 425 | /* Reset all bits in the PCI STATUS register */ | 
|  | 426 | SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); | 
|  | 427 |  | 
|  | 428 | SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 
|  | 429 | SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); | 
|  | 430 | SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 
|  | 431 |  | 
|  | 432 | Para.Para64 = 0; | 
|  | 433 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); | 
|  | 434 | } | 
|  | 435 |  | 
|  | 436 | #ifdef GENESIS | 
|  | 437 | if (pAC->GIni.GIGenesis) { | 
|  | 438 |  | 
|  | 439 | if ((HwStatus & IS_NO_STAT_M1) != 0) { | 
|  | 440 | /* Ignore it */ | 
|  | 441 | /* This situation is also indicated in the descriptor */ | 
|  | 442 | SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT); | 
|  | 443 | } | 
|  | 444 |  | 
|  | 445 | if ((HwStatus & IS_NO_STAT_M2) != 0) { | 
|  | 446 | /* Ignore it */ | 
|  | 447 | /* This situation is also indicated in the descriptor */ | 
|  | 448 | SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT); | 
|  | 449 | } | 
|  | 450 |  | 
|  | 451 | if ((HwStatus & IS_NO_TIST_M1) != 0) { | 
|  | 452 | /* Ignore it */ | 
|  | 453 | /* This situation is also indicated in the descriptor */ | 
|  | 454 | SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST); | 
|  | 455 | } | 
|  | 456 |  | 
|  | 457 | if ((HwStatus & IS_NO_TIST_M2) != 0) { | 
|  | 458 | /* Ignore it */ | 
|  | 459 | /* This situation is also indicated in the descriptor */ | 
|  | 460 | SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); | 
|  | 461 | } | 
|  | 462 | } | 
|  | 463 | #endif /* GENESIS */ | 
|  | 464 |  | 
|  | 465 | #ifdef YUKON | 
|  | 466 | if (pAC->GIni.GIYukon) { | 
|  | 467 | /* This is necessary only for Rx timing measurements */ | 
|  | 468 | if ((HwStatus & IS_IRQ_TIST_OV) != 0) { | 
|  | 469 | /* increment Time Stamp Timer counter (high) */ | 
|  | 470 | pAC->GIni.GITimeStampCnt++; | 
|  | 471 |  | 
|  | 472 | /* Clear Time Stamp Timer IRQ */ | 
|  | 473 | SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); | 
|  | 474 | } | 
|  | 475 |  | 
|  | 476 | if ((HwStatus & IS_IRQ_SENSOR) != 0) { | 
|  | 477 | /* no sensors on 32-bit Yukon */ | 
|  | 478 | if (pAC->GIni.GIYukon32Bit) { | 
|  | 479 | /* disable HW Error IRQ */ | 
|  | 480 | pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; | 
|  | 481 | } | 
|  | 482 | } | 
|  | 483 | } | 
|  | 484 | #endif /* YUKON */ | 
|  | 485 |  | 
|  | 486 | if ((HwStatus & IS_RAM_RD_PAR) != 0) { | 
|  | 487 | SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); | 
|  | 488 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); | 
|  | 489 | Para.Para64 = 0; | 
|  | 490 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); | 
|  | 491 | } | 
|  | 492 |  | 
|  | 493 | if ((HwStatus & IS_RAM_WR_PAR) != 0) { | 
|  | 494 | SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); | 
|  | 495 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); | 
|  | 496 | Para.Para64 = 0; | 
|  | 497 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); | 
|  | 498 | } | 
|  | 499 |  | 
|  | 500 | if ((HwStatus & IS_M1_PAR_ERR) != 0) { | 
|  | 501 | SkMacParity(pAC, IoC, MAC_1); | 
|  | 502 | } | 
|  | 503 |  | 
|  | 504 | if ((HwStatus & IS_M2_PAR_ERR) != 0) { | 
|  | 505 | SkMacParity(pAC, IoC, MAC_2); | 
|  | 506 | } | 
|  | 507 |  | 
|  | 508 | if ((HwStatus & IS_R1_PAR_ERR) != 0) { | 
|  | 509 | /* Clear IRQ */ | 
|  | 510 | SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P); | 
|  | 511 |  | 
|  | 512 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); | 
|  | 513 | Para.Para64 = MAC_1; | 
|  | 514 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 515 |  | 
|  | 516 | Para.Para32[0] = MAC_1; | 
|  | 517 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 518 | } | 
|  | 519 |  | 
|  | 520 | if ((HwStatus & IS_R2_PAR_ERR) != 0) { | 
|  | 521 | /* Clear IRQ */ | 
|  | 522 | SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P); | 
|  | 523 |  | 
|  | 524 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); | 
|  | 525 | Para.Para64 = MAC_2; | 
|  | 526 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 527 |  | 
|  | 528 | Para.Para32[0] = MAC_2; | 
|  | 529 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 530 | } | 
|  | 531 | }	/* SkGeHwErr */ | 
|  | 532 |  | 
|  | 533 |  | 
|  | 534 | /****************************************************************************** | 
|  | 535 | * | 
|  | 536 | *	SkGeSirqIsr() - Special Interrupt Service Routine | 
|  | 537 | * | 
|  | 538 | * Description: handles all non data transfer specific interrupts (slow path) | 
|  | 539 | * | 
|  | 540 | * Returns: N/A | 
|  | 541 | */ | 
|  | 542 | void SkGeSirqIsr( | 
|  | 543 | SK_AC	*pAC,		/* adapter context */ | 
|  | 544 | SK_IOC	IoC,		/* IO context */ | 
|  | 545 | SK_U32	Istatus)	/* Interrupt status word */ | 
|  | 546 | { | 
|  | 547 | SK_EVPARA	Para; | 
|  | 548 | SK_U32		RegVal32;	/* Read register value */ | 
|  | 549 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 550 | SK_U16 		PhyInt; | 
|  | 551 | int			i; | 
|  | 552 |  | 
|  | 553 | if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) { | 
|  | 554 | /* read the HW Error Interrupt source */ | 
|  | 555 | SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); | 
|  | 556 |  | 
|  | 557 | SkGeHwErr(pAC, IoC, RegVal32); | 
|  | 558 | } | 
|  | 559 |  | 
|  | 560 | /* | 
|  | 561 | * Packet Timeout interrupts | 
|  | 562 | */ | 
|  | 563 | /* Check whether MACs are correctly initialized */ | 
|  | 564 | if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) && | 
|  | 565 | pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) { | 
|  | 566 | /* MAC 1 was not initialized but Packet timeout occured */ | 
|  | 567 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004, | 
|  | 568 | SKERR_SIRQ_E004MSG); | 
|  | 569 | } | 
|  | 570 |  | 
|  | 571 | if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) && | 
|  | 572 | pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { | 
|  | 573 | /* MAC 2 was not initialized but Packet timeout occured */ | 
|  | 574 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, | 
|  | 575 | SKERR_SIRQ_E005MSG); | 
|  | 576 | } | 
|  | 577 |  | 
|  | 578 | if ((Istatus & IS_PA_TO_RX1) != 0) { | 
|  | 579 | /* Means network is filling us up */ | 
|  | 580 | SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002, | 
|  | 581 | SKERR_SIRQ_E002MSG); | 
|  | 582 | SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1); | 
|  | 583 | } | 
|  | 584 |  | 
|  | 585 | if ((Istatus & IS_PA_TO_RX2) != 0) { | 
|  | 586 | /* Means network is filling us up */ | 
|  | 587 | SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003, | 
|  | 588 | SKERR_SIRQ_E003MSG); | 
|  | 589 | SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2); | 
|  | 590 | } | 
|  | 591 |  | 
|  | 592 | if ((Istatus & IS_PA_TO_TX1) != 0) { | 
|  | 593 |  | 
|  | 594 | pPrt = &pAC->GIni.GP[0]; | 
|  | 595 |  | 
|  | 596 | /* May be a normal situation in a server with a slow network */ | 
|  | 597 | SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); | 
|  | 598 |  | 
|  | 599 | #ifdef GENESIS | 
|  | 600 | if (pAC->GIni.GIGenesis) { | 
|  | 601 | /* | 
|  | 602 | * workaround: if in half duplex mode, check for Tx hangup. | 
|  | 603 | * Read number of TX'ed bytes, wait for 10 ms, then compare | 
|  | 604 | * the number with current value. If nothing changed, we assume | 
|  | 605 | * that Tx is hanging and do a FIFO flush (see event routine). | 
|  | 606 | */ | 
|  | 607 | if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || | 
|  | 608 | pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && | 
|  | 609 | !pPrt->HalfDupTimerActive) { | 
|  | 610 | /* | 
|  | 611 | * many more pack. arb. timeouts may come in between, | 
|  | 612 | * we ignore those | 
|  | 613 | */ | 
|  | 614 | pPrt->HalfDupTimerActive = SK_TRUE; | 
|  | 615 | /* Snap statistic counters */ | 
|  | 616 | (void)SkXmUpdateStats(pAC, IoC, 0); | 
|  | 617 |  | 
|  | 618 | (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32); | 
|  | 619 |  | 
|  | 620 | pPrt->LastOctets = (SK_U64)RegVal32 << 32; | 
|  | 621 |  | 
|  | 622 | (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32); | 
|  | 623 |  | 
|  | 624 | pPrt->LastOctets += RegVal32; | 
|  | 625 |  | 
|  | 626 | Para.Para32[0] = 0; | 
|  | 627 | SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, | 
|  | 628 | SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); | 
|  | 629 | } | 
|  | 630 | } | 
|  | 631 | #endif /* GENESIS */ | 
|  | 632 | } | 
|  | 633 |  | 
|  | 634 | if ((Istatus & IS_PA_TO_TX2) != 0) { | 
|  | 635 |  | 
|  | 636 | pPrt = &pAC->GIni.GP[1]; | 
|  | 637 |  | 
|  | 638 | /* May be a normal situation in a server with a slow network */ | 
|  | 639 | SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); | 
|  | 640 |  | 
|  | 641 | #ifdef GENESIS | 
|  | 642 | if (pAC->GIni.GIGenesis) { | 
|  | 643 | /* workaround: see above */ | 
|  | 644 | if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || | 
|  | 645 | pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && | 
|  | 646 | !pPrt->HalfDupTimerActive) { | 
|  | 647 | pPrt->HalfDupTimerActive = SK_TRUE; | 
|  | 648 | /* Snap statistic counters */ | 
|  | 649 | (void)SkXmUpdateStats(pAC, IoC, 1); | 
|  | 650 |  | 
|  | 651 | (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32); | 
|  | 652 |  | 
|  | 653 | pPrt->LastOctets = (SK_U64)RegVal32 << 32; | 
|  | 654 |  | 
|  | 655 | (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32); | 
|  | 656 |  | 
|  | 657 | pPrt->LastOctets += RegVal32; | 
|  | 658 |  | 
|  | 659 | Para.Para32[0] = 1; | 
|  | 660 | SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, | 
|  | 661 | SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); | 
|  | 662 | } | 
|  | 663 | } | 
|  | 664 | #endif /* GENESIS */ | 
|  | 665 | } | 
|  | 666 |  | 
|  | 667 | /* Check interrupts of the particular queues */ | 
|  | 668 | if ((Istatus & IS_R1_C) != 0) { | 
|  | 669 | /* Clear IRQ */ | 
|  | 670 | SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); | 
|  | 671 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, | 
|  | 672 | SKERR_SIRQ_E006MSG); | 
|  | 673 | Para.Para64 = MAC_1; | 
|  | 674 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 675 | Para.Para32[0] = MAC_1; | 
|  | 676 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 677 | } | 
|  | 678 |  | 
|  | 679 | if ((Istatus & IS_R2_C) != 0) { | 
|  | 680 | /* Clear IRQ */ | 
|  | 681 | SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); | 
|  | 682 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, | 
|  | 683 | SKERR_SIRQ_E007MSG); | 
|  | 684 | Para.Para64 = MAC_2; | 
|  | 685 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 686 | Para.Para32[0] = MAC_2; | 
|  | 687 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 688 | } | 
|  | 689 |  | 
|  | 690 | if ((Istatus & IS_XS1_C) != 0) { | 
|  | 691 | /* Clear IRQ */ | 
|  | 692 | SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); | 
|  | 693 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, | 
|  | 694 | SKERR_SIRQ_E008MSG); | 
|  | 695 | Para.Para64 = MAC_1; | 
|  | 696 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 697 | Para.Para32[0] = MAC_1; | 
|  | 698 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 699 | } | 
|  | 700 |  | 
|  | 701 | if ((Istatus & IS_XA1_C) != 0) { | 
|  | 702 | /* Clear IRQ */ | 
|  | 703 | SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); | 
|  | 704 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, | 
|  | 705 | SKERR_SIRQ_E009MSG); | 
|  | 706 | Para.Para64 = MAC_1; | 
|  | 707 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 708 | Para.Para32[0] = MAC_1; | 
|  | 709 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 710 | } | 
|  | 711 |  | 
|  | 712 | if ((Istatus & IS_XS2_C) != 0) { | 
|  | 713 | /* Clear IRQ */ | 
|  | 714 | SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); | 
|  | 715 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, | 
|  | 716 | SKERR_SIRQ_E010MSG); | 
|  | 717 | Para.Para64 = MAC_2; | 
|  | 718 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 719 | Para.Para32[0] = MAC_2; | 
|  | 720 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 721 | } | 
|  | 722 |  | 
|  | 723 | if ((Istatus & IS_XA2_C) != 0) { | 
|  | 724 | /* Clear IRQ */ | 
|  | 725 | SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); | 
|  | 726 | SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, | 
|  | 727 | SKERR_SIRQ_E011MSG); | 
|  | 728 | Para.Para64 = MAC_2; | 
|  | 729 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); | 
|  | 730 | Para.Para32[0] = MAC_2; | 
|  | 731 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 732 | } | 
|  | 733 |  | 
|  | 734 | /* External reg interrupt */ | 
|  | 735 | if ((Istatus & IS_EXT_REG) != 0) { | 
|  | 736 | /* Test IRQs from PHY */ | 
|  | 737 | for (i = 0; i < pAC->GIni.GIMacsFound; i++) { | 
|  | 738 |  | 
|  | 739 | pPrt = &pAC->GIni.GP[i]; | 
|  | 740 |  | 
|  | 741 | if (pPrt->PState == SK_PRT_RESET) { | 
|  | 742 | continue; | 
|  | 743 | } | 
|  | 744 |  | 
|  | 745 | #ifdef GENESIS | 
|  | 746 | if (pAC->GIni.GIGenesis) { | 
|  | 747 |  | 
|  | 748 | switch (pPrt->PhyType) { | 
|  | 749 |  | 
|  | 750 | case SK_PHY_XMAC: | 
|  | 751 | break; | 
|  | 752 |  | 
|  | 753 | case SK_PHY_BCOM: | 
|  | 754 | SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); | 
|  | 755 |  | 
|  | 756 | if ((PhyInt & ~PHY_B_DEF_MSK) != 0) { | 
|  | 757 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 758 | ("Port %d Bcom Int: 0x%04X\n", | 
|  | 759 | i, PhyInt)); | 
|  | 760 | SkPhyIsrBcom(pAC, IoC, i, PhyInt); | 
|  | 761 | } | 
|  | 762 | break; | 
|  | 763 | #ifdef OTHER_PHY | 
|  | 764 | case SK_PHY_LONE: | 
|  | 765 | SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); | 
|  | 766 |  | 
|  | 767 | if ((PhyInt & PHY_L_DEF_MSK) != 0) { | 
|  | 768 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 769 | ("Port %d Lone Int: %x\n", | 
|  | 770 | i, PhyInt)); | 
|  | 771 | SkPhyIsrLone(pAC, IoC, i, PhyInt); | 
|  | 772 | } | 
|  | 773 | break; | 
|  | 774 | #endif /* OTHER_PHY */ | 
|  | 775 | } | 
|  | 776 | } | 
|  | 777 | #endif /* GENESIS */ | 
|  | 778 |  | 
|  | 779 | #ifdef YUKON | 
|  | 780 | if (pAC->GIni.GIYukon) { | 
|  | 781 | /* Read PHY Interrupt Status */ | 
|  | 782 | SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); | 
|  | 783 |  | 
|  | 784 | if ((PhyInt & PHY_M_DEF_MSK) != 0) { | 
|  | 785 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 786 | ("Port %d Marv Int: 0x%04X\n", | 
|  | 787 | i, PhyInt)); | 
|  | 788 | SkPhyIsrGmac(pAC, IoC, i, PhyInt); | 
|  | 789 | } | 
|  | 790 | } | 
|  | 791 | #endif /* YUKON */ | 
|  | 792 | } | 
|  | 793 | } | 
|  | 794 |  | 
|  | 795 | /* I2C Ready interrupt */ | 
|  | 796 | if ((Istatus & IS_I2C_READY) != 0) { | 
|  | 797 | #ifdef SK_SLIM | 
|  | 798 | SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); | 
|  | 799 | #else | 
|  | 800 | SkI2cIsr(pAC, IoC); | 
|  | 801 | #endif | 
|  | 802 | } | 
|  | 803 |  | 
|  | 804 | /* SW forced interrupt */ | 
|  | 805 | if ((Istatus & IS_IRQ_SW) != 0) { | 
|  | 806 | /* clear the software IRQ */ | 
|  | 807 | SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); | 
|  | 808 | } | 
|  | 809 |  | 
|  | 810 | if ((Istatus & IS_LNK_SYNC_M1) != 0) { | 
|  | 811 | /* | 
|  | 812 | * We do NOT need the Link Sync interrupt, because it shows | 
|  | 813 | * us only a link going down. | 
|  | 814 | */ | 
|  | 815 | /* clear interrupt */ | 
|  | 816 | SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); | 
|  | 817 | } | 
|  | 818 |  | 
|  | 819 | /* Check MAC after link sync counter */ | 
|  | 820 | if ((Istatus & IS_MAC1) != 0) { | 
|  | 821 | /* IRQ from MAC 1 */ | 
|  | 822 | SkMacIrq(pAC, IoC, MAC_1); | 
|  | 823 | } | 
|  | 824 |  | 
|  | 825 | if ((Istatus & IS_LNK_SYNC_M2) != 0) { | 
|  | 826 | /* | 
|  | 827 | * We do NOT need the Link Sync interrupt, because it shows | 
|  | 828 | * us only a link going down. | 
|  | 829 | */ | 
|  | 830 | /* clear interrupt */ | 
|  | 831 | SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); | 
|  | 832 | } | 
|  | 833 |  | 
|  | 834 | /* Check MAC after link sync counter */ | 
|  | 835 | if ((Istatus & IS_MAC2) != 0) { | 
|  | 836 | /* IRQ from MAC 2 */ | 
|  | 837 | SkMacIrq(pAC, IoC, MAC_2); | 
|  | 838 | } | 
|  | 839 |  | 
|  | 840 | /* Timer interrupt (served last) */ | 
|  | 841 | if ((Istatus & IS_TIMINT) != 0) { | 
|  | 842 | /* check for HW Errors */ | 
|  | 843 | if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { | 
|  | 844 | /* read the HW Error Interrupt source */ | 
|  | 845 | SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); | 
|  | 846 |  | 
|  | 847 | SkGeHwErr(pAC, IoC, RegVal32); | 
|  | 848 | } | 
|  | 849 |  | 
|  | 850 | SkHwtIsr(pAC, IoC); | 
|  | 851 | } | 
|  | 852 |  | 
|  | 853 | }	/* SkGeSirqIsr */ | 
|  | 854 |  | 
|  | 855 |  | 
|  | 856 | #ifdef GENESIS | 
|  | 857 | /****************************************************************************** | 
|  | 858 | * | 
|  | 859 | * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 | 
|  | 860 | * | 
|  | 861 | * return: | 
|  | 862 | *	0	o.k. nothing needed | 
|  | 863 | *	1	Restart needed on this port | 
|  | 864 | */ | 
|  | 865 | static int SkGePortCheckShorts( | 
|  | 866 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 867 | SK_IOC	IoC,		/* IO Context */ | 
|  | 868 | int		Port)		/* Which port should be checked */ | 
|  | 869 | { | 
|  | 870 | SK_U32		Shorts;			/* Short Event Counter */ | 
|  | 871 | SK_U32		CheckShorts;	/* Check value for Short Event Counter */ | 
|  | 872 | SK_U64		RxCts;			/* Rx Counter (packets on network) */ | 
|  | 873 | SK_U32		RxTmp;			/* Rx temp. Counter */ | 
|  | 874 | SK_U32		FcsErrCts;		/* FCS Error Counter */ | 
|  | 875 | SK_GEPORT	*pPrt;			/* GIni Port struct pointer */ | 
|  | 876 | int			Rtv;			/* Return value */ | 
|  | 877 | int			i; | 
|  | 878 |  | 
|  | 879 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 880 |  | 
|  | 881 | /* Default: no action */ | 
|  | 882 | Rtv = SK_HW_PS_NONE; | 
|  | 883 |  | 
|  | 884 | (void)SkXmUpdateStats(pAC, IoC, Port); | 
|  | 885 |  | 
|  | 886 | /* Extra precaution: check for short Event counter */ | 
|  | 887 | (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); | 
|  | 888 |  | 
|  | 889 | /* | 
|  | 890 | * Read Rx counters (packets seen on the network and not necessarily | 
|  | 891 | * really received. | 
|  | 892 | */ | 
|  | 893 | RxCts = 0; | 
|  | 894 |  | 
|  | 895 | for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) { | 
|  | 896 |  | 
|  | 897 | (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); | 
|  | 898 |  | 
|  | 899 | RxCts += (SK_U64)RxTmp; | 
|  | 900 | } | 
|  | 901 |  | 
|  | 902 | /* On default: check shorts against zero */ | 
|  | 903 | CheckShorts = 0; | 
|  | 904 |  | 
|  | 905 | /* Extra precaution on active links */ | 
|  | 906 | if (pPrt->PHWLinkUp) { | 
|  | 907 | /* Reset Link Restart counter */ | 
|  | 908 | pPrt->PLinkResCt = 0; | 
|  | 909 | pPrt->PAutoNegTOCt = 0; | 
|  | 910 |  | 
|  | 911 | /* If link is up check for 2 */ | 
|  | 912 | CheckShorts = 2; | 
|  | 913 |  | 
|  | 914 | (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); | 
|  | 915 |  | 
|  | 916 | if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && | 
|  | 917 | pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && | 
|  | 918 | (pPrt->PLinkMode == SK_LMODE_HALF || | 
|  | 919 | pPrt->PLinkMode == SK_LMODE_FULL)) { | 
|  | 920 | /* | 
|  | 921 | * This is autosensing and we are in the fallback | 
|  | 922 | * manual full/half duplex mode. | 
|  | 923 | */ | 
|  | 924 | if (RxCts == pPrt->PPrevRx) { | 
|  | 925 | /* Nothing received, restart link */ | 
|  | 926 | pPrt->PPrevFcs = FcsErrCts; | 
|  | 927 | pPrt->PPrevShorts = Shorts; | 
|  | 928 |  | 
|  | 929 | return(SK_HW_PS_RESTART); | 
|  | 930 | } | 
|  | 931 | else { | 
|  | 932 | pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; | 
|  | 933 | } | 
|  | 934 | } | 
|  | 935 |  | 
|  | 936 | if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || | 
|  | 937 | (!(FcsErrCts - pPrt->PPrevFcs))) { | 
|  | 938 | /* | 
|  | 939 | * Note: The compare with zero above has to be done the way shown, | 
|  | 940 | * otherwise the Linux driver will have a problem. | 
|  | 941 | */ | 
|  | 942 | /* | 
|  | 943 | * We received a bunch of frames or no CRC error occured on the | 
|  | 944 | * network -> ok. | 
|  | 945 | */ | 
|  | 946 | pPrt->PPrevRx = RxCts; | 
|  | 947 | pPrt->PPrevFcs = FcsErrCts; | 
|  | 948 | pPrt->PPrevShorts = Shorts; | 
|  | 949 |  | 
|  | 950 | return(SK_HW_PS_NONE); | 
|  | 951 | } | 
|  | 952 |  | 
|  | 953 | pPrt->PPrevFcs = FcsErrCts; | 
|  | 954 | } | 
|  | 955 |  | 
|  | 956 |  | 
|  | 957 | if ((Shorts - pPrt->PPrevShorts) > CheckShorts) { | 
|  | 958 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 959 | ("Short Event Count Restart Port %d \n", Port)); | 
|  | 960 | Rtv = SK_HW_PS_RESTART; | 
|  | 961 | } | 
|  | 962 |  | 
|  | 963 | pPrt->PPrevShorts = Shorts; | 
|  | 964 | pPrt->PPrevRx = RxCts; | 
|  | 965 |  | 
|  | 966 | return(Rtv); | 
|  | 967 | }	/* SkGePortCheckShorts */ | 
|  | 968 | #endif /* GENESIS */ | 
|  | 969 |  | 
|  | 970 |  | 
|  | 971 | /****************************************************************************** | 
|  | 972 | * | 
|  | 973 | * SkGePortCheckUp() - Check if the link is up | 
|  | 974 | * | 
|  | 975 | * return: | 
|  | 976 | *	0	o.k. nothing needed | 
|  | 977 | *	1	Restart needed on this port | 
|  | 978 | *	2	Link came up | 
|  | 979 | */ | 
|  | 980 | static int SkGePortCheckUp( | 
|  | 981 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 982 | SK_IOC	IoC,		/* IO Context */ | 
|  | 983 | int		Port)		/* Which port should be checked */ | 
|  | 984 | { | 
|  | 985 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 986 | SK_BOOL		AutoNeg;	/* Is Auto-negotiation used ? */ | 
|  | 987 | int			Rtv;		/* Return value */ | 
|  | 988 |  | 
|  | 989 | Rtv = SK_HW_PS_NONE; | 
|  | 990 |  | 
|  | 991 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 992 |  | 
|  | 993 | if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { | 
|  | 994 | AutoNeg = SK_FALSE; | 
|  | 995 | } | 
|  | 996 | else { | 
|  | 997 | AutoNeg = SK_TRUE; | 
|  | 998 | } | 
|  | 999 |  | 
|  | 1000 | #ifdef GENESIS | 
|  | 1001 | if (pAC->GIni.GIGenesis) { | 
|  | 1002 |  | 
|  | 1003 | switch (pPrt->PhyType) { | 
|  | 1004 |  | 
|  | 1005 | case SK_PHY_XMAC: | 
|  | 1006 | Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg); | 
|  | 1007 | break; | 
|  | 1008 | case SK_PHY_BCOM: | 
|  | 1009 | Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg); | 
|  | 1010 | break; | 
|  | 1011 | #ifdef OTHER_PHY | 
|  | 1012 | case SK_PHY_LONE: | 
|  | 1013 | Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg); | 
|  | 1014 | break; | 
|  | 1015 | case SK_PHY_NAT: | 
|  | 1016 | Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg); | 
|  | 1017 | break; | 
|  | 1018 | #endif /* OTHER_PHY */ | 
|  | 1019 | } | 
|  | 1020 | } | 
|  | 1021 | #endif /* GENESIS */ | 
|  | 1022 |  | 
|  | 1023 | #ifdef YUKON | 
|  | 1024 | if (pAC->GIni.GIYukon) { | 
|  | 1025 |  | 
|  | 1026 | Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg); | 
|  | 1027 | } | 
|  | 1028 | #endif /* YUKON */ | 
|  | 1029 |  | 
|  | 1030 | return(Rtv); | 
|  | 1031 | }	/* SkGePortCheckUp */ | 
|  | 1032 |  | 
|  | 1033 |  | 
|  | 1034 | #ifdef GENESIS | 
|  | 1035 | /****************************************************************************** | 
|  | 1036 | * | 
|  | 1037 | * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 | 
|  | 1038 | * | 
|  | 1039 | * return: | 
|  | 1040 | *	0	o.k. nothing needed | 
|  | 1041 | *	1	Restart needed on this port | 
|  | 1042 | *	2	Link came up | 
|  | 1043 | */ | 
|  | 1044 | static int SkGePortCheckUpXmac( | 
|  | 1045 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 1046 | SK_IOC	IoC,		/* IO Context */ | 
|  | 1047 | int		Port,		/* Which port should be checked */ | 
|  | 1048 | SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */ | 
|  | 1049 | { | 
|  | 1050 | SK_U32		Shorts;		/* Short Event Counter */ | 
|  | 1051 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 1052 | int			Done; | 
|  | 1053 | SK_U32		GpReg;		/* General Purpose register value */ | 
|  | 1054 | SK_U16		Isrc;		/* Interrupt source register */ | 
|  | 1055 | SK_U16		IsrcSum;	/* Interrupt source register sum */ | 
|  | 1056 | SK_U16		LpAb;		/* Link Partner Ability */ | 
|  | 1057 | SK_U16		ResAb;		/* Resolved Ability */ | 
|  | 1058 | SK_U16		ExtStat;	/* Extended Status Register */ | 
|  | 1059 | SK_U8		NextMode;	/* Next AutoSensing Mode */ | 
|  | 1060 |  | 
|  | 1061 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 1062 |  | 
|  | 1063 | if (pPrt->PHWLinkUp) { | 
|  | 1064 | if (pPrt->PhyType != SK_PHY_XMAC) { | 
|  | 1065 | return(SK_HW_PS_NONE); | 
|  | 1066 | } | 
|  | 1067 | else { | 
|  | 1068 | return(SkGePortCheckShorts(pAC, IoC, Port)); | 
|  | 1069 | } | 
|  | 1070 | } | 
|  | 1071 |  | 
|  | 1072 | IsrcSum = pPrt->PIsave; | 
|  | 1073 | pPrt->PIsave = 0; | 
|  | 1074 |  | 
|  | 1075 | /* Now wait for each port's link */ | 
|  | 1076 | if (pPrt->PLinkBroken) { | 
|  | 1077 | /* Link was broken */ | 
|  | 1078 | XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); | 
|  | 1079 |  | 
|  | 1080 | if ((GpReg & XM_GP_INP_ASS) == 0) { | 
|  | 1081 | /* The Link is in sync */ | 
|  | 1082 | XM_IN16(IoC, Port, XM_ISRC, &Isrc); | 
|  | 1083 | IsrcSum |= Isrc; | 
|  | 1084 | SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); | 
|  | 1085 |  | 
|  | 1086 | if ((Isrc & XM_IS_INP_ASS) == 0) { | 
|  | 1087 | /* It has been in sync since last time */ | 
|  | 1088 | /* Restart the PORT */ | 
|  | 1089 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1090 | ("Link in sync Restart Port %d\n", Port)); | 
|  | 1091 |  | 
|  | 1092 | (void)SkXmUpdateStats(pAC, IoC, Port); | 
|  | 1093 |  | 
|  | 1094 | /* We now need to reinitialize the PrevShorts counter */ | 
|  | 1095 | (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); | 
|  | 1096 | pPrt->PPrevShorts = Shorts; | 
|  | 1097 |  | 
|  | 1098 | pPrt->PLinkBroken = SK_FALSE; | 
|  | 1099 |  | 
|  | 1100 | /* | 
|  | 1101 | * Link Restart Workaround: | 
|  | 1102 | *  it may be possible that the other Link side | 
|  | 1103 | *  restarts its link as well an we detect | 
|  | 1104 | *  another LinkBroken. To prevent this | 
|  | 1105 | *  happening we check for a maximum number | 
|  | 1106 | *  of consecutive restart. If those happens, | 
|  | 1107 | *  we do NOT restart the active link and | 
|  | 1108 | *  check whether the link is now o.k. | 
|  | 1109 | */ | 
|  | 1110 | pPrt->PLinkResCt++; | 
|  | 1111 |  | 
|  | 1112 | pPrt->PAutoNegTimeOut = 0; | 
|  | 1113 |  | 
|  | 1114 | if (pPrt->PLinkResCt < SK_MAX_LRESTART) { | 
|  | 1115 | return(SK_HW_PS_RESTART); | 
|  | 1116 | } | 
|  | 1117 |  | 
|  | 1118 | pPrt->PLinkResCt = 0; | 
|  | 1119 |  | 
|  | 1120 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1121 | ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); | 
|  | 1122 | } | 
|  | 1123 | else { | 
|  | 1124 | pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); | 
|  | 1125 |  | 
|  | 1126 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1127 | ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); | 
|  | 1128 |  | 
|  | 1129 | /* Do nothing more if link is broken */ | 
|  | 1130 | return(SK_HW_PS_NONE); | 
|  | 1131 | } | 
|  | 1132 | } | 
|  | 1133 | else { | 
|  | 1134 | /* Do nothing more if link is broken */ | 
|  | 1135 | return(SK_HW_PS_NONE); | 
|  | 1136 | } | 
|  | 1137 |  | 
|  | 1138 | } | 
|  | 1139 | else { | 
|  | 1140 | /* Link was not broken, check if it is */ | 
|  | 1141 | XM_IN16(IoC, Port, XM_ISRC, &Isrc); | 
|  | 1142 | IsrcSum |= Isrc; | 
|  | 1143 | if ((Isrc & XM_IS_INP_ASS) != 0) { | 
|  | 1144 | XM_IN16(IoC, Port, XM_ISRC, &Isrc); | 
|  | 1145 | IsrcSum |= Isrc; | 
|  | 1146 | if ((Isrc & XM_IS_INP_ASS) != 0) { | 
|  | 1147 | XM_IN16(IoC, Port, XM_ISRC, &Isrc); | 
|  | 1148 | IsrcSum |= Isrc; | 
|  | 1149 | if ((Isrc & XM_IS_INP_ASS) != 0) { | 
|  | 1150 | pPrt->PLinkBroken = SK_TRUE; | 
|  | 1151 | /* Re-Init Link partner Autoneg flag */ | 
|  | 1152 | pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; | 
|  | 1153 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1154 | ("Link broken Port %d\n", Port)); | 
|  | 1155 |  | 
|  | 1156 | /* Cable removed-> reinit sense mode */ | 
|  | 1157 | SkHWInitDefSense(pAC, IoC, Port); | 
|  | 1158 |  | 
|  | 1159 | return(SK_HW_PS_RESTART); | 
|  | 1160 | } | 
|  | 1161 | } | 
|  | 1162 | } | 
|  | 1163 | else { | 
|  | 1164 | SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); | 
|  | 1165 |  | 
|  | 1166 | if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { | 
|  | 1167 | return(SK_HW_PS_RESTART); | 
|  | 1168 | } | 
|  | 1169 | } | 
|  | 1170 | } | 
|  | 1171 |  | 
|  | 1172 | /* | 
|  | 1173 | * here we usually can check whether the link is in sync and | 
|  | 1174 | * auto-negotiation is done. | 
|  | 1175 | */ | 
|  | 1176 | XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); | 
|  | 1177 | XM_IN16(IoC, Port, XM_ISRC, &Isrc); | 
|  | 1178 | IsrcSum |= Isrc; | 
|  | 1179 |  | 
|  | 1180 | SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); | 
|  | 1181 |  | 
|  | 1182 | if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) { | 
|  | 1183 | if ((GpReg & XM_GP_INP_ASS) == 0) { | 
|  | 1184 | /* Save Auto-negotiation Done interrupt only if link is in sync */ | 
|  | 1185 | pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); | 
|  | 1186 | } | 
|  | 1187 | #ifdef DEBUG | 
|  | 1188 | if ((pPrt->PIsave & XM_IS_AND) != 0) { | 
|  | 1189 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1190 | ("AutoNeg done rescheduled Port %d\n", Port)); | 
|  | 1191 | } | 
|  | 1192 | #endif /* DEBUG */ | 
|  | 1193 | return(SK_HW_PS_NONE); | 
|  | 1194 | } | 
|  | 1195 |  | 
|  | 1196 | if (AutoNeg) { | 
|  | 1197 | if ((IsrcSum & XM_IS_AND) != 0) { | 
|  | 1198 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1199 | Done = SkMacAutoNegDone(pAC, IoC, Port); | 
|  | 1200 | if (Done != SK_AND_OK) { | 
|  | 1201 | /* Get PHY parameters, for debugging only */ | 
|  | 1202 | SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb); | 
|  | 1203 | SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); | 
|  | 1204 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1205 | ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", | 
|  | 1206 | Port, LpAb, ResAb)); | 
|  | 1207 |  | 
|  | 1208 | /* Try next possible mode */ | 
|  | 1209 | NextMode = SkHWSenseGetNext(pAC, IoC, Port); | 
|  | 1210 | SkHWLinkDown(pAC, IoC, Port); | 
|  | 1211 | if (Done == SK_AND_DUP_CAP) { | 
|  | 1212 | /* GoTo next mode */ | 
|  | 1213 | SkHWSenseSetNext(pAC, IoC, Port, NextMode); | 
|  | 1214 | } | 
|  | 1215 |  | 
|  | 1216 | return(SK_HW_PS_RESTART); | 
|  | 1217 | } | 
|  | 1218 | /* | 
|  | 1219 | * Dummy Read extended status to prevent extra link down/ups | 
|  | 1220 | * (clear Page Received bit if set) | 
|  | 1221 | */ | 
|  | 1222 | SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); | 
|  | 1223 |  | 
|  | 1224 | return(SK_HW_PS_LINK); | 
|  | 1225 | } | 
|  | 1226 |  | 
|  | 1227 | /* AutoNeg not done, but HW link is up. Check for timeouts */ | 
|  | 1228 | pPrt->PAutoNegTimeOut++; | 
|  | 1229 | if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { | 
|  | 1230 | /* Increase the Timeout counter */ | 
|  | 1231 | pPrt->PAutoNegTOCt++; | 
|  | 1232 |  | 
|  | 1233 | /* Timeout occured */ | 
|  | 1234 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1235 | ("AutoNeg timeout Port %d\n", Port)); | 
|  | 1236 | if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && | 
|  | 1237 | pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { | 
|  | 1238 | /* Set Link manually up */ | 
|  | 1239 | SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); | 
|  | 1240 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1241 | ("Set manual full duplex Port %d\n", Port)); | 
|  | 1242 | } | 
|  | 1243 |  | 
|  | 1244 | if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && | 
|  | 1245 | pPrt->PLipaAutoNeg == SK_LIPA_AUTO && | 
|  | 1246 | pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { | 
|  | 1247 | /* | 
|  | 1248 | * This is rather complicated. | 
|  | 1249 | * we need to check here whether the LIPA_AUTO | 
|  | 1250 | * we saw before is false alert. We saw at one | 
|  | 1251 | * switch ( SR8800) that on boot time it sends | 
|  | 1252 | * just one auto-neg packet and does no further | 
|  | 1253 | * auto-negotiation. | 
|  | 1254 | * Solution: we restart the autosensing after | 
|  | 1255 | * a few timeouts. | 
|  | 1256 | */ | 
|  | 1257 | pPrt->PAutoNegTOCt = 0; | 
|  | 1258 | pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; | 
|  | 1259 | SkHWInitDefSense(pAC, IoC, Port); | 
|  | 1260 | } | 
|  | 1261 |  | 
|  | 1262 | /* Do the restart */ | 
|  | 1263 | return(SK_HW_PS_RESTART); | 
|  | 1264 | } | 
|  | 1265 | } | 
|  | 1266 | else { | 
|  | 1267 | /* Link is up and we don't need more */ | 
|  | 1268 | #ifdef DEBUG | 
|  | 1269 | if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { | 
|  | 1270 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1271 | ("ERROR: Lipa auto detected on port %d\n", Port)); | 
|  | 1272 | } | 
|  | 1273 | #endif /* DEBUG */ | 
|  | 1274 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1275 | ("Link sync(GP), Port %d\n", Port)); | 
|  | 1276 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1277 |  | 
|  | 1278 | /* | 
|  | 1279 | * Link sync (GP) and so assume a good connection. But if not received | 
|  | 1280 | * a bunch of frames received in a time slot (maybe broken tx cable) | 
|  | 1281 | * the port is restart. | 
|  | 1282 | */ | 
|  | 1283 | return(SK_HW_PS_LINK); | 
|  | 1284 | } | 
|  | 1285 |  | 
|  | 1286 | return(SK_HW_PS_NONE); | 
|  | 1287 | }	/* SkGePortCheckUpXmac */ | 
|  | 1288 |  | 
|  | 1289 |  | 
|  | 1290 | /****************************************************************************** | 
|  | 1291 | * | 
|  | 1292 | * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY | 
|  | 1293 | * | 
|  | 1294 | * return: | 
|  | 1295 | *	0	o.k. nothing needed | 
|  | 1296 | *	1	Restart needed on this port | 
|  | 1297 | *	2	Link came up | 
|  | 1298 | */ | 
|  | 1299 | static int SkGePortCheckUpBcom( | 
|  | 1300 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 1301 | SK_IOC	IoC,		/* IO Context */ | 
|  | 1302 | int		Port,		/* Which port should be checked */ | 
|  | 1303 | SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */ | 
|  | 1304 | { | 
|  | 1305 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 1306 | int			Done; | 
|  | 1307 | SK_U16		Isrc;		/* Interrupt source register */ | 
|  | 1308 | SK_U16		PhyStat;	/* Phy Status Register */ | 
|  | 1309 | SK_U16		ResAb;		/* Master/Slave resolution */ | 
|  | 1310 | SK_U16		Ctrl;		/* Broadcom control flags */ | 
|  | 1311 | #ifdef DEBUG | 
|  | 1312 | SK_U16		LpAb; | 
|  | 1313 | SK_U16		ExtStat; | 
|  | 1314 | #endif /* DEBUG */ | 
|  | 1315 |  | 
|  | 1316 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 1317 |  | 
|  | 1318 | /* Check for No HCD Link events (#10523) */ | 
|  | 1319 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); | 
|  | 1320 |  | 
|  | 1321 | #ifdef xDEBUG | 
|  | 1322 | if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) == | 
|  | 1323 | (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { | 
|  | 1324 |  | 
|  | 1325 | SK_U32	Stat1, Stat2, Stat3; | 
|  | 1326 |  | 
|  | 1327 | Stat1 = 0; | 
|  | 1328 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); | 
|  | 1329 | CMSMPrintString( | 
|  | 1330 | pAC->pConfigTable, | 
|  | 1331 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1332 | "CheckUp1 - Stat: %x, Mask: %x", | 
|  | 1333 | (void *)Isrc, | 
|  | 1334 | (void *)Stat1); | 
|  | 1335 |  | 
|  | 1336 | Stat1 = 0; | 
|  | 1337 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); | 
|  | 1338 | Stat2 = 0; | 
|  | 1339 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2); | 
|  | 1340 | Stat1 = Stat1 << 16 | Stat2; | 
|  | 1341 | Stat2 = 0; | 
|  | 1342 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); | 
|  | 1343 | Stat3 = 0; | 
|  | 1344 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); | 
|  | 1345 | Stat2 = Stat2 << 16 | Stat3; | 
|  | 1346 | CMSMPrintString( | 
|  | 1347 | pAC->pConfigTable, | 
|  | 1348 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1349 | "Ctrl/Stat: %x, AN Adv/LP: %x", | 
|  | 1350 | (void *)Stat1, | 
|  | 1351 | (void *)Stat2); | 
|  | 1352 |  | 
|  | 1353 | Stat1 = 0; | 
|  | 1354 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); | 
|  | 1355 | Stat2 = 0; | 
|  | 1356 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); | 
|  | 1357 | Stat1 = Stat1 << 16 | Stat2; | 
|  | 1358 | Stat2 = 0; | 
|  | 1359 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); | 
|  | 1360 | Stat3 = 0; | 
|  | 1361 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3); | 
|  | 1362 | Stat2 = Stat2 << 16 | Stat3; | 
|  | 1363 | CMSMPrintString( | 
|  | 1364 | pAC->pConfigTable, | 
|  | 1365 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1366 | "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", | 
|  | 1367 | (void *)Stat1, | 
|  | 1368 | (void *)Stat2); | 
|  | 1369 |  | 
|  | 1370 | Stat1 = 0; | 
|  | 1371 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); | 
|  | 1372 | Stat2 = 0; | 
|  | 1373 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); | 
|  | 1374 | Stat1 = Stat1 << 16 | Stat2; | 
|  | 1375 | Stat2 = 0; | 
|  | 1376 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); | 
|  | 1377 | Stat3 = 0; | 
|  | 1378 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); | 
|  | 1379 | Stat2 = Stat2 << 16 | Stat3; | 
|  | 1380 | CMSMPrintString( | 
|  | 1381 | pAC->pConfigTable, | 
|  | 1382 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1383 | "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", | 
|  | 1384 | (void *)Stat1, | 
|  | 1385 | (void *)Stat2); | 
|  | 1386 | } | 
|  | 1387 | #endif /* DEBUG */ | 
|  | 1388 |  | 
|  | 1389 | if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { | 
|  | 1390 | /* | 
|  | 1391 | * Workaround BCom Errata: | 
|  | 1392 | *	enable and disable loopback mode if "NO HCD" occurs. | 
|  | 1393 | */ | 
|  | 1394 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl); | 
|  | 1395 | SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, | 
|  | 1396 | (SK_U16)(Ctrl | PHY_CT_LOOP)); | 
|  | 1397 | SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, | 
|  | 1398 | (SK_U16)(Ctrl & ~PHY_CT_LOOP)); | 
|  | 1399 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1400 | ("No HCD Link event, Port %d\n", Port)); | 
|  | 1401 | #ifdef xDEBUG | 
|  | 1402 | CMSMPrintString( | 
|  | 1403 | pAC->pConfigTable, | 
|  | 1404 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1405 | "No HCD link event, port %d.", | 
|  | 1406 | (void *)Port, | 
|  | 1407 | (void *)NULL); | 
|  | 1408 | #endif /* DEBUG */ | 
|  | 1409 | } | 
|  | 1410 |  | 
|  | 1411 | /* Not obsolete: link status bit is latched to 0 and autoclearing! */ | 
|  | 1412 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); | 
|  | 1413 |  | 
|  | 1414 | if (pPrt->PHWLinkUp) { | 
|  | 1415 | return(SK_HW_PS_NONE); | 
|  | 1416 | } | 
|  | 1417 |  | 
|  | 1418 | #ifdef xDEBUG | 
|  | 1419 | { | 
|  | 1420 | SK_U32	Stat1, Stat2, Stat3; | 
|  | 1421 |  | 
|  | 1422 | Stat1 = 0; | 
|  | 1423 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); | 
|  | 1424 | CMSMPrintString( | 
|  | 1425 | pAC->pConfigTable, | 
|  | 1426 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1427 | "CheckUp1a - Stat: %x, Mask: %x", | 
|  | 1428 | (void *)Isrc, | 
|  | 1429 | (void *)Stat1); | 
|  | 1430 |  | 
|  | 1431 | Stat1 = 0; | 
|  | 1432 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); | 
|  | 1433 | Stat2 = 0; | 
|  | 1434 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); | 
|  | 1435 | Stat1 = Stat1 << 16 | PhyStat; | 
|  | 1436 | Stat2 = 0; | 
|  | 1437 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); | 
|  | 1438 | Stat3 = 0; | 
|  | 1439 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); | 
|  | 1440 | Stat2 = Stat2 << 16 | Stat3; | 
|  | 1441 | CMSMPrintString( | 
|  | 1442 | pAC->pConfigTable, | 
|  | 1443 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1444 | "Ctrl/Stat: %x, AN Adv/LP: %x", | 
|  | 1445 | (void *)Stat1, | 
|  | 1446 | (void *)Stat2); | 
|  | 1447 |  | 
|  | 1448 | Stat1 = 0; | 
|  | 1449 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); | 
|  | 1450 | Stat2 = 0; | 
|  | 1451 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); | 
|  | 1452 | Stat1 = Stat1 << 16 | Stat2; | 
|  | 1453 | Stat2 = 0; | 
|  | 1454 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); | 
|  | 1455 | Stat3 = 0; | 
|  | 1456 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); | 
|  | 1457 | Stat2 = Stat2 << 16 | ResAb; | 
|  | 1458 | CMSMPrintString( | 
|  | 1459 | pAC->pConfigTable, | 
|  | 1460 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1461 | "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", | 
|  | 1462 | (void *)Stat1, | 
|  | 1463 | (void *)Stat2); | 
|  | 1464 |  | 
|  | 1465 | Stat1 = 0; | 
|  | 1466 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); | 
|  | 1467 | Stat2 = 0; | 
|  | 1468 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); | 
|  | 1469 | Stat1 = Stat1 << 16 | Stat2; | 
|  | 1470 | Stat2 = 0; | 
|  | 1471 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); | 
|  | 1472 | Stat3 = 0; | 
|  | 1473 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); | 
|  | 1474 | Stat2 = Stat2 << 16 | Stat3; | 
|  | 1475 | CMSMPrintString( | 
|  | 1476 | pAC->pConfigTable, | 
|  | 1477 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1478 | "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", | 
|  | 1479 | (void *)Stat1, | 
|  | 1480 | (void *)Stat2); | 
|  | 1481 | } | 
|  | 1482 | #endif /* DEBUG */ | 
|  | 1483 |  | 
|  | 1484 | /* | 
|  | 1485 | * Here we usually can check whether the link is in sync and | 
|  | 1486 | * auto-negotiation is done. | 
|  | 1487 | */ | 
|  | 1488 |  | 
|  | 1489 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); | 
|  | 1490 |  | 
|  | 1491 | SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); | 
|  | 1492 |  | 
|  | 1493 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1494 | ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); | 
|  | 1495 |  | 
|  | 1496 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); | 
|  | 1497 |  | 
|  | 1498 | if ((ResAb & PHY_B_1000S_MSF) != 0) { | 
|  | 1499 | /* Error */ | 
|  | 1500 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1501 | ("Master/Slave Fault port %d\n", Port)); | 
|  | 1502 |  | 
|  | 1503 | pPrt->PAutoNegFail = SK_TRUE; | 
|  | 1504 | pPrt->PMSStatus = SK_MS_STAT_FAULT; | 
|  | 1505 |  | 
|  | 1506 | return(SK_HW_PS_RESTART); | 
|  | 1507 | } | 
|  | 1508 |  | 
|  | 1509 | if ((PhyStat & PHY_ST_LSYNC) == 0) { | 
|  | 1510 | return(SK_HW_PS_NONE); | 
|  | 1511 | } | 
|  | 1512 |  | 
|  | 1513 | pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? | 
|  | 1514 | SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; | 
|  | 1515 |  | 
|  | 1516 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1517 | ("Port %d, ResAb: 0x%04X\n", Port, ResAb)); | 
|  | 1518 |  | 
|  | 1519 | if (AutoNeg) { | 
|  | 1520 | if ((PhyStat & PHY_ST_AN_OVER) != 0) { | 
|  | 1521 |  | 
|  | 1522 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1523 |  | 
|  | 1524 | Done = SkMacAutoNegDone(pAC, IoC, Port); | 
|  | 1525 |  | 
|  | 1526 | if (Done != SK_AND_OK) { | 
|  | 1527 | #ifdef DEBUG | 
|  | 1528 | /* Get PHY parameters, for debugging only */ | 
|  | 1529 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); | 
|  | 1530 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); | 
|  | 1531 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1532 | ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", | 
|  | 1533 | Port, LpAb, ExtStat)); | 
|  | 1534 | #endif /* DEBUG */ | 
|  | 1535 | return(SK_HW_PS_RESTART); | 
|  | 1536 | } | 
|  | 1537 | else { | 
|  | 1538 | #ifdef xDEBUG | 
|  | 1539 | /* Dummy read ISR to prevent extra link downs/ups */ | 
|  | 1540 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); | 
|  | 1541 |  | 
|  | 1542 | if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { | 
|  | 1543 | CMSMPrintString( | 
|  | 1544 | pAC->pConfigTable, | 
|  | 1545 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1546 | "CheckUp2 - Stat: %x", | 
|  | 1547 | (void *)ExtStat, | 
|  | 1548 | (void *)NULL); | 
|  | 1549 | } | 
|  | 1550 | #endif /* DEBUG */ | 
|  | 1551 | return(SK_HW_PS_LINK); | 
|  | 1552 | } | 
|  | 1553 | } | 
|  | 1554 | } | 
|  | 1555 | else {	/* !AutoNeg */ | 
|  | 1556 | /* Link is up and we don't need more. */ | 
|  | 1557 | #ifdef DEBUG | 
|  | 1558 | if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { | 
|  | 1559 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1560 | ("ERROR: Lipa auto detected on port %d\n", Port)); | 
|  | 1561 | } | 
|  | 1562 | #endif /* DEBUG */ | 
|  | 1563 |  | 
|  | 1564 | #ifdef xDEBUG | 
|  | 1565 | /* Dummy read ISR to prevent extra link downs/ups */ | 
|  | 1566 | SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); | 
|  | 1567 |  | 
|  | 1568 | if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { | 
|  | 1569 | CMSMPrintString( | 
|  | 1570 | pAC->pConfigTable, | 
|  | 1571 | MSG_TYPE_RUNTIME_INFO, | 
|  | 1572 | "CheckUp3 - Stat: %x", | 
|  | 1573 | (void *)ExtStat, | 
|  | 1574 | (void *)NULL); | 
|  | 1575 | } | 
|  | 1576 | #endif /* DEBUG */ | 
|  | 1577 |  | 
|  | 1578 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1579 | ("Link sync(GP), Port %d\n", Port)); | 
|  | 1580 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1581 |  | 
|  | 1582 | return(SK_HW_PS_LINK); | 
|  | 1583 | } | 
|  | 1584 |  | 
|  | 1585 | return(SK_HW_PS_NONE); | 
|  | 1586 | }	/* SkGePortCheckUpBcom */ | 
|  | 1587 | #endif /* GENESIS */ | 
|  | 1588 |  | 
|  | 1589 |  | 
|  | 1590 | #ifdef YUKON | 
|  | 1591 | /****************************************************************************** | 
|  | 1592 | * | 
|  | 1593 | * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY | 
|  | 1594 | * | 
|  | 1595 | * return: | 
|  | 1596 | *	0	o.k. nothing needed | 
|  | 1597 | *	1	Restart needed on this port | 
|  | 1598 | *	2	Link came up | 
|  | 1599 | */ | 
|  | 1600 | static int SkGePortCheckUpGmac( | 
|  | 1601 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 1602 | SK_IOC	IoC,		/* IO Context */ | 
|  | 1603 | int		Port,		/* Which port should be checked */ | 
|  | 1604 | SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */ | 
|  | 1605 | { | 
|  | 1606 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 1607 | int			Done; | 
|  | 1608 | SK_U16		PhyIsrc;	/* PHY Interrupt source */ | 
|  | 1609 | SK_U16		PhyStat;	/* PPY Status */ | 
|  | 1610 | SK_U16		PhySpecStat;/* PHY Specific Status */ | 
|  | 1611 | SK_U16		ResAb;		/* Master/Slave resolution */ | 
|  | 1612 | SK_EVPARA	Para; | 
|  | 1613 | #ifdef DEBUG | 
|  | 1614 | SK_U16		Word;		/* I/O helper */ | 
|  | 1615 | #endif /* DEBUG */ | 
|  | 1616 |  | 
|  | 1617 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 1618 |  | 
|  | 1619 | if (pPrt->PHWLinkUp) { | 
|  | 1620 | return(SK_HW_PS_NONE); | 
|  | 1621 | } | 
|  | 1622 |  | 
|  | 1623 | /* Read PHY Status */ | 
|  | 1624 | SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); | 
|  | 1625 |  | 
|  | 1626 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1627 | ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); | 
|  | 1628 |  | 
|  | 1629 | /* Read PHY Interrupt Status */ | 
|  | 1630 | SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc); | 
|  | 1631 |  | 
|  | 1632 | if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) { | 
|  | 1633 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1634 | ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc)); | 
|  | 1635 | } | 
|  | 1636 |  | 
|  | 1637 | if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) { | 
|  | 1638 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1639 | ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc)); | 
|  | 1640 | } | 
|  | 1641 |  | 
|  | 1642 | SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); | 
|  | 1643 |  | 
|  | 1644 | SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); | 
|  | 1645 |  | 
|  | 1646 | if ((ResAb & PHY_B_1000S_MSF) != 0) { | 
|  | 1647 | /* Error */ | 
|  | 1648 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1649 | ("Master/Slave Fault port %d\n", Port)); | 
|  | 1650 |  | 
|  | 1651 | pPrt->PAutoNegFail = SK_TRUE; | 
|  | 1652 | pPrt->PMSStatus = SK_MS_STAT_FAULT; | 
|  | 1653 |  | 
|  | 1654 | return(SK_HW_PS_RESTART); | 
|  | 1655 | } | 
|  | 1656 |  | 
|  | 1657 | /* Read PHY Specific Status */ | 
|  | 1658 | SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); | 
|  | 1659 |  | 
|  | 1660 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1661 | ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat)); | 
|  | 1662 |  | 
|  | 1663 | #ifdef DEBUG | 
|  | 1664 | SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word); | 
|  | 1665 |  | 
|  | 1666 | if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 || | 
|  | 1667 | (PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  { | 
|  | 1668 | /* Read PHY Next Page Link Partner */ | 
|  | 1669 | SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word); | 
|  | 1670 |  | 
|  | 1671 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1672 | ("Page Received, NextPage: 0x%04X\n", Word)); | 
|  | 1673 | } | 
|  | 1674 | #endif /* DEBUG */ | 
|  | 1675 |  | 
|  | 1676 | if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { | 
|  | 1677 | return(SK_HW_PS_NONE); | 
|  | 1678 | } | 
|  | 1679 |  | 
|  | 1680 | if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 || | 
|  | 1681 | (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) { | 
|  | 1682 | /* Downshift detected */ | 
|  | 1683 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG); | 
|  | 1684 |  | 
|  | 1685 | Para.Para64 = Port; | 
|  | 1686 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para); | 
|  | 1687 |  | 
|  | 1688 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1689 | ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc)); | 
|  | 1690 | } | 
|  | 1691 |  | 
|  | 1692 | pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? | 
|  | 1693 | SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; | 
|  | 1694 |  | 
|  | 1695 | pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); | 
|  | 1696 |  | 
|  | 1697 | if (AutoNeg) { | 
|  | 1698 | /* Auto-Negotiation Over ? */ | 
|  | 1699 | if ((PhyStat & PHY_ST_AN_OVER) != 0) { | 
|  | 1700 |  | 
|  | 1701 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1702 |  | 
|  | 1703 | Done = SkMacAutoNegDone(pAC, IoC, Port); | 
|  | 1704 |  | 
|  | 1705 | if (Done != SK_AND_OK) { | 
|  | 1706 | return(SK_HW_PS_RESTART); | 
|  | 1707 | } | 
|  | 1708 |  | 
|  | 1709 | return(SK_HW_PS_LINK); | 
|  | 1710 | } | 
|  | 1711 | } | 
|  | 1712 | else {	/* !AutoNeg */ | 
|  | 1713 | /* Link is up and we don't need more */ | 
|  | 1714 | #ifdef DEBUG | 
|  | 1715 | if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { | 
|  | 1716 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1717 | ("ERROR: Lipa auto detected on port %d\n", Port)); | 
|  | 1718 | } | 
|  | 1719 | #endif /* DEBUG */ | 
|  | 1720 |  | 
|  | 1721 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1722 | ("Link sync, Port %d\n", Port)); | 
|  | 1723 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1724 |  | 
|  | 1725 | return(SK_HW_PS_LINK); | 
|  | 1726 | } | 
|  | 1727 |  | 
|  | 1728 | return(SK_HW_PS_NONE); | 
|  | 1729 | }	/* SkGePortCheckUpGmac */ | 
|  | 1730 | #endif /* YUKON */ | 
|  | 1731 |  | 
|  | 1732 |  | 
|  | 1733 | #ifdef OTHER_PHY | 
|  | 1734 | /****************************************************************************** | 
|  | 1735 | * | 
|  | 1736 | * SkGePortCheckUpLone() - Check if the link is up on Level One PHY | 
|  | 1737 | * | 
|  | 1738 | * return: | 
|  | 1739 | *	0	o.k. nothing needed | 
|  | 1740 | *	1	Restart needed on this port | 
|  | 1741 | *	2	Link came up | 
|  | 1742 | */ | 
|  | 1743 | static int SkGePortCheckUpLone( | 
|  | 1744 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 1745 | SK_IOC	IoC,		/* IO Context */ | 
|  | 1746 | int		Port,		/* Which port should be checked */ | 
|  | 1747 | SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */ | 
|  | 1748 | { | 
|  | 1749 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 1750 | int			Done; | 
|  | 1751 | SK_U16		Isrc;		/* Interrupt source register */ | 
|  | 1752 | SK_U16		LpAb;		/* Link Partner Ability */ | 
|  | 1753 | SK_U16		ExtStat;	/* Extended Status Register */ | 
|  | 1754 | SK_U16		PhyStat;	/* Phy Status Register */ | 
|  | 1755 | SK_U16		StatSum; | 
|  | 1756 | SK_U8		NextMode;	/* Next AutoSensing Mode */ | 
|  | 1757 |  | 
|  | 1758 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 1759 |  | 
|  | 1760 | if (pPrt->PHWLinkUp) { | 
|  | 1761 | return(SK_HW_PS_NONE); | 
|  | 1762 | } | 
|  | 1763 |  | 
|  | 1764 | StatSum = pPrt->PIsave; | 
|  | 1765 | pPrt->PIsave = 0; | 
|  | 1766 |  | 
|  | 1767 | /* | 
|  | 1768 | * here we usually can check whether the link is in sync and | 
|  | 1769 | * auto-negotiation is done. | 
|  | 1770 | */ | 
|  | 1771 | SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat); | 
|  | 1772 | StatSum |= PhyStat; | 
|  | 1773 |  | 
|  | 1774 | SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); | 
|  | 1775 |  | 
|  | 1776 | if ((PhyStat & PHY_ST_LSYNC) == 0) { | 
|  | 1777 | /* Save Auto-negotiation Done bit */ | 
|  | 1778 | pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER); | 
|  | 1779 | #ifdef DEBUG | 
|  | 1780 | if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) { | 
|  | 1781 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1782 | ("AutoNeg done rescheduled Port %d\n", Port)); | 
|  | 1783 | } | 
|  | 1784 | #endif /* DEBUG */ | 
|  | 1785 | return(SK_HW_PS_NONE); | 
|  | 1786 | } | 
|  | 1787 |  | 
|  | 1788 | if (AutoNeg) { | 
|  | 1789 | if ((StatSum & PHY_ST_AN_OVER) != 0) { | 
|  | 1790 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1791 | Done = SkMacAutoNegDone(pAC, IoC, Port); | 
|  | 1792 | if (Done != SK_AND_OK) { | 
|  | 1793 | /* Get PHY parameters, for debugging only */ | 
|  | 1794 | SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); | 
|  | 1795 | SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat); | 
|  | 1796 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1797 | ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", | 
|  | 1798 | Port, LpAb, ExtStat)); | 
|  | 1799 |  | 
|  | 1800 | /* Try next possible mode */ | 
|  | 1801 | NextMode = SkHWSenseGetNext(pAC, IoC, Port); | 
|  | 1802 | SkHWLinkDown(pAC, IoC, Port); | 
|  | 1803 | if (Done == SK_AND_DUP_CAP) { | 
|  | 1804 | /* GoTo next mode */ | 
|  | 1805 | SkHWSenseSetNext(pAC, IoC, Port, NextMode); | 
|  | 1806 | } | 
|  | 1807 |  | 
|  | 1808 | return(SK_HW_PS_RESTART); | 
|  | 1809 |  | 
|  | 1810 | } | 
|  | 1811 | else { | 
|  | 1812 | /* | 
|  | 1813 | * Dummy Read interrupt status to prevent | 
|  | 1814 | * extra link down/ups | 
|  | 1815 | */ | 
|  | 1816 | SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); | 
|  | 1817 | return(SK_HW_PS_LINK); | 
|  | 1818 | } | 
|  | 1819 | } | 
|  | 1820 |  | 
|  | 1821 | /* AutoNeg not done, but HW link is up. Check for timeouts */ | 
|  | 1822 | pPrt->PAutoNegTimeOut++; | 
|  | 1823 | if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { | 
|  | 1824 | /* Timeout occured */ | 
|  | 1825 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1826 | ("AutoNeg timeout Port %d\n", Port)); | 
|  | 1827 | if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && | 
|  | 1828 | pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { | 
|  | 1829 | /* Set Link manually up */ | 
|  | 1830 | SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); | 
|  | 1831 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1832 | ("Set manual full duplex Port %d\n", Port)); | 
|  | 1833 | } | 
|  | 1834 |  | 
|  | 1835 | /* Do the restart */ | 
|  | 1836 | return(SK_HW_PS_RESTART); | 
|  | 1837 | } | 
|  | 1838 | } | 
|  | 1839 | else { | 
|  | 1840 | /* Link is up and we don't need more */ | 
|  | 1841 | #ifdef DEBUG | 
|  | 1842 | if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { | 
|  | 1843 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 1844 | ("ERROR: Lipa auto detected on port %d\n", Port)); | 
|  | 1845 | } | 
|  | 1846 | #endif /* DEBUG */ | 
|  | 1847 |  | 
|  | 1848 | /* | 
|  | 1849 | * Dummy Read interrupt status to prevent | 
|  | 1850 | * extra link down/ups | 
|  | 1851 | */ | 
|  | 1852 | SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); | 
|  | 1853 |  | 
|  | 1854 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, | 
|  | 1855 | ("Link sync(GP), Port %d\n", Port)); | 
|  | 1856 | SkHWLinkUp(pAC, IoC, Port); | 
|  | 1857 |  | 
|  | 1858 | return(SK_HW_PS_LINK); | 
|  | 1859 | } | 
|  | 1860 |  | 
|  | 1861 | return(SK_HW_PS_NONE); | 
|  | 1862 | }	/* SkGePortCheckUpLone */ | 
|  | 1863 |  | 
|  | 1864 |  | 
|  | 1865 | /****************************************************************************** | 
|  | 1866 | * | 
|  | 1867 | * SkGePortCheckUpNat() - Check if the link is up on National PHY | 
|  | 1868 | * | 
|  | 1869 | * return: | 
|  | 1870 | *	0	o.k. nothing needed | 
|  | 1871 | *	1	Restart needed on this port | 
|  | 1872 | *	2	Link came up | 
|  | 1873 | */ | 
|  | 1874 | static int SkGePortCheckUpNat( | 
|  | 1875 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 1876 | SK_IOC	IoC,		/* IO Context */ | 
|  | 1877 | int		Port,		/* Which port should be checked */ | 
|  | 1878 | SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */ | 
|  | 1879 | { | 
|  | 1880 | /* todo: National */ | 
|  | 1881 | return(SK_HW_PS_NONE); | 
|  | 1882 | }	/* SkGePortCheckUpNat */ | 
|  | 1883 | #endif /* OTHER_PHY */ | 
|  | 1884 |  | 
|  | 1885 |  | 
|  | 1886 | /****************************************************************************** | 
|  | 1887 | * | 
|  | 1888 | *	SkGeSirqEvent() - Event Service Routine | 
|  | 1889 | * | 
|  | 1890 | * Description: | 
|  | 1891 | * | 
|  | 1892 | * Notes: | 
|  | 1893 | */ | 
|  | 1894 | int	SkGeSirqEvent( | 
|  | 1895 | SK_AC		*pAC,		/* Adapter Context */ | 
|  | 1896 | SK_IOC		IoC,		/* Io Context */ | 
|  | 1897 | SK_U32		Event,		/* Module specific Event */ | 
|  | 1898 | SK_EVPARA	Para)		/* Event specific Parameter */ | 
|  | 1899 | { | 
|  | 1900 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 1901 | SK_U32		Port; | 
|  | 1902 | SK_U32		Val32; | 
|  | 1903 | int			PortStat; | 
|  | 1904 | SK_U8		Val8; | 
|  | 1905 | #ifdef GENESIS | 
|  | 1906 | SK_U64		Octets; | 
|  | 1907 | #endif /* GENESIS */ | 
|  | 1908 |  | 
|  | 1909 | Port = Para.Para32[0]; | 
|  | 1910 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 1911 |  | 
|  | 1912 | switch (Event) { | 
|  | 1913 | case SK_HWEV_WATIM: | 
|  | 1914 | if (pPrt->PState == SK_PRT_RESET) { | 
|  | 1915 |  | 
|  | 1916 | PortStat = SK_HW_PS_NONE; | 
|  | 1917 | } | 
|  | 1918 | else { | 
|  | 1919 | /* Check whether port came up */ | 
|  | 1920 | PortStat = SkGePortCheckUp(pAC, IoC, (int)Port); | 
|  | 1921 | } | 
|  | 1922 |  | 
|  | 1923 | switch (PortStat) { | 
|  | 1924 | case SK_HW_PS_RESTART: | 
|  | 1925 | if (pPrt->PHWLinkUp) { | 
|  | 1926 | /* Set Link to down */ | 
|  | 1927 | SkHWLinkDown(pAC, IoC, (int)Port); | 
|  | 1928 |  | 
|  | 1929 | /* | 
|  | 1930 | * Signal directly to RLMT to ensure correct | 
|  | 1931 | * sequence of SWITCH and RESET event. | 
|  | 1932 | */ | 
|  | 1933 | SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); | 
|  | 1934 | } | 
|  | 1935 |  | 
|  | 1936 | /* Restart needed */ | 
|  | 1937 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); | 
|  | 1938 | break; | 
|  | 1939 |  | 
|  | 1940 | case SK_HW_PS_LINK: | 
|  | 1941 | /* Signal to RLMT */ | 
|  | 1942 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); | 
|  | 1943 | break; | 
|  | 1944 | } | 
|  | 1945 |  | 
|  | 1946 | /* Start again the check Timer */ | 
|  | 1947 | if (pPrt->PHWLinkUp) { | 
|  | 1948 | Val32 = SK_WA_ACT_TIME; | 
|  | 1949 | } | 
|  | 1950 | else { | 
|  | 1951 | Val32 = SK_WA_INA_TIME; | 
|  | 1952 | } | 
|  | 1953 |  | 
|  | 1954 | /* Todo: still needed for non-XMAC PHYs??? */ | 
|  | 1955 | /* Start workaround Errata #2 timer */ | 
|  | 1956 | SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32, | 
|  | 1957 | SKGE_HWAC, SK_HWEV_WATIM, Para); | 
|  | 1958 | break; | 
|  | 1959 |  | 
|  | 1960 | case SK_HWEV_PORT_START: | 
|  | 1961 | if (pPrt->PHWLinkUp) { | 
|  | 1962 | /* | 
|  | 1963 | * Signal directly to RLMT to ensure correct | 
|  | 1964 | * sequence of SWITCH and RESET event. | 
|  | 1965 | */ | 
|  | 1966 | SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); | 
|  | 1967 | } | 
|  | 1968 |  | 
|  | 1969 | SkHWLinkDown(pAC, IoC, (int)Port); | 
|  | 1970 |  | 
|  | 1971 | /* Schedule Port RESET */ | 
|  | 1972 | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); | 
|  | 1973 |  | 
|  | 1974 | /* Start workaround Errata #2 timer */ | 
|  | 1975 | SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, | 
|  | 1976 | SKGE_HWAC, SK_HWEV_WATIM, Para); | 
|  | 1977 | break; | 
|  | 1978 |  | 
|  | 1979 | case SK_HWEV_PORT_STOP: | 
|  | 1980 | if (pPrt->PHWLinkUp) { | 
|  | 1981 | /* | 
|  | 1982 | * Signal directly to RLMT to ensure correct | 
|  | 1983 | * sequence of SWITCH and RESET event. | 
|  | 1984 | */ | 
|  | 1985 | SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); | 
|  | 1986 | } | 
|  | 1987 |  | 
|  | 1988 | /* Stop Workaround Timer */ | 
|  | 1989 | SkTimerStop(pAC, IoC, &pPrt->PWaTimer); | 
|  | 1990 |  | 
|  | 1991 | SkHWLinkDown(pAC, IoC, (int)Port); | 
|  | 1992 | break; | 
|  | 1993 |  | 
|  | 1994 | case SK_HWEV_UPDATE_STAT: | 
|  | 1995 | /* We do NOT need to update any statistics */ | 
|  | 1996 | break; | 
|  | 1997 |  | 
|  | 1998 | case SK_HWEV_CLEAR_STAT: | 
|  | 1999 | /* We do NOT need to clear any statistics */ | 
|  | 2000 | for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) { | 
|  | 2001 | pPrt->PPrevRx = 0; | 
|  | 2002 | pPrt->PPrevFcs = 0; | 
|  | 2003 | pPrt->PPrevShorts = 0; | 
|  | 2004 | } | 
|  | 2005 | break; | 
|  | 2006 |  | 
|  | 2007 | case SK_HWEV_SET_LMODE: | 
|  | 2008 | Val8 = (SK_U8)Para.Para32[1]; | 
|  | 2009 | if (pPrt->PLinkModeConf != Val8) { | 
|  | 2010 | /* Set New link mode */ | 
|  | 2011 | pPrt->PLinkModeConf = Val8; | 
|  | 2012 |  | 
|  | 2013 | /* Restart Port */ | 
|  | 2014 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); | 
|  | 2015 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); | 
|  | 2016 | } | 
|  | 2017 | break; | 
|  | 2018 |  | 
|  | 2019 | case SK_HWEV_SET_FLOWMODE: | 
|  | 2020 | Val8 = (SK_U8)Para.Para32[1]; | 
|  | 2021 | if (pPrt->PFlowCtrlMode != Val8) { | 
|  | 2022 | /* Set New Flow Control mode */ | 
|  | 2023 | pPrt->PFlowCtrlMode = Val8; | 
|  | 2024 |  | 
|  | 2025 | /* Restart Port */ | 
|  | 2026 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); | 
|  | 2027 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); | 
|  | 2028 | } | 
|  | 2029 | break; | 
|  | 2030 |  | 
|  | 2031 | case SK_HWEV_SET_ROLE: | 
|  | 2032 | /* not possible for fiber */ | 
|  | 2033 | if (!pAC->GIni.GICopperType) { | 
|  | 2034 | break; | 
|  | 2035 | } | 
|  | 2036 | Val8 = (SK_U8)Para.Para32[1]; | 
|  | 2037 | if (pPrt->PMSMode != Val8) { | 
|  | 2038 | /* Set New Role (Master/Slave) mode */ | 
|  | 2039 | pPrt->PMSMode = Val8; | 
|  | 2040 |  | 
|  | 2041 | /* Restart Port */ | 
|  | 2042 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); | 
|  | 2043 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); | 
|  | 2044 | } | 
|  | 2045 | break; | 
|  | 2046 |  | 
|  | 2047 | case SK_HWEV_SET_SPEED: | 
|  | 2048 | if (pPrt->PhyType != SK_PHY_MARV_COPPER) { | 
|  | 2049 | break; | 
|  | 2050 | } | 
|  | 2051 | Val8 = (SK_U8)Para.Para32[1]; | 
|  | 2052 | if (pPrt->PLinkSpeed != Val8) { | 
|  | 2053 | /* Set New Speed parameter */ | 
|  | 2054 | pPrt->PLinkSpeed = Val8; | 
|  | 2055 |  | 
|  | 2056 | /* Restart Port */ | 
|  | 2057 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); | 
|  | 2058 | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); | 
|  | 2059 | } | 
|  | 2060 | break; | 
|  | 2061 |  | 
|  | 2062 | #ifdef GENESIS | 
|  | 2063 | case SK_HWEV_HALFDUP_CHK: | 
|  | 2064 | if (pAC->GIni.GIGenesis) { | 
|  | 2065 | /* | 
|  | 2066 | * half duplex hangup workaround. | 
|  | 2067 | * See packet arbiter timeout interrupt for description | 
|  | 2068 | */ | 
|  | 2069 | pPrt->HalfDupTimerActive = SK_FALSE; | 
|  | 2070 | if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || | 
|  | 2071 | pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { | 
|  | 2072 | /* Snap statistic counters */ | 
|  | 2073 | (void)SkXmUpdateStats(pAC, IoC, Port); | 
|  | 2074 |  | 
|  | 2075 | (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32); | 
|  | 2076 |  | 
|  | 2077 | Octets = (SK_U64)Val32 << 32; | 
|  | 2078 |  | 
|  | 2079 | (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32); | 
|  | 2080 |  | 
|  | 2081 | Octets += Val32; | 
|  | 2082 |  | 
|  | 2083 | if (pPrt->LastOctets == Octets) { | 
|  | 2084 | /* Tx hanging, a FIFO flush restarts it */ | 
|  | 2085 | SkMacFlushTxFifo(pAC, IoC, Port); | 
|  | 2086 | } | 
|  | 2087 | } | 
|  | 2088 | } | 
|  | 2089 | break; | 
|  | 2090 | #endif /* GENESIS */ | 
|  | 2091 |  | 
|  | 2092 | default: | 
|  | 2093 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); | 
|  | 2094 | break; | 
|  | 2095 | } | 
|  | 2096 |  | 
|  | 2097 | return(0); | 
|  | 2098 | }	/* SkGeSirqEvent */ | 
|  | 2099 |  | 
|  | 2100 |  | 
|  | 2101 | #ifdef GENESIS | 
|  | 2102 | /****************************************************************************** | 
|  | 2103 | * | 
|  | 2104 | *	SkPhyIsrBcom() - PHY interrupt service routine | 
|  | 2105 | * | 
|  | 2106 | * Description: handles all interrupts from BCom PHY | 
|  | 2107 | * | 
|  | 2108 | * Returns: N/A | 
|  | 2109 | */ | 
|  | 2110 | static void SkPhyIsrBcom( | 
|  | 2111 | SK_AC		*pAC,		/* Adapter Context */ | 
|  | 2112 | SK_IOC		IoC,		/* Io Context */ | 
|  | 2113 | int			Port,		/* Port Num = PHY Num */ | 
|  | 2114 | SK_U16		IStatus)	/* Interrupt Status */ | 
|  | 2115 | { | 
|  | 2116 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 2117 | SK_EVPARA	Para; | 
|  | 2118 |  | 
|  | 2119 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 2120 |  | 
|  | 2121 | if ((IStatus & PHY_B_IS_PSE) != 0) { | 
|  | 2122 | /* Incorrectable pair swap error */ | 
|  | 2123 | SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022, | 
|  | 2124 | SKERR_SIRQ_E022MSG); | 
|  | 2125 | } | 
|  | 2126 |  | 
|  | 2127 | if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { | 
|  | 2128 |  | 
|  | 2129 | SkHWLinkDown(pAC, IoC, Port); | 
|  | 2130 |  | 
|  | 2131 | Para.Para32[0] = (SK_U32)Port; | 
|  | 2132 | /* Signal to RLMT */ | 
|  | 2133 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 2134 |  | 
|  | 2135 | /* Start workaround Errata #2 timer */ | 
|  | 2136 | SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, | 
|  | 2137 | SKGE_HWAC, SK_HWEV_WATIM, Para); | 
|  | 2138 | } | 
|  | 2139 |  | 
|  | 2140 | }	/* SkPhyIsrBcom */ | 
|  | 2141 | #endif /* GENESIS */ | 
|  | 2142 |  | 
|  | 2143 |  | 
|  | 2144 | #ifdef YUKON | 
|  | 2145 | /****************************************************************************** | 
|  | 2146 | * | 
|  | 2147 | *	SkPhyIsrGmac() - PHY interrupt service routine | 
|  | 2148 | * | 
|  | 2149 | * Description: handles all interrupts from Marvell PHY | 
|  | 2150 | * | 
|  | 2151 | * Returns: N/A | 
|  | 2152 | */ | 
|  | 2153 | static void SkPhyIsrGmac( | 
|  | 2154 | SK_AC		*pAC,		/* Adapter Context */ | 
|  | 2155 | SK_IOC		IoC,		/* Io Context */ | 
|  | 2156 | int			Port,		/* Port Num = PHY Num */ | 
|  | 2157 | SK_U16		IStatus)	/* Interrupt Status */ | 
|  | 2158 | { | 
|  | 2159 | SK_GEPORT	*pPrt;		/* GIni Port struct pointer */ | 
|  | 2160 | SK_EVPARA	Para; | 
|  | 2161 | SK_U16		Word; | 
|  | 2162 |  | 
|  | 2163 | pPrt = &pAC->GIni.GP[Port]; | 
|  | 2164 |  | 
|  | 2165 | if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { | 
|  | 2166 |  | 
|  | 2167 | SkHWLinkDown(pAC, IoC, Port); | 
|  | 2168 |  | 
|  | 2169 | SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word); | 
|  | 2170 |  | 
|  | 2171 | SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, | 
|  | 2172 | ("AutoNeg.Adv: 0x%04X\n", Word)); | 
|  | 2173 |  | 
|  | 2174 | /* Set Auto-negotiation advertisement */ | 
|  | 2175 | if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) { | 
|  | 2176 | /* restore Asymmetric Pause bit */ | 
|  | 2177 | SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, | 
|  | 2178 | (SK_U16)(Word | PHY_M_AN_ASP)); | 
|  | 2179 | } | 
|  | 2180 |  | 
|  | 2181 | Para.Para32[0] = (SK_U32)Port; | 
|  | 2182 | /* Signal to RLMT */ | 
|  | 2183 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 2184 | } | 
|  | 2185 |  | 
|  | 2186 | if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { | 
|  | 2187 | /* Auto-Negotiation Error */ | 
|  | 2188 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); | 
|  | 2189 | } | 
|  | 2190 |  | 
|  | 2191 | if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { | 
|  | 2192 | /* FIFO Overflow/Underrun Error */ | 
|  | 2193 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); | 
|  | 2194 | } | 
|  | 2195 |  | 
|  | 2196 | }	/* SkPhyIsrGmac */ | 
|  | 2197 | #endif /* YUKON */ | 
|  | 2198 |  | 
|  | 2199 |  | 
|  | 2200 | #ifdef OTHER_PHY | 
|  | 2201 | /****************************************************************************** | 
|  | 2202 | * | 
|  | 2203 | *	SkPhyIsrLone() - PHY interrupt service routine | 
|  | 2204 | * | 
|  | 2205 | * Description: handles all interrupts from LONE PHY | 
|  | 2206 | * | 
|  | 2207 | * Returns: N/A | 
|  | 2208 | */ | 
|  | 2209 | static void SkPhyIsrLone( | 
|  | 2210 | SK_AC	*pAC,		/* Adapter Context */ | 
|  | 2211 | SK_IOC	IoC,		/* Io Context */ | 
|  | 2212 | int		Port,		/* Port Num = PHY Num */ | 
|  | 2213 | SK_U16	IStatus)	/* Interrupt Status */ | 
|  | 2214 | { | 
|  | 2215 | SK_EVPARA	Para; | 
|  | 2216 |  | 
|  | 2217 | if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { | 
|  | 2218 |  | 
|  | 2219 | SkHWLinkDown(pAC, IoC, Port); | 
|  | 2220 |  | 
|  | 2221 | Para.Para32[0] = (SK_U32)Port; | 
|  | 2222 | /* Signal to RLMT */ | 
|  | 2223 | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); | 
|  | 2224 | } | 
|  | 2225 |  | 
|  | 2226 | }	/* SkPhyIsrLone */ | 
|  | 2227 | #endif /* OTHER_PHY */ | 
|  | 2228 |  | 
|  | 2229 | /* End of File */ |