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