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