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