1 /******************************************************************************
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 */
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.";
44 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 },
50 BCOM_HACK BcomRegC0Hack
[] = {
51 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
52 { 0x15, 0x0A04 }, { 0x18, 0x0420 },
57 /* function prototypes ********************************************************/
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);
65 static void SkGmInitPhyMarv(SK_AC
*, SK_IOC
, int, SK_BOOL
);
66 static int SkGmAutoNegDoneMarv(SK_AC
*, SK_IOC
, int);
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 */
77 /******************************************************************************
79 * SkXmPhyRead() - Read from XMAC PHY register
81 * Description: reads a 16-bit word from XMAC PHY or ext. PHY
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 */
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
) {
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
);
116 /******************************************************************************
118 * SkXmPhyWrite() - Write to XMAC PHY register
120 * Description: writes a 16-bit word to XMAC PHY or ext. PHY
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 */
135 pPrt
= &pAC
->GIni
.GP
[Port
];
137 if (pPrt
->PhyType
!= SK_PHY_XMAC
) {
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
) {
152 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &Mmu
);
153 /* wait until 'Busy' is cleared */
154 } while ((Mmu
& XM_MMU_PHY_BUSY
) != 0);
161 /******************************************************************************
163 * SkGmPhyRead() - Read from GPHY register
165 * Description: reads a 16-bit word from GPHY through MDIO
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 */
183 VCPUgetTime(&SimCyle
, &SimLowTime
);
184 VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
185 PhyReg
, SimCyle
, SimLowTime
);
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) {
204 *pVal
|= GM_SMI_CT_BUSY
;
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
);
220 VCPUgetTime(&SimCyle
, &SimLowTime
);
221 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
222 SimCyle
, SimLowTime
);
228 /******************************************************************************
230 * SkGmPhyWrite() - Write to GPHY register
232 * Description: writes a 16-bit word to GPHY through MDIO
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 */
251 VCPUgetTime(&SimCyle
, &SimLowTime
);
252 VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
253 PhyReg
, Val
, SimCyle
, SimLowTime
);
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) {
273 Val
|= GM_SMI_CT_BUSY
;
277 /* read Timer value */
278 SK_IN32(IoC
, B2_TI_VAL
, &DWord
);
283 GM_IN16(IoC
, Port
, GM_SMI_CTRL
, &Ctrl
);
285 /* wait until 'Busy' is cleared */
286 } while (Ctrl
== Val
);
289 VCPUgetTime(&SimCyle
, &SimLowTime
);
290 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
291 SimCyle
, SimLowTime
);
299 /******************************************************************************
301 * SkGePhyRead() - Read from PHY register
303 * Description: calls a read PHY routine dep. on board type
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
;
321 r_func
= SkGmPhyRead
;
324 r_func(pAC
, IoC
, Port
, PhyReg
, pVal
);
328 /******************************************************************************
330 * SkGePhyWrite() - Write to PHY register
332 * Description: calls a write PHY routine dep. on board type
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
;
350 w_func
= SkGmPhyWrite
;
353 w_func(pAC
, IoC
, Port
, PhyReg
, Val
);
358 /******************************************************************************
360 * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
363 * enables / disables promiscuous mode by setting Mode Register (XMAC) or
364 * Receive Control Register (GMAC) dep. on board type
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 */
383 if (pAC
->GIni
.GIGenesis
) {
385 XM_IN32(IoC
, Port
, XM_MODE
, &MdReg
);
386 /* enable or disable promiscuous mode */
388 MdReg
|= XM_MD_ENA_PROM
;
391 MdReg
&= ~XM_MD_ENA_PROM
;
393 /* setup Mode Register */
394 XM_OUT32(IoC
, Port
, XM_MODE
, MdReg
);
399 if (pAC
->GIni
.GIYukon
) {
401 GM_IN16(IoC
, Port
, GM_RX_CTRL
, &RcReg
);
403 /* enable or disable unicast and multicast filtering */
405 RcReg
&= ~(GM_RXCR_UCF_ENA
| GM_RXCR_MCF_ENA
);
408 RcReg
|= (GM_RXCR_UCF_ENA
| GM_RXCR_MCF_ENA
);
410 /* setup Receive Control Register */
411 GM_OUT16(IoC
, Port
, GM_RX_CTRL
, RcReg
);
415 } /* SkMacPromiscMode*/
418 /******************************************************************************
420 * SkMacHashing() - Enable / Disable Hashing
423 * enables / disables hashing by setting Mode Register (XMAC) or
424 * Receive Control Register (GMAC) dep. on board type
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 */
443 if (pAC
->GIni
.GIGenesis
) {
445 XM_IN32(IoC
, Port
, XM_MODE
, &MdReg
);
446 /* enable or disable hashing */
448 MdReg
|= XM_MD_ENA_HASH
;
451 MdReg
&= ~XM_MD_ENA_HASH
;
453 /* setup Mode Register */
454 XM_OUT32(IoC
, Port
, XM_MODE
, MdReg
);
459 if (pAC
->GIni
.GIYukon
) {
461 GM_IN16(IoC
, Port
, GM_RX_CTRL
, &RcReg
);
463 /* enable or disable multicast filtering */
465 RcReg
|= GM_RXCR_MCF_ENA
;
468 RcReg
&= ~GM_RXCR_MCF_ENA
;
470 /* setup Receive Control Register */
471 GM_OUT16(IoC
, Port
, GM_RX_CTRL
, RcReg
);
479 /******************************************************************************
481 * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
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.
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 */
511 XM_IN16(IoC
, Port
, XM_RX_CMD
, &OldRxCmd
);
515 switch (Mode
& (SK_STRIP_FCS_ON
| SK_STRIP_FCS_OFF
)) {
516 case SK_STRIP_FCS_ON
:
517 RxCmd
|= XM_RX_STRIP_FCS
;
519 case SK_STRIP_FCS_OFF
:
520 RxCmd
&= ~XM_RX_STRIP_FCS
;
524 switch (Mode
& (SK_STRIP_PAD_ON
| SK_STRIP_PAD_OFF
)) {
525 case SK_STRIP_PAD_ON
:
526 RxCmd
|= XM_RX_STRIP_PAD
;
528 case SK_STRIP_PAD_OFF
:
529 RxCmd
&= ~XM_RX_STRIP_PAD
;
533 switch (Mode
& (SK_LENERR_OK_ON
| SK_LENERR_OK_OFF
)) {
534 case SK_LENERR_OK_ON
:
535 RxCmd
|= XM_RX_LENERR_OK
;
537 case SK_LENERR_OK_OFF
:
538 RxCmd
&= ~XM_RX_LENERR_OK
;
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
;
546 case SK_BIG_PK_OK_OFF
:
547 RxCmd
&= ~XM_RX_BIG_PK_OK
;
551 switch (Mode
& (SK_SELF_RX_ON
| SK_SELF_RX_OFF
)) {
553 RxCmd
|= XM_RX_SELF_RX
;
556 RxCmd
&= ~XM_RX_SELF_RX
;
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
);
567 /******************************************************************************
569 * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
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.
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 */
596 if ((Mode
& (SK_STRIP_FCS_ON
| SK_STRIP_FCS_OFF
)) != 0) {
598 GM_IN16(IoC
, Port
, GM_RX_CTRL
, &OldRxCmd
);
602 if ((Mode
& SK_STRIP_FCS_ON
) != 0) {
603 RxCmd
|= GM_RXCR_CRC_DIS
;
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
);
620 if ((Mode
& SK_BIG_PK_OK_ON
) != 0) {
621 RxCmd
|= GM_SMOD_JUMBO_ENA
;
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
);
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
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
);
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
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 */
678 if (pAC
->GIni
.GIGenesis
) {
680 XM_IN16(IoC
, Port
, XM_TX_CMD
, &Word
);
683 Word
&= ~XM_TX_NO_CRC
;
686 Word
|= XM_TX_NO_CRC
;
688 /* setup Tx Command Register */
689 XM_OUT16(IoC
, Port
, XM_TX_CMD
, Word
);
693 GM_IN16(IoC
, Port
, GM_TX_CTRL
, &Word
);
696 Word
&= ~GM_TXCR_CRC_DIS
;
699 Word
|= GM_TXCR_CRC_DIS
;
701 /* setup Tx Control Register */
702 GM_OUT16(IoC
, Port
, GM_TX_CTRL
, Word
);
711 /******************************************************************************
713 * SkXmClrExactAddr() - Clear Exact Match Address Registers
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'.
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) */
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
);
740 for (i
= StartNum
; i
<= StopNum
; i
++) {
741 XM_OUTADDR(IoC
, Port
, XM_EXM(i
), &ZeroAddr
[0]);
743 } /* SkXmClrExactAddr */
747 /******************************************************************************
749 * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
752 * Flush the transmit FIFO of the MAC specified by the index 'Port'
757 void SkMacFlushTxFifo(
758 SK_AC
*pAC
, /* adapter context */
759 SK_IOC IoC
, /* IO context */
760 int Port
) /* Port Index (MAC_1 + n) */
765 if (pAC
->GIni
.GIGenesis
) {
767 XM_IN32(IoC
, Port
, XM_MODE
, &MdReg
);
769 XM_OUT32(IoC
, Port
, XM_MODE
, MdReg
| XM_MD_FTF
);
774 if (pAC
->GIni
.GIYukon
) {
775 /* no way to flush the FIFO we have to issue a reset */
780 } /* SkMacFlushTxFifo */
783 /******************************************************************************
785 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
788 * Flush the receive FIFO of the MAC specified by the index 'Port'
793 void SkMacFlushRxFifo(
794 SK_AC
*pAC
, /* adapter context */
795 SK_IOC IoC
, /* IO context */
796 int Port
) /* Port Index (MAC_1 + n) */
801 if (pAC
->GIni
.GIGenesis
) {
803 XM_IN32(IoC
, Port
, XM_MODE
, &MdReg
);
805 XM_OUT32(IoC
, Port
, XM_MODE
, MdReg
| XM_MD_FRF
);
810 if (pAC
->GIni
.GIYukon
) {
811 /* no way to flush the FIFO we have to issue a reset */
816 } /* SkMacFlushRxFifo */
820 /******************************************************************************
822 * SkXmSoftRst() - Do a XMAC software reset
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.
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.
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
) {
876 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_INT_MASK
, 0xffff);
880 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_LONE_INT_ENAB
, 0);
884 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
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
);
901 /******************************************************************************
903 * SkXmHardRst() - Do a XMAC hardware reset
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).
912 * It is absolutely necessary to reset the SW_RST Bit first
913 * before calling this function.
918 static void SkXmHardRst(
919 SK_AC
*pAC
, /* adapter context */
920 SK_IOC IoC
, /* IO context */
921 int Port
) /* Port Index (MAC_1 + n) */
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
);
934 if (TOut
++ > 10000) {
936 * Adapter seems to be in RESET state.
937 * Registers cannot be written.
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
);
955 Reg
|= GP_DIR_0
; /* set to output */
956 Reg
&= ~GP_IO_0
; /* set PHY reset (active low) */
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
);
966 SK_IN32(IoC
, B2_GP_IO
, &Reg
);
971 /******************************************************************************
973 * SkXmClearRst() - Release the PHY & XMAC reset
980 static void SkXmClearRst(
981 SK_AC
*pAC
, /* adapter context */
982 SK_IOC IoC
, /* IO context */
983 int Port
) /* Port Index (MAC_1 + n) */
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
);
995 DWord
|= (GP_DIR_0
| GP_IO_0
); /* set to output */
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 */
1011 /******************************************************************************
1013 * SkGmSoftRst() - Do a GMAC software reset
1016 * The GPHY registers should not be destroyed during this
1017 * kind of software reset.
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};
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
));
1050 /******************************************************************************
1052 * SkGmHardRst() - Do a GMAC hardware reset
1059 static void SkGmHardRst(
1060 SK_AC
*pAC
, /* adapter context */
1061 SK_IOC IoC
, /* IO context */
1062 int Port
) /* Port Index (MAC_1 + n) */
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
);
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
);
1087 /******************************************************************************
1089 * SkGmClearRst() - Release the GPHY & GMAC reset
1096 static void SkGmClearRst(
1097 SK_AC
*pAC
, /* adapter context */
1098 SK_IOC IoC
, /* IO context */
1099 int Port
) /* Port Index (MAC_1 + n) */
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
);
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
);
1140 /* clear GMAC Control reset */
1141 SK_OUT32(IoC
, MR_ADDR(Port
, GMAC_CTRL
), GMC_PAUSE_ON
| GMC_RST_CLR
);
1146 SK_IN32(IoC
, MR_ADDR(Port
, GPHY_CTRL
), &DWord
);
1148 SK_IN32(IoC
, B0_ISRC
, &DWord
);
1151 } /* SkGmClearRst */
1155 /******************************************************************************
1157 * SkMacSoftRst() - Do a MAC software reset
1159 * Description: calls a MAC software reset routine dep. on board type
1165 SK_AC
*pAC
, /* adapter context */
1166 SK_IOC IoC
, /* IO context */
1167 int Port
) /* Port Index (MAC_1 + n) */
1171 pPrt
= &pAC
->GIni
.GP
[Port
];
1173 /* disable receiver and transmitter */
1174 SkMacRxTxDisable(pAC
, IoC
, Port
);
1177 if (pAC
->GIni
.GIGenesis
) {
1179 SkXmSoftRst(pAC
, IoC
, Port
);
1181 #endif /* GENESIS */
1184 if (pAC
->GIni
.GIYukon
) {
1186 SkGmSoftRst(pAC
, IoC
, Port
);
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
1210 SK_AC
*pAC
, /* adapter context */
1211 SK_IOC IoC
, /* IO context */
1212 int Port
) /* Port Index (MAC_1 + n) */
1216 if (pAC
->GIni
.GIGenesis
) {
1218 SkXmHardRst(pAC
, IoC
, Port
);
1220 #endif /* GENESIS */
1223 if (pAC
->GIni
.GIYukon
) {
1225 SkGmHardRst(pAC
, IoC
, Port
);
1229 pAC
->GIni
.GP
[Port
].PState
= SK_PRT_RESET
;
1231 } /* SkMacHardRst */
1234 /******************************************************************************
1236 * SkMacClearRst() - Clear the MAC reset
1238 * Description: calls a clear MAC reset routine dep. on board type
1244 SK_AC
*pAC
, /* adapter context */
1245 SK_IOC IoC
, /* IO context */
1246 int Port
) /* Port Index (MAC_1 + n) */
1250 if (pAC
->GIni
.GIGenesis
) {
1252 SkXmClearRst(pAC
, IoC
, Port
);
1254 #endif /* GENESIS */
1257 if (pAC
->GIni
.GIYukon
) {
1259 SkGmClearRst(pAC
, IoC
, Port
);
1263 } /* SkMacClearRst */
1267 /******************************************************************************
1269 * SkXmInitMac() - Initialize the XMAC II
1272 * Initialize the XMAC of the specified port.
1273 * The XMAC must be reset or stopped before calling this function.
1276 * The XMAC's Rx and Tx state machine is still disabled when returning.
1282 SK_AC
*pAC
, /* adapter context */
1283 SK_IOC IoC
, /* IO context */
1284 int Port
) /* Port Index (MAC_1 + n) */
1290 pPrt
= &pAC
->GIni
.GP
[Port
];
1292 if (pPrt
->PState
== SK_PRT_STOP
) {
1293 /* Port State: SK_PRT_STOP */
1294 /* Verify that the reset bit is cleared */
1295 SK_IN16(IoC
, MR_ADDR(Port
, TX_MFF_CTRL1
), &SWord
);
1297 if ((SWord
& MFF_SET_MAC_RST
) != 0) {
1298 /* PState does not match HW state */
1299 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_HWI_E006
, SKERR_HWI_E006MSG
);
1301 pPrt
->PState
= SK_PRT_RESET
;
1305 if (pPrt
->PState
== SK_PRT_RESET
) {
1307 SkXmClearRst(pAC
, IoC
, Port
);
1309 if (pPrt
->PhyType
!= SK_PHY_XMAC
) {
1310 /* read Id from external PHY (all have the same address) */
1311 SkXmPhyRead(pAC
, IoC
, Port
, PHY_XMAC_ID1
, &pPrt
->PhyId1
);
1314 * Optimize MDIO transfer by suppressing preamble.
1315 * Must be done AFTER first access to BCOM chip.
1317 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &SWord
);
1319 XM_OUT16(IoC
, Port
, XM_MMU_CMD
, SWord
| XM_MMU_NO_PRE
);
1321 if (pPrt
->PhyId1
== PHY_BCOM_ID1_C0
) {
1323 * Workaround BCOM Errata for the C0 type.
1324 * Write magic patterns to reserved registers.
1327 while (BcomRegC0Hack
[i
].PhyReg
!= 0) {
1328 SkXmPhyWrite(pAC
, IoC
, Port
, BcomRegC0Hack
[i
].PhyReg
,
1329 BcomRegC0Hack
[i
].PhyVal
);
1333 else if (pPrt
->PhyId1
== PHY_BCOM_ID1_A1
) {
1335 * Workaround BCOM Errata for the A1 type.
1336 * Write magic patterns to reserved registers.
1339 while (BcomRegA1Hack
[i
].PhyReg
!= 0) {
1340 SkXmPhyWrite(pAC
, IoC
, Port
, BcomRegA1Hack
[i
].PhyReg
,
1341 BcomRegA1Hack
[i
].PhyVal
);
1347 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1348 * Disable Power Management after reset.
1350 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, &SWord
);
1352 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
,
1353 (SK_U16
)(SWord
| PHY_B_AC_DIS_PM
));
1355 /* PHY LED initialization is done in SkGeXmitLED() */
1358 /* Dummy read the Interrupt source register */
1359 XM_IN16(IoC
, Port
, XM_ISRC
, &SWord
);
1362 * The auto-negotiation process starts immediately after
1363 * clearing the reset. The auto-negotiation process should be
1364 * started by the SIRQ, therefore stop it here immediately.
1366 SkMacInitPhy(pAC
, IoC
, Port
, SK_FALSE
);
1369 /* temp. code: enable signal detect */
1370 /* WARNING: do not override GMII setting above */
1371 XM_OUT16(IoC
, Port
, XM_HW_CFG
, XM_HW_COM4SIG
);
1376 * configure the XMACs Station Address
1377 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1378 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1380 for (i
= 0; i
< 3; i
++) {
1382 * The following 2 statements are together endianess
1383 * independent. Remember this when changing.
1385 SK_IN16(IoC
, (B2_MAC_2
+ Port
* 8 + i
* 2), &SWord
);
1387 XM_OUT16(IoC
, Port
, (XM_SA
+ i
* 2), SWord
);
1390 /* Tx Inter Packet Gap (XM_TX_IPG): use default */
1391 /* Tx High Water Mark (XM_TX_HI_WM): use default */
1392 /* Tx Low Water Mark (XM_TX_LO_WM): use default */
1393 /* Host Request Threshold (XM_HT_THR): use default */
1394 /* Rx Request Threshold (XM_RX_THR): use default */
1395 /* Rx Low Water Mark (XM_RX_LO_WM): use default */
1397 /* configure Rx High Water Mark (XM_RX_HI_WM) */
1398 XM_OUT16(IoC
, Port
, XM_RX_HI_WM
, SK_XM_RX_HI_WM
);
1400 /* Configure Tx Request Threshold */
1401 SWord
= SK_XM_THR_SL
; /* for single port */
1403 if (pAC
->GIni
.GIMacsFound
> 1) {
1404 switch (pAC
->GIni
.GIPortUsage
) {
1406 SWord
= SK_XM_THR_REDL
; /* redundant link */
1409 SWord
= SK_XM_THR_MULL
; /* load balancing */
1412 SWord
= SK_XM_THR_JUMBO
; /* jumbo frames */
1415 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_HWI_E014
, SKERR_HWI_E014MSG
);
1419 XM_OUT16(IoC
, Port
, XM_TX_THR
, SWord
);
1421 /* setup register defaults for the Tx Command Register */
1422 XM_OUT16(IoC
, Port
, XM_TX_CMD
, XM_TX_AUTO_PAD
);
1424 /* setup register defaults for the Rx Command Register */
1425 SWord
= XM_RX_STRIP_FCS
| XM_RX_LENERR_OK
;
1427 if (pAC
->GIni
.GIPortUsage
== SK_JUMBO_LINK
) {
1428 SWord
|= XM_RX_BIG_PK_OK
;
1431 if (pPrt
->PLinkMode
== SK_LMODE_HALF
) {
1433 * If in manual half duplex mode the other side might be in
1434 * full duplex mode, so ignore if a carrier extension is not seen
1435 * on frames received
1437 SWord
|= XM_RX_DIS_CEXT
;
1440 XM_OUT16(IoC
, Port
, XM_RX_CMD
, SWord
);
1443 * setup register defaults for the Mode Register
1444 * - Don't strip error frames to avoid Store & Forward
1446 * - Enable 'Check Station Address' bit
1447 * - Enable 'Check Address Array' bit
1449 XM_OUT32(IoC
, Port
, XM_MODE
, XM_DEF_MODE
);
1452 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1453 * - Enable all bits excepting 'Octets Rx OK Low CntOv'
1454 * and 'Octets Rx OK Hi Cnt Ov'.
1456 XM_OUT32(IoC
, Port
, XM_RX_EV_MSK
, XMR_DEF_MSK
);
1459 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1460 * - Enable all bits excepting 'Octets Tx OK Low CntOv'
1461 * and 'Octets Tx OK Hi Cnt Ov'.
1463 XM_OUT32(IoC
, Port
, XM_TX_EV_MSK
, XMT_DEF_MSK
);
1466 * Do NOT init XMAC interrupt mask here.
1467 * All interrupts remain disable until link comes up!
1471 * Any additional configuration changes may be done now.
1472 * The last action is to enable the Rx and Tx state machine.
1473 * This should be done after the auto-negotiation process
1474 * has been completed successfully.
1477 #endif /* GENESIS */
1481 /******************************************************************************
1483 * SkGmInitMac() - Initialize the GMAC
1486 * Initialize the GMAC of the specified port.
1487 * The GMAC must be reset or stopped before calling this function.
1490 * The GMAC's Rx and Tx state machine is still disabled when returning.
1496 SK_AC
*pAC
, /* adapter context */
1497 SK_IOC IoC
, /* IO context */
1498 int Port
) /* Port Index (MAC_1 + n) */
1505 pPrt
= &pAC
->GIni
.GP
[Port
];
1507 if (pPrt
->PState
== SK_PRT_STOP
) {
1508 /* Port State: SK_PRT_STOP */
1509 /* Verify that the reset bit is cleared */
1510 SK_IN32(IoC
, MR_ADDR(Port
, GMAC_CTRL
), &DWord
);
1512 if ((DWord
& GMC_RST_SET
) != 0) {
1513 /* PState does not match HW state */
1514 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_HWI_E006
, SKERR_HWI_E006MSG
);
1516 pPrt
->PState
= SK_PRT_RESET
;
1520 if (pPrt
->PState
== SK_PRT_RESET
) {
1522 SkGmHardRst(pAC
, IoC
, Port
);
1524 SkGmClearRst(pAC
, IoC
, Port
);
1526 /* Auto-negotiation ? */
1527 if (pPrt
->PLinkMode
== SK_LMODE_HALF
|| pPrt
->PLinkMode
== SK_LMODE_FULL
) {
1528 /* Auto-negotiation disabled */
1530 /* get General Purpose Control */
1531 GM_IN16(IoC
, Port
, GM_GP_CTRL
, &SWord
);
1533 /* disable auto-update for speed, duplex and flow-control */
1534 SWord
|= GM_GPCR_AU_ALL_DIS
;
1536 /* setup General Purpose Control Register */
1537 GM_OUT16(IoC
, Port
, GM_GP_CTRL
, SWord
);
1539 SWord
= GM_GPCR_AU_ALL_DIS
;
1545 /* speed settings */
1546 switch (pPrt
->PLinkSpeed
) {
1547 case SK_LSPEED_AUTO
:
1548 case SK_LSPEED_1000MBPS
:
1549 SWord
|= GM_GPCR_SPEED_1000
| GM_GPCR_SPEED_100
;
1551 case SK_LSPEED_100MBPS
:
1552 SWord
|= GM_GPCR_SPEED_100
;
1554 case SK_LSPEED_10MBPS
:
1558 /* duplex settings */
1559 if (pPrt
->PLinkMode
!= SK_LMODE_HALF
) {
1560 /* set full duplex */
1561 SWord
|= GM_GPCR_DUP_FULL
;
1564 /* flow-control settings */
1565 switch (pPrt
->PFlowCtrlMode
) {
1566 case SK_FLOW_MODE_NONE
:
1568 SK_OUT32(IoC
, MR_ADDR(Port
, GMAC_CTRL
), GMC_PAUSE_OFF
);
1569 /* disable Tx & Rx flow-control */
1570 SWord
|= GM_GPCR_FC_TX_DIS
| GM_GPCR_FC_RX_DIS
| GM_GPCR_AU_FCT_DIS
;
1572 case SK_FLOW_MODE_LOC_SEND
:
1573 /* disable Rx flow-control */
1574 SWord
|= GM_GPCR_FC_RX_DIS
| GM_GPCR_AU_FCT_DIS
;
1576 case SK_FLOW_MODE_SYMMETRIC
:
1577 case SK_FLOW_MODE_SYM_OR_REM
:
1578 /* enable Tx & Rx flow-control */
1582 /* setup General Purpose Control Register */
1583 GM_OUT16(IoC
, Port
, GM_GP_CTRL
, SWord
);
1585 /* dummy read the Interrupt Source Register */
1586 SK_IN16(IoC
, GMAC_IRQ_SRC
, &SWord
);
1589 /* read Id from PHY */
1590 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_ID1
, &pPrt
->PhyId1
);
1592 SkGmInitPhyMarv(pAC
, IoC
, Port
, SK_FALSE
);
1596 (void)SkGmResetCounter(pAC
, IoC
, Port
);
1598 /* setup Transmit Control Register */
1599 GM_OUT16(IoC
, Port
, GM_TX_CTRL
, TX_COL_THR(pPrt
->PMacColThres
));
1601 /* setup Receive Control Register */
1602 GM_OUT16(IoC
, Port
, GM_RX_CTRL
, GM_RXCR_UCF_ENA
| GM_RXCR_MCF_ENA
|
1605 /* setup Transmit Flow Control Register */
1606 GM_OUT16(IoC
, Port
, GM_TX_FLOW_CTRL
, 0xffff);
1608 /* setup Transmit Parameter Register */
1610 GM_IN16(IoC
, Port
, GM_TX_PARAM
, &SWord
);
1613 SWord
= TX_JAM_LEN_VAL(pPrt
->PMacJamLen
) |
1614 TX_JAM_IPG_VAL(pPrt
->PMacJamIpgVal
) |
1615 TX_IPG_JAM_DATA(pPrt
->PMacJamIpgData
);
1617 GM_OUT16(IoC
, Port
, GM_TX_PARAM
, SWord
);
1619 /* configure the Serial Mode Register */
1621 GM_IN16(IoC
, Port
, GM_SERIAL_MODE
, &SWord
);
1624 SWord
= GM_SMOD_VLAN_ENA
| IPG_DATA_VAL(pPrt
->PMacIpgData
);
1626 if (pPrt
->PMacLimit4
) {
1627 /* reset of collision counter after 4 consecutive collisions */
1628 SWord
|= GM_SMOD_LIMIT_4
;
1631 if (pAC
->GIni
.GIPortUsage
== SK_JUMBO_LINK
) {
1632 /* enable jumbo mode (Max. Frame Length = 9018) */
1633 SWord
|= GM_SMOD_JUMBO_ENA
;
1636 GM_OUT16(IoC
, Port
, GM_SERIAL_MODE
, SWord
);
1639 * configure the GMACs Station Addresses
1640 * in PROM you can find our addresses at:
1641 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1642 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1643 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1646 for (i
= 0; i
< 3; i
++) {
1648 * The following 2 statements are together endianess
1649 * independent. Remember this when changing.
1651 /* physical address: will be used for pause frames */
1652 SK_IN16(IoC
, (B2_MAC_2
+ Port
* 8 + i
* 2), &SWord
);
1655 /* WA for deviation #16 */
1656 if (pAC
->GIni
.GIChipId
== CHIP_ID_YUKON
&& pAC
->GIni
.GIChipRev
== 0) {
1657 /* swap the address bytes */
1658 SWord
= ((SWord
& 0xff00) >> 8) | ((SWord
& 0x00ff) << 8);
1660 /* write to register in reversed order */
1661 GM_OUT16(IoC
, Port
, (GM_SRC_ADDR_1L
+ (2 - i
) * 4), SWord
);
1664 GM_OUT16(IoC
, Port
, (GM_SRC_ADDR_1L
+ i
* 4), SWord
);
1667 GM_OUT16(IoC
, Port
, (GM_SRC_ADDR_1L
+ i
* 4), SWord
);
1668 #endif /* WA_DEV_16 */
1670 /* virtual address: will be used for data */
1671 SK_IN16(IoC
, (B2_MAC_1
+ Port
* 8 + i
* 2), &SWord
);
1673 GM_OUT16(IoC
, Port
, (GM_SRC_ADDR_2L
+ i
* 4), SWord
);
1675 /* reset Multicast filtering Hash registers 1-3 */
1676 GM_OUT16(IoC
, Port
, GM_MC_ADDR_H1
+ 4*i
, 0);
1679 /* reset Multicast filtering Hash register 4 */
1680 GM_OUT16(IoC
, Port
, GM_MC_ADDR_H4
, 0);
1682 /* enable interrupt mask for counter overflows */
1683 GM_OUT16(IoC
, Port
, GM_TX_IRQ_MSK
, 0);
1684 GM_OUT16(IoC
, Port
, GM_RX_IRQ_MSK
, 0);
1685 GM_OUT16(IoC
, Port
, GM_TR_IRQ_MSK
, 0);
1687 #if defined(SK_DIAG) || defined(DEBUG)
1688 /* read General Purpose Status */
1689 GM_IN16(IoC
, Port
, GM_GP_STAT
, &SWord
);
1691 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1692 ("MAC Stat Reg.=0x%04X\n", SWord
));
1693 #endif /* SK_DIAG || DEBUG */
1696 c_print("MAC Stat Reg=0x%04X\n", SWord
);
1697 #endif /* SK_DIAG */
1704 /******************************************************************************
1706 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1709 * This function initializes the XMACs Duplex Mode.
1710 * It should be called after successfully finishing
1711 * the Auto-negotiation Process
1717 SK_AC
*pAC
, /* adapter context */
1718 SK_IOC IoC
, /* IO context */
1719 int Port
) /* Port Index (MAC_1 + n) */
1721 switch (pAC
->GIni
.GP
[Port
].PLinkModeStatus
) {
1722 case SK_LMODE_STAT_AUTOHALF
:
1723 case SK_LMODE_STAT_HALF
:
1724 /* Configuration Actions for Half Duplex Mode */
1726 * XM_BURST = default value. We are probable not quick
1727 * enough at the 'XMAC' bus to burst 8kB.
1728 * The XMAC stops bursting if no transmit frames
1729 * are available or the burst limit is exceeded.
1731 /* XM_TX_RT_LIM = default value (15) */
1732 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
1734 case SK_LMODE_STAT_AUTOFULL
:
1735 case SK_LMODE_STAT_FULL
:
1736 /* Configuration Actions for Full Duplex Mode */
1738 * The duplex mode is configured by the PHY,
1739 * therefore it seems to be that there is nothing
1743 case SK_LMODE_STAT_UNKNOWN
:
1745 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_HWI_E007
, SKERR_HWI_E007MSG
);
1748 } /* SkXmInitDupMd */
1751 /******************************************************************************
1753 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1756 * This function initializes the Pause Mode which should
1757 * be used for this port.
1758 * It should be called after successfully finishing
1759 * the Auto-negotiation Process
1764 void SkXmInitPauseMd(
1765 SK_AC
*pAC
, /* adapter context */
1766 SK_IOC IoC
, /* IO context */
1767 int Port
) /* Port Index (MAC_1 + n) */
1773 pPrt
= &pAC
->GIni
.GP
[Port
];
1775 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &Word
);
1777 if (pPrt
->PFlowCtrlStatus
== SK_FLOW_STAT_NONE
||
1778 pPrt
->PFlowCtrlStatus
== SK_FLOW_STAT_LOC_SEND
) {
1780 /* Disable Pause Frame Reception */
1781 Word
|= XM_MMU_IGN_PF
;
1785 * enabling pause frame reception is required for 1000BT
1786 * because the XMAC is not reset if the link is going down
1788 /* Enable Pause Frame Reception */
1789 Word
&= ~XM_MMU_IGN_PF
;
1792 XM_OUT16(IoC
, Port
, XM_MMU_CMD
, Word
);
1794 XM_IN32(IoC
, Port
, XM_MODE
, &DWord
);
1796 if (pPrt
->PFlowCtrlStatus
== SK_FLOW_STAT_SYMMETRIC
||
1797 pPrt
->PFlowCtrlStatus
== SK_FLOW_STAT_LOC_SEND
) {
1800 * Configure Pause Frame Generation
1801 * Use internal and external Pause Frame Generation.
1802 * Sending pause frames is edge triggered.
1803 * Send a Pause frame with the maximum pause time if
1804 * internal oder external FIFO full condition occurs.
1805 * Send a zero pause time frame to re-start transmission.
1808 /* XM_PAUSE_DA = '010000C28001' (default) */
1810 /* XM_MAC_PTIME = 0xffff (maximum) */
1811 /* remember this value is defined in big endian (!) */
1812 XM_OUT16(IoC
, Port
, XM_MAC_PTIME
, 0xffff);
1814 /* Set Pause Mode in Mode Register */
1815 DWord
|= XM_PAUSE_MODE
;
1817 /* Set Pause Mode in MAC Rx FIFO */
1818 SK_OUT16(IoC
, MR_ADDR(Port
, RX_MFF_CTRL1
), MFF_ENA_PAUSE
);
1822 * disable pause frame generation is required for 1000BT
1823 * because the XMAC is not reset if the link is going down
1825 /* Disable Pause Mode in Mode Register */
1826 DWord
&= ~XM_PAUSE_MODE
;
1828 /* Disable Pause Mode in MAC Rx FIFO */
1829 SK_OUT16(IoC
, MR_ADDR(Port
, RX_MFF_CTRL1
), MFF_DIS_PAUSE
);
1832 XM_OUT32(IoC
, Port
, XM_MODE
, DWord
);
1833 } /* SkXmInitPauseMd*/
1836 /******************************************************************************
1838 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
1840 * Description: initializes all the XMACs Phy registers
1847 static void SkXmInitPhyXmac(
1848 SK_AC
*pAC
, /* adapter context */
1849 SK_IOC IoC
, /* IO context */
1850 int Port
, /* Port Index (MAC_1 + n) */
1851 SK_BOOL DoLoop
) /* Should a Phy LoopBack be set-up? */
1856 pPrt
= &pAC
->GIni
.GP
[Port
];
1859 /* Auto-negotiation ? */
1860 if (pPrt
->PLinkMode
== SK_LMODE_HALF
|| pPrt
->PLinkMode
== SK_LMODE_FULL
) {
1861 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1862 ("InitPhyXmac: no auto-negotiation Port %d\n", Port
));
1863 /* Set DuplexMode in Config register */
1864 if (pPrt
->PLinkMode
== SK_LMODE_FULL
) {
1865 Ctrl
|= PHY_CT_DUP_MD
;
1869 * Do NOT enable Auto-negotiation here. This would hold
1870 * the link down because no IDLEs are transmitted
1874 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1875 ("InitPhyXmac: with auto-negotiation Port %d\n", Port
));
1876 /* Set Auto-negotiation advertisement */
1878 /* Set Full/half duplex capabilities */
1879 switch (pPrt
->PLinkMode
) {
1880 case SK_LMODE_AUTOHALF
:
1881 Ctrl
|= PHY_X_AN_HD
;
1883 case SK_LMODE_AUTOFULL
:
1884 Ctrl
|= PHY_X_AN_FD
;
1886 case SK_LMODE_AUTOBOTH
:
1887 Ctrl
|= PHY_X_AN_FD
| PHY_X_AN_HD
;
1890 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E015
,
1894 /* Set Flow-control capabilities */
1895 switch (pPrt
->PFlowCtrlMode
) {
1896 case SK_FLOW_MODE_NONE
:
1897 Ctrl
|= PHY_X_P_NO_PAUSE
;
1899 case SK_FLOW_MODE_LOC_SEND
:
1900 Ctrl
|= PHY_X_P_ASYM_MD
;
1902 case SK_FLOW_MODE_SYMMETRIC
:
1903 Ctrl
|= PHY_X_P_SYM_MD
;
1905 case SK_FLOW_MODE_SYM_OR_REM
:
1906 Ctrl
|= PHY_X_P_BOTH_MD
;
1909 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E016
,
1913 /* Write AutoNeg Advertisement Register */
1914 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_XMAC_AUNE_ADV
, Ctrl
);
1916 /* Restart Auto-negotiation */
1917 Ctrl
= PHY_CT_ANE
| PHY_CT_RE_CFG
;
1921 /* Set the Phy Loopback bit, too */
1922 Ctrl
|= PHY_CT_LOOP
;
1925 /* Write to the Phy control register */
1926 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_XMAC_CTRL
, Ctrl
);
1927 } /* SkXmInitPhyXmac */
1930 /******************************************************************************
1932 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
1934 * Description: initializes all the Broadcom Phy registers
1941 static void SkXmInitPhyBcom(
1942 SK_AC
*pAC
, /* adapter context */
1943 SK_IOC IoC
, /* IO context */
1944 int Port
, /* Port Index (MAC_1 + n) */
1945 SK_BOOL DoLoop
) /* Should a Phy LoopBack be set-up? */
1954 Ctrl1
= PHY_CT_SP1000
;
1956 Ctrl3
= PHY_SEL_TYPE
;
1957 Ctrl4
= PHY_B_PEC_EN_LTR
;
1958 Ctrl5
= PHY_B_AC_TX_TST
;
1960 pPrt
= &pAC
->GIni
.GP
[Port
];
1962 /* manually Master/Slave ? */
1963 if (pPrt
->PMSMode
!= SK_MS_MODE_AUTO
) {
1964 Ctrl2
|= PHY_B_1000C_MSE
;
1966 if (pPrt
->PMSMode
== SK_MS_MODE_MASTER
) {
1967 Ctrl2
|= PHY_B_1000C_MSC
;
1970 /* Auto-negotiation ? */
1971 if (pPrt
->PLinkMode
== SK_LMODE_HALF
|| pPrt
->PLinkMode
== SK_LMODE_FULL
) {
1972 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1973 ("InitPhyBcom: no auto-negotiation Port %d\n", Port
));
1974 /* Set DuplexMode in Config register */
1975 if (pPrt
->PLinkMode
== SK_LMODE_FULL
) {
1976 Ctrl1
|= PHY_CT_DUP_MD
;
1979 /* Determine Master/Slave manually if not already done */
1980 if (pPrt
->PMSMode
== SK_MS_MODE_AUTO
) {
1981 Ctrl2
|= PHY_B_1000C_MSE
; /* set it to Slave */
1985 * Do NOT enable Auto-negotiation here. This would hold
1986 * the link down because no IDLES are transmitted
1990 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
1991 ("InitPhyBcom: with auto-negotiation Port %d\n", Port
));
1992 /* Set Auto-negotiation advertisement */
1995 * Workaround BCOM Errata #1 for the C5 type.
1996 * 1000Base-T Link Acquisition Failure in Slave Mode
1997 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
1999 Ctrl2
|= PHY_B_1000C_RD
;
2001 /* Set Full/half duplex capabilities */
2002 switch (pPrt
->PLinkMode
) {
2003 case SK_LMODE_AUTOHALF
:
2004 Ctrl2
|= PHY_B_1000C_AHD
;
2006 case SK_LMODE_AUTOFULL
:
2007 Ctrl2
|= PHY_B_1000C_AFD
;
2009 case SK_LMODE_AUTOBOTH
:
2010 Ctrl2
|= PHY_B_1000C_AFD
| PHY_B_1000C_AHD
;
2013 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E015
,
2017 /* Set Flow-control capabilities */
2018 switch (pPrt
->PFlowCtrlMode
) {
2019 case SK_FLOW_MODE_NONE
:
2020 Ctrl3
|= PHY_B_P_NO_PAUSE
;
2022 case SK_FLOW_MODE_LOC_SEND
:
2023 Ctrl3
|= PHY_B_P_ASYM_MD
;
2025 case SK_FLOW_MODE_SYMMETRIC
:
2026 Ctrl3
|= PHY_B_P_SYM_MD
;
2028 case SK_FLOW_MODE_SYM_OR_REM
:
2029 Ctrl3
|= PHY_B_P_BOTH_MD
;
2032 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E016
,
2036 /* Restart Auto-negotiation */
2037 Ctrl1
|= PHY_CT_ANE
| PHY_CT_RE_CFG
;
2040 /* Initialize LED register here? */
2041 /* No. Please do it in SkDgXmitLed() (if required) and swap
2042 init order of LEDs and XMAC. (MAl) */
2044 /* Write 1000Base-T Control Register */
2045 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_1000T_CTRL
, Ctrl2
);
2046 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2047 ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2
));
2049 /* Write AutoNeg Advertisement Register */
2050 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_AUNE_ADV
, Ctrl3
);
2051 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2052 ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3
));
2055 /* Set the Phy Loopback bit, too */
2056 Ctrl1
|= PHY_CT_LOOP
;
2059 if (pAC
->GIni
.GIPortUsage
== SK_JUMBO_LINK
) {
2060 /* configure FIFO to high latency for transmission of ext. packets */
2061 Ctrl4
|= PHY_B_PEC_HIGH_LA
;
2063 /* configure reception of extended packets */
2064 Ctrl5
|= PHY_B_AC_LONG_PACK
;
2066 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, Ctrl5
);
2069 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2070 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_P_EXT_CTRL
, Ctrl4
);
2072 /* Write to the Phy control register */
2073 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_CTRL
, Ctrl1
);
2074 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2075 ("PHY Control Reg=0x%04X\n", Ctrl1
));
2076 } /* SkXmInitPhyBcom */
2077 #endif /* GENESIS */
2082 /******************************************************************************
2084 * SkGmEnterLowPowerMode()
2087 * This function sets the Marvell Alaska PHY to the low power mode
2088 * given by parameter mode.
2089 * The following low power modes are available:
2091 * - Coma Mode (Deep Sleep):
2092 * Power consumption: ~15 - 30 mW
2093 * The PHY cannot wake up on its own.
2095 * - IEEE 22.2.4.1.5 compatible power down mode
2096 * Power consumption: ~240 mW
2097 * The PHY cannot wake up on its own.
2099 * - energy detect mode
2100 * Power consumption: ~160 mW
2101 * The PHY can wake up on its own by detecting activity
2102 * on the CAT 5 cable.
2104 * - energy detect plus mode
2105 * Power consumption: ~150 mW
2106 * The PHY can wake up on its own by detecting activity
2107 * on the CAT 5 cable.
2108 * Connected devices can be woken up by sending normal link
2109 * pulses every one second.
2117 int SkGmEnterLowPowerMode(
2118 SK_AC
*pAC
, /* adapter context */
2119 SK_IOC IoC
, /* IO context */
2120 int Port
, /* Port Index (e.g. MAC_1) */
2121 SK_U8 Mode
) /* low power mode */
2128 if (pAC
->GIni
.GIYukonLite
&&
2129 pAC
->GIni
.GIChipRev
== CHIP_REV_YU_LITE_A3
) {
2131 /* save current power mode */
2132 LastMode
= pAC
->GIni
.GP
[Port
].PPhyPowerState
;
2133 pAC
->GIni
.GP
[Port
].PPhyPowerState
= Mode
;
2136 /* coma mode (deep sleep) */
2137 case PHY_PM_DEEP_SLEEP
:
2138 /* setup General Purpose Control Register */
2139 GM_OUT16(IoC
, 0, GM_GP_CTRL
, GM_GPCR_FL_PASS
|
2140 GM_GPCR_SPEED_100
| GM_GPCR_AU_ALL_DIS
);
2142 /* apply COMA mode workaround */
2143 SkGmPhyWrite(pAC
, IoC
, Port
, 29, 0x001f);
2144 SkGmPhyWrite(pAC
, IoC
, Port
, 30, 0xfff3);
2146 SK_IN32(IoC
, PCI_C(PCI_OUR_REG_1
), &DWord
);
2148 SK_OUT8(IoC
, B2_TST_CTRL1
, TST_CFG_WRITE_ON
);
2150 /* Set PHY to Coma Mode */
2151 SK_OUT32(IoC
, PCI_C(PCI_OUR_REG_1
), DWord
| PCI_PHY_COMA
);
2153 SK_OUT8(IoC
, B2_TST_CTRL1
, TST_CFG_WRITE_OFF
);
2157 /* IEEE 22.2.4.1.5 compatible power down mode */
2158 case PHY_PM_IEEE_POWER_DOWN
:
2160 * - disable MAC 125 MHz clock
2161 * - allow MAC power down
2163 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, &Word
);
2164 Word
|= PHY_M_PC_DIS_125CLK
;
2165 Word
&= ~PHY_M_PC_MAC_POW_UP
;
2166 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, Word
);
2169 * register changes must be followed by a software
2170 * reset to take effect
2172 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CTRL
, &Word
);
2173 Word
|= PHY_CT_RESET
;
2174 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_CTRL
, Word
);
2176 /* switch IEEE compatible power down mode on */
2177 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CTRL
, &Word
);
2178 Word
|= PHY_CT_PDOWN
;
2179 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_CTRL
, Word
);
2182 /* energy detect and energy detect plus mode */
2183 case PHY_PM_ENERGY_DETECT
:
2184 case PHY_PM_ENERGY_DETECT_PLUS
:
2186 * - disable MAC 125 MHz clock
2188 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, &Word
);
2189 Word
|= PHY_M_PC_DIS_125CLK
;
2190 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, Word
);
2192 /* activate energy detect mode 1 */
2193 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, &Word
);
2195 /* energy detect mode */
2196 if (Mode
== PHY_PM_ENERGY_DETECT
) {
2197 Word
|= PHY_M_PC_EN_DET
;
2199 /* energy detect plus mode */
2201 Word
|= PHY_M_PC_EN_DET_PLUS
;
2204 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, Word
);
2207 * reinitialize the PHY to force a software reset
2208 * which is necessary after the register settings
2209 * for the energy detect modes.
2210 * Furthermore reinitialisation prevents that the
2211 * PHY is running out of a stable state.
2213 SkGmInitPhyMarv(pAC
, IoC
, Port
, SK_FALSE
);
2216 /* don't change current power mode */
2218 pAC
->GIni
.GP
[Port
].PPhyPowerState
= LastMode
;
2223 /* low power modes are not supported by this chip */
2230 } /* SkGmEnterLowPowerMode */
2232 /******************************************************************************
2234 * SkGmLeaveLowPowerMode()
2237 * Leave the current low power mode and switch to normal mode
2245 int SkGmLeaveLowPowerMode(
2246 SK_AC
*pAC
, /* adapter context */
2247 SK_IOC IoC
, /* IO context */
2248 int Port
) /* Port Index (e.g. MAC_1) */
2255 if (pAC
->GIni
.GIYukonLite
&&
2256 pAC
->GIni
.GIChipRev
== CHIP_REV_YU_LITE_A3
) {
2258 /* save current power mode */
2259 LastMode
= pAC
->GIni
.GP
[Port
].PPhyPowerState
;
2260 pAC
->GIni
.GP
[Port
].PPhyPowerState
= PHY_PM_OPERATIONAL_MODE
;
2263 /* coma mode (deep sleep) */
2264 case PHY_PM_DEEP_SLEEP
:
2265 SK_IN32(IoC
, PCI_C(PCI_OUR_REG_1
), &DWord
);
2267 SK_OUT8(IoC
, B2_TST_CTRL1
, TST_CFG_WRITE_ON
);
2269 /* Release PHY from Coma Mode */
2270 SK_OUT32(IoC
, PCI_C(PCI_OUR_REG_1
), DWord
& ~PCI_PHY_COMA
);
2272 SK_OUT8(IoC
, B2_TST_CTRL1
, TST_CFG_WRITE_OFF
);
2274 SK_IN32(IoC
, B2_GP_IO
, &DWord
);
2277 DWord
|= (GP_DIR_9
| GP_IO_9
);
2280 SK_OUT32(IoC
, B2_GP_IO
, DWord
);
2282 DWord
&= ~GP_IO_9
; /* clear PHY reset (active high) */
2284 /* clear PHY reset */
2285 SK_OUT32(IoC
, B2_GP_IO
, DWord
);
2288 /* IEEE 22.2.4.1.5 compatible power down mode */
2289 case PHY_PM_IEEE_POWER_DOWN
:
2291 * - enable MAC 125 MHz clock
2292 * - set MAC power up
2294 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, &Word
);
2295 Word
&= ~PHY_M_PC_DIS_125CLK
;
2296 Word
|= PHY_M_PC_MAC_POW_UP
;
2297 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, Word
);
2300 * register changes must be followed by a software
2301 * reset to take effect
2303 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CTRL
, &Word
);
2304 Word
|= PHY_CT_RESET
;
2305 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_CTRL
, Word
);
2307 /* switch IEEE compatible power down mode off */
2308 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CTRL
, &Word
);
2309 Word
&= ~PHY_CT_PDOWN
;
2310 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_CTRL
, Word
);
2313 /* energy detect and energy detect plus mode */
2314 case PHY_PM_ENERGY_DETECT
:
2315 case PHY_PM_ENERGY_DETECT_PLUS
:
2317 * - enable MAC 125 MHz clock
2319 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, &Word
);
2320 Word
&= ~PHY_M_PC_DIS_125CLK
;
2321 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, Word
);
2323 /* disable energy detect mode */
2324 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, &Word
);
2325 Word
&= ~PHY_M_PC_EN_DET_MSK
;
2326 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, Word
);
2329 * reinitialize the PHY to force a software reset
2330 * which is necessary after the register settings
2331 * for the energy detect modes.
2332 * Furthermore reinitialisation prevents that the
2333 * PHY is running out of a stable state.
2335 SkGmInitPhyMarv(pAC
, IoC
, Port
, SK_FALSE
);
2338 /* don't change current power mode */
2340 pAC
->GIni
.GP
[Port
].PPhyPowerState
= LastMode
;
2345 /* low power modes are not supported by this chip */
2352 } /* SkGmLeaveLowPowerMode */
2353 #endif /* !SK_SLIM */
2356 /******************************************************************************
2358 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2360 * Description: initializes all the Marvell Phy registers
2367 static void SkGmInitPhyMarv(
2368 SK_AC
*pAC
, /* adapter context */
2369 SK_IOC IoC
, /* IO context */
2370 int Port
, /* Port Index (MAC_1 + n) */
2371 SK_BOOL DoLoop
) /* Should a Phy LoopBack be set-up? */
2380 #if defined(SK_DIAG) || defined(DEBUG)
2384 #endif /* SK_DIAG || DEBUG */
2386 pPrt
= &pAC
->GIni
.GP
[Port
];
2388 /* Auto-negotiation ? */
2389 if (pPrt
->PLinkMode
== SK_LMODE_HALF
|| pPrt
->PLinkMode
== SK_LMODE_FULL
) {
2396 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2397 ("InitPhyMarv: Port %d, auto-negotiation %s\n",
2398 Port
, AutoNeg
? "ON" : "OFF"));
2401 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2405 /* Set 'MAC Power up'-bit, set Manual MDI configuration */
2406 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
,
2407 PHY_M_PC_MAC_POW_UP
);
2409 else if (AutoNeg
&& pPrt
->PLinkSpeed
== SK_LSPEED_AUTO
) {
2410 /* Read Ext. PHY Specific Control */
2411 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_EXT_CTRL
, &ExtPhyCtrl
);
2413 ExtPhyCtrl
&= ~(PHY_M_EC_M_DSC_MSK
| PHY_M_EC_S_DSC_MSK
|
2414 PHY_M_EC_MAC_S_MSK
);
2416 ExtPhyCtrl
|= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ
) |
2417 PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
2419 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_EXT_CTRL
, ExtPhyCtrl
);
2420 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2421 ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl
));
2424 /* Read PHY Control */
2425 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CTRL
, &PhyCtrl
);
2428 /* Disable Auto-negotiation */
2429 PhyCtrl
&= ~PHY_CT_ANE
;
2432 PhyCtrl
|= PHY_CT_RESET
;
2433 /* Assert software reset */
2434 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_CTRL
, PhyCtrl
);
2437 PhyCtrl
= 0 /* PHY_CT_COL_TST */;
2439 AutoNegAdv
= PHY_SEL_TYPE
;
2441 /* manually Master/Slave ? */
2442 if (pPrt
->PMSMode
!= SK_MS_MODE_AUTO
) {
2443 /* enable Manual Master/Slave */
2444 C1000BaseT
|= PHY_M_1000C_MSE
;
2446 if (pPrt
->PMSMode
== SK_MS_MODE_MASTER
) {
2447 C1000BaseT
|= PHY_M_1000C_MSC
; /* set it to Master */
2451 /* Auto-negotiation ? */
2454 if (pPrt
->PLinkMode
== SK_LMODE_FULL
) {
2455 /* Set Full Duplex Mode */
2456 PhyCtrl
|= PHY_CT_DUP_MD
;
2459 /* Set Master/Slave manually if not already done */
2460 if (pPrt
->PMSMode
== SK_MS_MODE_AUTO
) {
2461 C1000BaseT
|= PHY_M_1000C_MSE
; /* set it to Slave */
2465 switch (pPrt
->PLinkSpeed
) {
2466 case SK_LSPEED_AUTO
:
2467 case SK_LSPEED_1000MBPS
:
2468 PhyCtrl
|= PHY_CT_SP1000
;
2470 case SK_LSPEED_100MBPS
:
2471 PhyCtrl
|= PHY_CT_SP100
;
2473 case SK_LSPEED_10MBPS
:
2476 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E019
,
2481 PhyCtrl
|= PHY_CT_RESET
;
2485 /* Set Auto-negotiation advertisement */
2487 if (pAC
->GIni
.GICopperType
) {
2488 /* Set Speed capabilities */
2489 switch (pPrt
->PLinkSpeed
) {
2490 case SK_LSPEED_AUTO
:
2491 C1000BaseT
|= PHY_M_1000C_AHD
| PHY_M_1000C_AFD
;
2492 AutoNegAdv
|= PHY_M_AN_100_FD
| PHY_M_AN_100_HD
|
2493 PHY_M_AN_10_FD
| PHY_M_AN_10_HD
;
2495 case SK_LSPEED_1000MBPS
:
2496 C1000BaseT
|= PHY_M_1000C_AHD
| PHY_M_1000C_AFD
;
2498 case SK_LSPEED_100MBPS
:
2499 AutoNegAdv
|= PHY_M_AN_100_FD
| PHY_M_AN_100_HD
|
2500 /* advertise 10Base-T also */
2501 PHY_M_AN_10_FD
| PHY_M_AN_10_HD
;
2503 case SK_LSPEED_10MBPS
:
2504 AutoNegAdv
|= PHY_M_AN_10_FD
| PHY_M_AN_10_HD
;
2507 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E019
,
2511 /* Set Full/half duplex capabilities */
2512 switch (pPrt
->PLinkMode
) {
2513 case SK_LMODE_AUTOHALF
:
2514 C1000BaseT
&= ~PHY_M_1000C_AFD
;
2515 AutoNegAdv
&= ~(PHY_M_AN_100_FD
| PHY_M_AN_10_FD
);
2517 case SK_LMODE_AUTOFULL
:
2518 C1000BaseT
&= ~PHY_M_1000C_AHD
;
2519 AutoNegAdv
&= ~(PHY_M_AN_100_HD
| PHY_M_AN_10_HD
);
2521 case SK_LMODE_AUTOBOTH
:
2524 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E015
,
2528 /* Set Flow-control capabilities */
2529 switch (pPrt
->PFlowCtrlMode
) {
2530 case SK_FLOW_MODE_NONE
:
2531 AutoNegAdv
|= PHY_B_P_NO_PAUSE
;
2533 case SK_FLOW_MODE_LOC_SEND
:
2534 AutoNegAdv
|= PHY_B_P_ASYM_MD
;
2536 case SK_FLOW_MODE_SYMMETRIC
:
2537 AutoNegAdv
|= PHY_B_P_SYM_MD
;
2539 case SK_FLOW_MODE_SYM_OR_REM
:
2540 AutoNegAdv
|= PHY_B_P_BOTH_MD
;
2543 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E016
,
2547 else { /* special defines for FIBER (88E1011S only) */
2549 /* Set Full/half duplex capabilities */
2550 switch (pPrt
->PLinkMode
) {
2551 case SK_LMODE_AUTOHALF
:
2552 AutoNegAdv
|= PHY_M_AN_1000X_AHD
;
2554 case SK_LMODE_AUTOFULL
:
2555 AutoNegAdv
|= PHY_M_AN_1000X_AFD
;
2557 case SK_LMODE_AUTOBOTH
:
2558 AutoNegAdv
|= PHY_M_AN_1000X_AHD
| PHY_M_AN_1000X_AFD
;
2561 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E015
,
2565 /* Set Flow-control capabilities */
2566 switch (pPrt
->PFlowCtrlMode
) {
2567 case SK_FLOW_MODE_NONE
:
2568 AutoNegAdv
|= PHY_M_P_NO_PAUSE_X
;
2570 case SK_FLOW_MODE_LOC_SEND
:
2571 AutoNegAdv
|= PHY_M_P_ASYM_MD_X
;
2573 case SK_FLOW_MODE_SYMMETRIC
:
2574 AutoNegAdv
|= PHY_M_P_SYM_MD_X
;
2576 case SK_FLOW_MODE_SYM_OR_REM
:
2577 AutoNegAdv
|= PHY_M_P_BOTH_MD_X
;
2580 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E016
,
2586 /* Restart Auto-negotiation */
2587 PhyCtrl
|= PHY_CT_ANE
| PHY_CT_RE_CFG
;
2593 * E-mail from Gu Lin (08-03-2002):
2596 /* Program PHY register 30 as 16'h0708 for simulation speed up */
2597 SkGmPhyWrite(pAC
, IoC
, Port
, 30, 0x0700 /* 0x0708 */);
2603 /* Write 1000Base-T Control Register */
2604 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_1000T_CTRL
, C1000BaseT
);
2605 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2606 ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT
));
2608 /* Write AutoNeg Advertisement Register */
2609 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_AUNE_ADV
, AutoNegAdv
);
2610 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2611 ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv
));
2615 /* Set the PHY Loopback bit */
2616 PhyCtrl
|= PHY_CT_LOOP
;
2619 /* Program PHY register 16 as 16'h0400 to force link good */
2620 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
, PHY_M_PC_FL_GOOD
);
2624 if (pPrt
->PLinkSpeed
!= SK_LSPEED_AUTO
) {
2625 /* Write Ext. PHY Specific Control */
2626 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_EXT_CTRL
,
2627 (SK_U16
)((pPrt
->PLinkSpeed
+ 2) << 4));
2632 else if (pPrt
->PLinkSpeed
== SK_LSPEED_10MBPS
) {
2633 /* Write PHY Specific Control */
2634 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_PHY_CTRL
,
2635 PHY_M_PC_EN_DET_MSK
);
2639 /* Write to the PHY Control register */
2640 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_CTRL
, PhyCtrl
);
2641 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2642 ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl
));
2648 LedCtrl
= PHY_M_LED_PULS_DUR(PULS_170MS
) | PHY_M_LED_BLINK_RT(BLINK_84MS
);
2650 if ((pAC
->GIni
.GILedBlinkCtrl
& SK_ACT_LED_BLINK
) != 0) {
2651 LedCtrl
|= PHY_M_LEDC_RX_CTRL
| PHY_M_LEDC_TX_CTRL
;
2654 if ((pAC
->GIni
.GILedBlinkCtrl
& SK_DUP_LED_NORMAL
) != 0) {
2655 LedCtrl
|= PHY_M_LEDC_DP_CTRL
;
2658 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_LED_CTRL
, LedCtrl
);
2660 if ((pAC
->GIni
.GILedBlinkCtrl
& SK_LED_LINK100_ON
) != 0) {
2661 /* only in forced 100 Mbps mode */
2662 if (!AutoNeg
&& pPrt
->PLinkSpeed
== SK_LSPEED_100MBPS
) {
2664 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_LED_OVER
,
2665 PHY_M_LED_MO_100(MO_LED_ON
));
2670 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl
);
2671 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT
);
2672 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv
);
2673 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl
);
2674 #endif /* SK_DIAG */
2676 #if defined(SK_DIAG) || defined(DEBUG)
2677 /* Read PHY Control */
2678 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CTRL
, &PhyCtrl
);
2679 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2680 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl
));
2682 /* Read 1000Base-T Control Register */
2683 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_1000T_CTRL
, &C1000BaseT
);
2684 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2685 ("1000B-T Ctrl =0x%04X\n", C1000BaseT
));
2687 /* Read AutoNeg Advertisement Register */
2688 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_AUNE_ADV
, &AutoNegAdv
);
2689 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2690 ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv
));
2692 /* Read Ext. PHY Specific Control */
2693 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_EXT_CTRL
, &ExtPhyCtrl
);
2694 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2695 ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl
));
2697 /* Read PHY Status */
2698 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_STAT
, &PhyStat
);
2699 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2700 ("PHY Stat Reg.=0x%04X\n", PhyStat
));
2701 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_STAT
, &PhyStat1
);
2702 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2703 ("PHY Stat Reg.=0x%04X\n", PhyStat1
));
2705 /* Read PHY Specific Status */
2706 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_STAT
, &PhySpecStat
);
2707 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2708 ("PHY Spec Stat=0x%04X\n", PhySpecStat
));
2709 #endif /* SK_DIAG || DEBUG */
2712 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl
);
2713 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT
);
2714 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv
);
2715 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl
);
2716 c_print("PHY Stat Reg=0x%04X\n", PhyStat
);
2717 c_print("PHY Stat Reg=0x%04X\n", PhyStat1
);
2718 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat
);
2719 #endif /* SK_DIAG */
2723 } /* SkGmInitPhyMarv */
2728 /******************************************************************************
2730 * SkXmInitPhyLone() - Initialize the Level One Phy registers
2732 * Description: initializes all the Level One Phy registers
2739 static void SkXmInitPhyLone(
2740 SK_AC
*pAC
, /* adapter context */
2741 SK_IOC IoC
, /* IO context */
2742 int Port
, /* Port Index (MAC_1 + n) */
2743 SK_BOOL DoLoop
) /* Should a Phy LoopBack be set-up? */
2750 Ctrl1
= PHY_CT_SP1000
;
2752 Ctrl3
= PHY_SEL_TYPE
;
2754 pPrt
= &pAC
->GIni
.GP
[Port
];
2756 /* manually Master/Slave ? */
2757 if (pPrt
->PMSMode
!= SK_MS_MODE_AUTO
) {
2758 Ctrl2
|= PHY_L_1000C_MSE
;
2760 if (pPrt
->PMSMode
== SK_MS_MODE_MASTER
) {
2761 Ctrl2
|= PHY_L_1000C_MSC
;
2764 /* Auto-negotiation ? */
2765 if (pPrt
->PLinkMode
== SK_LMODE_HALF
|| pPrt
->PLinkMode
== SK_LMODE_FULL
) {
2767 * level one spec say: "1000 Mbps: manual mode not allowed"
2768 * but lets see what happens...
2770 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2771 ("InitPhyLone: no auto-negotiation Port %d\n", Port
));
2772 /* Set DuplexMode in Config register */
2773 if (pPrt
->PLinkMode
== SK_LMODE_FULL
) {
2774 Ctrl1
|= PHY_CT_DUP_MD
;
2777 /* Determine Master/Slave manually if not already done */
2778 if (pPrt
->PMSMode
== SK_MS_MODE_AUTO
) {
2779 Ctrl2
|= PHY_L_1000C_MSE
; /* set it to Slave */
2783 * Do NOT enable Auto-negotiation here. This would hold
2784 * the link down because no IDLES are transmitted
2788 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2789 ("InitPhyLone: with auto-negotiation Port %d\n", Port
));
2790 /* Set Auto-negotiation advertisement */
2792 /* Set Full/half duplex capabilities */
2793 switch (pPrt
->PLinkMode
) {
2794 case SK_LMODE_AUTOHALF
:
2795 Ctrl2
|= PHY_L_1000C_AHD
;
2797 case SK_LMODE_AUTOFULL
:
2798 Ctrl2
|= PHY_L_1000C_AFD
;
2800 case SK_LMODE_AUTOBOTH
:
2801 Ctrl2
|= PHY_L_1000C_AFD
| PHY_L_1000C_AHD
;
2804 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E015
,
2808 /* Set Flow-control capabilities */
2809 switch (pPrt
->PFlowCtrlMode
) {
2810 case SK_FLOW_MODE_NONE
:
2811 Ctrl3
|= PHY_L_P_NO_PAUSE
;
2813 case SK_FLOW_MODE_LOC_SEND
:
2814 Ctrl3
|= PHY_L_P_ASYM_MD
;
2816 case SK_FLOW_MODE_SYMMETRIC
:
2817 Ctrl3
|= PHY_L_P_SYM_MD
;
2819 case SK_FLOW_MODE_SYM_OR_REM
:
2820 Ctrl3
|= PHY_L_P_BOTH_MD
;
2823 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E016
,
2827 /* Restart Auto-negotiation */
2828 Ctrl1
= PHY_CT_ANE
| PHY_CT_RE_CFG
;
2831 /* Write 1000Base-T Control Register */
2832 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_LONE_1000T_CTRL
, Ctrl2
);
2833 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2834 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2
));
2836 /* Write AutoNeg Advertisement Register */
2837 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_LONE_AUNE_ADV
, Ctrl3
);
2838 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2839 ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3
));
2842 /* Set the Phy Loopback bit, too */
2843 Ctrl1
|= PHY_CT_LOOP
;
2846 /* Write to the Phy control register */
2847 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_LONE_CTRL
, Ctrl1
);
2848 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2849 ("PHY Control Reg=0x%04X\n", Ctrl1
));
2850 } /* SkXmInitPhyLone */
2853 /******************************************************************************
2855 * SkXmInitPhyNat() - Initialize the National Phy registers
2857 * Description: initializes all the National Phy registers
2864 static void SkXmInitPhyNat(
2865 SK_AC
*pAC
, /* adapter context */
2866 SK_IOC IoC
, /* IO context */
2867 int Port
, /* Port Index (MAC_1 + n) */
2868 SK_BOOL DoLoop
) /* Should a Phy LoopBack be set-up? */
2870 /* todo: National */
2871 } /* SkXmInitPhyNat */
2872 #endif /* OTHER_PHY */
2875 /******************************************************************************
2877 * SkMacInitPhy() - Initialize the PHY registers
2879 * Description: calls the Init PHY routines dep. on board type
2887 SK_AC
*pAC
, /* adapter context */
2888 SK_IOC IoC
, /* IO context */
2889 int Port
, /* Port Index (MAC_1 + n) */
2890 SK_BOOL DoLoop
) /* Should a Phy LoopBack be set-up? */
2894 pPrt
= &pAC
->GIni
.GP
[Port
];
2897 if (pAC
->GIni
.GIGenesis
) {
2899 switch (pPrt
->PhyType
) {
2901 SkXmInitPhyXmac(pAC
, IoC
, Port
, DoLoop
);
2904 SkXmInitPhyBcom(pAC
, IoC
, Port
, DoLoop
);
2908 SkXmInitPhyLone(pAC
, IoC
, Port
, DoLoop
);
2911 SkXmInitPhyNat(pAC
, IoC
, Port
, DoLoop
);
2913 #endif /* OTHER_PHY */
2916 #endif /* GENESIS */
2919 if (pAC
->GIni
.GIYukon
) {
2921 SkGmInitPhyMarv(pAC
, IoC
, Port
, DoLoop
);
2925 } /* SkMacInitPhy */
2929 /******************************************************************************
2931 * SkXmAutoNegDoneXmac() - Auto-negotiation handling
2934 * This function handles the auto-negotiation if the Done bit is set.
2938 * SK_AND_DUP_CAP Duplex capability error happened
2939 * SK_AND_OTHER Other error happened
2941 static int SkXmAutoNegDoneXmac(
2942 SK_AC
*pAC
, /* adapter context */
2943 SK_IOC IoC
, /* IO context */
2944 int Port
) /* Port Index (MAC_1 + n) */
2947 SK_U16 ResAb
; /* Resolved Ability */
2948 SK_U16 LPAb
; /* Link Partner Ability */
2950 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2951 ("AutoNegDoneXmac, Port %d\n", Port
));
2953 pPrt
= &pAC
->GIni
.GP
[Port
];
2955 /* Get PHY parameters */
2956 SkXmPhyRead(pAC
, IoC
, Port
, PHY_XMAC_AUNE_LP
, &LPAb
);
2957 SkXmPhyRead(pAC
, IoC
, Port
, PHY_XMAC_RES_ABI
, &ResAb
);
2959 if ((LPAb
& PHY_X_AN_RFB
) != 0) {
2960 /* At least one of the remote fault bit is set */
2962 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2963 ("AutoNegFail: Remote fault bit set Port %d\n", Port
));
2964 pPrt
->PAutoNegFail
= SK_TRUE
;
2965 return(SK_AND_OTHER
);
2968 /* Check Duplex mismatch */
2969 if ((ResAb
& (PHY_X_RS_HD
| PHY_X_RS_FD
)) == PHY_X_RS_FD
) {
2970 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOFULL
;
2972 else if ((ResAb
& (PHY_X_RS_HD
| PHY_X_RS_FD
)) == PHY_X_RS_HD
) {
2973 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOHALF
;
2977 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
2978 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port
));
2979 pPrt
->PAutoNegFail
= SK_TRUE
;
2980 return(SK_AND_DUP_CAP
);
2983 /* Check PAUSE mismatch */
2984 /* We are NOT using chapter 4.23 of the Xaqti manual */
2985 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2986 if ((pPrt
->PFlowCtrlMode
== SK_FLOW_MODE_SYMMETRIC
||
2987 pPrt
->PFlowCtrlMode
== SK_FLOW_MODE_SYM_OR_REM
) &&
2988 (LPAb
& PHY_X_P_SYM_MD
) != 0) {
2989 /* Symmetric PAUSE */
2990 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_SYMMETRIC
;
2992 else if (pPrt
->PFlowCtrlMode
== SK_FLOW_MODE_SYM_OR_REM
&&
2993 (LPAb
& PHY_X_RS_PAUSE
) == PHY_X_P_ASYM_MD
) {
2994 /* Enable PAUSE receive, disable PAUSE transmit */
2995 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_REM_SEND
;
2997 else if (pPrt
->PFlowCtrlMode
== SK_FLOW_MODE_LOC_SEND
&&
2998 (LPAb
& PHY_X_RS_PAUSE
) == PHY_X_P_BOTH_MD
) {
2999 /* Disable PAUSE receive, enable PAUSE transmit */
3000 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_LOC_SEND
;
3003 /* PAUSE mismatch -> no PAUSE */
3004 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_NONE
;
3006 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_1000MBPS
;
3009 } /* SkXmAutoNegDoneXmac */
3012 /******************************************************************************
3014 * SkXmAutoNegDoneBcom() - Auto-negotiation handling
3017 * This function handles the auto-negotiation if the Done bit is set.
3021 * SK_AND_DUP_CAP Duplex capability error happened
3022 * SK_AND_OTHER Other error happened
3024 static int SkXmAutoNegDoneBcom(
3025 SK_AC
*pAC
, /* adapter context */
3026 SK_IOC IoC
, /* IO context */
3027 int Port
) /* Port Index (MAC_1 + n) */
3030 SK_U16 LPAb
; /* Link Partner Ability */
3031 SK_U16 AuxStat
; /* Auxiliary Status */
3035 SK_U16 ResAb
; /* Resolved Ability */
3038 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3039 ("AutoNegDoneBcom, Port %d\n", Port
));
3040 pPrt
= &pAC
->GIni
.GP
[Port
];
3042 /* Get PHY parameters */
3043 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUNE_LP
, &LPAb
);
3046 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_1000T_STAT
, &ResAb
);
3049 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_STAT
, &AuxStat
);
3051 if ((LPAb
& PHY_B_AN_RF
) != 0) {
3052 /* Remote fault bit is set: Error */
3053 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3054 ("AutoNegFail: Remote fault bit set Port %d\n", Port
));
3055 pPrt
->PAutoNegFail
= SK_TRUE
;
3056 return(SK_AND_OTHER
);
3059 /* Check Duplex mismatch */
3060 if ((AuxStat
& PHY_B_AS_AN_RES_MSK
) == PHY_B_RES_1000FD
) {
3061 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOFULL
;
3063 else if ((AuxStat
& PHY_B_AS_AN_RES_MSK
) == PHY_B_RES_1000HD
) {
3064 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOHALF
;
3068 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3069 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port
));
3070 pPrt
->PAutoNegFail
= SK_TRUE
;
3071 return(SK_AND_DUP_CAP
);
3076 /* Check Master/Slave resolution */
3077 if ((ResAb
& PHY_B_1000S_MSF
) != 0) {
3078 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3079 ("Master/Slave Fault Port %d\n", Port
));
3080 pPrt
->PAutoNegFail
= SK_TRUE
;
3081 pPrt
->PMSStatus
= SK_MS_STAT_FAULT
;
3082 return(SK_AND_OTHER
);
3085 pPrt
->PMSStatus
= ((ResAb
& PHY_B_1000S_MSR
) != 0) ?
3086 SK_MS_STAT_MASTER
: SK_MS_STAT_SLAVE
;
3089 /* Check PAUSE mismatch ??? */
3090 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3091 if ((AuxStat
& PHY_B_AS_PAUSE_MSK
) == PHY_B_AS_PAUSE_MSK
) {
3092 /* Symmetric PAUSE */
3093 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_SYMMETRIC
;
3095 else if ((AuxStat
& PHY_B_AS_PAUSE_MSK
) == PHY_B_AS_PRR
) {
3096 /* Enable PAUSE receive, disable PAUSE transmit */
3097 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_REM_SEND
;
3099 else if ((AuxStat
& PHY_B_AS_PAUSE_MSK
) == PHY_B_AS_PRT
) {
3100 /* Disable PAUSE receive, enable PAUSE transmit */
3101 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_LOC_SEND
;
3104 /* PAUSE mismatch -> no PAUSE */
3105 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_NONE
;
3107 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_1000MBPS
;
3110 } /* SkXmAutoNegDoneBcom */
3111 #endif /* GENESIS */
3115 /******************************************************************************
3117 * SkGmAutoNegDoneMarv() - Auto-negotiation handling
3120 * This function handles the auto-negotiation if the Done bit is set.
3124 * SK_AND_DUP_CAP Duplex capability error happened
3125 * SK_AND_OTHER Other error happened
3127 static int SkGmAutoNegDoneMarv(
3128 SK_AC
*pAC
, /* adapter context */
3129 SK_IOC IoC
, /* IO context */
3130 int Port
) /* Port Index (MAC_1 + n) */
3133 SK_U16 LPAb
; /* Link Partner Ability */
3134 SK_U16 ResAb
; /* Resolved Ability */
3135 SK_U16 AuxStat
; /* Auxiliary Status */
3137 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3138 ("AutoNegDoneMarv, Port %d\n", Port
));
3139 pPrt
= &pAC
->GIni
.GP
[Port
];
3141 /* Get PHY parameters */
3142 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_AUNE_LP
, &LPAb
);
3143 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3144 ("Link P.Abil.=0x%04X\n", LPAb
));
3146 if ((LPAb
& PHY_M_AN_RF
) != 0) {
3147 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3148 ("AutoNegFail: Remote fault bit set Port %d\n", Port
));
3149 pPrt
->PAutoNegFail
= SK_TRUE
;
3150 return(SK_AND_OTHER
);
3153 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_1000T_STAT
, &ResAb
);
3155 /* Check Master/Slave resolution */
3156 if ((ResAb
& PHY_B_1000S_MSF
) != 0) {
3157 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3158 ("Master/Slave Fault Port %d\n", Port
));
3159 pPrt
->PAutoNegFail
= SK_TRUE
;
3160 pPrt
->PMSStatus
= SK_MS_STAT_FAULT
;
3161 return(SK_AND_OTHER
);
3164 pPrt
->PMSStatus
= ((ResAb
& PHY_B_1000S_MSR
) != 0) ?
3165 (SK_U8
)SK_MS_STAT_MASTER
: (SK_U8
)SK_MS_STAT_SLAVE
;
3167 /* Read PHY Specific Status */
3168 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_PHY_STAT
, &AuxStat
);
3170 /* Check Speed & Duplex resolved */
3171 if ((AuxStat
& PHY_M_PS_SPDUP_RES
) == 0) {
3172 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3173 ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port
));
3174 pPrt
->PAutoNegFail
= SK_TRUE
;
3175 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_UNKNOWN
;
3176 return(SK_AND_DUP_CAP
);
3179 if ((AuxStat
& PHY_M_PS_FULL_DUP
) != 0) {
3180 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOFULL
;
3183 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOHALF
;
3186 /* Check PAUSE mismatch ??? */
3187 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3188 if ((AuxStat
& PHY_M_PS_PAUSE_MSK
) == PHY_M_PS_PAUSE_MSK
) {
3189 /* Symmetric PAUSE */
3190 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_SYMMETRIC
;
3192 else if ((AuxStat
& PHY_M_PS_PAUSE_MSK
) == PHY_M_PS_RX_P_EN
) {
3193 /* Enable PAUSE receive, disable PAUSE transmit */
3194 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_REM_SEND
;
3196 else if ((AuxStat
& PHY_M_PS_PAUSE_MSK
) == PHY_M_PS_TX_P_EN
) {
3197 /* Disable PAUSE receive, enable PAUSE transmit */
3198 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_LOC_SEND
;
3201 /* PAUSE mismatch -> no PAUSE */
3202 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_NONE
;
3205 /* set used link speed */
3206 switch ((unsigned)(AuxStat
& PHY_M_PS_SPEED_MSK
)) {
3207 case (unsigned)PHY_M_PS_SPEED_1000
:
3208 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_1000MBPS
;
3210 case PHY_M_PS_SPEED_100
:
3211 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_100MBPS
;
3214 pPrt
->PLinkSpeedUsed
= (SK_U8
)SK_LSPEED_STAT_10MBPS
;
3218 } /* SkGmAutoNegDoneMarv */
3223 /******************************************************************************
3225 * SkXmAutoNegDoneLone() - Auto-negotiation handling
3228 * This function handles the auto-negotiation if the Done bit is set.
3232 * SK_AND_DUP_CAP Duplex capability error happened
3233 * SK_AND_OTHER Other error happened
3235 static int SkXmAutoNegDoneLone(
3236 SK_AC
*pAC
, /* adapter context */
3237 SK_IOC IoC
, /* IO context */
3238 int Port
) /* Port Index (MAC_1 + n) */
3241 SK_U16 ResAb
; /* Resolved Ability */
3242 SK_U16 LPAb
; /* Link Partner Ability */
3243 SK_U16 QuickStat
; /* Auxiliary Status */
3245 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3246 ("AutoNegDoneLone, Port %d\n", Port
));
3247 pPrt
= &pAC
->GIni
.GP
[Port
];
3249 /* Get PHY parameters */
3250 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_AUNE_LP
, &LPAb
);
3251 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_1000T_STAT
, &ResAb
);
3252 SkXmPhyRead(pAC
, IoC
, Port
, PHY_LONE_Q_STAT
, &QuickStat
);
3254 if ((LPAb
& PHY_L_AN_RF
) != 0) {
3255 /* Remote fault bit is set */
3257 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3258 ("AutoNegFail: Remote fault bit set Port %d\n", Port
));
3259 pPrt
->PAutoNegFail
= SK_TRUE
;
3260 return(SK_AND_OTHER
);
3263 /* Check Duplex mismatch */
3264 if ((QuickStat
& PHY_L_QS_DUP_MOD
) != 0) {
3265 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOFULL
;
3268 pPrt
->PLinkModeStatus
= (SK_U8
)SK_LMODE_STAT_AUTOHALF
;
3271 /* Check Master/Slave resolution */
3272 if ((ResAb
& PHY_L_1000S_MSF
) != 0) {
3274 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3275 ("Master/Slave Fault Port %d\n", Port
));
3276 pPrt
->PAutoNegFail
= SK_TRUE
;
3277 pPrt
->PMSStatus
= SK_MS_STAT_FAULT
;
3278 return(SK_AND_OTHER
);
3280 else if (ResAb
& PHY_L_1000S_MSR
) {
3281 pPrt
->PMSStatus
= SK_MS_STAT_MASTER
;
3284 pPrt
->PMSStatus
= SK_MS_STAT_SLAVE
;
3287 /* Check PAUSE mismatch */
3288 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3289 /* we must manually resolve the abilities here */
3290 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_NONE
;
3292 switch (pPrt
->PFlowCtrlMode
) {
3293 case SK_FLOW_MODE_NONE
:
3296 case SK_FLOW_MODE_LOC_SEND
:
3297 if ((QuickStat
& (PHY_L_QS_PAUSE
| PHY_L_QS_AS_PAUSE
)) ==
3298 (PHY_L_QS_PAUSE
| PHY_L_QS_AS_PAUSE
)) {
3299 /* Disable PAUSE receive, enable PAUSE transmit */
3300 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_LOC_SEND
;
3303 case SK_FLOW_MODE_SYMMETRIC
:
3304 if ((QuickStat
& PHY_L_QS_PAUSE
) != 0) {
3305 /* Symmetric PAUSE */
3306 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_SYMMETRIC
;
3309 case SK_FLOW_MODE_SYM_OR_REM
:
3310 if ((QuickStat
& (PHY_L_QS_PAUSE
| PHY_L_QS_AS_PAUSE
)) ==
3311 PHY_L_QS_AS_PAUSE
) {
3312 /* Enable PAUSE receive, disable PAUSE transmit */
3313 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_REM_SEND
;
3315 else if ((QuickStat
& PHY_L_QS_PAUSE
) != 0) {
3316 /* Symmetric PAUSE */
3317 pPrt
->PFlowCtrlStatus
= SK_FLOW_STAT_SYMMETRIC
;
3321 SK_ERR_LOG(pAC
, SK_ERRCL_SW
| SK_ERRCL_INIT
, SKERR_HWI_E016
,
3326 } /* SkXmAutoNegDoneLone */
3329 /******************************************************************************
3331 * SkXmAutoNegDoneNat() - Auto-negotiation handling
3334 * This function handles the auto-negotiation if the Done bit is set.
3338 * SK_AND_DUP_CAP Duplex capability error happened
3339 * SK_AND_OTHER Other error happened
3341 static int SkXmAutoNegDoneNat(
3342 SK_AC
*pAC
, /* adapter context */
3343 SK_IOC IoC
, /* IO context */
3344 int Port
) /* Port Index (MAC_1 + n) */
3346 /* todo: National */
3348 } /* SkXmAutoNegDoneNat */
3349 #endif /* OTHER_PHY */
3352 /******************************************************************************
3354 * SkMacAutoNegDone() - Auto-negotiation handling
3356 * Description: calls the auto-negotiation done routines dep. on board type
3360 * SK_AND_DUP_CAP Duplex capability error happened
3361 * SK_AND_OTHER Other error happened
3363 int SkMacAutoNegDone(
3364 SK_AC
*pAC
, /* adapter context */
3365 SK_IOC IoC
, /* IO context */
3366 int Port
) /* Port Index (MAC_1 + n) */
3373 pPrt
= &pAC
->GIni
.GP
[Port
];
3376 if (pAC
->GIni
.GIGenesis
) {
3378 switch (pPrt
->PhyType
) {
3381 Rtv
= SkXmAutoNegDoneXmac(pAC
, IoC
, Port
);
3384 Rtv
= SkXmAutoNegDoneBcom(pAC
, IoC
, Port
);
3388 Rtv
= SkXmAutoNegDoneLone(pAC
, IoC
, Port
);
3391 Rtv
= SkXmAutoNegDoneNat(pAC
, IoC
, Port
);
3393 #endif /* OTHER_PHY */
3395 return(SK_AND_OTHER
);
3398 #endif /* GENESIS */
3401 if (pAC
->GIni
.GIYukon
) {
3403 Rtv
= SkGmAutoNegDoneMarv(pAC
, IoC
, Port
);
3407 if (Rtv
!= SK_AND_OK
) {
3411 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3412 ("AutoNeg done Port %d\n", Port
));
3414 /* We checked everything and may now enable the link */
3415 pPrt
->PAutoNegFail
= SK_FALSE
;
3417 SkMacRxTxEnable(pAC
, IoC
, Port
);
3420 } /* SkMacAutoNegDone */
3424 /******************************************************************************
3426 * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3429 * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3434 static void SkXmSetRxTxEn(
3435 SK_AC
*pAC
, /* Adapter Context */
3436 SK_IOC IoC
, /* IO context */
3437 int Port
, /* Port Index (MAC_1 + n) */
3438 int Para
) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3442 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &Word
);
3444 switch (Para
& (SK_MAC_LOOPB_ON
| SK_MAC_LOOPB_OFF
)) {
3445 case SK_MAC_LOOPB_ON
:
3446 Word
|= XM_MMU_MAC_LB
;
3448 case SK_MAC_LOOPB_OFF
:
3449 Word
&= ~XM_MMU_MAC_LB
;
3453 switch (Para
& (SK_PHY_LOOPB_ON
| SK_PHY_LOOPB_OFF
)) {
3454 case SK_PHY_LOOPB_ON
:
3455 Word
|= XM_MMU_GMII_LOOP
;
3457 case SK_PHY_LOOPB_OFF
:
3458 Word
&= ~XM_MMU_GMII_LOOP
;
3462 switch (Para
& (SK_PHY_FULLD_ON
| SK_PHY_FULLD_OFF
)) {
3463 case SK_PHY_FULLD_ON
:
3464 Word
|= XM_MMU_GMII_FD
;
3466 case SK_PHY_FULLD_OFF
:
3467 Word
&= ~XM_MMU_GMII_FD
;
3471 XM_OUT16(IoC
, Port
, XM_MMU_CMD
, Word
| XM_MMU_ENA_RX
| XM_MMU_ENA_TX
);
3473 /* dummy read to ensure writing */
3474 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &Word
);
3476 } /* SkXmSetRxTxEn */
3477 #endif /* GENESIS */
3481 /******************************************************************************
3483 * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3486 * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3491 static void SkGmSetRxTxEn(
3492 SK_AC
*pAC
, /* Adapter Context */
3493 SK_IOC IoC
, /* IO context */
3494 int Port
, /* Port Index (MAC_1 + n) */
3495 int Para
) /* Parameter to set: MAC LoopBack, Duplex Mode */
3499 GM_IN16(IoC
, Port
, GM_GP_CTRL
, &Ctrl
);
3501 switch (Para
& (SK_MAC_LOOPB_ON
| SK_MAC_LOOPB_OFF
)) {
3502 case SK_MAC_LOOPB_ON
:
3503 Ctrl
|= GM_GPCR_LOOP_ENA
;
3505 case SK_MAC_LOOPB_OFF
:
3506 Ctrl
&= ~GM_GPCR_LOOP_ENA
;
3510 switch (Para
& (SK_PHY_FULLD_ON
| SK_PHY_FULLD_OFF
)) {
3511 case SK_PHY_FULLD_ON
:
3512 Ctrl
|= GM_GPCR_DUP_FULL
;
3514 case SK_PHY_FULLD_OFF
:
3515 Ctrl
&= ~GM_GPCR_DUP_FULL
;
3519 GM_OUT16(IoC
, Port
, GM_GP_CTRL
, (SK_U16
)(Ctrl
| GM_GPCR_RX_ENA
|
3522 /* dummy read to ensure writing */
3523 GM_IN16(IoC
, Port
, GM_GP_CTRL
, &Ctrl
);
3525 } /* SkGmSetRxTxEn */
3530 /******************************************************************************
3532 * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3534 * Description: calls the Special Set Rx/Tx Enable routines dep. on board type
3538 void SkMacSetRxTxEn(
3539 SK_AC
*pAC
, /* Adapter Context */
3540 SK_IOC IoC
, /* IO context */
3541 int Port
, /* Port Index (MAC_1 + n) */
3545 if (pAC
->GIni
.GIGenesis
) {
3547 SkXmSetRxTxEn(pAC
, IoC
, Port
, Para
);
3549 #endif /* GENESIS */
3552 if (pAC
->GIni
.GIYukon
) {
3554 SkGmSetRxTxEn(pAC
, IoC
, Port
, Para
);
3558 } /* SkMacSetRxTxEn */
3559 #endif /* !SK_SLIM */
3562 /******************************************************************************
3564 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3566 * Description: enables Rx/Tx dep. on board type
3570 * != 0 Error happened
3572 int SkMacRxTxEnable(
3573 SK_AC
*pAC
, /* adapter context */
3574 SK_IOC IoC
, /* IO context */
3575 int Port
) /* Port Index (MAC_1 + n) */
3578 SK_U16 Reg
; /* 16-bit register value */
3579 SK_U16 IntMask
; /* MAC interrupt mask */
3584 pPrt
= &pAC
->GIni
.GP
[Port
];
3586 if (!pPrt
->PHWLinkUp
) {
3587 /* The Hardware link is NOT up */
3591 if ((pPrt
->PLinkMode
== SK_LMODE_AUTOHALF
||
3592 pPrt
->PLinkMode
== SK_LMODE_AUTOFULL
||
3593 pPrt
->PLinkMode
== SK_LMODE_AUTOBOTH
) &&
3594 pPrt
->PAutoNegFail
) {
3595 /* Auto-negotiation is not done or failed */
3600 if (pAC
->GIni
.GIGenesis
) {
3601 /* set Duplex Mode and Pause Mode */
3602 SkXmInitDupMd(pAC
, IoC
, Port
);
3604 SkXmInitPauseMd(pAC
, IoC
, Port
);
3607 * Initialize the Interrupt Mask Register. Default IRQs are...
3608 * - Link Asynchronous Event
3609 * - Link Partner requests config
3610 * - Auto Negotiation Done
3611 * - Rx Counter Event Overflow
3612 * - Tx Counter Event Overflow
3613 * - Transmit FIFO Underrun
3615 IntMask
= XM_DEF_MSK
;
3618 /* add IRQ for Receive FIFO Overflow */
3619 IntMask
&= ~XM_IS_RXF_OV
;
3622 if (pPrt
->PhyType
!= SK_PHY_XMAC
) {
3623 /* disable GP0 interrupt bit */
3624 IntMask
|= XM_IS_INP_ASS
;
3626 XM_OUT16(IoC
, Port
, XM_IMSK
, IntMask
);
3628 /* get MMU Command Reg. */
3629 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &Reg
);
3631 if (pPrt
->PhyType
!= SK_PHY_XMAC
&&
3632 (pPrt
->PLinkModeStatus
== SK_LMODE_STAT_FULL
||
3633 pPrt
->PLinkModeStatus
== SK_LMODE_STAT_AUTOFULL
)) {
3634 /* set to Full Duplex */
3635 Reg
|= XM_MMU_GMII_FD
;
3638 switch (pPrt
->PhyType
) {
3641 * Workaround BCOM Errata (#10523) for all BCom Phys
3642 * Enable Power Management after link up
3644 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, &SWord
);
3645 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
,
3646 (SK_U16
)(SWord
& ~PHY_B_AC_DIS_PM
));
3647 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_INT_MASK
,
3648 (SK_U16
)PHY_B_DEF_MSK
);
3652 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_LONE_INT_ENAB
, PHY_L_DEF_MSK
);
3656 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3657 /* no interrupts possible from National ??? */
3659 #endif /* OTHER_PHY */
3663 XM_OUT16(IoC
, Port
, XM_MMU_CMD
, Reg
| XM_MMU_ENA_RX
| XM_MMU_ENA_TX
);
3665 #endif /* GENESIS */
3668 if (pAC
->GIni
.GIYukon
) {
3670 * Initialize the Interrupt Mask Register. Default IRQs are...
3671 * - Rx Counter Event Overflow
3672 * - Tx Counter Event Overflow
3673 * - Transmit FIFO Underrun
3675 IntMask
= GMAC_DEF_MSK
;
3678 /* add IRQ for Receive FIFO Overrun */
3679 IntMask
|= GM_IS_RX_FF_OR
;
3682 SK_OUT8(IoC
, GMAC_IRQ_MSK
, (SK_U8
)IntMask
);
3684 /* get General Purpose Control */
3685 GM_IN16(IoC
, Port
, GM_GP_CTRL
, &Reg
);
3687 if (pPrt
->PLinkModeStatus
== SK_LMODE_STAT_FULL
||
3688 pPrt
->PLinkModeStatus
== SK_LMODE_STAT_AUTOFULL
) {
3689 /* set to Full Duplex */
3690 Reg
|= GM_GPCR_DUP_FULL
;
3694 GM_OUT16(IoC
, Port
, GM_GP_CTRL
, (SK_U16
)(Reg
| GM_GPCR_RX_ENA
|
3698 /* Enable all PHY interrupts */
3699 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_INT_MASK
,
3700 (SK_U16
)PHY_M_DEF_MSK
);
3707 } /* SkMacRxTxEnable */
3710 /******************************************************************************
3712 * SkMacRxTxDisable() - Disable Receiver and Transmitter
3714 * Description: disables Rx/Tx dep. on board type
3718 void SkMacRxTxDisable(
3719 SK_AC
*pAC
, /* Adapter Context */
3720 SK_IOC IoC
, /* IO context */
3721 int Port
) /* Port Index (MAC_1 + n) */
3726 if (pAC
->GIni
.GIGenesis
) {
3728 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &Word
);
3730 XM_OUT16(IoC
, Port
, XM_MMU_CMD
, Word
& ~(XM_MMU_ENA_RX
| XM_MMU_ENA_TX
));
3732 /* dummy read to ensure writing */
3733 XM_IN16(IoC
, Port
, XM_MMU_CMD
, &Word
);
3735 #endif /* GENESIS */
3738 if (pAC
->GIni
.GIYukon
) {
3740 GM_IN16(IoC
, Port
, GM_GP_CTRL
, &Word
);
3742 GM_OUT16(IoC
, Port
, GM_GP_CTRL
, (SK_U16
)(Word
& ~(GM_GPCR_RX_ENA
|
3745 /* dummy read to ensure writing */
3746 GM_IN16(IoC
, Port
, GM_GP_CTRL
, &Word
);
3750 } /* SkMacRxTxDisable */
3753 /******************************************************************************
3755 * SkMacIrqDisable() - Disable IRQ from MAC
3757 * Description: sets the IRQ-mask to disable IRQ dep. on board type
3761 void SkMacIrqDisable(
3762 SK_AC
*pAC
, /* Adapter Context */
3763 SK_IOC IoC
, /* IO context */
3764 int Port
) /* Port Index (MAC_1 + n) */
3771 pPrt
= &pAC
->GIni
.GP
[Port
];
3774 if (pAC
->GIni
.GIGenesis
) {
3776 /* disable all XMAC IRQs */
3777 XM_OUT16(IoC
, Port
, XM_IMSK
, 0xffff);
3779 /* Disable all PHY interrupts */
3780 switch (pPrt
->PhyType
) {
3782 /* Make sure that PHY is initialized */
3783 if (pPrt
->PState
!= SK_PRT_RESET
) {
3784 /* NOT allowed if BCOM is in RESET state */
3785 /* Workaround BCOM Errata (#10523) all BCom */
3786 /* Disable Power Management if link is down */
3787 SkXmPhyRead(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
, &Word
);
3788 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_AUX_CTRL
,
3789 (SK_U16
)(Word
| PHY_B_AC_DIS_PM
));
3790 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_BCOM_INT_MASK
, 0xffff);
3795 SkXmPhyWrite(pAC
, IoC
, Port
, PHY_LONE_INT_ENAB
, 0);
3799 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3801 #endif /* OTHER_PHY */
3804 #endif /* GENESIS */
3807 if (pAC
->GIni
.GIYukon
) {
3808 /* disable all GMAC IRQs */
3809 SK_OUT8(IoC
, GMAC_IRQ_MSK
, 0);
3812 /* Disable all PHY interrupts */
3813 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_INT_MASK
, 0);
3818 } /* SkMacIrqDisable */
3822 /******************************************************************************
3824 * SkXmSendCont() - Enable / Disable Send Continuous Mode
3826 * Description: enable / disable Send Continuous Mode on XMAC
3832 SK_AC
*pAC
, /* adapter context */
3833 SK_IOC IoC
, /* IO context */
3834 int Port
, /* Port Index (MAC_1 + n) */
3835 SK_BOOL Enable
) /* Enable / Disable */
3839 XM_IN32(IoC
, Port
, XM_MODE
, &MdReg
);
3842 MdReg
|= XM_MD_TX_CONT
;
3845 MdReg
&= ~XM_MD_TX_CONT
;
3847 /* setup Mode Register */
3848 XM_OUT32(IoC
, Port
, XM_MODE
, MdReg
);
3850 } /* SkXmSendCont */
3853 /******************************************************************************
3855 * SkMacTimeStamp() - Enable / Disable Time Stamp
3857 * Description: enable / disable Time Stamp generation for Rx packets
3862 void SkMacTimeStamp(
3863 SK_AC
*pAC
, /* adapter context */
3864 SK_IOC IoC
, /* IO context */
3865 int Port
, /* Port Index (MAC_1 + n) */
3866 SK_BOOL Enable
) /* Enable / Disable */
3871 if (pAC
->GIni
.GIGenesis
) {
3873 XM_IN32(IoC
, Port
, XM_MODE
, &MdReg
);
3879 MdReg
&= ~XM_MD_ATS
;
3881 /* setup Mode Register */
3882 XM_OUT32(IoC
, Port
, XM_MODE
, MdReg
);
3886 TimeCtrl
= GMT_ST_START
| GMT_ST_CLR_IRQ
;
3889 TimeCtrl
= GMT_ST_STOP
| GMT_ST_CLR_IRQ
;
3891 /* Start/Stop Time Stamp Timer */
3892 SK_OUT8(IoC
, GMAC_TI_ST_CTRL
, TimeCtrl
);
3895 } /* SkMacTimeStamp*/
3897 #else /* !SK_DIAG */
3900 /******************************************************************************
3902 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
3904 * This function analyses the Interrupt status word. If any of the
3905 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
3908 void SkXmAutoNegLipaXmac(
3909 SK_AC
*pAC
, /* adapter context */
3910 SK_IOC IoC
, /* IO context */
3911 int Port
, /* Port Index (MAC_1 + n) */
3912 SK_U16 IStatus
) /* Interrupt Status word to analyse */
3916 pPrt
= &pAC
->GIni
.GP
[Port
];
3918 if (pPrt
->PLipaAutoNeg
!= SK_LIPA_AUTO
&&
3919 (IStatus
& (XM_IS_LIPA_RC
| XM_IS_RX_PAGE
| XM_IS_AND
)) != 0) {
3921 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3922 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
3924 pPrt
->PLipaAutoNeg
= SK_LIPA_AUTO
;
3926 } /* SkXmAutoNegLipaXmac */
3927 #endif /* GENESIS */
3930 /******************************************************************************
3932 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
3934 * This function analyses the PHY status word.
3935 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
3938 void SkMacAutoNegLipaPhy(
3939 SK_AC
*pAC
, /* adapter context */
3940 SK_IOC IoC
, /* IO context */
3941 int Port
, /* Port Index (MAC_1 + n) */
3942 SK_U16 PhyStat
) /* PHY Status word to analyse */
3946 pPrt
= &pAC
->GIni
.GP
[Port
];
3948 if (pPrt
->PLipaAutoNeg
!= SK_LIPA_AUTO
&&
3949 (PhyStat
& PHY_ST_AN_OVER
) != 0) {
3951 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
3952 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
3954 pPrt
->PLipaAutoNeg
= SK_LIPA_AUTO
;
3956 } /* SkMacAutoNegLipaPhy */
3960 /******************************************************************************
3962 * SkXmIrq() - Interrupt Service Routine
3964 * Description: services an Interrupt Request of the XMAC
3967 * With an external PHY, some interrupt bits are not meaningfull any more:
3968 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
3969 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
3970 * - Page Received (bit #9) XM_IS_RX_PAGE
3971 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
3972 * - AutoNegDone (bit #7) XM_IS_AND
3973 * Also probably not valid any more is the GP0 input bit:
3974 * - GPRegisterBit0set XM_IS_INP_ASS
3980 SK_AC
*pAC
, /* adapter context */
3981 SK_IOC IoC
, /* IO context */
3982 int Port
) /* Port Index (MAC_1 + n) */
3986 SK_U16 IStatus
; /* Interrupt status read from the XMAC */
3989 SK_U64 OverflowStatus
;
3992 pPrt
= &pAC
->GIni
.GP
[Port
];
3994 XM_IN16(IoC
, Port
, XM_ISRC
, &IStatus
);
3996 /* LinkPartner Auto-negable? */
3997 if (pPrt
->PhyType
== SK_PHY_XMAC
) {
3998 SkXmAutoNegLipaXmac(pAC
, IoC
, Port
, IStatus
);
4001 /* mask bits that are not used with ext. PHY */
4002 IStatus
&= ~(XM_IS_LNK_AE
| XM_IS_LIPA_RC
|
4003 XM_IS_RX_PAGE
| XM_IS_TX_PAGE
|
4004 XM_IS_AND
| XM_IS_INP_ASS
);
4007 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
4008 ("XmacIrq Port %d Isr 0x%04X\n", Port
, IStatus
));
4010 if (!pPrt
->PHWLinkUp
) {
4011 /* Spurious XMAC interrupt */
4012 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
4013 ("SkXmIrq: spurious interrupt on Port %d\n", Port
));
4017 if ((IStatus
& XM_IS_INP_ASS
) != 0) {
4018 /* Reread ISR Register if link is not in sync */
4019 XM_IN16(IoC
, Port
, XM_ISRC
, &IStatus2
);
4021 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
4022 ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
4023 Port
, IStatus
, IStatus2
));
4024 IStatus
&= ~XM_IS_INP_ASS
;
4025 IStatus
|= IStatus2
;
4028 if ((IStatus
& XM_IS_LNK_AE
) != 0) {
4029 /* not used, GP0 is used instead */
4032 if ((IStatus
& XM_IS_TX_ABORT
) != 0) {
4036 if ((IStatus
& XM_IS_FRC_INT
) != 0) {
4037 /* not used, use ASIC IRQ instead if needed */
4040 if ((IStatus
& (XM_IS_INP_ASS
| XM_IS_LIPA_RC
| XM_IS_RX_PAGE
)) != 0) {
4041 SkHWLinkDown(pAC
, IoC
, Port
);
4043 /* Signal to RLMT */
4044 Para
.Para32
[0] = (SK_U32
)Port
;
4045 SkEventQueue(pAC
, SKGE_RLMT
, SK_RLMT_LINK_DOWN
, Para
);
4047 /* Start workaround Errata #2 timer */
4048 SkTimerStart(pAC
, IoC
, &pPrt
->PWaTimer
, SK_WA_INA_TIME
,
4049 SKGE_HWAC
, SK_HWEV_WATIM
, Para
);
4052 if ((IStatus
& XM_IS_RX_PAGE
) != 0) {
4056 if ((IStatus
& XM_IS_TX_PAGE
) != 0) {
4060 if ((IStatus
& XM_IS_AND
) != 0) {
4061 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
4062 ("SkXmIrq: AND on link that is up Port %d\n", Port
));
4065 if ((IStatus
& XM_IS_TSC_OV
) != 0) {
4069 /* Combined Tx & Rx Counter Overflow SIRQ Event */
4070 if ((IStatus
& (XM_IS_RXC_OV
| XM_IS_TXC_OV
)) != 0) {
4072 SkXmOverflowStatus(pAC
, IoC
, Port
, IStatus
, &OverflowStatus
);
4074 Para
.Para32
[0] = (SK_U32
)Port
;
4075 Para
.Para32
[1] = (SK_U32
)IStatus
;
4076 SkPnmiEvent(pAC
, IoC
, SK_PNMI_EVT_SIRQ_OVERFLOW
, Para
);
4077 #endif /* SK_SLIM */
4080 if ((IStatus
& XM_IS_RXF_OV
) != 0) {
4081 /* normal situation -> no effect */
4087 if ((IStatus
& XM_IS_TXF_UR
) != 0) {
4088 /* may NOT happen -> error log */
4089 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_SIRQ_E020
, SKERR_SIRQ_E020MSG
);
4092 if ((IStatus
& XM_IS_TX_COMP
) != 0) {
4093 /* not served here */
4096 if ((IStatus
& XM_IS_RX_COMP
) != 0) {
4097 /* not served here */
4100 #endif /* GENESIS */
4104 /******************************************************************************
4106 * SkGmIrq() - Interrupt Service Routine
4108 * Description: services an Interrupt Request of the GMAC
4116 SK_AC
*pAC
, /* adapter context */
4117 SK_IOC IoC
, /* IO context */
4118 int Port
) /* Port Index (MAC_1 + n) */
4121 SK_U8 IStatus
; /* Interrupt status */
4123 SK_U64 OverflowStatus
;
4128 pPrt
= &pAC
->GIni
.GP
[Port
];
4130 SK_IN8(IoC
, GMAC_IRQ_SRC
, &IStatus
);
4133 /* LinkPartner Auto-negable? */
4134 SkMacAutoNegLipaPhy(pAC
, IoC
, Port
, IStatus
);
4137 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_IRQ
,
4138 ("GmacIrq Port %d Isr 0x%04X\n", Port
, IStatus
));
4140 /* Combined Tx & Rx Counter Overflow SIRQ Event */
4141 if (IStatus
& (GM_IS_RX_CO_OV
| GM_IS_TX_CO_OV
)) {
4142 /* these IRQs will be cleared by reading GMACs register */
4144 SkGmOverflowStatus(pAC
, IoC
, Port
, IStatus
, &OverflowStatus
);
4146 Para
.Para32
[0] = (SK_U32
)Port
;
4147 Para
.Para32
[1] = (SK_U32
)IStatus
;
4148 SkPnmiEvent(pAC
, IoC
, SK_PNMI_EVT_SIRQ_OVERFLOW
, Para
);
4152 if (IStatus
& GM_IS_RX_FF_OR
) {
4153 /* clear GMAC Rx FIFO Overrun IRQ */
4154 SK_OUT8(IoC
, MR_ADDR(Port
, RX_GMF_CTRL_T
), (SK_U8
)GMF_CLI_RX_FO
);
4160 if (IStatus
& GM_IS_TX_FF_UR
) {
4161 /* clear GMAC Tx FIFO Underrun IRQ */
4162 SK_OUT8(IoC
, MR_ADDR(Port
, TX_GMF_CTRL_T
), (SK_U8
)GMF_CLI_TX_FU
);
4163 /* may NOT happen -> error log */
4164 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_SIRQ_E020
, SKERR_SIRQ_E020MSG
);
4167 if (IStatus
& GM_IS_TX_COMPL
) {
4168 /* not served here */
4171 if (IStatus
& GM_IS_RX_COMPL
) {
4172 /* not served here */
4178 /******************************************************************************
4180 * SkMacIrq() - Interrupt Service Routine for MAC
4182 * Description: calls the Interrupt Service Routine dep. on board type
4188 SK_AC
*pAC
, /* adapter context */
4189 SK_IOC IoC
, /* IO context */
4190 int Port
) /* Port Index (MAC_1 + n) */
4193 if (pAC
->GIni
.GIGenesis
) {
4195 SkXmIrq(pAC
, IoC
, Port
);
4197 #endif /* GENESIS */
4200 if (pAC
->GIni
.GIYukon
) {
4202 SkGmIrq(pAC
, IoC
, Port
);
4208 #endif /* !SK_DIAG */
4211 /******************************************************************************
4213 * SkXmUpdateStats() - Force the XMAC to output the current statistic
4216 * The XMAC holds its statistic internally. To obtain the current
4217 * values a command must be sent so that the statistic data will
4218 * be written to a predefined memory area on the adapter.
4222 * 1: something went wrong
4224 int SkXmUpdateStats(
4225 SK_AC
*pAC
, /* adapter context */
4226 SK_IOC IoC
, /* IO context */
4227 unsigned int Port
) /* Port Index (MAC_1 + n) */
4233 pPrt
= &pAC
->GIni
.GP
[Port
];
4236 /* Send an update command to XMAC specified */
4237 XM_OUT16(IoC
, Port
, XM_STAT_CMD
, XM_SC_SNP_TXC
| XM_SC_SNP_RXC
);
4240 * It is an auto-clearing register. If the command bits
4241 * went to zero again, the statistics are transferred.
4242 * Normally the command should be executed immediately.
4243 * But just to be sure we execute a loop.
4247 XM_IN16(IoC
, Port
, XM_STAT_CMD
, &StatReg
);
4249 if (++WaitIndex
> 10) {
4251 SK_ERR_LOG(pAC
, SK_ERRCL_HW
, SKERR_HWI_E021
, SKERR_HWI_E021MSG
);
4255 } while ((StatReg
& (XM_SC_SNP_TXC
| XM_SC_SNP_RXC
)) != 0);
4258 } /* SkXmUpdateStats */
4261 /******************************************************************************
4263 * SkXmMacStatistic() - Get XMAC counter value
4266 * Gets the 32bit counter value. Except for the octet counters
4267 * the lower 32bit are counted in hardware and the upper 32bit
4268 * must be counted in software by monitoring counter overflow interrupts.
4272 * 1: something went wrong
4274 int SkXmMacStatistic(
4275 SK_AC
*pAC
, /* adapter context */
4276 SK_IOC IoC
, /* IO context */
4277 unsigned int Port
, /* Port Index (MAC_1 + n) */
4278 SK_U16 StatAddr
, /* MIB counter base address */
4279 SK_U32 SK_FAR
*pVal
) /* ptr to return statistic value */
4281 if ((StatAddr
< XM_TXF_OK
) || (StatAddr
> XM_RXF_MAX_SZ
)) {
4283 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_HWI_E022
, SKERR_HWI_E022MSG
);
4288 XM_IN32(IoC
, Port
, StatAddr
, pVal
);
4291 } /* SkXmMacStatistic */
4294 /******************************************************************************
4296 * SkXmResetCounter() - Clear MAC statistic counter
4299 * Force the XMAC to clear its statistic counter.
4303 * 1: something went wrong
4305 int SkXmResetCounter(
4306 SK_AC
*pAC
, /* adapter context */
4307 SK_IOC IoC
, /* IO context */
4308 unsigned int Port
) /* Port Index (MAC_1 + n) */
4310 XM_OUT16(IoC
, Port
, XM_STAT_CMD
, XM_SC_CLR_RXC
| XM_SC_CLR_TXC
);
4311 /* Clear two times according to Errata #3 */
4312 XM_OUT16(IoC
, Port
, XM_STAT_CMD
, XM_SC_CLR_RXC
| XM_SC_CLR_TXC
);
4315 } /* SkXmResetCounter */
4318 /******************************************************************************
4320 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4323 * Checks the source causing an counter overflow interrupt. On success the
4324 * resulting counter overflow status is written to <pStatus>, whereas the
4325 * upper dword stores the XMAC ReceiveCounterEvent register and the lower
4326 * dword the XMAC TransmitCounterEvent register.
4329 * For XMAC the interrupt source is a self-clearing register, so the source
4330 * must be checked only once. SIRQ module does another check to be sure
4331 * that no interrupt get lost during process time.
4335 * 1: something went wrong
4337 int SkXmOverflowStatus(
4338 SK_AC
*pAC
, /* adapter context */
4339 SK_IOC IoC
, /* IO context */
4340 unsigned int Port
, /* Port Index (MAC_1 + n) */
4341 SK_U16 IStatus
, /* Interupt Status from MAC */
4342 SK_U64 SK_FAR
*pStatus
) /* ptr for return overflow status value */
4344 SK_U64 Status
; /* Overflow status */
4349 if ((IStatus
& XM_IS_RXC_OV
) != 0) {
4351 XM_IN32(IoC
, Port
, XM_RX_CNT_EV
, &RegVal
);
4352 Status
|= (SK_U64
)RegVal
<< 32;
4355 if ((IStatus
& XM_IS_TXC_OV
) != 0) {
4357 XM_IN32(IoC
, Port
, XM_TX_CNT_EV
, &RegVal
);
4358 Status
|= (SK_U64
)RegVal
;
4364 } /* SkXmOverflowStatus */
4365 #endif /* GENESIS */
4369 /******************************************************************************
4371 * SkGmUpdateStats() - Force the GMAC to output the current statistic
4374 * Empty function for GMAC. Statistic data is accessible in direct way.
4378 * 1: something went wrong
4380 int SkGmUpdateStats(
4381 SK_AC
*pAC
, /* adapter context */
4382 SK_IOC IoC
, /* IO context */
4383 unsigned int Port
) /* Port Index (MAC_1 + n) */
4389 /******************************************************************************
4391 * SkGmMacStatistic() - Get GMAC counter value
4394 * Gets the 32bit counter value. Except for the octet counters
4395 * the lower 32bit are counted in hardware and the upper 32bit
4396 * must be counted in software by monitoring counter overflow interrupts.
4400 * 1: something went wrong
4402 int SkGmMacStatistic(
4403 SK_AC
*pAC
, /* adapter context */
4404 SK_IOC IoC
, /* IO context */
4405 unsigned int Port
, /* Port Index (MAC_1 + n) */
4406 SK_U16 StatAddr
, /* MIB counter base address */
4407 SK_U32 SK_FAR
*pVal
) /* ptr to return statistic value */
4410 if ((StatAddr
< GM_RXF_UC_OK
) || (StatAddr
> GM_TXE_FIFO_UR
)) {
4412 SK_ERR_LOG(pAC
, SK_ERRCL_SW
, SKERR_HWI_E022
, SKERR_HWI_E022MSG
);
4414 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
4415 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr
));
4419 GM_IN32(IoC
, Port
, StatAddr
, pVal
);
4422 } /* SkGmMacStatistic */
4425 /******************************************************************************
4427 * SkGmResetCounter() - Clear MAC statistic counter
4430 * Force GMAC to clear its statistic counter.
4434 * 1: something went wrong
4436 int SkGmResetCounter(
4437 SK_AC
*pAC
, /* adapter context */
4438 SK_IOC IoC
, /* IO context */
4439 unsigned int Port
) /* Port Index (MAC_1 + n) */
4441 SK_U16 Reg
; /* Phy Address Register */
4445 GM_IN16(IoC
, Port
, GM_PHY_ADDR
, &Reg
);
4447 /* set MIB Clear Counter Mode */
4448 GM_OUT16(IoC
, Port
, GM_PHY_ADDR
, Reg
| GM_PAR_MIB_CLR
);
4450 /* read all MIB Counters with Clear Mode set */
4451 for (i
= 0; i
< GM_MIB_CNT_SIZE
; i
++) {
4452 /* the reset is performed only when the lower 16 bits are read */
4453 GM_IN16(IoC
, Port
, GM_MIB_CNT_BASE
+ 8*i
, &Word
);
4456 /* clear MIB Clear Counter Mode */
4457 GM_OUT16(IoC
, Port
, GM_PHY_ADDR
, Reg
);
4460 } /* SkGmResetCounter */
4463 /******************************************************************************
4465 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4468 * Checks the source causing an counter overflow interrupt. On success the
4469 * resulting counter overflow status is written to <pStatus>, whereas the
4470 * the following bit coding is used:
4472 * 55:48 - TxRx interrupt register bit7:0
4473 * 32:47 - Rx interrupt register
4475 * 23:16 - TxRx interrupt register bit15:8
4476 * 15:0 - Tx interrupt register
4480 * 1: something went wrong
4482 int SkGmOverflowStatus(
4483 SK_AC
*pAC
, /* adapter context */
4484 SK_IOC IoC
, /* IO context */
4485 unsigned int Port
, /* Port Index (MAC_1 + n) */
4486 SK_U16 IStatus
, /* Interupt Status from MAC */
4487 SK_U64 SK_FAR
*pStatus
) /* ptr for return overflow status value */
4489 SK_U64 Status
; /* Overflow status */
4494 if ((IStatus
& GM_IS_RX_CO_OV
) != 0) {
4495 /* this register is self-clearing after read */
4496 GM_IN16(IoC
, Port
, GM_RX_IRQ_SRC
, &RegVal
);
4497 Status
|= (SK_U64
)RegVal
<< 32;
4500 if ((IStatus
& GM_IS_TX_CO_OV
) != 0) {
4501 /* this register is self-clearing after read */
4502 GM_IN16(IoC
, Port
, GM_TX_IRQ_SRC
, &RegVal
);
4503 Status
|= (SK_U64
)RegVal
;
4506 /* this register is self-clearing after read */
4507 GM_IN16(IoC
, Port
, GM_TR_IRQ_SRC
, &RegVal
);
4508 /* Rx overflow interrupt register bits (LoByte)*/
4509 Status
|= (SK_U64
)((SK_U8
)RegVal
) << 48;
4510 /* Tx overflow interrupt register bits (HiByte)*/
4511 Status
|= (SK_U64
)(RegVal
>> 8) << 16;
4516 } /* SkGmOverflowStatus */
4520 /******************************************************************************
4522 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4525 * starts the cable diagnostic test if 'StartTest' is true
4526 * gets the results if 'StartTest' is true
4528 * NOTE: this test is meaningful only when link is down
4532 * 1: no YUKON copper
4533 * 2: test in progress
4535 int SkGmCableDiagStatus(
4536 SK_AC
*pAC
, /* adapter context */
4537 SK_IOC IoC
, /* IO context */
4538 int Port
, /* Port Index (MAC_1 + n) */
4539 SK_BOOL StartTest
) /* flag for start / get result */
4545 pPrt
= &pAC
->GIni
.GP
[Port
];
4547 if (pPrt
->PhyType
!= SK_PHY_MARV_COPPER
) {
4553 /* only start the cable test */
4554 if ((pPrt
->PhyId1
& PHY_I1_REV_MSK
) < 4) {
4555 /* apply TDR workaround from Marvell */
4556 SkGmPhyWrite(pAC
, IoC
, Port
, 29, 0x001e);
4558 SkGmPhyWrite(pAC
, IoC
, Port
, 30, 0xcc00);
4559 SkGmPhyWrite(pAC
, IoC
, Port
, 30, 0xc800);
4560 SkGmPhyWrite(pAC
, IoC
, Port
, 30, 0xc400);
4561 SkGmPhyWrite(pAC
, IoC
, Port
, 30, 0xc000);
4562 SkGmPhyWrite(pAC
, IoC
, Port
, 30, 0xc100);
4565 /* set address to 0 for MDI[0] */
4566 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_EXT_ADR
, 0);
4568 /* Read Cable Diagnostic Reg */
4569 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CABLE_DIAG
, &RegVal
);
4571 /* start Cable Diagnostic Test */
4572 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_CABLE_DIAG
,
4573 (SK_U16
)(RegVal
| PHY_M_CABD_ENA_TEST
));
4578 /* Read Cable Diagnostic Reg */
4579 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CABLE_DIAG
, &RegVal
);
4581 SK_DBG_MSG(pAC
, SK_DBGMOD_HWM
, SK_DBGCAT_CTRL
,
4582 ("PHY Cable Diag.=0x%04X\n", RegVal
));
4584 if ((RegVal
& PHY_M_CABD_ENA_TEST
) != 0) {
4585 /* test is running */
4589 /* get the test results */
4590 for (i
= 0; i
< 4; i
++) {
4591 /* set address to i for MDI[i] */
4592 SkGmPhyWrite(pAC
, IoC
, Port
, PHY_MARV_EXT_ADR
, (SK_U16
)i
);
4594 /* get Cable Diagnostic values */
4595 SkGmPhyRead(pAC
, IoC
, Port
, PHY_MARV_CABLE_DIAG
, &RegVal
);
4597 pPrt
->PMdiPairLen
[i
] = (SK_U8
)(RegVal
& PHY_M_CABD_DIST_MSK
);
4599 pPrt
->PMdiPairSts
[i
] = (SK_U8
)((RegVal
& PHY_M_CABD_STAT_MSK
) >> 13);
4603 } /* SkGmCableDiagStatus */
4604 #endif /* !SK_SLIM */