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