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