Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / net / sk98lin / skxmac2.c
blobb4e75022a657f5b125fca3056fe1672a6aeb0517
1 /******************************************************************************
3 * Name: skxmac2.c
4 * Project: Gigabit Ethernet Adapters, Common Modules
5 * Version: $Revision: 1.102 $
6 * Date: $Date: 2003/10/02 16:53:58 $
7 * Purpose: Contains functions to initialize the MACs and PHYs
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect.
14 * (C)Copyright 2002-2003 Marvell.
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.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
25 #include "h/skdrv1st.h"
26 #include "h/skdrv2nd.h"
28 /* typedefs *******************************************************************/
30 /* BCOM PHY magic pattern list */
31 typedef struct s_PhyHack {
32 int PhyReg; /* Phy register */
33 SK_U16 PhyVal; /* Value to write */
34 } BCOM_HACK;
36 /* local variables ************************************************************/
38 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
39 static const char SysKonnectFileId[] =
40 "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
41 #endif
43 #ifdef GENESIS
44 static BCOM_HACK BcomRegA1Hack[] = {
45 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
46 { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
47 { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
48 { 0, 0 }
50 static BCOM_HACK BcomRegC0Hack[] = {
51 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
52 { 0x15, 0x0A04 }, { 0x18, 0x0420 },
53 { 0, 0 }
55 #endif
57 /* function prototypes ********************************************************/
58 #ifdef GENESIS
59 static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
60 static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
61 static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
62 static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
63 #endif /* GENESIS */
64 #ifdef YUKON
65 static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
66 static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
67 #endif /* YUKON */
68 #ifdef OTHER_PHY
69 static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
70 static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
71 static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
72 static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
73 #endif /* OTHER_PHY */
76 #ifdef GENESIS
77 /******************************************************************************
79 * SkXmPhyRead() - Read from XMAC PHY register
81 * Description: reads a 16-bit word from XMAC PHY or ext. PHY
83 * Returns:
84 * nothing
86 void SkXmPhyRead(
87 SK_AC *pAC, /* Adapter Context */
88 SK_IOC IoC, /* I/O Context */
89 int Port, /* Port Index (MAC_1 + n) */
90 int PhyReg, /* Register Address (Offset) */
91 SK_U16 SK_FAR *pVal) /* Pointer to Value */
93 SK_U16 Mmu;
94 SK_GEPORT *pPrt;
96 pPrt = &pAC->GIni.GP[Port];
98 /* write the PHY register's address */
99 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
101 /* get the PHY register's value */
102 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
104 if (pPrt->PhyType != SK_PHY_XMAC) {
105 do {
106 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
107 /* wait until 'Ready' is set */
108 } while ((Mmu & XM_MMU_PHY_RDY) == 0);
110 /* get the PHY register's value */
111 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
113 } /* SkXmPhyRead */
116 /******************************************************************************
118 * SkXmPhyWrite() - Write to XMAC PHY register
120 * Description: writes a 16-bit word to XMAC PHY or ext. PHY
122 * Returns:
123 * nothing
125 void SkXmPhyWrite(
126 SK_AC *pAC, /* Adapter Context */
127 SK_IOC IoC, /* I/O Context */
128 int Port, /* Port Index (MAC_1 + n) */
129 int PhyReg, /* Register Address (Offset) */
130 SK_U16 Val) /* Value */
132 SK_U16 Mmu;
133 SK_GEPORT *pPrt;
135 pPrt = &pAC->GIni.GP[Port];
137 if (pPrt->PhyType != SK_PHY_XMAC) {
138 do {
139 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
140 /* wait until 'Busy' is cleared */
141 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
144 /* write the PHY register's address */
145 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
147 /* write the PHY register's value */
148 XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
150 if (pPrt->PhyType != SK_PHY_XMAC) {
151 do {
152 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
153 /* wait until 'Busy' is cleared */
154 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
156 } /* SkXmPhyWrite */
157 #endif /* GENESIS */
160 #ifdef YUKON
161 /******************************************************************************
163 * SkGmPhyRead() - Read from GPHY register
165 * Description: reads a 16-bit word from GPHY through MDIO
167 * Returns:
168 * nothing
170 void SkGmPhyRead(
171 SK_AC *pAC, /* Adapter Context */
172 SK_IOC IoC, /* I/O Context */
173 int Port, /* Port Index (MAC_1 + n) */
174 int PhyReg, /* Register Address (Offset) */
175 SK_U16 SK_FAR *pVal) /* Pointer to Value */
177 SK_U16 Ctrl;
178 SK_GEPORT *pPrt;
179 #ifdef VCPU
180 u_long SimCyle;
181 u_long SimLowTime;
183 VCPUgetTime(&SimCyle, &SimLowTime);
184 VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
185 PhyReg, SimCyle, SimLowTime);
186 #endif /* VCPU */
188 pPrt = &pAC->GIni.GP[Port];
190 /* set PHY-Register offset and 'Read' OpCode (= 1) */
191 *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
192 GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
194 GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
196 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
198 /* additional check for MDC/MDIO activity */
199 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
200 *pVal = 0;
201 return;
204 *pVal |= GM_SMI_CT_BUSY;
206 do {
207 #ifdef VCPU
208 VCPUwaitTime(1000);
209 #endif /* VCPU */
211 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
213 /* wait until 'ReadValid' is set */
214 } while (Ctrl == *pVal);
216 /* get the PHY register's value */
217 GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
219 #ifdef VCPU
220 VCPUgetTime(&SimCyle, &SimLowTime);
221 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
222 SimCyle, SimLowTime);
223 #endif /* VCPU */
225 } /* SkGmPhyRead */
228 /******************************************************************************
230 * SkGmPhyWrite() - Write to GPHY register
232 * Description: writes a 16-bit word to GPHY through MDIO
234 * Returns:
235 * nothing
237 void SkGmPhyWrite(
238 SK_AC *pAC, /* Adapter Context */
239 SK_IOC IoC, /* I/O Context */
240 int Port, /* Port Index (MAC_1 + n) */
241 int PhyReg, /* Register Address (Offset) */
242 SK_U16 Val) /* Value */
244 SK_U16 Ctrl;
245 SK_GEPORT *pPrt;
246 #ifdef VCPU
247 SK_U32 DWord;
248 u_long SimCyle;
249 u_long SimLowTime;
251 VCPUgetTime(&SimCyle, &SimLowTime);
252 VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
253 PhyReg, Val, SimCyle, SimLowTime);
254 #endif /* VCPU */
256 pPrt = &pAC->GIni.GP[Port];
258 /* write the PHY register's value */
259 GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
261 /* set PHY-Register offset and 'Write' OpCode (= 0) */
262 Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
264 GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
266 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
268 /* additional check for MDC/MDIO activity */
269 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
270 return;
273 Val |= GM_SMI_CT_BUSY;
275 do {
276 #ifdef VCPU
277 /* read Timer value */
278 SK_IN32(IoC, B2_TI_VAL, &DWord);
280 VCPUwaitTime(1000);
281 #endif /* VCPU */
283 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
285 /* wait until 'Busy' is cleared */
286 } while (Ctrl == Val);
288 #ifdef VCPU
289 VCPUgetTime(&SimCyle, &SimLowTime);
290 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
291 SimCyle, SimLowTime);
292 #endif /* VCPU */
294 } /* SkGmPhyWrite */
295 #endif /* YUKON */
298 #ifdef SK_DIAG
299 /******************************************************************************
301 * SkGePhyRead() - Read from PHY register
303 * Description: calls a read PHY routine dep. on board type
305 * Returns:
306 * nothing
308 void SkGePhyRead(
309 SK_AC *pAC, /* Adapter Context */
310 SK_IOC IoC, /* I/O Context */
311 int Port, /* Port Index (MAC_1 + n) */
312 int PhyReg, /* Register Address (Offset) */
313 SK_U16 *pVal) /* Pointer to Value */
315 void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
317 if (pAC->GIni.GIGenesis) {
318 r_func = SkXmPhyRead;
320 else {
321 r_func = SkGmPhyRead;
324 r_func(pAC, IoC, Port, PhyReg, pVal);
325 } /* SkGePhyRead */
328 /******************************************************************************
330 * SkGePhyWrite() - Write to PHY register
332 * Description: calls a write PHY routine dep. on board type
334 * Returns:
335 * nothing
337 void SkGePhyWrite(
338 SK_AC *pAC, /* Adapter Context */
339 SK_IOC IoC, /* I/O Context */
340 int Port, /* Port Index (MAC_1 + n) */
341 int PhyReg, /* Register Address (Offset) */
342 SK_U16 Val) /* Value */
344 void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
346 if (pAC->GIni.GIGenesis) {
347 w_func = SkXmPhyWrite;
349 else {
350 w_func = SkGmPhyWrite;
353 w_func(pAC, IoC, Port, PhyReg, Val);
354 } /* SkGePhyWrite */
355 #endif /* SK_DIAG */
358 /******************************************************************************
360 * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
362 * Description:
363 * enables / disables promiscuous mode by setting Mode Register (XMAC) or
364 * Receive Control Register (GMAC) dep. on board type
366 * Returns:
367 * nothing
369 void SkMacPromiscMode(
370 SK_AC *pAC, /* adapter context */
371 SK_IOC IoC, /* IO context */
372 int Port, /* Port Index (MAC_1 + n) */
373 SK_BOOL Enable) /* Enable / Disable */
375 #ifdef YUKON
376 SK_U16 RcReg;
377 #endif
378 #ifdef GENESIS
379 SK_U32 MdReg;
380 #endif
382 #ifdef GENESIS
383 if (pAC->GIni.GIGenesis) {
385 XM_IN32(IoC, Port, XM_MODE, &MdReg);
386 /* enable or disable promiscuous mode */
387 if (Enable) {
388 MdReg |= XM_MD_ENA_PROM;
390 else {
391 MdReg &= ~XM_MD_ENA_PROM;
393 /* setup Mode Register */
394 XM_OUT32(IoC, Port, XM_MODE, MdReg);
396 #endif /* GENESIS */
398 #ifdef YUKON
399 if (pAC->GIni.GIYukon) {
401 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
403 /* enable or disable unicast and multicast filtering */
404 if (Enable) {
405 RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
407 else {
408 RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
410 /* setup Receive Control Register */
411 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
413 #endif /* YUKON */
415 } /* SkMacPromiscMode*/
418 /******************************************************************************
420 * SkMacHashing() - Enable / Disable Hashing
422 * Description:
423 * enables / disables hashing by setting Mode Register (XMAC) or
424 * Receive Control Register (GMAC) dep. on board type
426 * Returns:
427 * nothing
429 void SkMacHashing(
430 SK_AC *pAC, /* adapter context */
431 SK_IOC IoC, /* IO context */
432 int Port, /* Port Index (MAC_1 + n) */
433 SK_BOOL Enable) /* Enable / Disable */
435 #ifdef YUKON
436 SK_U16 RcReg;
437 #endif
438 #ifdef GENESIS
439 SK_U32 MdReg;
440 #endif
442 #ifdef GENESIS
443 if (pAC->GIni.GIGenesis) {
445 XM_IN32(IoC, Port, XM_MODE, &MdReg);
446 /* enable or disable hashing */
447 if (Enable) {
448 MdReg |= XM_MD_ENA_HASH;
450 else {
451 MdReg &= ~XM_MD_ENA_HASH;
453 /* setup Mode Register */
454 XM_OUT32(IoC, Port, XM_MODE, MdReg);
456 #endif /* GENESIS */
458 #ifdef YUKON
459 if (pAC->GIni.GIYukon) {
461 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
463 /* enable or disable multicast filtering */
464 if (Enable) {
465 RcReg |= GM_RXCR_MCF_ENA;
467 else {
468 RcReg &= ~GM_RXCR_MCF_ENA;
470 /* setup Receive Control Register */
471 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
473 #endif /* YUKON */
475 } /* SkMacHashing*/
478 #ifdef SK_DIAG
479 /******************************************************************************
481 * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
483 * Description:
484 * The features
485 * - FCS stripping, SK_STRIP_FCS_ON/OFF
486 * - pad byte stripping, SK_STRIP_PAD_ON/OFF
487 * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
488 * for inrange length error frames
489 * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
490 * for frames > 1514 bytes
491 * - enable Rx of own packets SK_SELF_RX_ON/OFF
493 * for incoming packets may be enabled/disabled by this function.
494 * Additional modes may be added later.
495 * Multiple modes can be enabled/disabled at the same time.
496 * The new configuration is written to the Rx Command register immediately.
498 * Returns:
499 * nothing
501 static void SkXmSetRxCmd(
502 SK_AC *pAC, /* adapter context */
503 SK_IOC IoC, /* IO context */
504 int Port, /* Port Index (MAC_1 + n) */
505 int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
506 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
508 SK_U16 OldRxCmd;
509 SK_U16 RxCmd;
511 XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
513 RxCmd = OldRxCmd;
515 switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
516 case SK_STRIP_FCS_ON:
517 RxCmd |= XM_RX_STRIP_FCS;
518 break;
519 case SK_STRIP_FCS_OFF:
520 RxCmd &= ~XM_RX_STRIP_FCS;
521 break;
524 switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
525 case SK_STRIP_PAD_ON:
526 RxCmd |= XM_RX_STRIP_PAD;
527 break;
528 case SK_STRIP_PAD_OFF:
529 RxCmd &= ~XM_RX_STRIP_PAD;
530 break;
533 switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
534 case SK_LENERR_OK_ON:
535 RxCmd |= XM_RX_LENERR_OK;
536 break;
537 case SK_LENERR_OK_OFF:
538 RxCmd &= ~XM_RX_LENERR_OK;
539 break;
542 switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
543 case SK_BIG_PK_OK_ON:
544 RxCmd |= XM_RX_BIG_PK_OK;
545 break;
546 case SK_BIG_PK_OK_OFF:
547 RxCmd &= ~XM_RX_BIG_PK_OK;
548 break;
551 switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
552 case SK_SELF_RX_ON:
553 RxCmd |= XM_RX_SELF_RX;
554 break;
555 case SK_SELF_RX_OFF:
556 RxCmd &= ~XM_RX_SELF_RX;
557 break;
560 /* Write the new mode to the Rx command register if required */
561 if (OldRxCmd != RxCmd) {
562 XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
564 } /* SkXmSetRxCmd */
567 /******************************************************************************
569 * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
571 * Description:
572 * The features
573 * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
574 * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
575 * for frames > 1514 bytes
576 * - enable Rx of own packets SK_SELF_RX_ON/OFF
578 * for incoming packets may be enabled/disabled by this function.
579 * Additional modes may be added later.
580 * Multiple modes can be enabled/disabled at the same time.
581 * The new configuration is written to the Rx Command register immediately.
583 * Returns:
584 * nothing
586 static void SkGmSetRxCmd(
587 SK_AC *pAC, /* adapter context */
588 SK_IOC IoC, /* IO context */
589 int Port, /* Port Index (MAC_1 + n) */
590 int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
591 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
593 SK_U16 OldRxCmd;
594 SK_U16 RxCmd;
596 if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
598 GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
600 RxCmd = OldRxCmd;
602 if ((Mode & SK_STRIP_FCS_ON) != 0) {
603 RxCmd |= GM_RXCR_CRC_DIS;
605 else {
606 RxCmd &= ~GM_RXCR_CRC_DIS;
608 /* Write the new mode to the Rx control register if required */
609 if (OldRxCmd != RxCmd) {
610 GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
614 if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
616 GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
618 RxCmd = OldRxCmd;
620 if ((Mode & SK_BIG_PK_OK_ON) != 0) {
621 RxCmd |= GM_SMOD_JUMBO_ENA;
623 else {
624 RxCmd &= ~GM_SMOD_JUMBO_ENA;
626 /* Write the new mode to the Rx control register if required */
627 if (OldRxCmd != RxCmd) {
628 GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
631 } /* SkGmSetRxCmd */
634 /******************************************************************************
636 * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
638 * Description: modifies the MAC's Rx Control reg. dep. on board type
640 * Returns:
641 * nothing
643 void SkMacSetRxCmd(
644 SK_AC *pAC, /* adapter context */
645 SK_IOC IoC, /* IO context */
646 int Port, /* Port Index (MAC_1 + n) */
647 int Mode) /* Rx Mode */
649 if (pAC->GIni.GIGenesis) {
651 SkXmSetRxCmd(pAC, IoC, Port, Mode);
653 else {
655 SkGmSetRxCmd(pAC, IoC, Port, Mode);
658 } /* SkMacSetRxCmd */
661 /******************************************************************************
663 * SkMacCrcGener() - Enable / Disable CRC Generation
665 * Description: enables / disables CRC generation dep. on board type
667 * Returns:
668 * nothing
670 void SkMacCrcGener(
671 SK_AC *pAC, /* adapter context */
672 SK_IOC IoC, /* IO context */
673 int Port, /* Port Index (MAC_1 + n) */
674 SK_BOOL Enable) /* Enable / Disable */
676 SK_U16 Word;
678 if (pAC->GIni.GIGenesis) {
680 XM_IN16(IoC, Port, XM_TX_CMD, &Word);
682 if (Enable) {
683 Word &= ~XM_TX_NO_CRC;
685 else {
686 Word |= XM_TX_NO_CRC;
688 /* setup Tx Command Register */
689 XM_OUT16(IoC, Port, XM_TX_CMD, Word);
691 else {
693 GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
695 if (Enable) {
696 Word &= ~GM_TXCR_CRC_DIS;
698 else {
699 Word |= GM_TXCR_CRC_DIS;
701 /* setup Tx Control Register */
702 GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
705 } /* SkMacCrcGener*/
707 #endif /* SK_DIAG */
710 #ifdef GENESIS
711 /******************************************************************************
713 * SkXmClrExactAddr() - Clear Exact Match Address Registers
715 * Description:
716 * All Exact Match Address registers of the XMAC 'Port' will be
717 * cleared starting with 'StartNum' up to (and including) the
718 * Exact Match address number of 'StopNum'.
720 * Returns:
721 * nothing
723 void SkXmClrExactAddr(
724 SK_AC *pAC, /* adapter context */
725 SK_IOC IoC, /* IO context */
726 int Port, /* Port Index (MAC_1 + n) */
727 int StartNum, /* Begin with this Address Register Index (0..15) */
728 int StopNum) /* Stop after finished with this Register Idx (0..15) */
730 int i;
731 SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
733 if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
734 StartNum > StopNum) {
736 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
737 return;
740 for (i = StartNum; i <= StopNum; i++) {
741 XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
743 } /* SkXmClrExactAddr */
744 #endif /* GENESIS */
747 /******************************************************************************
749 * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
751 * Description:
752 * Flush the transmit FIFO of the MAC specified by the index 'Port'
754 * Returns:
755 * nothing
757 void SkMacFlushTxFifo(
758 SK_AC *pAC, /* adapter context */
759 SK_IOC IoC, /* IO context */
760 int Port) /* Port Index (MAC_1 + n) */
762 #ifdef GENESIS
763 SK_U32 MdReg;
765 if (pAC->GIni.GIGenesis) {
767 XM_IN32(IoC, Port, XM_MODE, &MdReg);
769 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
771 #endif /* GENESIS */
773 #ifdef YUKON
774 if (pAC->GIni.GIYukon) {
775 /* no way to flush the FIFO we have to issue a reset */
776 /* TBD */
778 #endif /* YUKON */
780 } /* SkMacFlushTxFifo */
783 /******************************************************************************
785 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
787 * Description:
788 * Flush the receive FIFO of the MAC specified by the index 'Port'
790 * Returns:
791 * nothing
793 static void SkMacFlushRxFifo(
794 SK_AC *pAC, /* adapter context */
795 SK_IOC IoC, /* IO context */
796 int Port) /* Port Index (MAC_1 + n) */
798 #ifdef GENESIS
799 SK_U32 MdReg;
801 if (pAC->GIni.GIGenesis) {
803 XM_IN32(IoC, Port, XM_MODE, &MdReg);
805 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
807 #endif /* GENESIS */
809 #ifdef YUKON
810 if (pAC->GIni.GIYukon) {
811 /* no way to flush the FIFO we have to issue a reset */
812 /* TBD */
814 #endif /* YUKON */
816 } /* SkMacFlushRxFifo */
819 #ifdef GENESIS
820 /******************************************************************************
822 * SkXmSoftRst() - Do a XMAC software reset
824 * Description:
825 * The PHY registers should not be destroyed during this
826 * kind of software reset. Therefore the XMAC Software Reset
827 * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
829 * The software reset is done by
830 * - disabling the Rx and Tx state machine,
831 * - resetting the statistics module,
832 * - clear all other significant XMAC Mode,
833 * Command, and Control Registers
834 * - clearing the Hash Register and the
835 * Exact Match Address registers, and
836 * - flushing the XMAC's Rx and Tx FIFOs.
838 * Note:
839 * Another requirement when stopping the XMAC is to
840 * avoid sending corrupted frames on the network.
841 * Disabling the Tx state machine will NOT interrupt
842 * the currently transmitted frame. But we must take care
843 * that the Tx FIFO is cleared AFTER the current frame
844 * is complete sent to the network.
846 * It takes about 12ns to send a frame with 1538 bytes.
847 * One PCI clock goes at least 15ns (66MHz). Therefore
848 * after reading XM_GP_PORT back, we are sure that the
849 * transmitter is disabled AND idle. And this means
850 * we may flush the transmit FIFO now.
852 * Returns:
853 * nothing
855 static void SkXmSoftRst(
856 SK_AC *pAC, /* adapter context */
857 SK_IOC IoC, /* IO context */
858 int Port) /* Port Index (MAC_1 + n) */
860 SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
862 /* reset the statistics module */
863 XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
865 /* disable all XMAC IRQs */
866 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
868 XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
870 XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
871 XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
873 /* disable all PHY IRQs */
874 switch (pAC->GIni.GP[Port].PhyType) {
875 case SK_PHY_BCOM:
876 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
877 break;
878 #ifdef OTHER_PHY
879 case SK_PHY_LONE:
880 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
881 break;
882 case SK_PHY_NAT:
883 /* todo: National
884 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
885 break;
886 #endif /* OTHER_PHY */
889 /* clear the Hash Register */
890 XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
892 /* clear the Exact Match Address registers */
893 SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
895 /* clear the Source Check Address registers */
896 XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
898 } /* SkXmSoftRst */
901 /******************************************************************************
903 * SkXmHardRst() - Do a XMAC hardware reset
905 * Description:
906 * The XMAC of the specified 'Port' and all connected devices
907 * (PHY and SERDES) will receive a reset signal on its *Reset pins.
908 * External PHYs must be reset by clearing a bit in the GPIO register
909 * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
911 * ATTENTION:
912 * It is absolutely necessary to reset the SW_RST Bit first
913 * before calling this function.
915 * Returns:
916 * nothing
918 static void SkXmHardRst(
919 SK_AC *pAC, /* adapter context */
920 SK_IOC IoC, /* IO context */
921 int Port) /* Port Index (MAC_1 + n) */
923 SK_U32 Reg;
924 int i;
925 int TOut;
926 SK_U16 Word;
928 for (i = 0; i < 4; i++) {
929 /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
930 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
932 TOut = 0;
933 do {
934 if (TOut++ > 10000) {
936 * Adapter seems to be in RESET state.
937 * Registers cannot be written.
939 return;
942 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
944 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
946 } while ((Word & MFF_SET_MAC_RST) == 0);
949 /* For external PHYs there must be special handling */
950 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
952 SK_IN32(IoC, B2_GP_IO, &Reg);
954 if (Port == 0) {
955 Reg |= GP_DIR_0; /* set to output */
956 Reg &= ~GP_IO_0; /* set PHY reset (active low) */
958 else {
959 Reg |= GP_DIR_2; /* set to output */
960 Reg &= ~GP_IO_2; /* set PHY reset (active low) */
962 /* reset external PHY */
963 SK_OUT32(IoC, B2_GP_IO, Reg);
965 /* short delay */
966 SK_IN32(IoC, B2_GP_IO, &Reg);
968 } /* SkXmHardRst */
971 /******************************************************************************
973 * SkXmClearRst() - Release the PHY & XMAC reset
975 * Description:
977 * Returns:
978 * nothing
980 static void SkXmClearRst(
981 SK_AC *pAC, /* adapter context */
982 SK_IOC IoC, /* IO context */
983 int Port) /* Port Index (MAC_1 + n) */
985 SK_U32 DWord;
987 /* clear HW reset */
988 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
990 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
992 SK_IN32(IoC, B2_GP_IO, &DWord);
994 if (Port == 0) {
995 DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
997 else {
998 DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
1000 /* Clear PHY reset */
1001 SK_OUT32(IoC, B2_GP_IO, DWord);
1003 /* Enable GMII interface */
1004 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
1006 } /* SkXmClearRst */
1007 #endif /* GENESIS */
1010 #ifdef YUKON
1011 /******************************************************************************
1013 * SkGmSoftRst() - Do a GMAC software reset
1015 * Description:
1016 * The GPHY registers should not be destroyed during this
1017 * kind of software reset.
1019 * Returns:
1020 * nothing
1022 static void SkGmSoftRst(
1023 SK_AC *pAC, /* adapter context */
1024 SK_IOC IoC, /* IO context */
1025 int Port) /* Port Index (MAC_1 + n) */
1027 SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1028 SK_U16 RxCtrl;
1030 /* reset the statistics module */
1032 /* disable all GMAC IRQs */
1033 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
1035 /* disable all PHY IRQs */
1036 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
1038 /* clear the Hash Register */
1039 GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
1041 /* Enable Unicast and Multicast filtering */
1042 GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
1044 GM_OUT16(IoC, Port, GM_RX_CTRL,
1045 (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
1047 } /* SkGmSoftRst */
1050 /******************************************************************************
1052 * SkGmHardRst() - Do a GMAC hardware reset
1054 * Description:
1056 * Returns:
1057 * nothing
1059 static void SkGmHardRst(
1060 SK_AC *pAC, /* adapter context */
1061 SK_IOC IoC, /* IO context */
1062 int Port) /* Port Index (MAC_1 + n) */
1064 SK_U32 DWord;
1066 /* WA code for COMA mode */
1067 if (pAC->GIni.GIYukonLite &&
1068 pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
1070 SK_IN32(IoC, B2_GP_IO, &DWord);
1072 DWord |= (GP_DIR_9 | GP_IO_9);
1074 /* set PHY reset */
1075 SK_OUT32(IoC, B2_GP_IO, DWord);
1078 /* set GPHY Control reset */
1079 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1081 /* set GMAC Control reset */
1082 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1084 } /* SkGmHardRst */
1087 /******************************************************************************
1089 * SkGmClearRst() - Release the GPHY & GMAC reset
1091 * Description:
1093 * Returns:
1094 * nothing
1096 static void SkGmClearRst(
1097 SK_AC *pAC, /* adapter context */
1098 SK_IOC IoC, /* IO context */
1099 int Port) /* Port Index (MAC_1 + n) */
1101 SK_U32 DWord;
1103 #ifdef XXX
1104 /* clear GMAC Control reset */
1105 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
1107 /* set GMAC Control reset */
1108 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1109 #endif /* XXX */
1111 /* WA code for COMA mode */
1112 if (pAC->GIni.GIYukonLite &&
1113 pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
1115 SK_IN32(IoC, B2_GP_IO, &DWord);
1117 DWord |= GP_DIR_9; /* set to output */
1118 DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
1120 /* clear PHY reset */
1121 SK_OUT32(IoC, B2_GP_IO, DWord);
1124 /* set HWCFG_MODE */
1125 DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
1126 GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
1127 (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
1128 GPC_HWCFG_GMII_FIB);
1130 /* set GPHY Control reset */
1131 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
1133 /* release GPHY Control reset */
1134 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
1136 #ifdef VCPU
1137 VCpuWait(9000);
1138 #endif /* VCPU */
1140 /* clear GMAC Control reset */
1141 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
1143 #ifdef VCPU
1144 VCpuWait(2000);
1146 SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
1148 SK_IN32(IoC, B0_ISRC, &DWord);
1149 #endif /* VCPU */
1151 } /* SkGmClearRst */
1152 #endif /* YUKON */
1155 /******************************************************************************
1157 * SkMacSoftRst() - Do a MAC software reset
1159 * Description: calls a MAC software reset routine dep. on board type
1161 * Returns:
1162 * nothing
1164 void SkMacSoftRst(
1165 SK_AC *pAC, /* adapter context */
1166 SK_IOC IoC, /* IO context */
1167 int Port) /* Port Index (MAC_1 + n) */
1169 SK_GEPORT *pPrt;
1171 pPrt = &pAC->GIni.GP[Port];
1173 /* disable receiver and transmitter */
1174 SkMacRxTxDisable(pAC, IoC, Port);
1176 #ifdef GENESIS
1177 if (pAC->GIni.GIGenesis) {
1179 SkXmSoftRst(pAC, IoC, Port);
1181 #endif /* GENESIS */
1183 #ifdef YUKON
1184 if (pAC->GIni.GIYukon) {
1186 SkGmSoftRst(pAC, IoC, Port);
1188 #endif /* YUKON */
1190 /* flush the MAC's Rx and Tx FIFOs */
1191 SkMacFlushTxFifo(pAC, IoC, Port);
1193 SkMacFlushRxFifo(pAC, IoC, Port);
1195 pPrt->PState = SK_PRT_STOP;
1197 } /* SkMacSoftRst */
1200 /******************************************************************************
1202 * SkMacHardRst() - Do a MAC hardware reset
1204 * Description: calls a MAC hardware reset routine dep. on board type
1206 * Returns:
1207 * nothing
1209 void SkMacHardRst(
1210 SK_AC *pAC, /* adapter context */
1211 SK_IOC IoC, /* IO context */
1212 int Port) /* Port Index (MAC_1 + n) */
1215 #ifdef GENESIS
1216 if (pAC->GIni.GIGenesis) {
1218 SkXmHardRst(pAC, IoC, Port);
1220 #endif /* GENESIS */
1222 #ifdef YUKON
1223 if (pAC->GIni.GIYukon) {
1225 SkGmHardRst(pAC, IoC, Port);
1227 #endif /* YUKON */
1229 pAC->GIni.GP[Port].PState = SK_PRT_RESET;
1231 } /* SkMacHardRst */
1234 #ifdef GENESIS
1235 /******************************************************************************
1237 * SkXmInitMac() - Initialize the XMAC II
1239 * Description:
1240 * Initialize the XMAC of the specified port.
1241 * The XMAC must be reset or stopped before calling this function.
1243 * Note:
1244 * The XMAC's Rx and Tx state machine is still disabled when returning.
1246 * Returns:
1247 * nothing
1249 void SkXmInitMac(
1250 SK_AC *pAC, /* adapter context */
1251 SK_IOC IoC, /* IO context */
1252 int Port) /* Port Index (MAC_1 + n) */
1254 SK_GEPORT *pPrt;
1255 int i;
1256 SK_U16 SWord;
1258 pPrt = &pAC->GIni.GP[Port];
1260 if (pPrt->PState == SK_PRT_STOP) {
1261 /* Port State: SK_PRT_STOP */
1262 /* Verify that the reset bit is cleared */
1263 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1265 if ((SWord & MFF_SET_MAC_RST) != 0) {
1266 /* PState does not match HW state */
1267 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1268 /* Correct it */
1269 pPrt->PState = SK_PRT_RESET;
1273 if (pPrt->PState == SK_PRT_RESET) {
1275 SkXmClearRst(pAC, IoC, Port);
1277 if (pPrt->PhyType != SK_PHY_XMAC) {
1278 /* read Id from external PHY (all have the same address) */
1279 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1282 * Optimize MDIO transfer by suppressing preamble.
1283 * Must be done AFTER first access to BCOM chip.
1285 XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
1287 XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1289 if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1291 * Workaround BCOM Errata for the C0 type.
1292 * Write magic patterns to reserved registers.
1294 i = 0;
1295 while (BcomRegC0Hack[i].PhyReg != 0) {
1296 SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1297 BcomRegC0Hack[i].PhyVal);
1298 i++;
1301 else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1303 * Workaround BCOM Errata for the A1 type.
1304 * Write magic patterns to reserved registers.
1306 i = 0;
1307 while (BcomRegA1Hack[i].PhyReg != 0) {
1308 SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1309 BcomRegA1Hack[i].PhyVal);
1310 i++;
1315 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1316 * Disable Power Management after reset.
1318 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
1320 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1321 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
1323 /* PHY LED initialization is done in SkGeXmitLED() */
1326 /* Dummy read the Interrupt source register */
1327 XM_IN16(IoC, Port, XM_ISRC, &SWord);
1330 * The auto-negotiation process starts immediately after
1331 * clearing the reset. The auto-negotiation process should be
1332 * started by the SIRQ, therefore stop it here immediately.
1334 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1336 #ifdef TEST_ONLY
1337 /* temp. code: enable signal detect */
1338 /* WARNING: do not override GMII setting above */
1339 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1340 #endif
1344 * configure the XMACs Station Address
1345 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1346 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1348 for (i = 0; i < 3; i++) {
1350 * The following 2 statements are together endianess
1351 * independent. Remember this when changing.
1353 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1355 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1358 /* Tx Inter Packet Gap (XM_TX_IPG): use default */
1359 /* Tx High Water Mark (XM_TX_HI_WM): use default */
1360 /* Tx Low Water Mark (XM_TX_LO_WM): use default */
1361 /* Host Request Threshold (XM_HT_THR): use default */
1362 /* Rx Request Threshold (XM_RX_THR): use default */
1363 /* Rx Low Water Mark (XM_RX_LO_WM): use default */
1365 /* configure Rx High Water Mark (XM_RX_HI_WM) */
1366 XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1368 /* Configure Tx Request Threshold */
1369 SWord = SK_XM_THR_SL; /* for single port */
1371 if (pAC->GIni.GIMacsFound > 1) {
1372 switch (pAC->GIni.GIPortUsage) {
1373 case SK_RED_LINK:
1374 SWord = SK_XM_THR_REDL; /* redundant link */
1375 break;
1376 case SK_MUL_LINK:
1377 SWord = SK_XM_THR_MULL; /* load balancing */
1378 break;
1379 case SK_JUMBO_LINK:
1380 SWord = SK_XM_THR_JUMBO; /* jumbo frames */
1381 break;
1382 default:
1383 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1384 break;
1387 XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1389 /* setup register defaults for the Tx Command Register */
1390 XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1392 /* setup register defaults for the Rx Command Register */
1393 SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1395 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1396 SWord |= XM_RX_BIG_PK_OK;
1399 if (pPrt->PLinkMode == SK_LMODE_HALF) {
1401 * If in manual half duplex mode the other side might be in
1402 * full duplex mode, so ignore if a carrier extension is not seen
1403 * on frames received
1405 SWord |= XM_RX_DIS_CEXT;
1408 XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1411 * setup register defaults for the Mode Register
1412 * - Don't strip error frames to avoid Store & Forward
1413 * on the Rx side.
1414 * - Enable 'Check Station Address' bit
1415 * - Enable 'Check Address Array' bit
1417 XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1420 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1421 * - Enable all bits excepting 'Octets Rx OK Low CntOv'
1422 * and 'Octets Rx OK Hi Cnt Ov'.
1424 XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1427 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1428 * - Enable all bits excepting 'Octets Tx OK Low CntOv'
1429 * and 'Octets Tx OK Hi Cnt Ov'.
1431 XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1434 * Do NOT init XMAC interrupt mask here.
1435 * All interrupts remain disable until link comes up!
1439 * Any additional configuration changes may be done now.
1440 * The last action is to enable the Rx and Tx state machine.
1441 * This should be done after the auto-negotiation process
1442 * has been completed successfully.
1444 } /* SkXmInitMac */
1445 #endif /* GENESIS */
1448 #ifdef YUKON
1449 /******************************************************************************
1451 * SkGmInitMac() - Initialize the GMAC
1453 * Description:
1454 * Initialize the GMAC of the specified port.
1455 * The GMAC must be reset or stopped before calling this function.
1457 * Note:
1458 * The GMAC's Rx and Tx state machine is still disabled when returning.
1460 * Returns:
1461 * nothing
1463 void SkGmInitMac(
1464 SK_AC *pAC, /* adapter context */
1465 SK_IOC IoC, /* IO context */
1466 int Port) /* Port Index (MAC_1 + n) */
1468 SK_GEPORT *pPrt;
1469 int i;
1470 SK_U16 SWord;
1471 SK_U32 DWord;
1473 pPrt = &pAC->GIni.GP[Port];
1475 if (pPrt->PState == SK_PRT_STOP) {
1476 /* Port State: SK_PRT_STOP */
1477 /* Verify that the reset bit is cleared */
1478 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
1480 if ((DWord & GMC_RST_SET) != 0) {
1481 /* PState does not match HW state */
1482 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1483 /* Correct it */
1484 pPrt->PState = SK_PRT_RESET;
1488 if (pPrt->PState == SK_PRT_RESET) {
1490 SkGmHardRst(pAC, IoC, Port);
1492 SkGmClearRst(pAC, IoC, Port);
1494 /* Auto-negotiation ? */
1495 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1496 /* Auto-negotiation disabled */
1498 /* get General Purpose Control */
1499 GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
1501 /* disable auto-update for speed, duplex and flow-control */
1502 SWord |= GM_GPCR_AU_ALL_DIS;
1504 /* setup General Purpose Control Register */
1505 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1507 SWord = GM_GPCR_AU_ALL_DIS;
1509 else {
1510 SWord = 0;
1513 /* speed settings */
1514 switch (pPrt->PLinkSpeed) {
1515 case SK_LSPEED_AUTO:
1516 case SK_LSPEED_1000MBPS:
1517 SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1518 break;
1519 case SK_LSPEED_100MBPS:
1520 SWord |= GM_GPCR_SPEED_100;
1521 break;
1522 case SK_LSPEED_10MBPS:
1523 break;
1526 /* duplex settings */
1527 if (pPrt->PLinkMode != SK_LMODE_HALF) {
1528 /* set full duplex */
1529 SWord |= GM_GPCR_DUP_FULL;
1532 /* flow-control settings */
1533 switch (pPrt->PFlowCtrlMode) {
1534 case SK_FLOW_MODE_NONE:
1535 /* set Pause Off */
1536 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
1537 /* disable Tx & Rx flow-control */
1538 SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1539 break;
1540 case SK_FLOW_MODE_LOC_SEND:
1541 /* disable Rx flow-control */
1542 SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1543 break;
1544 case SK_FLOW_MODE_SYMMETRIC:
1545 case SK_FLOW_MODE_SYM_OR_REM:
1546 /* enable Tx & Rx flow-control */
1547 break;
1550 /* setup General Purpose Control Register */
1551 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1553 /* dummy read the Interrupt Source Register */
1554 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
1556 #ifndef VCPU
1557 /* read Id from PHY */
1558 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
1560 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1561 #endif /* VCPU */
1564 (void)SkGmResetCounter(pAC, IoC, Port);
1566 /* setup Transmit Control Register */
1567 GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
1569 /* setup Receive Control Register */
1570 GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1571 GM_RXCR_CRC_DIS);
1573 /* setup Transmit Flow Control Register */
1574 GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1576 /* setup Transmit Parameter Register */
1577 #ifdef VCPU
1578 GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1579 #endif /* VCPU */
1581 SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
1582 TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
1583 TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
1585 GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1587 /* configure the Serial Mode Register */
1588 #ifdef VCPU
1589 GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1590 #endif /* VCPU */
1592 SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
1594 if (pPrt->PMacLimit4) {
1595 /* reset of collision counter after 4 consecutive collisions */
1596 SWord |= GM_SMOD_LIMIT_4;
1599 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1600 /* enable jumbo mode (Max. Frame Length = 9018) */
1601 SWord |= GM_SMOD_JUMBO_ENA;
1604 GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
1607 * configure the GMACs Station Addresses
1608 * in PROM you can find our addresses at:
1609 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1610 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1611 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1614 for (i = 0; i < 3; i++) {
1616 * The following 2 statements are together endianess
1617 * independent. Remember this when changing.
1619 /* physical address: will be used for pause frames */
1620 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1622 #ifdef WA_DEV_16
1623 /* WA for deviation #16 */
1624 if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
1625 /* swap the address bytes */
1626 SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
1628 /* write to register in reversed order */
1629 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
1631 else {
1632 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1634 #else
1635 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1636 #endif /* WA_DEV_16 */
1638 /* virtual address: will be used for data */
1639 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
1641 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
1643 /* reset Multicast filtering Hash registers 1-3 */
1644 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
1647 /* reset Multicast filtering Hash register 4 */
1648 GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
1650 /* enable interrupt mask for counter overflows */
1651 GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
1652 GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
1653 GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
1655 #if defined(SK_DIAG) || defined(DEBUG)
1656 /* read General Purpose Status */
1657 GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
1659 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1660 ("MAC Stat Reg.=0x%04X\n", SWord));
1661 #endif /* SK_DIAG || DEBUG */
1663 #ifdef SK_DIAG
1664 c_print("MAC Stat Reg=0x%04X\n", SWord);
1665 #endif /* SK_DIAG */
1667 } /* SkGmInitMac */
1668 #endif /* YUKON */
1671 #ifdef GENESIS
1672 /******************************************************************************
1674 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1676 * Description:
1677 * This function initializes the XMACs Duplex Mode.
1678 * It should be called after successfully finishing
1679 * the Auto-negotiation Process
1681 * Returns:
1682 * nothing
1684 static void SkXmInitDupMd(
1685 SK_AC *pAC, /* adapter context */
1686 SK_IOC IoC, /* IO context */
1687 int Port) /* Port Index (MAC_1 + n) */
1689 switch (pAC->GIni.GP[Port].PLinkModeStatus) {
1690 case SK_LMODE_STAT_AUTOHALF:
1691 case SK_LMODE_STAT_HALF:
1692 /* Configuration Actions for Half Duplex Mode */
1694 * XM_BURST = default value. We are probable not quick
1695 * enough at the 'XMAC' bus to burst 8kB.
1696 * The XMAC stops bursting if no transmit frames
1697 * are available or the burst limit is exceeded.
1699 /* XM_TX_RT_LIM = default value (15) */
1700 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
1701 break;
1702 case SK_LMODE_STAT_AUTOFULL:
1703 case SK_LMODE_STAT_FULL:
1704 /* Configuration Actions for Full Duplex Mode */
1706 * The duplex mode is configured by the PHY,
1707 * therefore it seems to be that there is nothing
1708 * to do here.
1710 break;
1711 case SK_LMODE_STAT_UNKNOWN:
1712 default:
1713 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
1714 break;
1716 } /* SkXmInitDupMd */
1719 /******************************************************************************
1721 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1723 * Description:
1724 * This function initializes the Pause Mode which should
1725 * be used for this port.
1726 * It should be called after successfully finishing
1727 * the Auto-negotiation Process
1729 * Returns:
1730 * nothing
1732 static void SkXmInitPauseMd(
1733 SK_AC *pAC, /* adapter context */
1734 SK_IOC IoC, /* IO context */
1735 int Port) /* Port Index (MAC_1 + n) */
1737 SK_GEPORT *pPrt;
1738 SK_U32 DWord;
1739 SK_U16 Word;
1741 pPrt = &pAC->GIni.GP[Port];
1743 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
1745 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
1746 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1748 /* Disable Pause Frame Reception */
1749 Word |= XM_MMU_IGN_PF;
1751 else {
1753 * enabling pause frame reception is required for 1000BT
1754 * because the XMAC is not reset if the link is going down
1756 /* Enable Pause Frame Reception */
1757 Word &= ~XM_MMU_IGN_PF;
1760 XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
1762 XM_IN32(IoC, Port, XM_MODE, &DWord);
1764 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
1765 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1768 * Configure Pause Frame Generation
1769 * Use internal and external Pause Frame Generation.
1770 * Sending pause frames is edge triggered.
1771 * Send a Pause frame with the maximum pause time if
1772 * internal oder external FIFO full condition occurs.
1773 * Send a zero pause time frame to re-start transmission.
1776 /* XM_PAUSE_DA = '010000C28001' (default) */
1778 /* XM_MAC_PTIME = 0xffff (maximum) */
1779 /* remember this value is defined in big endian (!) */
1780 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
1782 /* Set Pause Mode in Mode Register */
1783 DWord |= XM_PAUSE_MODE;
1785 /* Set Pause Mode in MAC Rx FIFO */
1786 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
1788 else {
1790 * disable pause frame generation is required for 1000BT
1791 * because the XMAC is not reset if the link is going down
1793 /* Disable Pause Mode in Mode Register */
1794 DWord &= ~XM_PAUSE_MODE;
1796 /* Disable Pause Mode in MAC Rx FIFO */
1797 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
1800 XM_OUT32(IoC, Port, XM_MODE, DWord);
1801 } /* SkXmInitPauseMd*/
1804 /******************************************************************************
1806 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
1808 * Description: initializes all the XMACs Phy registers
1810 * Note:
1812 * Returns:
1813 * nothing
1815 static void SkXmInitPhyXmac(
1816 SK_AC *pAC, /* adapter context */
1817 SK_IOC IoC, /* IO context */
1818 int Port, /* Port Index (MAC_1 + n) */
1819 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
1821 SK_GEPORT *pPrt;
1822 SK_U16 Ctrl;
1824 pPrt = &pAC->GIni.GP[Port];
1825 Ctrl = 0;
1827 /* Auto-negotiation ? */
1828 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1829 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1830 ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
1831 /* Set DuplexMode in Config register */
1832 if (pPrt->PLinkMode == SK_LMODE_FULL) {
1833 Ctrl |= PHY_CT_DUP_MD;
1837 * Do NOT enable Auto-negotiation here. This would hold
1838 * the link down because no IDLEs are transmitted
1841 else {
1842 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1843 ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
1844 /* Set Auto-negotiation advertisement */
1846 /* Set Full/half duplex capabilities */
1847 switch (pPrt->PLinkMode) {
1848 case SK_LMODE_AUTOHALF:
1849 Ctrl |= PHY_X_AN_HD;
1850 break;
1851 case SK_LMODE_AUTOFULL:
1852 Ctrl |= PHY_X_AN_FD;
1853 break;
1854 case SK_LMODE_AUTOBOTH:
1855 Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
1856 break;
1857 default:
1858 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
1859 SKERR_HWI_E015MSG);
1862 /* Set Flow-control capabilities */
1863 switch (pPrt->PFlowCtrlMode) {
1864 case SK_FLOW_MODE_NONE:
1865 Ctrl |= PHY_X_P_NO_PAUSE;
1866 break;
1867 case SK_FLOW_MODE_LOC_SEND:
1868 Ctrl |= PHY_X_P_ASYM_MD;
1869 break;
1870 case SK_FLOW_MODE_SYMMETRIC:
1871 Ctrl |= PHY_X_P_SYM_MD;
1872 break;
1873 case SK_FLOW_MODE_SYM_OR_REM:
1874 Ctrl |= PHY_X_P_BOTH_MD;
1875 break;
1876 default:
1877 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
1878 SKERR_HWI_E016MSG);
1881 /* Write AutoNeg Advertisement Register */
1882 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
1884 /* Restart Auto-negotiation */
1885 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
1888 if (DoLoop) {
1889 /* Set the Phy Loopback bit, too */
1890 Ctrl |= PHY_CT_LOOP;
1893 /* Write to the Phy control register */
1894 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
1895 } /* SkXmInitPhyXmac */
1898 /******************************************************************************
1900 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
1902 * Description: initializes all the Broadcom Phy registers
1904 * Note:
1906 * Returns:
1907 * nothing
1909 static void SkXmInitPhyBcom(
1910 SK_AC *pAC, /* adapter context */
1911 SK_IOC IoC, /* IO context */
1912 int Port, /* Port Index (MAC_1 + n) */
1913 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
1915 SK_GEPORT *pPrt;
1916 SK_U16 Ctrl1;
1917 SK_U16 Ctrl2;
1918 SK_U16 Ctrl3;
1919 SK_U16 Ctrl4;
1920 SK_U16 Ctrl5;
1922 Ctrl1 = PHY_CT_SP1000;
1923 Ctrl2 = 0;
1924 Ctrl3 = PHY_SEL_TYPE;
1925 Ctrl4 = PHY_B_PEC_EN_LTR;
1926 Ctrl5 = PHY_B_AC_TX_TST;
1928 pPrt = &pAC->GIni.GP[Port];
1930 /* manually Master/Slave ? */
1931 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
1932 Ctrl2 |= PHY_B_1000C_MSE;
1934 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
1935 Ctrl2 |= PHY_B_1000C_MSC;
1938 /* Auto-negotiation ? */
1939 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1940 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1941 ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
1942 /* Set DuplexMode in Config register */
1943 if (pPrt->PLinkMode == SK_LMODE_FULL) {
1944 Ctrl1 |= PHY_CT_DUP_MD;
1947 /* Determine Master/Slave manually if not already done */
1948 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
1949 Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
1953 * Do NOT enable Auto-negotiation here. This would hold
1954 * the link down because no IDLES are transmitted
1957 else {
1958 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1959 ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
1960 /* Set Auto-negotiation advertisement */
1963 * Workaround BCOM Errata #1 for the C5 type.
1964 * 1000Base-T Link Acquisition Failure in Slave Mode
1965 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
1967 Ctrl2 |= PHY_B_1000C_RD;
1969 /* Set Full/half duplex capabilities */
1970 switch (pPrt->PLinkMode) {
1971 case SK_LMODE_AUTOHALF:
1972 Ctrl2 |= PHY_B_1000C_AHD;
1973 break;
1974 case SK_LMODE_AUTOFULL:
1975 Ctrl2 |= PHY_B_1000C_AFD;
1976 break;
1977 case SK_LMODE_AUTOBOTH:
1978 Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
1979 break;
1980 default:
1981 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
1982 SKERR_HWI_E015MSG);
1985 /* Set Flow-control capabilities */
1986 switch (pPrt->PFlowCtrlMode) {
1987 case SK_FLOW_MODE_NONE:
1988 Ctrl3 |= PHY_B_P_NO_PAUSE;
1989 break;
1990 case SK_FLOW_MODE_LOC_SEND:
1991 Ctrl3 |= PHY_B_P_ASYM_MD;
1992 break;
1993 case SK_FLOW_MODE_SYMMETRIC:
1994 Ctrl3 |= PHY_B_P_SYM_MD;
1995 break;
1996 case SK_FLOW_MODE_SYM_OR_REM:
1997 Ctrl3 |= PHY_B_P_BOTH_MD;
1998 break;
1999 default:
2000 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2001 SKERR_HWI_E016MSG);
2004 /* Restart Auto-negotiation */
2005 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2008 /* Initialize LED register here? */
2009 /* No. Please do it in SkDgXmitLed() (if required) and swap
2010 init order of LEDs and XMAC. (MAl) */
2012 /* Write 1000Base-T Control Register */
2013 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2014 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2015 ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2017 /* Write AutoNeg Advertisement Register */
2018 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2019 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2020 ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2022 if (DoLoop) {
2023 /* Set the Phy Loopback bit, too */
2024 Ctrl1 |= PHY_CT_LOOP;
2027 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2028 /* configure FIFO to high latency for transmission of ext. packets */
2029 Ctrl4 |= PHY_B_PEC_HIGH_LA;
2031 /* configure reception of extended packets */
2032 Ctrl5 |= PHY_B_AC_LONG_PACK;
2034 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2037 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2038 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
2040 /* Write to the Phy control register */
2041 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2042 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2043 ("PHY Control Reg=0x%04X\n", Ctrl1));
2044 } /* SkXmInitPhyBcom */
2045 #endif /* GENESIS */
2047 #ifdef YUKON
2048 /******************************************************************************
2050 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2052 * Description: initializes all the Marvell Phy registers
2054 * Note:
2056 * Returns:
2057 * nothing
2059 static void SkGmInitPhyMarv(
2060 SK_AC *pAC, /* adapter context */
2061 SK_IOC IoC, /* IO context */
2062 int Port, /* Port Index (MAC_1 + n) */
2063 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2065 SK_GEPORT *pPrt;
2066 SK_U16 PhyCtrl;
2067 SK_U16 C1000BaseT;
2068 SK_U16 AutoNegAdv;
2069 SK_U16 ExtPhyCtrl;
2070 SK_U16 LedCtrl;
2071 SK_BOOL AutoNeg;
2072 #if defined(SK_DIAG) || defined(DEBUG)
2073 SK_U16 PhyStat;
2074 SK_U16 PhyStat1;
2075 SK_U16 PhySpecStat;
2076 #endif /* SK_DIAG || DEBUG */
2078 pPrt = &pAC->GIni.GP[Port];
2080 /* Auto-negotiation ? */
2081 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2082 AutoNeg = SK_FALSE;
2084 else {
2085 AutoNeg = SK_TRUE;
2088 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2089 ("InitPhyMarv: Port %d, auto-negotiation %s\n",
2090 Port, AutoNeg ? "ON" : "OFF"));
2092 #ifdef VCPU
2093 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2094 Port, DoLoop);
2095 #else /* VCPU */
2096 if (DoLoop) {
2097 /* Set 'MAC Power up'-bit, set Manual MDI configuration */
2098 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2099 PHY_M_PC_MAC_POW_UP);
2101 else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
2102 /* Read Ext. PHY Specific Control */
2103 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2105 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2106 PHY_M_EC_MAC_S_MSK);
2108 ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
2109 PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
2111 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2112 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2113 ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2116 /* Read PHY Control */
2117 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2119 if (!AutoNeg) {
2120 /* Disable Auto-negotiation */
2121 PhyCtrl &= ~PHY_CT_ANE;
2124 PhyCtrl |= PHY_CT_RESET;
2125 /* Assert software reset */
2126 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2127 #endif /* VCPU */
2129 PhyCtrl = 0 /* PHY_CT_COL_TST */;
2130 C1000BaseT = 0;
2131 AutoNegAdv = PHY_SEL_TYPE;
2133 /* manually Master/Slave ? */
2134 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2135 /* enable Manual Master/Slave */
2136 C1000BaseT |= PHY_M_1000C_MSE;
2138 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2139 C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
2143 /* Auto-negotiation ? */
2144 if (!AutoNeg) {
2146 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2147 /* Set Full Duplex Mode */
2148 PhyCtrl |= PHY_CT_DUP_MD;
2151 /* Set Master/Slave manually if not already done */
2152 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2153 C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
2156 /* Set Speed */
2157 switch (pPrt->PLinkSpeed) {
2158 case SK_LSPEED_AUTO:
2159 case SK_LSPEED_1000MBPS:
2160 PhyCtrl |= PHY_CT_SP1000;
2161 break;
2162 case SK_LSPEED_100MBPS:
2163 PhyCtrl |= PHY_CT_SP100;
2164 break;
2165 case SK_LSPEED_10MBPS:
2166 break;
2167 default:
2168 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2169 SKERR_HWI_E019MSG);
2172 if (!DoLoop) {
2173 PhyCtrl |= PHY_CT_RESET;
2176 else {
2177 /* Set Auto-negotiation advertisement */
2179 if (pAC->GIni.GICopperType) {
2180 /* Set Speed capabilities */
2181 switch (pPrt->PLinkSpeed) {
2182 case SK_LSPEED_AUTO:
2183 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2184 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2185 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2186 break;
2187 case SK_LSPEED_1000MBPS:
2188 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2189 break;
2190 case SK_LSPEED_100MBPS:
2191 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2192 /* advertise 10Base-T also */
2193 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2194 break;
2195 case SK_LSPEED_10MBPS:
2196 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2197 break;
2198 default:
2199 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2200 SKERR_HWI_E019MSG);
2203 /* Set Full/half duplex capabilities */
2204 switch (pPrt->PLinkMode) {
2205 case SK_LMODE_AUTOHALF:
2206 C1000BaseT &= ~PHY_M_1000C_AFD;
2207 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2208 break;
2209 case SK_LMODE_AUTOFULL:
2210 C1000BaseT &= ~PHY_M_1000C_AHD;
2211 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2212 break;
2213 case SK_LMODE_AUTOBOTH:
2214 break;
2215 default:
2216 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2217 SKERR_HWI_E015MSG);
2220 /* Set Flow-control capabilities */
2221 switch (pPrt->PFlowCtrlMode) {
2222 case SK_FLOW_MODE_NONE:
2223 AutoNegAdv |= PHY_B_P_NO_PAUSE;
2224 break;
2225 case SK_FLOW_MODE_LOC_SEND:
2226 AutoNegAdv |= PHY_B_P_ASYM_MD;
2227 break;
2228 case SK_FLOW_MODE_SYMMETRIC:
2229 AutoNegAdv |= PHY_B_P_SYM_MD;
2230 break;
2231 case SK_FLOW_MODE_SYM_OR_REM:
2232 AutoNegAdv |= PHY_B_P_BOTH_MD;
2233 break;
2234 default:
2235 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2236 SKERR_HWI_E016MSG);
2239 else { /* special defines for FIBER (88E1011S only) */
2241 /* Set Full/half duplex capabilities */
2242 switch (pPrt->PLinkMode) {
2243 case SK_LMODE_AUTOHALF:
2244 AutoNegAdv |= PHY_M_AN_1000X_AHD;
2245 break;
2246 case SK_LMODE_AUTOFULL:
2247 AutoNegAdv |= PHY_M_AN_1000X_AFD;
2248 break;
2249 case SK_LMODE_AUTOBOTH:
2250 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2251 break;
2252 default:
2253 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2254 SKERR_HWI_E015MSG);
2257 /* Set Flow-control capabilities */
2258 switch (pPrt->PFlowCtrlMode) {
2259 case SK_FLOW_MODE_NONE:
2260 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2261 break;
2262 case SK_FLOW_MODE_LOC_SEND:
2263 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2264 break;
2265 case SK_FLOW_MODE_SYMMETRIC:
2266 AutoNegAdv |= PHY_M_P_SYM_MD_X;
2267 break;
2268 case SK_FLOW_MODE_SYM_OR_REM:
2269 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2270 break;
2271 default:
2272 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2273 SKERR_HWI_E016MSG);
2277 if (!DoLoop) {
2278 /* Restart Auto-negotiation */
2279 PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
2283 #ifdef VCPU
2285 * E-mail from Gu Lin (08-03-2002):
2288 /* Program PHY register 30 as 16'h0708 for simulation speed up */
2289 SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
2291 VCpuWait(2000);
2293 #else /* VCPU */
2295 /* Write 1000Base-T Control Register */
2296 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2297 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2298 ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
2300 /* Write AutoNeg Advertisement Register */
2301 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2302 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2303 ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
2304 #endif /* VCPU */
2306 if (DoLoop) {
2307 /* Set the PHY Loopback bit */
2308 PhyCtrl |= PHY_CT_LOOP;
2310 #ifdef XXX
2311 /* Program PHY register 16 as 16'h0400 to force link good */
2312 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2313 #endif /* XXX */
2315 #ifndef VCPU
2316 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2317 /* Write Ext. PHY Specific Control */
2318 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2319 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2321 #endif /* VCPU */
2323 #ifdef TEST_ONLY
2324 else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2325 /* Write PHY Specific Control */
2326 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2327 PHY_M_PC_EN_DET_MSK);
2329 #endif
2331 /* Write to the PHY Control register */
2332 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2333 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2334 ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2336 #ifdef VCPU
2337 VCpuWait(2000);
2338 #else
2340 LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2342 if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
2343 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2346 if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
2347 LedCtrl |= PHY_M_LEDC_DP_CTRL;
2350 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2352 if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
2353 /* only in forced 100 Mbps mode */
2354 if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
2356 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
2357 PHY_M_LED_MO_100(MO_LED_ON));
2361 #ifdef SK_DIAG
2362 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2363 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2364 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2365 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2366 #endif /* SK_DIAG */
2368 #if defined(SK_DIAG) || defined(DEBUG)
2369 /* Read PHY Control */
2370 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2371 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2372 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2374 /* Read 1000Base-T Control Register */
2375 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2376 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2377 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
2379 /* Read AutoNeg Advertisement Register */
2380 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2381 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2382 ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
2384 /* Read Ext. PHY Specific Control */
2385 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2386 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2387 ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2389 /* Read PHY Status */
2390 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2391 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2392 ("PHY Stat Reg.=0x%04X\n", PhyStat));
2393 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2394 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2395 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
2397 /* Read PHY Specific Status */
2398 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2399 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2400 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
2401 #endif /* SK_DIAG || DEBUG */
2403 #ifdef SK_DIAG
2404 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2405 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2406 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2407 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2408 c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2409 c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2410 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2411 #endif /* SK_DIAG */
2413 #endif /* VCPU */
2415 } /* SkGmInitPhyMarv */
2416 #endif /* YUKON */
2419 #ifdef OTHER_PHY
2420 /******************************************************************************
2422 * SkXmInitPhyLone() - Initialize the Level One Phy registers
2424 * Description: initializes all the Level One Phy registers
2426 * Note:
2428 * Returns:
2429 * nothing
2431 static void SkXmInitPhyLone(
2432 SK_AC *pAC, /* adapter context */
2433 SK_IOC IoC, /* IO context */
2434 int Port, /* Port Index (MAC_1 + n) */
2435 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2437 SK_GEPORT *pPrt;
2438 SK_U16 Ctrl1;
2439 SK_U16 Ctrl2;
2440 SK_U16 Ctrl3;
2442 Ctrl1 = PHY_CT_SP1000;
2443 Ctrl2 = 0;
2444 Ctrl3 = PHY_SEL_TYPE;
2446 pPrt = &pAC->GIni.GP[Port];
2448 /* manually Master/Slave ? */
2449 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2450 Ctrl2 |= PHY_L_1000C_MSE;
2452 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2453 Ctrl2 |= PHY_L_1000C_MSC;
2456 /* Auto-negotiation ? */
2457 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2459 * level one spec say: "1000 Mbps: manual mode not allowed"
2460 * but lets see what happens...
2462 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2463 ("InitPhyLone: no auto-negotiation Port %d\n", Port));
2464 /* Set DuplexMode in Config register */
2465 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2466 Ctrl1 |= PHY_CT_DUP_MD;
2469 /* Determine Master/Slave manually if not already done */
2470 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2471 Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
2475 * Do NOT enable Auto-negotiation here. This would hold
2476 * the link down because no IDLES are transmitted
2479 else {
2480 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2481 ("InitPhyLone: with auto-negotiation Port %d\n", Port));
2482 /* Set Auto-negotiation advertisement */
2484 /* Set Full/half duplex capabilities */
2485 switch (pPrt->PLinkMode) {
2486 case SK_LMODE_AUTOHALF:
2487 Ctrl2 |= PHY_L_1000C_AHD;
2488 break;
2489 case SK_LMODE_AUTOFULL:
2490 Ctrl2 |= PHY_L_1000C_AFD;
2491 break;
2492 case SK_LMODE_AUTOBOTH:
2493 Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2494 break;
2495 default:
2496 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2497 SKERR_HWI_E015MSG);
2500 /* Set Flow-control capabilities */
2501 switch (pPrt->PFlowCtrlMode) {
2502 case SK_FLOW_MODE_NONE:
2503 Ctrl3 |= PHY_L_P_NO_PAUSE;
2504 break;
2505 case SK_FLOW_MODE_LOC_SEND:
2506 Ctrl3 |= PHY_L_P_ASYM_MD;
2507 break;
2508 case SK_FLOW_MODE_SYMMETRIC:
2509 Ctrl3 |= PHY_L_P_SYM_MD;
2510 break;
2511 case SK_FLOW_MODE_SYM_OR_REM:
2512 Ctrl3 |= PHY_L_P_BOTH_MD;
2513 break;
2514 default:
2515 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2516 SKERR_HWI_E016MSG);
2519 /* Restart Auto-negotiation */
2520 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2523 /* Write 1000Base-T Control Register */
2524 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2525 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2526 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2528 /* Write AutoNeg Advertisement Register */
2529 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2530 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2531 ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2533 if (DoLoop) {
2534 /* Set the Phy Loopback bit, too */
2535 Ctrl1 |= PHY_CT_LOOP;
2538 /* Write to the Phy control register */
2539 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2540 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2541 ("PHY Control Reg=0x%04X\n", Ctrl1));
2542 } /* SkXmInitPhyLone */
2545 /******************************************************************************
2547 * SkXmInitPhyNat() - Initialize the National Phy registers
2549 * Description: initializes all the National Phy registers
2551 * Note:
2553 * Returns:
2554 * nothing
2556 static void SkXmInitPhyNat(
2557 SK_AC *pAC, /* adapter context */
2558 SK_IOC IoC, /* IO context */
2559 int Port, /* Port Index (MAC_1 + n) */
2560 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2562 /* todo: National */
2563 } /* SkXmInitPhyNat */
2564 #endif /* OTHER_PHY */
2567 /******************************************************************************
2569 * SkMacInitPhy() - Initialize the PHY registers
2571 * Description: calls the Init PHY routines dep. on board type
2573 * Note:
2575 * Returns:
2576 * nothing
2578 void SkMacInitPhy(
2579 SK_AC *pAC, /* adapter context */
2580 SK_IOC IoC, /* IO context */
2581 int Port, /* Port Index (MAC_1 + n) */
2582 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2584 SK_GEPORT *pPrt;
2586 pPrt = &pAC->GIni.GP[Port];
2588 #ifdef GENESIS
2589 if (pAC->GIni.GIGenesis) {
2591 switch (pPrt->PhyType) {
2592 case SK_PHY_XMAC:
2593 SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2594 break;
2595 case SK_PHY_BCOM:
2596 SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2597 break;
2598 #ifdef OTHER_PHY
2599 case SK_PHY_LONE:
2600 SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2601 break;
2602 case SK_PHY_NAT:
2603 SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2604 break;
2605 #endif /* OTHER_PHY */
2608 #endif /* GENESIS */
2610 #ifdef YUKON
2611 if (pAC->GIni.GIYukon) {
2613 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2615 #endif /* YUKON */
2617 } /* SkMacInitPhy */
2620 #ifdef GENESIS
2621 /******************************************************************************
2623 * SkXmAutoNegDoneXmac() - Auto-negotiation handling
2625 * Description:
2626 * This function handles the auto-negotiation if the Done bit is set.
2628 * Returns:
2629 * SK_AND_OK o.k.
2630 * SK_AND_DUP_CAP Duplex capability error happened
2631 * SK_AND_OTHER Other error happened
2633 static int SkXmAutoNegDoneXmac(
2634 SK_AC *pAC, /* adapter context */
2635 SK_IOC IoC, /* IO context */
2636 int Port) /* Port Index (MAC_1 + n) */
2638 SK_GEPORT *pPrt;
2639 SK_U16 ResAb; /* Resolved Ability */
2640 SK_U16 LPAb; /* Link Partner Ability */
2642 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2643 ("AutoNegDoneXmac, Port %d\n", Port));
2645 pPrt = &pAC->GIni.GP[Port];
2647 /* Get PHY parameters */
2648 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
2649 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
2651 if ((LPAb & PHY_X_AN_RFB) != 0) {
2652 /* At least one of the remote fault bit is set */
2653 /* Error */
2654 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2655 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2656 pPrt->PAutoNegFail = SK_TRUE;
2657 return(SK_AND_OTHER);
2660 /* Check Duplex mismatch */
2661 if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
2662 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
2664 else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
2665 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
2667 else {
2668 /* Error */
2669 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2670 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2671 pPrt->PAutoNegFail = SK_TRUE;
2672 return(SK_AND_DUP_CAP);
2675 /* Check PAUSE mismatch */
2676 /* We are NOT using chapter 4.23 of the Xaqti manual */
2677 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2678 if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
2679 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
2680 (LPAb & PHY_X_P_SYM_MD) != 0) {
2681 /* Symmetric PAUSE */
2682 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2684 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
2685 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
2686 /* Enable PAUSE receive, disable PAUSE transmit */
2687 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2689 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
2690 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
2691 /* Disable PAUSE receive, enable PAUSE transmit */
2692 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2694 else {
2695 /* PAUSE mismatch -> no PAUSE */
2696 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2698 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
2700 return(SK_AND_OK);
2701 } /* SkXmAutoNegDoneXmac */
2704 /******************************************************************************
2706 * SkXmAutoNegDoneBcom() - Auto-negotiation handling
2708 * Description:
2709 * This function handles the auto-negotiation if the Done bit is set.
2711 * Returns:
2712 * SK_AND_OK o.k.
2713 * SK_AND_DUP_CAP Duplex capability error happened
2714 * SK_AND_OTHER Other error happened
2716 static int SkXmAutoNegDoneBcom(
2717 SK_AC *pAC, /* adapter context */
2718 SK_IOC IoC, /* IO context */
2719 int Port) /* Port Index (MAC_1 + n) */
2721 SK_GEPORT *pPrt;
2722 SK_U16 LPAb; /* Link Partner Ability */
2723 SK_U16 AuxStat; /* Auxiliary Status */
2725 #ifdef TEST_ONLY
2726 01-Sep-2000 RA;:;:
2727 SK_U16 ResAb; /* Resolved Ability */
2728 #endif /* 0 */
2730 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2731 ("AutoNegDoneBcom, Port %d\n", Port));
2732 pPrt = &pAC->GIni.GP[Port];
2734 /* Get PHY parameters */
2735 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
2736 #ifdef TEST_ONLY
2737 01-Sep-2000 RA;:;:
2738 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
2739 #endif /* 0 */
2741 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
2743 if ((LPAb & PHY_B_AN_RF) != 0) {
2744 /* Remote fault bit is set: Error */
2745 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2746 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2747 pPrt->PAutoNegFail = SK_TRUE;
2748 return(SK_AND_OTHER);
2751 /* Check Duplex mismatch */
2752 if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
2753 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
2755 else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
2756 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
2758 else {
2759 /* Error */
2760 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2761 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2762 pPrt->PAutoNegFail = SK_TRUE;
2763 return(SK_AND_DUP_CAP);
2766 #ifdef TEST_ONLY
2767 01-Sep-2000 RA;:;:
2768 /* Check Master/Slave resolution */
2769 if ((ResAb & PHY_B_1000S_MSF) != 0) {
2770 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2771 ("Master/Slave Fault Port %d\n", Port));
2772 pPrt->PAutoNegFail = SK_TRUE;
2773 pPrt->PMSStatus = SK_MS_STAT_FAULT;
2774 return(SK_AND_OTHER);
2777 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
2778 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
2779 #endif /* 0 */
2781 /* Check PAUSE mismatch ??? */
2782 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2783 if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
2784 /* Symmetric PAUSE */
2785 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2787 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
2788 /* Enable PAUSE receive, disable PAUSE transmit */
2789 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2791 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
2792 /* Disable PAUSE receive, enable PAUSE transmit */
2793 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2795 else {
2796 /* PAUSE mismatch -> no PAUSE */
2797 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2799 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
2801 return(SK_AND_OK);
2802 } /* SkXmAutoNegDoneBcom */
2803 #endif /* GENESIS */
2806 #ifdef YUKON
2807 /******************************************************************************
2809 * SkGmAutoNegDoneMarv() - Auto-negotiation handling
2811 * Description:
2812 * This function handles the auto-negotiation if the Done bit is set.
2814 * Returns:
2815 * SK_AND_OK o.k.
2816 * SK_AND_DUP_CAP Duplex capability error happened
2817 * SK_AND_OTHER Other error happened
2819 static int SkGmAutoNegDoneMarv(
2820 SK_AC *pAC, /* adapter context */
2821 SK_IOC IoC, /* IO context */
2822 int Port) /* Port Index (MAC_1 + n) */
2824 SK_GEPORT *pPrt;
2825 SK_U16 LPAb; /* Link Partner Ability */
2826 SK_U16 ResAb; /* Resolved Ability */
2827 SK_U16 AuxStat; /* Auxiliary Status */
2829 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2830 ("AutoNegDoneMarv, Port %d\n", Port));
2831 pPrt = &pAC->GIni.GP[Port];
2833 /* Get PHY parameters */
2834 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
2835 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2836 ("Link P.Abil.=0x%04X\n", LPAb));
2838 if ((LPAb & PHY_M_AN_RF) != 0) {
2839 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2840 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2841 pPrt->PAutoNegFail = SK_TRUE;
2842 return(SK_AND_OTHER);
2845 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
2847 /* Check Master/Slave resolution */
2848 if ((ResAb & PHY_B_1000S_MSF) != 0) {
2849 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2850 ("Master/Slave Fault Port %d\n", Port));
2851 pPrt->PAutoNegFail = SK_TRUE;
2852 pPrt->PMSStatus = SK_MS_STAT_FAULT;
2853 return(SK_AND_OTHER);
2856 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
2857 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
2859 /* Read PHY Specific Status */
2860 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
2862 /* Check Speed & Duplex resolved */
2863 if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
2864 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2865 ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
2866 pPrt->PAutoNegFail = SK_TRUE;
2867 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
2868 return(SK_AND_DUP_CAP);
2871 if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
2872 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
2874 else {
2875 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
2878 /* Check PAUSE mismatch ??? */
2879 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2880 if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
2881 /* Symmetric PAUSE */
2882 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2884 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
2885 /* Enable PAUSE receive, disable PAUSE transmit */
2886 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2888 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
2889 /* Disable PAUSE receive, enable PAUSE transmit */
2890 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2892 else {
2893 /* PAUSE mismatch -> no PAUSE */
2894 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2897 /* set used link speed */
2898 switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
2899 case (unsigned)PHY_M_PS_SPEED_1000:
2900 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
2901 break;
2902 case PHY_M_PS_SPEED_100:
2903 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
2904 break;
2905 default:
2906 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
2909 return(SK_AND_OK);
2910 } /* SkGmAutoNegDoneMarv */
2911 #endif /* YUKON */
2914 #ifdef OTHER_PHY
2915 /******************************************************************************
2917 * SkXmAutoNegDoneLone() - Auto-negotiation handling
2919 * Description:
2920 * This function handles the auto-negotiation if the Done bit is set.
2922 * Returns:
2923 * SK_AND_OK o.k.
2924 * SK_AND_DUP_CAP Duplex capability error happened
2925 * SK_AND_OTHER Other error happened
2927 static int SkXmAutoNegDoneLone(
2928 SK_AC *pAC, /* adapter context */
2929 SK_IOC IoC, /* IO context */
2930 int Port) /* Port Index (MAC_1 + n) */
2932 SK_GEPORT *pPrt;
2933 SK_U16 ResAb; /* Resolved Ability */
2934 SK_U16 LPAb; /* Link Partner Ability */
2935 SK_U16 QuickStat; /* Auxiliary Status */
2937 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2938 ("AutoNegDoneLone, Port %d\n", Port));
2939 pPrt = &pAC->GIni.GP[Port];
2941 /* Get PHY parameters */
2942 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
2943 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
2944 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
2946 if ((LPAb & PHY_L_AN_RF) != 0) {
2947 /* Remote fault bit is set */
2948 /* Error */
2949 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2950 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2951 pPrt->PAutoNegFail = SK_TRUE;
2952 return(SK_AND_OTHER);
2955 /* Check Duplex mismatch */
2956 if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
2957 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
2959 else {
2960 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
2963 /* Check Master/Slave resolution */
2964 if ((ResAb & PHY_L_1000S_MSF) != 0) {
2965 /* Error */
2966 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2967 ("Master/Slave Fault Port %d\n", Port));
2968 pPrt->PAutoNegFail = SK_TRUE;
2969 pPrt->PMSStatus = SK_MS_STAT_FAULT;
2970 return(SK_AND_OTHER);
2972 else if (ResAb & PHY_L_1000S_MSR) {
2973 pPrt->PMSStatus = SK_MS_STAT_MASTER;
2975 else {
2976 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
2979 /* Check PAUSE mismatch */
2980 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2981 /* we must manually resolve the abilities here */
2982 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2984 switch (pPrt->PFlowCtrlMode) {
2985 case SK_FLOW_MODE_NONE:
2986 /* default */
2987 break;
2988 case SK_FLOW_MODE_LOC_SEND:
2989 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
2990 (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
2991 /* Disable PAUSE receive, enable PAUSE transmit */
2992 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2994 break;
2995 case SK_FLOW_MODE_SYMMETRIC:
2996 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
2997 /* Symmetric PAUSE */
2998 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3000 break;
3001 case SK_FLOW_MODE_SYM_OR_REM:
3002 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3003 PHY_L_QS_AS_PAUSE) {
3004 /* Enable PAUSE receive, disable PAUSE transmit */
3005 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3007 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3008 /* Symmetric PAUSE */
3009 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3011 break;
3012 default:
3013 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3014 SKERR_HWI_E016MSG);
3017 return(SK_AND_OK);
3018 } /* SkXmAutoNegDoneLone */
3021 /******************************************************************************
3023 * SkXmAutoNegDoneNat() - Auto-negotiation handling
3025 * Description:
3026 * This function handles the auto-negotiation if the Done bit is set.
3028 * Returns:
3029 * SK_AND_OK o.k.
3030 * SK_AND_DUP_CAP Duplex capability error happened
3031 * SK_AND_OTHER Other error happened
3033 static int SkXmAutoNegDoneNat(
3034 SK_AC *pAC, /* adapter context */
3035 SK_IOC IoC, /* IO context */
3036 int Port) /* Port Index (MAC_1 + n) */
3038 /* todo: National */
3039 return(SK_AND_OK);
3040 } /* SkXmAutoNegDoneNat */
3041 #endif /* OTHER_PHY */
3044 /******************************************************************************
3046 * SkMacAutoNegDone() - Auto-negotiation handling
3048 * Description: calls the auto-negotiation done routines dep. on board type
3050 * Returns:
3051 * SK_AND_OK o.k.
3052 * SK_AND_DUP_CAP Duplex capability error happened
3053 * SK_AND_OTHER Other error happened
3055 int SkMacAutoNegDone(
3056 SK_AC *pAC, /* adapter context */
3057 SK_IOC IoC, /* IO context */
3058 int Port) /* Port Index (MAC_1 + n) */
3060 SK_GEPORT *pPrt;
3061 int Rtv;
3063 Rtv = SK_AND_OK;
3065 pPrt = &pAC->GIni.GP[Port];
3067 #ifdef GENESIS
3068 if (pAC->GIni.GIGenesis) {
3070 switch (pPrt->PhyType) {
3072 case SK_PHY_XMAC:
3073 Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3074 break;
3075 case SK_PHY_BCOM:
3076 Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3077 break;
3078 #ifdef OTHER_PHY
3079 case SK_PHY_LONE:
3080 Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3081 break;
3082 case SK_PHY_NAT:
3083 Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3084 break;
3085 #endif /* OTHER_PHY */
3086 default:
3087 return(SK_AND_OTHER);
3090 #endif /* GENESIS */
3092 #ifdef YUKON
3093 if (pAC->GIni.GIYukon) {
3095 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3097 #endif /* YUKON */
3099 if (Rtv != SK_AND_OK) {
3100 return(Rtv);
3103 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3104 ("AutoNeg done Port %d\n", Port));
3106 /* We checked everything and may now enable the link */
3107 pPrt->PAutoNegFail = SK_FALSE;
3109 SkMacRxTxEnable(pAC, IoC, Port);
3111 return(SK_AND_OK);
3112 } /* SkMacAutoNegDone */
3115 /******************************************************************************
3117 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3119 * Description: enables Rx/Tx dep. on board type
3121 * Returns:
3122 * 0 o.k.
3123 * != 0 Error happened
3125 int SkMacRxTxEnable(
3126 SK_AC *pAC, /* adapter context */
3127 SK_IOC IoC, /* IO context */
3128 int Port) /* Port Index (MAC_1 + n) */
3130 SK_GEPORT *pPrt;
3131 SK_U16 Reg; /* 16-bit register value */
3132 SK_U16 IntMask; /* MAC interrupt mask */
3133 #ifdef GENESIS
3134 SK_U16 SWord;
3135 #endif
3137 pPrt = &pAC->GIni.GP[Port];
3139 if (!pPrt->PHWLinkUp) {
3140 /* The Hardware link is NOT up */
3141 return(0);
3144 if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3145 pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3146 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3147 pPrt->PAutoNegFail) {
3148 /* Auto-negotiation is not done or failed */
3149 return(0);
3152 #ifdef GENESIS
3153 if (pAC->GIni.GIGenesis) {
3154 /* set Duplex Mode and Pause Mode */
3155 SkXmInitDupMd(pAC, IoC, Port);
3157 SkXmInitPauseMd(pAC, IoC, Port);
3160 * Initialize the Interrupt Mask Register. Default IRQs are...
3161 * - Link Asynchronous Event
3162 * - Link Partner requests config
3163 * - Auto Negotiation Done
3164 * - Rx Counter Event Overflow
3165 * - Tx Counter Event Overflow
3166 * - Transmit FIFO Underrun
3168 IntMask = XM_DEF_MSK;
3170 #ifdef DEBUG
3171 /* add IRQ for Receive FIFO Overflow */
3172 IntMask &= ~XM_IS_RXF_OV;
3173 #endif /* DEBUG */
3175 if (pPrt->PhyType != SK_PHY_XMAC) {
3176 /* disable GP0 interrupt bit */
3177 IntMask |= XM_IS_INP_ASS;
3179 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
3181 /* get MMU Command Reg. */
3182 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
3184 if (pPrt->PhyType != SK_PHY_XMAC &&
3185 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3186 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3187 /* set to Full Duplex */
3188 Reg |= XM_MMU_GMII_FD;
3191 switch (pPrt->PhyType) {
3192 case SK_PHY_BCOM:
3194 * Workaround BCOM Errata (#10523) for all BCom Phys
3195 * Enable Power Management after link up
3197 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3198 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3199 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3200 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
3201 (SK_U16)PHY_B_DEF_MSK);
3202 break;
3203 #ifdef OTHER_PHY
3204 case SK_PHY_LONE:
3205 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3206 break;
3207 case SK_PHY_NAT:
3208 /* todo National:
3209 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3210 /* no interrupts possible from National ??? */
3211 break;
3212 #endif /* OTHER_PHY */
3215 /* enable Rx/Tx */
3216 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3218 #endif /* GENESIS */
3220 #ifdef YUKON
3221 if (pAC->GIni.GIYukon) {
3223 * Initialize the Interrupt Mask Register. Default IRQs are...
3224 * - Rx Counter Event Overflow
3225 * - Tx Counter Event Overflow
3226 * - Transmit FIFO Underrun
3228 IntMask = GMAC_DEF_MSK;
3230 #ifdef DEBUG
3231 /* add IRQ for Receive FIFO Overrun */
3232 IntMask |= GM_IS_RX_FF_OR;
3233 #endif /* DEBUG */
3235 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
3237 /* get General Purpose Control */
3238 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
3240 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3241 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3242 /* set to Full Duplex */
3243 Reg |= GM_GPCR_DUP_FULL;
3246 /* enable Rx/Tx */
3247 GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
3248 GM_GPCR_TX_ENA));
3250 #ifndef VCPU
3251 /* Enable all PHY interrupts */
3252 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
3253 (SK_U16)PHY_M_DEF_MSK);
3254 #endif /* VCPU */
3256 #endif /* YUKON */
3258 return(0);
3260 } /* SkMacRxTxEnable */
3263 /******************************************************************************
3265 * SkMacRxTxDisable() - Disable Receiver and Transmitter
3267 * Description: disables Rx/Tx dep. on board type
3269 * Returns: N/A
3271 void SkMacRxTxDisable(
3272 SK_AC *pAC, /* Adapter Context */
3273 SK_IOC IoC, /* IO context */
3274 int Port) /* Port Index (MAC_1 + n) */
3276 SK_U16 Word;
3278 #ifdef GENESIS
3279 if (pAC->GIni.GIGenesis) {
3281 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3283 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
3285 /* dummy read to ensure writing */
3286 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3288 #endif /* GENESIS */
3290 #ifdef YUKON
3291 if (pAC->GIni.GIYukon) {
3293 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3295 GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
3296 GM_GPCR_TX_ENA)));
3298 /* dummy read to ensure writing */
3299 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3301 #endif /* YUKON */
3303 } /* SkMacRxTxDisable */
3306 /******************************************************************************
3308 * SkMacIrqDisable() - Disable IRQ from MAC
3310 * Description: sets the IRQ-mask to disable IRQ dep. on board type
3312 * Returns: N/A
3314 void SkMacIrqDisable(
3315 SK_AC *pAC, /* Adapter Context */
3316 SK_IOC IoC, /* IO context */
3317 int Port) /* Port Index (MAC_1 + n) */
3319 SK_GEPORT *pPrt;
3320 #ifdef GENESIS
3321 SK_U16 Word;
3322 #endif
3324 pPrt = &pAC->GIni.GP[Port];
3326 #ifdef GENESIS
3327 if (pAC->GIni.GIGenesis) {
3329 /* disable all XMAC IRQs */
3330 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
3332 /* Disable all PHY interrupts */
3333 switch (pPrt->PhyType) {
3334 case SK_PHY_BCOM:
3335 /* Make sure that PHY is initialized */
3336 if (pPrt->PState != SK_PRT_RESET) {
3337 /* NOT allowed if BCOM is in RESET state */
3338 /* Workaround BCOM Errata (#10523) all BCom */
3339 /* Disable Power Management if link is down */
3340 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3341 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3342 (SK_U16)(Word | PHY_B_AC_DIS_PM));
3343 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3345 break;
3346 #ifdef OTHER_PHY
3347 case SK_PHY_LONE:
3348 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3349 break;
3350 case SK_PHY_NAT:
3351 /* todo: National
3352 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3353 break;
3354 #endif /* OTHER_PHY */
3357 #endif /* GENESIS */
3359 #ifdef YUKON
3360 if (pAC->GIni.GIYukon) {
3361 /* disable all GMAC IRQs */
3362 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
3364 #ifndef VCPU
3365 /* Disable all PHY interrupts */
3366 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3367 #endif /* VCPU */
3369 #endif /* YUKON */
3371 } /* SkMacIrqDisable */
3374 #ifdef SK_DIAG
3375 /******************************************************************************
3377 * SkXmSendCont() - Enable / Disable Send Continuous Mode
3379 * Description: enable / disable Send Continuous Mode on XMAC
3381 * Returns:
3382 * nothing
3384 void SkXmSendCont(
3385 SK_AC *pAC, /* adapter context */
3386 SK_IOC IoC, /* IO context */
3387 int Port, /* Port Index (MAC_1 + n) */
3388 SK_BOOL Enable) /* Enable / Disable */
3390 SK_U32 MdReg;
3392 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3394 if (Enable) {
3395 MdReg |= XM_MD_TX_CONT;
3397 else {
3398 MdReg &= ~XM_MD_TX_CONT;
3400 /* setup Mode Register */
3401 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3403 } /* SkXmSendCont */
3406 /******************************************************************************
3408 * SkMacTimeStamp() - Enable / Disable Time Stamp
3410 * Description: enable / disable Time Stamp generation for Rx packets
3412 * Returns:
3413 * nothing
3415 void SkMacTimeStamp(
3416 SK_AC *pAC, /* adapter context */
3417 SK_IOC IoC, /* IO context */
3418 int Port, /* Port Index (MAC_1 + n) */
3419 SK_BOOL Enable) /* Enable / Disable */
3421 SK_U32 MdReg;
3422 SK_U8 TimeCtrl;
3424 if (pAC->GIni.GIGenesis) {
3426 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3428 if (Enable) {
3429 MdReg |= XM_MD_ATS;
3431 else {
3432 MdReg &= ~XM_MD_ATS;
3434 /* setup Mode Register */
3435 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3437 else {
3438 if (Enable) {
3439 TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3441 else {
3442 TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3444 /* Start/Stop Time Stamp Timer */
3445 SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
3448 } /* SkMacTimeStamp*/
3450 #else /* !SK_DIAG */
3452 #ifdef GENESIS
3453 /******************************************************************************
3455 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
3457 * This function analyses the Interrupt status word. If any of the
3458 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
3459 * is set true.
3461 void SkXmAutoNegLipaXmac(
3462 SK_AC *pAC, /* adapter context */
3463 SK_IOC IoC, /* IO context */
3464 int Port, /* Port Index (MAC_1 + n) */
3465 SK_U16 IStatus) /* Interrupt Status word to analyse */
3467 SK_GEPORT *pPrt;
3469 pPrt = &pAC->GIni.GP[Port];
3471 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3472 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
3474 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3475 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
3476 Port, IStatus));
3477 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
3479 } /* SkXmAutoNegLipaXmac */
3480 #endif /* GENESIS */
3483 /******************************************************************************
3485 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
3487 * This function analyses the PHY status word.
3488 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
3489 * is set true.
3491 void SkMacAutoNegLipaPhy(
3492 SK_AC *pAC, /* adapter context */
3493 SK_IOC IoC, /* IO context */
3494 int Port, /* Port Index (MAC_1 + n) */
3495 SK_U16 PhyStat) /* PHY Status word to analyse */
3497 SK_GEPORT *pPrt;
3499 pPrt = &pAC->GIni.GP[Port];
3501 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3502 (PhyStat & PHY_ST_AN_OVER) != 0) {
3504 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3505 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
3506 Port, PhyStat));
3507 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
3509 } /* SkMacAutoNegLipaPhy */
3512 #ifdef GENESIS
3513 /******************************************************************************
3515 * SkXmIrq() - Interrupt Service Routine
3517 * Description: services an Interrupt Request of the XMAC
3519 * Note:
3520 * With an external PHY, some interrupt bits are not meaningfull any more:
3521 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
3522 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
3523 * - Page Received (bit #9) XM_IS_RX_PAGE
3524 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
3525 * - AutoNegDone (bit #7) XM_IS_AND
3526 * Also probably not valid any more is the GP0 input bit:
3527 * - GPRegisterBit0set XM_IS_INP_ASS
3529 * Returns:
3530 * nothing
3532 static void SkXmIrq(
3533 SK_AC *pAC, /* adapter context */
3534 SK_IOC IoC, /* IO context */
3535 int Port) /* Port Index (MAC_1 + n) */
3537 SK_GEPORT *pPrt;
3538 SK_EVPARA Para;
3539 SK_U16 IStatus; /* Interrupt status read from the XMAC */
3540 SK_U16 IStatus2;
3541 #ifdef SK_SLIM
3542 SK_U64 OverflowStatus;
3543 #endif
3545 pPrt = &pAC->GIni.GP[Port];
3547 XM_IN16(IoC, Port, XM_ISRC, &IStatus);
3549 /* LinkPartner Auto-negable? */
3550 if (pPrt->PhyType == SK_PHY_XMAC) {
3551 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
3553 else {
3554 /* mask bits that are not used with ext. PHY */
3555 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
3556 XM_IS_RX_PAGE | XM_IS_TX_PAGE |
3557 XM_IS_AND | XM_IS_INP_ASS);
3560 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3561 ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
3563 if (!pPrt->PHWLinkUp) {
3564 /* Spurious XMAC interrupt */
3565 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3566 ("SkXmIrq: spurious interrupt on Port %d\n", Port));
3567 return;
3570 if ((IStatus & XM_IS_INP_ASS) != 0) {
3571 /* Reread ISR Register if link is not in sync */
3572 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
3574 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3575 ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
3576 Port, IStatus, IStatus2));
3577 IStatus &= ~XM_IS_INP_ASS;
3578 IStatus |= IStatus2;
3581 if ((IStatus & XM_IS_LNK_AE) != 0) {
3582 /* not used, GP0 is used instead */
3585 if ((IStatus & XM_IS_TX_ABORT) != 0) {
3586 /* not used */
3589 if ((IStatus & XM_IS_FRC_INT) != 0) {
3590 /* not used, use ASIC IRQ instead if needed */
3593 if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
3594 SkHWLinkDown(pAC, IoC, Port);
3596 /* Signal to RLMT */
3597 Para.Para32[0] = (SK_U32)Port;
3598 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
3600 /* Start workaround Errata #2 timer */
3601 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
3602 SKGE_HWAC, SK_HWEV_WATIM, Para);
3605 if ((IStatus & XM_IS_RX_PAGE) != 0) {
3606 /* not used */
3609 if ((IStatus & XM_IS_TX_PAGE) != 0) {
3610 /* not used */
3613 if ((IStatus & XM_IS_AND) != 0) {
3614 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3615 ("SkXmIrq: AND on link that is up Port %d\n", Port));
3618 if ((IStatus & XM_IS_TSC_OV) != 0) {
3619 /* not used */
3622 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3623 if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
3624 #ifdef SK_SLIM
3625 SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
3626 #else
3627 Para.Para32[0] = (SK_U32)Port;
3628 Para.Para32[1] = (SK_U32)IStatus;
3629 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3630 #endif /* SK_SLIM */
3633 if ((IStatus & XM_IS_RXF_OV) != 0) {
3634 /* normal situation -> no effect */
3635 #ifdef DEBUG
3636 pPrt->PRxOverCnt++;
3637 #endif /* DEBUG */
3640 if ((IStatus & XM_IS_TXF_UR) != 0) {
3641 /* may NOT happen -> error log */
3642 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3645 if ((IStatus & XM_IS_TX_COMP) != 0) {
3646 /* not served here */
3649 if ((IStatus & XM_IS_RX_COMP) != 0) {
3650 /* not served here */
3652 } /* SkXmIrq */
3653 #endif /* GENESIS */
3656 #ifdef YUKON
3657 /******************************************************************************
3659 * SkGmIrq() - Interrupt Service Routine
3661 * Description: services an Interrupt Request of the GMAC
3663 * Note:
3665 * Returns:
3666 * nothing
3668 static void SkGmIrq(
3669 SK_AC *pAC, /* adapter context */
3670 SK_IOC IoC, /* IO context */
3671 int Port) /* Port Index (MAC_1 + n) */
3673 SK_GEPORT *pPrt;
3674 SK_U8 IStatus; /* Interrupt status */
3675 #ifdef SK_SLIM
3676 SK_U64 OverflowStatus;
3677 #else
3678 SK_EVPARA Para;
3679 #endif
3681 pPrt = &pAC->GIni.GP[Port];
3683 SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
3685 #ifdef XXX
3686 /* LinkPartner Auto-negable? */
3687 SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
3688 #endif /* XXX */
3690 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3691 ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
3693 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3694 if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
3695 /* these IRQs will be cleared by reading GMACs register */
3696 #ifdef SK_SLIM
3697 SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
3698 #else
3699 Para.Para32[0] = (SK_U32)Port;
3700 Para.Para32[1] = (SK_U32)IStatus;
3701 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3702 #endif
3705 if (IStatus & GM_IS_RX_FF_OR) {
3706 /* clear GMAC Rx FIFO Overrun IRQ */
3707 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
3708 #ifdef DEBUG
3709 pPrt->PRxOverCnt++;
3710 #endif /* DEBUG */
3713 if (IStatus & GM_IS_TX_FF_UR) {
3714 /* clear GMAC Tx FIFO Underrun IRQ */
3715 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
3716 /* may NOT happen -> error log */
3717 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3720 if (IStatus & GM_IS_TX_COMPL) {
3721 /* not served here */
3724 if (IStatus & GM_IS_RX_COMPL) {
3725 /* not served here */
3727 } /* SkGmIrq */
3728 #endif /* YUKON */
3731 /******************************************************************************
3733 * SkMacIrq() - Interrupt Service Routine for MAC
3735 * Description: calls the Interrupt Service Routine dep. on board type
3737 * Returns:
3738 * nothing
3740 void SkMacIrq(
3741 SK_AC *pAC, /* adapter context */
3742 SK_IOC IoC, /* IO context */
3743 int Port) /* Port Index (MAC_1 + n) */
3745 #ifdef GENESIS
3746 if (pAC->GIni.GIGenesis) {
3747 /* IRQ from XMAC */
3748 SkXmIrq(pAC, IoC, Port);
3750 #endif /* GENESIS */
3752 #ifdef YUKON
3753 if (pAC->GIni.GIYukon) {
3754 /* IRQ from GMAC */
3755 SkGmIrq(pAC, IoC, Port);
3757 #endif /* YUKON */
3759 } /* SkMacIrq */
3761 #endif /* !SK_DIAG */
3763 #ifdef GENESIS
3764 /******************************************************************************
3766 * SkXmUpdateStats() - Force the XMAC to output the current statistic
3768 * Description:
3769 * The XMAC holds its statistic internally. To obtain the current
3770 * values a command must be sent so that the statistic data will
3771 * be written to a predefined memory area on the adapter.
3773 * Returns:
3774 * 0: success
3775 * 1: something went wrong
3777 int SkXmUpdateStats(
3778 SK_AC *pAC, /* adapter context */
3779 SK_IOC IoC, /* IO context */
3780 unsigned int Port) /* Port Index (MAC_1 + n) */
3782 SK_GEPORT *pPrt;
3783 SK_U16 StatReg;
3784 int WaitIndex;
3786 pPrt = &pAC->GIni.GP[Port];
3787 WaitIndex = 0;
3789 /* Send an update command to XMAC specified */
3790 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
3793 * It is an auto-clearing register. If the command bits
3794 * went to zero again, the statistics are transferred.
3795 * Normally the command should be executed immediately.
3796 * But just to be sure we execute a loop.
3798 do {
3800 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
3802 if (++WaitIndex > 10) {
3804 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
3806 return(1);
3808 } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
3810 return(0);
3811 } /* SkXmUpdateStats */
3814 /******************************************************************************
3816 * SkXmMacStatistic() - Get XMAC counter value
3818 * Description:
3819 * Gets the 32bit counter value. Except for the octet counters
3820 * the lower 32bit are counted in hardware and the upper 32bit
3821 * must be counted in software by monitoring counter overflow interrupts.
3823 * Returns:
3824 * 0: success
3825 * 1: something went wrong
3827 int SkXmMacStatistic(
3828 SK_AC *pAC, /* adapter context */
3829 SK_IOC IoC, /* IO context */
3830 unsigned int Port, /* Port Index (MAC_1 + n) */
3831 SK_U16 StatAddr, /* MIB counter base address */
3832 SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
3834 if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
3836 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
3838 return(1);
3841 XM_IN32(IoC, Port, StatAddr, pVal);
3843 return(0);
3844 } /* SkXmMacStatistic */
3847 /******************************************************************************
3849 * SkXmResetCounter() - Clear MAC statistic counter
3851 * Description:
3852 * Force the XMAC to clear its statistic counter.
3854 * Returns:
3855 * 0: success
3856 * 1: something went wrong
3858 int SkXmResetCounter(
3859 SK_AC *pAC, /* adapter context */
3860 SK_IOC IoC, /* IO context */
3861 unsigned int Port) /* Port Index (MAC_1 + n) */
3863 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
3864 /* Clear two times according to Errata #3 */
3865 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
3867 return(0);
3868 } /* SkXmResetCounter */
3871 /******************************************************************************
3873 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
3875 * Description:
3876 * Checks the source causing an counter overflow interrupt. On success the
3877 * resulting counter overflow status is written to <pStatus>, whereas the
3878 * upper dword stores the XMAC ReceiveCounterEvent register and the lower
3879 * dword the XMAC TransmitCounterEvent register.
3881 * Note:
3882 * For XMAC the interrupt source is a self-clearing register, so the source
3883 * must be checked only once. SIRQ module does another check to be sure
3884 * that no interrupt get lost during process time.
3886 * Returns:
3887 * 0: success
3888 * 1: something went wrong
3890 int SkXmOverflowStatus(
3891 SK_AC *pAC, /* adapter context */
3892 SK_IOC IoC, /* IO context */
3893 unsigned int Port, /* Port Index (MAC_1 + n) */
3894 SK_U16 IStatus, /* Interupt Status from MAC */
3895 SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
3897 SK_U64 Status; /* Overflow status */
3898 SK_U32 RegVal;
3900 Status = 0;
3902 if ((IStatus & XM_IS_RXC_OV) != 0) {
3904 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
3905 Status |= (SK_U64)RegVal << 32;
3908 if ((IStatus & XM_IS_TXC_OV) != 0) {
3910 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
3911 Status |= (SK_U64)RegVal;
3914 *pStatus = Status;
3916 return(0);
3917 } /* SkXmOverflowStatus */
3918 #endif /* GENESIS */
3921 #ifdef YUKON
3922 /******************************************************************************
3924 * SkGmUpdateStats() - Force the GMAC to output the current statistic
3926 * Description:
3927 * Empty function for GMAC. Statistic data is accessible in direct way.
3929 * Returns:
3930 * 0: success
3931 * 1: something went wrong
3933 int SkGmUpdateStats(
3934 SK_AC *pAC, /* adapter context */
3935 SK_IOC IoC, /* IO context */
3936 unsigned int Port) /* Port Index (MAC_1 + n) */
3938 return(0);
3942 /******************************************************************************
3944 * SkGmMacStatistic() - Get GMAC counter value
3946 * Description:
3947 * Gets the 32bit counter value. Except for the octet counters
3948 * the lower 32bit are counted in hardware and the upper 32bit
3949 * must be counted in software by monitoring counter overflow interrupts.
3951 * Returns:
3952 * 0: success
3953 * 1: something went wrong
3955 int SkGmMacStatistic(
3956 SK_AC *pAC, /* adapter context */
3957 SK_IOC IoC, /* IO context */
3958 unsigned int Port, /* Port Index (MAC_1 + n) */
3959 SK_U16 StatAddr, /* MIB counter base address */
3960 SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
3963 if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
3965 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
3967 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3968 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
3969 return(1);
3972 GM_IN32(IoC, Port, StatAddr, pVal);
3974 return(0);
3975 } /* SkGmMacStatistic */
3978 /******************************************************************************
3980 * SkGmResetCounter() - Clear MAC statistic counter
3982 * Description:
3983 * Force GMAC to clear its statistic counter.
3985 * Returns:
3986 * 0: success
3987 * 1: something went wrong
3989 int SkGmResetCounter(
3990 SK_AC *pAC, /* adapter context */
3991 SK_IOC IoC, /* IO context */
3992 unsigned int Port) /* Port Index (MAC_1 + n) */
3994 SK_U16 Reg; /* Phy Address Register */
3995 SK_U16 Word;
3996 int i;
3998 GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4000 /* set MIB Clear Counter Mode */
4001 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
4003 /* read all MIB Counters with Clear Mode set */
4004 for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4005 /* the reset is performed only when the lower 16 bits are read */
4006 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4009 /* clear MIB Clear Counter Mode */
4010 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4012 return(0);
4013 } /* SkGmResetCounter */
4016 /******************************************************************************
4018 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4020 * Description:
4021 * Checks the source causing an counter overflow interrupt. On success the
4022 * resulting counter overflow status is written to <pStatus>, whereas the
4023 * the following bit coding is used:
4024 * 63:56 - unused
4025 * 55:48 - TxRx interrupt register bit7:0
4026 * 32:47 - Rx interrupt register
4027 * 31:24 - unused
4028 * 23:16 - TxRx interrupt register bit15:8
4029 * 15:0 - Tx interrupt register
4031 * Returns:
4032 * 0: success
4033 * 1: something went wrong
4035 int SkGmOverflowStatus(
4036 SK_AC *pAC, /* adapter context */
4037 SK_IOC IoC, /* IO context */
4038 unsigned int Port, /* Port Index (MAC_1 + n) */
4039 SK_U16 IStatus, /* Interupt Status from MAC */
4040 SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
4042 SK_U64 Status; /* Overflow status */
4043 SK_U16 RegVal;
4045 Status = 0;
4047 if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4048 /* this register is self-clearing after read */
4049 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4050 Status |= (SK_U64)RegVal << 32;
4053 if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4054 /* this register is self-clearing after read */
4055 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4056 Status |= (SK_U64)RegVal;
4059 /* this register is self-clearing after read */
4060 GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4061 /* Rx overflow interrupt register bits (LoByte)*/
4062 Status |= (SK_U64)((SK_U8)RegVal) << 48;
4063 /* Tx overflow interrupt register bits (HiByte)*/
4064 Status |= (SK_U64)(RegVal >> 8) << 16;
4066 *pStatus = Status;
4068 return(0);
4069 } /* SkGmOverflowStatus */
4072 #ifndef SK_SLIM
4073 /******************************************************************************
4075 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4077 * Description:
4078 * starts the cable diagnostic test if 'StartTest' is true
4079 * gets the results if 'StartTest' is true
4081 * NOTE: this test is meaningful only when link is down
4083 * Returns:
4084 * 0: success
4085 * 1: no YUKON copper
4086 * 2: test in progress
4088 int SkGmCableDiagStatus(
4089 SK_AC *pAC, /* adapter context */
4090 SK_IOC IoC, /* IO context */
4091 int Port, /* Port Index (MAC_1 + n) */
4092 SK_BOOL StartTest) /* flag for start / get result */
4094 int i;
4095 SK_U16 RegVal;
4096 SK_GEPORT *pPrt;
4098 pPrt = &pAC->GIni.GP[Port];
4100 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
4102 return(1);
4105 if (StartTest) {
4106 /* only start the cable test */
4107 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4108 /* apply TDR workaround from Marvell */
4109 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
4111 SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4112 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4113 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4114 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4115 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4118 /* set address to 0 for MDI[0] */
4119 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4121 /* Read Cable Diagnostic Reg */
4122 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4124 /* start Cable Diagnostic Test */
4125 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4126 (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
4128 return(0);
4131 /* Read Cable Diagnostic Reg */
4132 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4134 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4135 ("PHY Cable Diag.=0x%04X\n", RegVal));
4137 if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4138 /* test is running */
4139 return(2);
4142 /* get the test results */
4143 for (i = 0; i < 4; i++) {
4144 /* set address to i for MDI[i] */
4145 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4147 /* get Cable Diagnostic values */
4148 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4150 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4152 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4155 return(0);
4156 } /* SkGmCableDiagStatus */
4157 #endif /* !SK_SLIM */
4158 #endif /* YUKON */
4160 /* End of file */