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