Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13 2251 lines 59 kB view raw
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)))) 50static 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 63static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL); 64static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL); 65static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16); 66#endif /* GENESIS */ 67#ifdef YUKON 68static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL); 69static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16); 70#endif /* YUKON */ 71#ifdef OTHER_PHY 72static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL); 73static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL); 74static 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 */ 82static 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 */ 99intro() 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 */ 111static void SkHWInitDefSense( 112SK_AC *pAC, /* adapter context */ 113SK_IOC IoC, /* IO context */ 114int 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 */ 147static SK_U8 SkHWSenseGetNext( 148SK_AC *pAC, /* adapter context */ 149SK_IOC IoC, /* IO context */ 150int 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 */ 181static void SkHWSenseSetNext( 182SK_AC *pAC, /* adapter context */ 183SK_IOC IoC, /* IO context */ 184int Port, /* Port Index (MAC_1 + n) */ 185SK_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 */ 216void SkHWLinkDown( 217SK_AC *pAC, /* adapter context */ 218SK_IOC IoC, /* IO context */ 219int 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 */ 268void SkHWLinkUp( 269SK_AC *pAC, /* adapter context */ 270SK_IOC IoC, /* IO context */ 271int 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 */ 331static void SkMacParity( 332SK_AC *pAC, /* adapter context */ 333SK_IOC IoC, /* IO context */ 334int 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 */ 408static void SkGeHwErr( 409SK_AC *pAC, /* adapter context */ 410SK_IOC IoC, /* IO context */ 411SK_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 */ 542void SkGeSirqIsr( 543SK_AC *pAC, /* adapter context */ 544SK_IOC IoC, /* IO context */ 545SK_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#ifdef XXX 616 Len = sizeof(SK_U64); 617 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, 618 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 0), 619 pAC->Rlmt.Port[0].Net->NetNumber); 620 621 pPrt->LastOctets = Octets; 622#endif /* XXX */ 623 /* Snap statistic counters */ 624 (void)SkXmUpdateStats(pAC, IoC, 0); 625 626 (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32); 627 628 pPrt->LastOctets = (SK_U64)RegVal32 << 32; 629 630 (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32); 631 632 pPrt->LastOctets += RegVal32; 633 634 Para.Para32[0] = 0; 635 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, 636 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); 637 } 638 } 639#endif /* GENESIS */ 640 } 641 642 if ((Istatus & IS_PA_TO_TX2) != 0) { 643 644 pPrt = &pAC->GIni.GP[1]; 645 646 /* May be a normal situation in a server with a slow network */ 647 SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); 648 649#ifdef GENESIS 650 if (pAC->GIni.GIGenesis) { 651 /* workaround: see above */ 652 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || 653 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && 654 !pPrt->HalfDupTimerActive) { 655 pPrt->HalfDupTimerActive = SK_TRUE; 656#ifdef XXX 657 Len = sizeof(SK_U64); 658 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, 659 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 1), 660 pAC->Rlmt.Port[1].Net->NetNumber); 661 662 pPrt->LastOctets = Octets; 663#endif /* XXX */ 664 /* Snap statistic counters */ 665 (void)SkXmUpdateStats(pAC, IoC, 1); 666 667 (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32); 668 669 pPrt->LastOctets = (SK_U64)RegVal32 << 32; 670 671 (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32); 672 673 pPrt->LastOctets += RegVal32; 674 675 Para.Para32[0] = 1; 676 SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, 677 SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); 678 } 679 } 680#endif /* GENESIS */ 681 } 682 683 /* Check interrupts of the particular queues */ 684 if ((Istatus & IS_R1_C) != 0) { 685 /* Clear IRQ */ 686 SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); 687 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, 688 SKERR_SIRQ_E006MSG); 689 Para.Para64 = MAC_1; 690 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); 691 Para.Para32[0] = MAC_1; 692 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 693 } 694 695 if ((Istatus & IS_R2_C) != 0) { 696 /* Clear IRQ */ 697 SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); 698 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, 699 SKERR_SIRQ_E007MSG); 700 Para.Para64 = MAC_2; 701 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); 702 Para.Para32[0] = MAC_2; 703 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 704 } 705 706 if ((Istatus & IS_XS1_C) != 0) { 707 /* Clear IRQ */ 708 SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); 709 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, 710 SKERR_SIRQ_E008MSG); 711 Para.Para64 = MAC_1; 712 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); 713 Para.Para32[0] = MAC_1; 714 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 715 } 716 717 if ((Istatus & IS_XA1_C) != 0) { 718 /* Clear IRQ */ 719 SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); 720 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, 721 SKERR_SIRQ_E009MSG); 722 Para.Para64 = MAC_1; 723 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); 724 Para.Para32[0] = MAC_1; 725 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 726 } 727 728 if ((Istatus & IS_XS2_C) != 0) { 729 /* Clear IRQ */ 730 SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); 731 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, 732 SKERR_SIRQ_E010MSG); 733 Para.Para64 = MAC_2; 734 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); 735 Para.Para32[0] = MAC_2; 736 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 737 } 738 739 if ((Istatus & IS_XA2_C) != 0) { 740 /* Clear IRQ */ 741 SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); 742 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, 743 SKERR_SIRQ_E011MSG); 744 Para.Para64 = MAC_2; 745 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); 746 Para.Para32[0] = MAC_2; 747 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 748 } 749 750 /* External reg interrupt */ 751 if ((Istatus & IS_EXT_REG) != 0) { 752 /* Test IRQs from PHY */ 753 for (i = 0; i < pAC->GIni.GIMacsFound; i++) { 754 755 pPrt = &pAC->GIni.GP[i]; 756 757 if (pPrt->PState == SK_PRT_RESET) { 758 continue; 759 } 760 761#ifdef GENESIS 762 if (pAC->GIni.GIGenesis) { 763 764 switch (pPrt->PhyType) { 765 766 case SK_PHY_XMAC: 767 break; 768 769 case SK_PHY_BCOM: 770 SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); 771 772 if ((PhyInt & ~PHY_B_DEF_MSK) != 0) { 773 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 774 ("Port %d Bcom Int: 0x%04X\n", 775 i, PhyInt)); 776 SkPhyIsrBcom(pAC, IoC, i, PhyInt); 777 } 778 break; 779#ifdef OTHER_PHY 780 case SK_PHY_LONE: 781 SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); 782 783 if ((PhyInt & PHY_L_DEF_MSK) != 0) { 784 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 785 ("Port %d Lone Int: %x\n", 786 i, PhyInt)); 787 SkPhyIsrLone(pAC, IoC, i, PhyInt); 788 } 789 break; 790#endif /* OTHER_PHY */ 791 } 792 } 793#endif /* GENESIS */ 794 795#ifdef YUKON 796 if (pAC->GIni.GIYukon) { 797 /* Read PHY Interrupt Status */ 798 SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); 799 800 if ((PhyInt & PHY_M_DEF_MSK) != 0) { 801 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 802 ("Port %d Marv Int: 0x%04X\n", 803 i, PhyInt)); 804 SkPhyIsrGmac(pAC, IoC, i, PhyInt); 805 } 806 } 807#endif /* YUKON */ 808 } 809 } 810 811 /* I2C Ready interrupt */ 812 if ((Istatus & IS_I2C_READY) != 0) { 813#ifdef SK_SLIM 814 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); 815#else 816 SkI2cIsr(pAC, IoC); 817#endif 818 } 819 820 /* SW forced interrupt */ 821 if ((Istatus & IS_IRQ_SW) != 0) { 822 /* clear the software IRQ */ 823 SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); 824 } 825 826 if ((Istatus & IS_LNK_SYNC_M1) != 0) { 827 /* 828 * We do NOT need the Link Sync interrupt, because it shows 829 * us only a link going down. 830 */ 831 /* clear interrupt */ 832 SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); 833 } 834 835 /* Check MAC after link sync counter */ 836 if ((Istatus & IS_MAC1) != 0) { 837 /* IRQ from MAC 1 */ 838 SkMacIrq(pAC, IoC, MAC_1); 839 } 840 841 if ((Istatus & IS_LNK_SYNC_M2) != 0) { 842 /* 843 * We do NOT need the Link Sync interrupt, because it shows 844 * us only a link going down. 845 */ 846 /* clear interrupt */ 847 SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); 848 } 849 850 /* Check MAC after link sync counter */ 851 if ((Istatus & IS_MAC2) != 0) { 852 /* IRQ from MAC 2 */ 853 SkMacIrq(pAC, IoC, MAC_2); 854 } 855 856 /* Timer interrupt (served last) */ 857 if ((Istatus & IS_TIMINT) != 0) { 858 /* check for HW Errors */ 859 if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { 860 /* read the HW Error Interrupt source */ 861 SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); 862 863 SkGeHwErr(pAC, IoC, RegVal32); 864 } 865 866 SkHwtIsr(pAC, IoC); 867 } 868 869} /* SkGeSirqIsr */ 870 871 872#ifdef GENESIS 873/****************************************************************************** 874 * 875 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 876 * 877 * return: 878 * 0 o.k. nothing needed 879 * 1 Restart needed on this port 880 */ 881static int SkGePortCheckShorts( 882SK_AC *pAC, /* Adapter Context */ 883SK_IOC IoC, /* IO Context */ 884int Port) /* Which port should be checked */ 885{ 886 SK_U32 Shorts; /* Short Event Counter */ 887 SK_U32 CheckShorts; /* Check value for Short Event Counter */ 888 SK_U64 RxCts; /* Rx Counter (packets on network) */ 889 SK_U32 RxTmp; /* Rx temp. Counter */ 890 SK_U32 FcsErrCts; /* FCS Error Counter */ 891 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 892 int Rtv; /* Return value */ 893 int i; 894 895 pPrt = &pAC->GIni.GP[Port]; 896 897 /* Default: no action */ 898 Rtv = SK_HW_PS_NONE; 899 900 (void)SkXmUpdateStats(pAC, IoC, Port); 901 902 /* Extra precaution: check for short Event counter */ 903 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); 904 905 /* 906 * Read Rx counters (packets seen on the network and not necessarily 907 * really received. 908 */ 909 RxCts = 0; 910 911 for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) { 912 913 (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); 914 915 RxCts += (SK_U64)RxTmp; 916 } 917 918 /* On default: check shorts against zero */ 919 CheckShorts = 0; 920 921 /* Extra precaution on active links */ 922 if (pPrt->PHWLinkUp) { 923 /* Reset Link Restart counter */ 924 pPrt->PLinkResCt = 0; 925 pPrt->PAutoNegTOCt = 0; 926 927 /* If link is up check for 2 */ 928 CheckShorts = 2; 929 930 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); 931 932 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && 933 pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && 934 (pPrt->PLinkMode == SK_LMODE_HALF || 935 pPrt->PLinkMode == SK_LMODE_FULL)) { 936 /* 937 * This is autosensing and we are in the fallback 938 * manual full/half duplex mode. 939 */ 940 if (RxCts == pPrt->PPrevRx) { 941 /* Nothing received, restart link */ 942 pPrt->PPrevFcs = FcsErrCts; 943 pPrt->PPrevShorts = Shorts; 944 945 return(SK_HW_PS_RESTART); 946 } 947 else { 948 pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; 949 } 950 } 951 952 if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || 953 (!(FcsErrCts - pPrt->PPrevFcs))) { 954 /* 955 * Note: The compare with zero above has to be done the way shown, 956 * otherwise the Linux driver will have a problem. 957 */ 958 /* 959 * We received a bunch of frames or no CRC error occured on the 960 * network -> ok. 961 */ 962 pPrt->PPrevRx = RxCts; 963 pPrt->PPrevFcs = FcsErrCts; 964 pPrt->PPrevShorts = Shorts; 965 966 return(SK_HW_PS_NONE); 967 } 968 969 pPrt->PPrevFcs = FcsErrCts; 970 } 971 972 973 if ((Shorts - pPrt->PPrevShorts) > CheckShorts) { 974 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 975 ("Short Event Count Restart Port %d \n", Port)); 976 Rtv = SK_HW_PS_RESTART; 977 } 978 979 pPrt->PPrevShorts = Shorts; 980 pPrt->PPrevRx = RxCts; 981 982 return(Rtv); 983} /* SkGePortCheckShorts */ 984#endif /* GENESIS */ 985 986 987/****************************************************************************** 988 * 989 * SkGePortCheckUp() - Check if the link is up 990 * 991 * return: 992 * 0 o.k. nothing needed 993 * 1 Restart needed on this port 994 * 2 Link came up 995 */ 996static int SkGePortCheckUp( 997SK_AC *pAC, /* Adapter Context */ 998SK_IOC IoC, /* IO Context */ 999int Port) /* Which port should be checked */ 1000{ 1001 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 1002 SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ 1003 int Rtv; /* Return value */ 1004 1005 Rtv = SK_HW_PS_NONE; 1006 1007 pPrt = &pAC->GIni.GP[Port]; 1008 1009 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { 1010 AutoNeg = SK_FALSE; 1011 } 1012 else { 1013 AutoNeg = SK_TRUE; 1014 } 1015 1016#ifdef GENESIS 1017 if (pAC->GIni.GIGenesis) { 1018 1019 switch (pPrt->PhyType) { 1020 1021 case SK_PHY_XMAC: 1022 Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg); 1023 break; 1024 case SK_PHY_BCOM: 1025 Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg); 1026 break; 1027#ifdef OTHER_PHY 1028 case SK_PHY_LONE: 1029 Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg); 1030 break; 1031 case SK_PHY_NAT: 1032 Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg); 1033 break; 1034#endif /* OTHER_PHY */ 1035 } 1036 } 1037#endif /* GENESIS */ 1038 1039#ifdef YUKON 1040 if (pAC->GIni.GIYukon) { 1041 1042 Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg); 1043 } 1044#endif /* YUKON */ 1045 1046 return(Rtv); 1047} /* SkGePortCheckUp */ 1048 1049 1050#ifdef GENESIS 1051/****************************************************************************** 1052 * 1053 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 1054 * 1055 * return: 1056 * 0 o.k. nothing needed 1057 * 1 Restart needed on this port 1058 * 2 Link came up 1059 */ 1060static int SkGePortCheckUpXmac( 1061SK_AC *pAC, /* Adapter Context */ 1062SK_IOC IoC, /* IO Context */ 1063int Port, /* Which port should be checked */ 1064SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ 1065{ 1066 SK_U32 Shorts; /* Short Event Counter */ 1067 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 1068 int Done; 1069 SK_U32 GpReg; /* General Purpose register value */ 1070 SK_U16 Isrc; /* Interrupt source register */ 1071 SK_U16 IsrcSum; /* Interrupt source register sum */ 1072 SK_U16 LpAb; /* Link Partner Ability */ 1073 SK_U16 ResAb; /* Resolved Ability */ 1074 SK_U16 ExtStat; /* Extended Status Register */ 1075 SK_U8 NextMode; /* Next AutoSensing Mode */ 1076 1077 pPrt = &pAC->GIni.GP[Port]; 1078 1079 if (pPrt->PHWLinkUp) { 1080 if (pPrt->PhyType != SK_PHY_XMAC) { 1081 return(SK_HW_PS_NONE); 1082 } 1083 else { 1084 return(SkGePortCheckShorts(pAC, IoC, Port)); 1085 } 1086 } 1087 1088 IsrcSum = pPrt->PIsave; 1089 pPrt->PIsave = 0; 1090 1091 /* Now wait for each port's link */ 1092 if (pPrt->PLinkBroken) { 1093 /* Link was broken */ 1094 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); 1095 1096 if ((GpReg & XM_GP_INP_ASS) == 0) { 1097 /* The Link is in sync */ 1098 XM_IN16(IoC, Port, XM_ISRC, &Isrc); 1099 IsrcSum |= Isrc; 1100 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); 1101 1102 if ((Isrc & XM_IS_INP_ASS) == 0) { 1103 /* It has been in sync since last time */ 1104 /* Restart the PORT */ 1105 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1106 ("Link in sync Restart Port %d\n", Port)); 1107 1108 (void)SkXmUpdateStats(pAC, IoC, Port); 1109 1110 /* We now need to reinitialize the PrevShorts counter */ 1111 (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); 1112 pPrt->PPrevShorts = Shorts; 1113 1114 pPrt->PLinkBroken = SK_FALSE; 1115 1116 /* 1117 * Link Restart Workaround: 1118 * it may be possible that the other Link side 1119 * restarts its link as well an we detect 1120 * another LinkBroken. To prevent this 1121 * happening we check for a maximum number 1122 * of consecutive restart. If those happens, 1123 * we do NOT restart the active link and 1124 * check whether the link is now o.k. 1125 */ 1126 pPrt->PLinkResCt++; 1127 1128 pPrt->PAutoNegTimeOut = 0; 1129 1130 if (pPrt->PLinkResCt < SK_MAX_LRESTART) { 1131 return(SK_HW_PS_RESTART); 1132 } 1133 1134 pPrt->PLinkResCt = 0; 1135 1136 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1137 ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); 1138 } 1139 else { 1140 pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); 1141 1142 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1143 ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); 1144 1145 /* Do nothing more if link is broken */ 1146 return(SK_HW_PS_NONE); 1147 } 1148 } 1149 else { 1150 /* Do nothing more if link is broken */ 1151 return(SK_HW_PS_NONE); 1152 } 1153 1154 } 1155 else { 1156 /* Link was not broken, check if it is */ 1157 XM_IN16(IoC, Port, XM_ISRC, &Isrc); 1158 IsrcSum |= Isrc; 1159 if ((Isrc & XM_IS_INP_ASS) != 0) { 1160 XM_IN16(IoC, Port, XM_ISRC, &Isrc); 1161 IsrcSum |= Isrc; 1162 if ((Isrc & XM_IS_INP_ASS) != 0) { 1163 XM_IN16(IoC, Port, XM_ISRC, &Isrc); 1164 IsrcSum |= Isrc; 1165 if ((Isrc & XM_IS_INP_ASS) != 0) { 1166 pPrt->PLinkBroken = SK_TRUE; 1167 /* Re-Init Link partner Autoneg flag */ 1168 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; 1169 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1170 ("Link broken Port %d\n", Port)); 1171 1172 /* Cable removed-> reinit sense mode */ 1173 SkHWInitDefSense(pAC, IoC, Port); 1174 1175 return(SK_HW_PS_RESTART); 1176 } 1177 } 1178 } 1179 else { 1180 SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); 1181 1182 if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { 1183 return(SK_HW_PS_RESTART); 1184 } 1185 } 1186 } 1187 1188 /* 1189 * here we usually can check whether the link is in sync and 1190 * auto-negotiation is done. 1191 */ 1192 XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); 1193 XM_IN16(IoC, Port, XM_ISRC, &Isrc); 1194 IsrcSum |= Isrc; 1195 1196 SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); 1197 1198 if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) { 1199 if ((GpReg & XM_GP_INP_ASS) == 0) { 1200 /* Save Auto-negotiation Done interrupt only if link is in sync */ 1201 pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); 1202 } 1203#ifdef DEBUG 1204 if ((pPrt->PIsave & XM_IS_AND) != 0) { 1205 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1206 ("AutoNeg done rescheduled Port %d\n", Port)); 1207 } 1208#endif /* DEBUG */ 1209 return(SK_HW_PS_NONE); 1210 } 1211 1212 if (AutoNeg) { 1213 if ((IsrcSum & XM_IS_AND) != 0) { 1214 SkHWLinkUp(pAC, IoC, Port); 1215 Done = SkMacAutoNegDone(pAC, IoC, Port); 1216 if (Done != SK_AND_OK) { 1217 /* Get PHY parameters, for debugging only */ 1218 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb); 1219 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); 1220 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1221 ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", 1222 Port, LpAb, ResAb)); 1223 1224 /* Try next possible mode */ 1225 NextMode = SkHWSenseGetNext(pAC, IoC, Port); 1226 SkHWLinkDown(pAC, IoC, Port); 1227 if (Done == SK_AND_DUP_CAP) { 1228 /* GoTo next mode */ 1229 SkHWSenseSetNext(pAC, IoC, Port, NextMode); 1230 } 1231 1232 return(SK_HW_PS_RESTART); 1233 } 1234 /* 1235 * Dummy Read extended status to prevent extra link down/ups 1236 * (clear Page Received bit if set) 1237 */ 1238 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); 1239 1240 return(SK_HW_PS_LINK); 1241 } 1242 1243 /* AutoNeg not done, but HW link is up. Check for timeouts */ 1244 pPrt->PAutoNegTimeOut++; 1245 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { 1246 /* Increase the Timeout counter */ 1247 pPrt->PAutoNegTOCt++; 1248 1249 /* Timeout occured */ 1250 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1251 ("AutoNeg timeout Port %d\n", Port)); 1252 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && 1253 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { 1254 /* Set Link manually up */ 1255 SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); 1256 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1257 ("Set manual full duplex Port %d\n", Port)); 1258 } 1259 1260 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && 1261 pPrt->PLipaAutoNeg == SK_LIPA_AUTO && 1262 pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { 1263 /* 1264 * This is rather complicated. 1265 * we need to check here whether the LIPA_AUTO 1266 * we saw before is false alert. We saw at one 1267 * switch ( SR8800) that on boot time it sends 1268 * just one auto-neg packet and does no further 1269 * auto-negotiation. 1270 * Solution: we restart the autosensing after 1271 * a few timeouts. 1272 */ 1273 pPrt->PAutoNegTOCt = 0; 1274 pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; 1275 SkHWInitDefSense(pAC, IoC, Port); 1276 } 1277 1278 /* Do the restart */ 1279 return(SK_HW_PS_RESTART); 1280 } 1281 } 1282 else { 1283 /* Link is up and we don't need more */ 1284#ifdef DEBUG 1285 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { 1286 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1287 ("ERROR: Lipa auto detected on port %d\n", Port)); 1288 } 1289#endif /* DEBUG */ 1290 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1291 ("Link sync(GP), Port %d\n", Port)); 1292 SkHWLinkUp(pAC, IoC, Port); 1293 1294 /* 1295 * Link sync (GP) and so assume a good connection. But if not received 1296 * a bunch of frames received in a time slot (maybe broken tx cable) 1297 * the port is restart. 1298 */ 1299 return(SK_HW_PS_LINK); 1300 } 1301 1302 return(SK_HW_PS_NONE); 1303} /* SkGePortCheckUpXmac */ 1304 1305 1306/****************************************************************************** 1307 * 1308 * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY 1309 * 1310 * return: 1311 * 0 o.k. nothing needed 1312 * 1 Restart needed on this port 1313 * 2 Link came up 1314 */ 1315static int SkGePortCheckUpBcom( 1316SK_AC *pAC, /* Adapter Context */ 1317SK_IOC IoC, /* IO Context */ 1318int Port, /* Which port should be checked */ 1319SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ 1320{ 1321 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 1322 int Done; 1323 SK_U16 Isrc; /* Interrupt source register */ 1324 SK_U16 PhyStat; /* Phy Status Register */ 1325 SK_U16 ResAb; /* Master/Slave resolution */ 1326 SK_U16 Ctrl; /* Broadcom control flags */ 1327#ifdef DEBUG 1328 SK_U16 LpAb; 1329 SK_U16 ExtStat; 1330#endif /* DEBUG */ 1331 1332 pPrt = &pAC->GIni.GP[Port]; 1333 1334 /* Check for No HCD Link events (#10523) */ 1335 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); 1336 1337#ifdef xDEBUG 1338 if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) == 1339 (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { 1340 1341 SK_U32 Stat1, Stat2, Stat3; 1342 1343 Stat1 = 0; 1344 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); 1345 CMSMPrintString( 1346 pAC->pConfigTable, 1347 MSG_TYPE_RUNTIME_INFO, 1348 "CheckUp1 - Stat: %x, Mask: %x", 1349 (void *)Isrc, 1350 (void *)Stat1); 1351 1352 Stat1 = 0; 1353 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); 1354 Stat2 = 0; 1355 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2); 1356 Stat1 = Stat1 << 16 | Stat2; 1357 Stat2 = 0; 1358 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); 1359 Stat3 = 0; 1360 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); 1361 Stat2 = Stat2 << 16 | Stat3; 1362 CMSMPrintString( 1363 pAC->pConfigTable, 1364 MSG_TYPE_RUNTIME_INFO, 1365 "Ctrl/Stat: %x, AN Adv/LP: %x", 1366 (void *)Stat1, 1367 (void *)Stat2); 1368 1369 Stat1 = 0; 1370 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); 1371 Stat2 = 0; 1372 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); 1373 Stat1 = Stat1 << 16 | Stat2; 1374 Stat2 = 0; 1375 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); 1376 Stat3 = 0; 1377 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3); 1378 Stat2 = Stat2 << 16 | Stat3; 1379 CMSMPrintString( 1380 pAC->pConfigTable, 1381 MSG_TYPE_RUNTIME_INFO, 1382 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", 1383 (void *)Stat1, 1384 (void *)Stat2); 1385 1386 Stat1 = 0; 1387 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); 1388 Stat2 = 0; 1389 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); 1390 Stat1 = Stat1 << 16 | Stat2; 1391 Stat2 = 0; 1392 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); 1393 Stat3 = 0; 1394 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); 1395 Stat2 = Stat2 << 16 | Stat3; 1396 CMSMPrintString( 1397 pAC->pConfigTable, 1398 MSG_TYPE_RUNTIME_INFO, 1399 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", 1400 (void *)Stat1, 1401 (void *)Stat2); 1402 } 1403#endif /* DEBUG */ 1404 1405 if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { 1406 /* 1407 * Workaround BCom Errata: 1408 * enable and disable loopback mode if "NO HCD" occurs. 1409 */ 1410 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl); 1411 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, 1412 (SK_U16)(Ctrl | PHY_CT_LOOP)); 1413 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, 1414 (SK_U16)(Ctrl & ~PHY_CT_LOOP)); 1415 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1416 ("No HCD Link event, Port %d\n", Port)); 1417#ifdef xDEBUG 1418 CMSMPrintString( 1419 pAC->pConfigTable, 1420 MSG_TYPE_RUNTIME_INFO, 1421 "No HCD link event, port %d.", 1422 (void *)Port, 1423 (void *)NULL); 1424#endif /* DEBUG */ 1425 } 1426 1427 /* Not obsolete: link status bit is latched to 0 and autoclearing! */ 1428 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); 1429 1430 if (pPrt->PHWLinkUp) { 1431 return(SK_HW_PS_NONE); 1432 } 1433 1434#ifdef xDEBUG 1435 { 1436 SK_U32 Stat1, Stat2, Stat3; 1437 1438 Stat1 = 0; 1439 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); 1440 CMSMPrintString( 1441 pAC->pConfigTable, 1442 MSG_TYPE_RUNTIME_INFO, 1443 "CheckUp1a - Stat: %x, Mask: %x", 1444 (void *)Isrc, 1445 (void *)Stat1); 1446 1447 Stat1 = 0; 1448 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); 1449 Stat2 = 0; 1450 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); 1451 Stat1 = Stat1 << 16 | PhyStat; 1452 Stat2 = 0; 1453 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); 1454 Stat3 = 0; 1455 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); 1456 Stat2 = Stat2 << 16 | Stat3; 1457 CMSMPrintString( 1458 pAC->pConfigTable, 1459 MSG_TYPE_RUNTIME_INFO, 1460 "Ctrl/Stat: %x, AN Adv/LP: %x", 1461 (void *)Stat1, 1462 (void *)Stat2); 1463 1464 Stat1 = 0; 1465 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); 1466 Stat2 = 0; 1467 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); 1468 Stat1 = Stat1 << 16 | Stat2; 1469 Stat2 = 0; 1470 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); 1471 Stat3 = 0; 1472 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); 1473 Stat2 = Stat2 << 16 | ResAb; 1474 CMSMPrintString( 1475 pAC->pConfigTable, 1476 MSG_TYPE_RUNTIME_INFO, 1477 "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", 1478 (void *)Stat1, 1479 (void *)Stat2); 1480 1481 Stat1 = 0; 1482 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); 1483 Stat2 = 0; 1484 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); 1485 Stat1 = Stat1 << 16 | Stat2; 1486 Stat2 = 0; 1487 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); 1488 Stat3 = 0; 1489 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); 1490 Stat2 = Stat2 << 16 | Stat3; 1491 CMSMPrintString( 1492 pAC->pConfigTable, 1493 MSG_TYPE_RUNTIME_INFO, 1494 "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", 1495 (void *)Stat1, 1496 (void *)Stat2); 1497 } 1498#endif /* DEBUG */ 1499 1500 /* 1501 * Here we usually can check whether the link is in sync and 1502 * auto-negotiation is done. 1503 */ 1504 1505 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); 1506 1507 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); 1508 1509 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1510 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); 1511 1512 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); 1513 1514 if ((ResAb & PHY_B_1000S_MSF) != 0) { 1515 /* Error */ 1516 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1517 ("Master/Slave Fault port %d\n", Port)); 1518 1519 pPrt->PAutoNegFail = SK_TRUE; 1520 pPrt->PMSStatus = SK_MS_STAT_FAULT; 1521 1522 return(SK_HW_PS_RESTART); 1523 } 1524 1525 if ((PhyStat & PHY_ST_LSYNC) == 0) { 1526 return(SK_HW_PS_NONE); 1527 } 1528 1529 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? 1530 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; 1531 1532 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1533 ("Port %d, ResAb: 0x%04X\n", Port, ResAb)); 1534 1535 if (AutoNeg) { 1536 if ((PhyStat & PHY_ST_AN_OVER) != 0) { 1537 1538 SkHWLinkUp(pAC, IoC, Port); 1539 1540 Done = SkMacAutoNegDone(pAC, IoC, Port); 1541 1542 if (Done != SK_AND_OK) { 1543#ifdef DEBUG 1544 /* Get PHY parameters, for debugging only */ 1545 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); 1546 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); 1547 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1548 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", 1549 Port, LpAb, ExtStat)); 1550#endif /* DEBUG */ 1551 return(SK_HW_PS_RESTART); 1552 } 1553 else { 1554#ifdef xDEBUG 1555 /* Dummy read ISR to prevent extra link downs/ups */ 1556 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); 1557 1558 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { 1559 CMSMPrintString( 1560 pAC->pConfigTable, 1561 MSG_TYPE_RUNTIME_INFO, 1562 "CheckUp2 - Stat: %x", 1563 (void *)ExtStat, 1564 (void *)NULL); 1565 } 1566#endif /* DEBUG */ 1567 return(SK_HW_PS_LINK); 1568 } 1569 } 1570 } 1571 else { /* !AutoNeg */ 1572 /* Link is up and we don't need more. */ 1573#ifdef DEBUG 1574 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { 1575 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1576 ("ERROR: Lipa auto detected on port %d\n", Port)); 1577 } 1578#endif /* DEBUG */ 1579 1580#ifdef xDEBUG 1581 /* Dummy read ISR to prevent extra link downs/ups */ 1582 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); 1583 1584 if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { 1585 CMSMPrintString( 1586 pAC->pConfigTable, 1587 MSG_TYPE_RUNTIME_INFO, 1588 "CheckUp3 - Stat: %x", 1589 (void *)ExtStat, 1590 (void *)NULL); 1591 } 1592#endif /* DEBUG */ 1593 1594 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1595 ("Link sync(GP), Port %d\n", Port)); 1596 SkHWLinkUp(pAC, IoC, Port); 1597 1598 return(SK_HW_PS_LINK); 1599 } 1600 1601 return(SK_HW_PS_NONE); 1602} /* SkGePortCheckUpBcom */ 1603#endif /* GENESIS */ 1604 1605 1606#ifdef YUKON 1607/****************************************************************************** 1608 * 1609 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY 1610 * 1611 * return: 1612 * 0 o.k. nothing needed 1613 * 1 Restart needed on this port 1614 * 2 Link came up 1615 */ 1616static int SkGePortCheckUpGmac( 1617SK_AC *pAC, /* Adapter Context */ 1618SK_IOC IoC, /* IO Context */ 1619int Port, /* Which port should be checked */ 1620SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ 1621{ 1622 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 1623 int Done; 1624 SK_U16 PhyIsrc; /* PHY Interrupt source */ 1625 SK_U16 PhyStat; /* PPY Status */ 1626 SK_U16 PhySpecStat;/* PHY Specific Status */ 1627 SK_U16 ResAb; /* Master/Slave resolution */ 1628 SK_EVPARA Para; 1629#ifdef DEBUG 1630 SK_U16 Word; /* I/O helper */ 1631#endif /* DEBUG */ 1632 1633 pPrt = &pAC->GIni.GP[Port]; 1634 1635 if (pPrt->PHWLinkUp) { 1636 return(SK_HW_PS_NONE); 1637 } 1638 1639 /* Read PHY Status */ 1640 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); 1641 1642 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1643 ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); 1644 1645 /* Read PHY Interrupt Status */ 1646 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc); 1647 1648 if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) { 1649 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1650 ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc)); 1651 } 1652 1653 if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) { 1654 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1655 ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc)); 1656 } 1657 1658 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); 1659 1660 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); 1661 1662 if ((ResAb & PHY_B_1000S_MSF) != 0) { 1663 /* Error */ 1664 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1665 ("Master/Slave Fault port %d\n", Port)); 1666 1667 pPrt->PAutoNegFail = SK_TRUE; 1668 pPrt->PMSStatus = SK_MS_STAT_FAULT; 1669 1670 return(SK_HW_PS_RESTART); 1671 } 1672 1673 /* Read PHY Specific Status */ 1674 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); 1675 1676 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1677 ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat)); 1678 1679#ifdef DEBUG 1680 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word); 1681 1682 if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 || 1683 (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) { 1684 /* Read PHY Next Page Link Partner */ 1685 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word); 1686 1687 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1688 ("Page Received, NextPage: 0x%04X\n", Word)); 1689 } 1690#endif /* DEBUG */ 1691 1692 if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { 1693 return(SK_HW_PS_NONE); 1694 } 1695 1696 if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 || 1697 (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) { 1698 /* Downshift detected */ 1699 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG); 1700 1701 Para.Para64 = Port; 1702 SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para); 1703 1704 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1705 ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc)); 1706 } 1707 1708 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? 1709 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; 1710 1711 pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); 1712 1713 if (AutoNeg) { 1714 /* Auto-Negotiation Over ? */ 1715 if ((PhyStat & PHY_ST_AN_OVER) != 0) { 1716 1717 SkHWLinkUp(pAC, IoC, Port); 1718 1719 Done = SkMacAutoNegDone(pAC, IoC, Port); 1720 1721 if (Done != SK_AND_OK) { 1722 return(SK_HW_PS_RESTART); 1723 } 1724 1725 return(SK_HW_PS_LINK); 1726 } 1727 } 1728 else { /* !AutoNeg */ 1729 /* Link is up and we don't need more */ 1730#ifdef DEBUG 1731 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { 1732 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1733 ("ERROR: Lipa auto detected on port %d\n", Port)); 1734 } 1735#endif /* DEBUG */ 1736 1737 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1738 ("Link sync, Port %d\n", Port)); 1739 SkHWLinkUp(pAC, IoC, Port); 1740 1741 return(SK_HW_PS_LINK); 1742 } 1743 1744 return(SK_HW_PS_NONE); 1745} /* SkGePortCheckUpGmac */ 1746#endif /* YUKON */ 1747 1748 1749#ifdef OTHER_PHY 1750/****************************************************************************** 1751 * 1752 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY 1753 * 1754 * return: 1755 * 0 o.k. nothing needed 1756 * 1 Restart needed on this port 1757 * 2 Link came up 1758 */ 1759static int SkGePortCheckUpLone( 1760SK_AC *pAC, /* Adapter Context */ 1761SK_IOC IoC, /* IO Context */ 1762int Port, /* Which port should be checked */ 1763SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ 1764{ 1765 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 1766 int Done; 1767 SK_U16 Isrc; /* Interrupt source register */ 1768 SK_U16 LpAb; /* Link Partner Ability */ 1769 SK_U16 ExtStat; /* Extended Status Register */ 1770 SK_U16 PhyStat; /* Phy Status Register */ 1771 SK_U16 StatSum; 1772 SK_U8 NextMode; /* Next AutoSensing Mode */ 1773 1774 pPrt = &pAC->GIni.GP[Port]; 1775 1776 if (pPrt->PHWLinkUp) { 1777 return(SK_HW_PS_NONE); 1778 } 1779 1780 StatSum = pPrt->PIsave; 1781 pPrt->PIsave = 0; 1782 1783 /* 1784 * here we usually can check whether the link is in sync and 1785 * auto-negotiation is done. 1786 */ 1787 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat); 1788 StatSum |= PhyStat; 1789 1790 SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); 1791 1792 if ((PhyStat & PHY_ST_LSYNC) == 0) { 1793 /* Save Auto-negotiation Done bit */ 1794 pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER); 1795#ifdef DEBUG 1796 if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) { 1797 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1798 ("AutoNeg done rescheduled Port %d\n", Port)); 1799 } 1800#endif /* DEBUG */ 1801 return(SK_HW_PS_NONE); 1802 } 1803 1804 if (AutoNeg) { 1805 if ((StatSum & PHY_ST_AN_OVER) != 0) { 1806 SkHWLinkUp(pAC, IoC, Port); 1807 Done = SkMacAutoNegDone(pAC, IoC, Port); 1808 if (Done != SK_AND_OK) { 1809 /* Get PHY parameters, for debugging only */ 1810 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); 1811 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat); 1812 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1813 ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", 1814 Port, LpAb, ExtStat)); 1815 1816 /* Try next possible mode */ 1817 NextMode = SkHWSenseGetNext(pAC, IoC, Port); 1818 SkHWLinkDown(pAC, IoC, Port); 1819 if (Done == SK_AND_DUP_CAP) { 1820 /* GoTo next mode */ 1821 SkHWSenseSetNext(pAC, IoC, Port, NextMode); 1822 } 1823 1824 return(SK_HW_PS_RESTART); 1825 1826 } 1827 else { 1828 /* 1829 * Dummy Read interrupt status to prevent 1830 * extra link down/ups 1831 */ 1832 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); 1833 return(SK_HW_PS_LINK); 1834 } 1835 } 1836 1837 /* AutoNeg not done, but HW link is up. Check for timeouts */ 1838 pPrt->PAutoNegTimeOut++; 1839 if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { 1840 /* Timeout occured */ 1841 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1842 ("AutoNeg timeout Port %d\n", Port)); 1843 if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && 1844 pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { 1845 /* Set Link manually up */ 1846 SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); 1847 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1848 ("Set manual full duplex Port %d\n", Port)); 1849 } 1850 1851 /* Do the restart */ 1852 return(SK_HW_PS_RESTART); 1853 } 1854 } 1855 else { 1856 /* Link is up and we don't need more */ 1857#ifdef DEBUG 1858 if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { 1859 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1860 ("ERROR: Lipa auto detected on port %d\n", Port)); 1861 } 1862#endif /* DEBUG */ 1863 1864 /* 1865 * Dummy Read interrupt status to prevent 1866 * extra link down/ups 1867 */ 1868 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); 1869 1870 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 1871 ("Link sync(GP), Port %d\n", Port)); 1872 SkHWLinkUp(pAC, IoC, Port); 1873 1874 return(SK_HW_PS_LINK); 1875 } 1876 1877 return(SK_HW_PS_NONE); 1878} /* SkGePortCheckUpLone */ 1879 1880 1881/****************************************************************************** 1882 * 1883 * SkGePortCheckUpNat() - Check if the link is up on National PHY 1884 * 1885 * return: 1886 * 0 o.k. nothing needed 1887 * 1 Restart needed on this port 1888 * 2 Link came up 1889 */ 1890static int SkGePortCheckUpNat( 1891SK_AC *pAC, /* Adapter Context */ 1892SK_IOC IoC, /* IO Context */ 1893int Port, /* Which port should be checked */ 1894SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ 1895{ 1896 /* todo: National */ 1897 return(SK_HW_PS_NONE); 1898} /* SkGePortCheckUpNat */ 1899#endif /* OTHER_PHY */ 1900 1901 1902/****************************************************************************** 1903 * 1904 * SkGeSirqEvent() - Event Service Routine 1905 * 1906 * Description: 1907 * 1908 * Notes: 1909 */ 1910int SkGeSirqEvent( 1911SK_AC *pAC, /* Adapter Context */ 1912SK_IOC IoC, /* Io Context */ 1913SK_U32 Event, /* Module specific Event */ 1914SK_EVPARA Para) /* Event specific Parameter */ 1915{ 1916 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 1917 SK_U32 Port; 1918 SK_U32 Val32; 1919 int PortStat; 1920 SK_U8 Val8; 1921#ifdef GENESIS 1922 SK_U64 Octets; 1923#endif /* GENESIS */ 1924 1925 Port = Para.Para32[0]; 1926 pPrt = &pAC->GIni.GP[Port]; 1927 1928 switch (Event) { 1929 case SK_HWEV_WATIM: 1930 if (pPrt->PState == SK_PRT_RESET) { 1931 1932 PortStat = SK_HW_PS_NONE; 1933 } 1934 else { 1935 /* Check whether port came up */ 1936 PortStat = SkGePortCheckUp(pAC, IoC, (int)Port); 1937 } 1938 1939 switch (PortStat) { 1940 case SK_HW_PS_RESTART: 1941 if (pPrt->PHWLinkUp) { 1942 /* Set Link to down */ 1943 SkHWLinkDown(pAC, IoC, (int)Port); 1944 1945 /* 1946 * Signal directly to RLMT to ensure correct 1947 * sequence of SWITCH and RESET event. 1948 */ 1949 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); 1950 } 1951 1952 /* Restart needed */ 1953 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); 1954 break; 1955 1956 case SK_HW_PS_LINK: 1957 /* Signal to RLMT */ 1958 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); 1959 break; 1960 } 1961 1962 /* Start again the check Timer */ 1963 if (pPrt->PHWLinkUp) { 1964 Val32 = SK_WA_ACT_TIME; 1965 } 1966 else { 1967 Val32 = SK_WA_INA_TIME; 1968 } 1969 1970 /* Todo: still needed for non-XMAC PHYs??? */ 1971 /* Start workaround Errata #2 timer */ 1972 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32, 1973 SKGE_HWAC, SK_HWEV_WATIM, Para); 1974 break; 1975 1976 case SK_HWEV_PORT_START: 1977 if (pPrt->PHWLinkUp) { 1978 /* 1979 * Signal directly to RLMT to ensure correct 1980 * sequence of SWITCH and RESET event. 1981 */ 1982 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); 1983 } 1984 1985 SkHWLinkDown(pAC, IoC, (int)Port); 1986 1987 /* Schedule Port RESET */ 1988 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); 1989 1990 /* Start workaround Errata #2 timer */ 1991 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, 1992 SKGE_HWAC, SK_HWEV_WATIM, Para); 1993 break; 1994 1995 case SK_HWEV_PORT_STOP: 1996 if (pPrt->PHWLinkUp) { 1997 /* 1998 * Signal directly to RLMT to ensure correct 1999 * sequence of SWITCH and RESET event. 2000 */ 2001 SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); 2002 } 2003 2004 /* Stop Workaround Timer */ 2005 SkTimerStop(pAC, IoC, &pPrt->PWaTimer); 2006 2007 SkHWLinkDown(pAC, IoC, (int)Port); 2008 break; 2009 2010 case SK_HWEV_UPDATE_STAT: 2011 /* We do NOT need to update any statistics */ 2012 break; 2013 2014 case SK_HWEV_CLEAR_STAT: 2015 /* We do NOT need to clear any statistics */ 2016 for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) { 2017 pPrt->PPrevRx = 0; 2018 pPrt->PPrevFcs = 0; 2019 pPrt->PPrevShorts = 0; 2020 } 2021 break; 2022 2023 case SK_HWEV_SET_LMODE: 2024 Val8 = (SK_U8)Para.Para32[1]; 2025 if (pPrt->PLinkModeConf != Val8) { 2026 /* Set New link mode */ 2027 pPrt->PLinkModeConf = Val8; 2028 2029 /* Restart Port */ 2030 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); 2031 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); 2032 } 2033 break; 2034 2035 case SK_HWEV_SET_FLOWMODE: 2036 Val8 = (SK_U8)Para.Para32[1]; 2037 if (pPrt->PFlowCtrlMode != Val8) { 2038 /* Set New Flow Control mode */ 2039 pPrt->PFlowCtrlMode = Val8; 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_ROLE: 2048 /* not possible for fiber */ 2049 if (!pAC->GIni.GICopperType) { 2050 break; 2051 } 2052 Val8 = (SK_U8)Para.Para32[1]; 2053 if (pPrt->PMSMode != Val8) { 2054 /* Set New Role (Master/Slave) mode */ 2055 pPrt->PMSMode = Val8; 2056 2057 /* Restart Port */ 2058 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); 2059 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); 2060 } 2061 break; 2062 2063 case SK_HWEV_SET_SPEED: 2064 if (pPrt->PhyType != SK_PHY_MARV_COPPER) { 2065 break; 2066 } 2067 Val8 = (SK_U8)Para.Para32[1]; 2068 if (pPrt->PLinkSpeed != Val8) { 2069 /* Set New Speed parameter */ 2070 pPrt->PLinkSpeed = Val8; 2071 2072 /* Restart Port */ 2073 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); 2074 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); 2075 } 2076 break; 2077 2078#ifdef GENESIS 2079 case SK_HWEV_HALFDUP_CHK: 2080 if (pAC->GIni.GIGenesis) { 2081 /* 2082 * half duplex hangup workaround. 2083 * See packet arbiter timeout interrupt for description 2084 */ 2085 pPrt->HalfDupTimerActive = SK_FALSE; 2086 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || 2087 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { 2088#ifdef XXX 2089 Len = sizeof(SK_U64); 2090 SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets, 2091 &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port), 2092 pAC->Rlmt.Port[Port].Net->NetNumber); 2093#endif /* XXX */ 2094 /* Snap statistic counters */ 2095 (void)SkXmUpdateStats(pAC, IoC, Port); 2096 2097 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32); 2098 2099 Octets = (SK_U64)Val32 << 32; 2100 2101 (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32); 2102 2103 Octets += Val32; 2104 2105 if (pPrt->LastOctets == Octets) { 2106 /* Tx hanging, a FIFO flush restarts it */ 2107 SkMacFlushTxFifo(pAC, IoC, Port); 2108 } 2109 } 2110 } 2111 break; 2112#endif /* GENESIS */ 2113 2114 default: 2115 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); 2116 break; 2117 } 2118 2119 return(0); 2120} /* SkGeSirqEvent */ 2121 2122 2123#ifdef GENESIS 2124/****************************************************************************** 2125 * 2126 * SkPhyIsrBcom() - PHY interrupt service routine 2127 * 2128 * Description: handles all interrupts from BCom PHY 2129 * 2130 * Returns: N/A 2131 */ 2132static void SkPhyIsrBcom( 2133SK_AC *pAC, /* Adapter Context */ 2134SK_IOC IoC, /* Io Context */ 2135int Port, /* Port Num = PHY Num */ 2136SK_U16 IStatus) /* Interrupt Status */ 2137{ 2138 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 2139 SK_EVPARA Para; 2140 2141 pPrt = &pAC->GIni.GP[Port]; 2142 2143 if ((IStatus & PHY_B_IS_PSE) != 0) { 2144 /* Incorrectable pair swap error */ 2145 SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022, 2146 SKERR_SIRQ_E022MSG); 2147 } 2148 2149 if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { 2150 2151 SkHWLinkDown(pAC, IoC, Port); 2152 2153 Para.Para32[0] = (SK_U32)Port; 2154 /* Signal to RLMT */ 2155 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 2156 2157 /* Start workaround Errata #2 timer */ 2158 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, 2159 SKGE_HWAC, SK_HWEV_WATIM, Para); 2160 } 2161 2162} /* SkPhyIsrBcom */ 2163#endif /* GENESIS */ 2164 2165 2166#ifdef YUKON 2167/****************************************************************************** 2168 * 2169 * SkPhyIsrGmac() - PHY interrupt service routine 2170 * 2171 * Description: handles all interrupts from Marvell PHY 2172 * 2173 * Returns: N/A 2174 */ 2175static void SkPhyIsrGmac( 2176SK_AC *pAC, /* Adapter Context */ 2177SK_IOC IoC, /* Io Context */ 2178int Port, /* Port Num = PHY Num */ 2179SK_U16 IStatus) /* Interrupt Status */ 2180{ 2181 SK_GEPORT *pPrt; /* GIni Port struct pointer */ 2182 SK_EVPARA Para; 2183 SK_U16 Word; 2184 2185 pPrt = &pAC->GIni.GP[Port]; 2186 2187 if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { 2188 2189 SkHWLinkDown(pAC, IoC, Port); 2190 2191 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word); 2192 2193 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2194 ("AutoNeg.Adv: 0x%04X\n", Word)); 2195 2196 /* Set Auto-negotiation advertisement */ 2197 if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) { 2198 /* restore Asymmetric Pause bit */ 2199 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, 2200 (SK_U16)(Word | PHY_M_AN_ASP)); 2201 } 2202 2203 Para.Para32[0] = (SK_U32)Port; 2204 /* Signal to RLMT */ 2205 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 2206 } 2207 2208 if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { 2209 /* Auto-Negotiation Error */ 2210 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); 2211 } 2212 2213 if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { 2214 /* FIFO Overflow/Underrun Error */ 2215 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); 2216 } 2217 2218} /* SkPhyIsrGmac */ 2219#endif /* YUKON */ 2220 2221 2222#ifdef OTHER_PHY 2223/****************************************************************************** 2224 * 2225 * SkPhyIsrLone() - PHY interrupt service routine 2226 * 2227 * Description: handles all interrupts from LONE PHY 2228 * 2229 * Returns: N/A 2230 */ 2231static void SkPhyIsrLone( 2232SK_AC *pAC, /* Adapter Context */ 2233SK_IOC IoC, /* Io Context */ 2234int Port, /* Port Num = PHY Num */ 2235SK_U16 IStatus) /* Interrupt Status */ 2236{ 2237 SK_EVPARA Para; 2238 2239 if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { 2240 2241 SkHWLinkDown(pAC, IoC, Port); 2242 2243 Para.Para32[0] = (SK_U32)Port; 2244 /* Signal to RLMT */ 2245 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 2246 } 2247 2248} /* SkPhyIsrLone */ 2249#endif /* OTHER_PHY */ 2250 2251/* End of File */