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