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