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