1 /******************************************************************************
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
7 * Purpose: Contains functions to initialize the MACs and PHYs
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2003 SysKonnect GmbH.
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * The information in this file is provided "AS IS" without warranty.
22 ******************************************************************************/
24 /******************************************************************************
29 * Revision 1.1.3.1 2011-02-28 14:53:20 lothar
30 * imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
32 * Revision 1.91 2003/02/05 15:09:34 rschmidt
33 * Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv().
34 * Disabled auto-update for speed, duplex and flow-control when
35 * auto-negotiation is not enabled (Bug Id #10766).
38 * Revision 1.90 2003/01/29 13:35:19 rschmidt
39 * Increment Rx FIFO Overflow counter only in DEBUG-mode.
40 * Corrected define for blinking active LED.
42 * Revision 1.89 2003/01/28 16:37:45 rschmidt
43 * Changed init for blinking active LED
45 * Revision 1.88 2003/01/28 10:09:38 rschmidt
46 * Added debug outputs in SkGmInitMac().
47 * Added customized init of LED registers in SkGmInitPhyMarv(),
48 * for blinking active LED (#ifdef ACT_LED_BLINK) and
49 * for normal duplex LED (#ifdef DUP_LED_NORMAL).
52 * Revision 1.87 2002/12/10 14:39:05 rschmidt
53 * Improved initialization of GPHY in SkGmInitPhyMarv().
56 * Revision 1.86 2002/12/09 15:01:12 rschmidt
57 * Added setup of Ext. PHY Specific Ctrl Reg (downshift feature).
59 * Revision 1.85 2002/12/05 14:09:16 rschmidt
60 * Improved avoiding endless loop in SkGmPhyWrite(), SkGmPhyWrite().
61 * Added additional advertising for 10Base-T when 100Base-T is selected.
62 * Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter.
65 * Revision 1.84 2002/11/15 12:50:09 rschmidt
66 * Changed SkGmCableDiagStatus() when getting results.
68 * Revision 1.83 2002/11/13 10:28:29 rschmidt
69 * Added some typecasts to avoid compiler warnings.
71 * Revision 1.82 2002/11/13 09:20:46 rschmidt
72 * Replaced for(..) with do {} while (...) in SkXmUpdateStats().
73 * Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic().
74 * Added SkGmCableDiagStatus() for Virtual Cable Test (VCT).
77 * Revision 1.81 2002/10/28 14:28:08 rschmidt
78 * Changed MAC address setup for GMAC in SkGmInitMac().
79 * Optimized handling of counter overflow IRQ in SkGmOverflowStatus().
82 * Revision 1.80 2002/10/14 15:29:44 rschmidt
83 * Corrected disabling of all PHY IRQs.
84 * Added WA for deviation #16 (address used for pause packets).
85 * Set Pause Mode in SkMacRxTxEnable() only for Genesis.
86 * Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode.
87 * SkXmTimeStamp() replaced by SkMacTimeStamp().
88 * Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq().
91 * Revision 1.79 2002/10/10 15:55:36 mkarl
92 * changes for PLinkSpeedUsed
94 * Revision 1.78 2002/09/12 09:39:51 rwahl
95 * Removed deactivate code for SIRQ overflow event separate for TX/RX.
97 * Revision 1.77 2002/09/09 12:26:37 mkarl
98 * added handling for Yukon to SkXmTimeStamp
100 * Revision 1.76 2002/08/21 16:41:16 rschmidt
101 * Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE.
102 * Added forced speed settings in SkGmInitPhyMarv().
103 * Added settings of full/half duplex capabilities for YUKON Fiber.
106 * Revision 1.75 2002/08/16 15:12:01 rschmidt
107 * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
108 * Added function SkMacHashing() for ADDR-Module.
109 * Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced
111 * Removed functions SkGmGetMuxConfig().
112 * Added HWCFG_MODE init for YUKON Fiber.
113 * Changed initialization of GPHY in SkGmInitPhyMarv().
114 * Changed check of parameter in SkXmMacStatistic().
117 * Revision 1.74 2002/08/12 14:00:17 rschmidt
118 * Replaced usage of Broadcom PHY Ids with defines.
119 * Corrected error messages in SkGmMacStatistic().
120 * Made SkMacPromiscMode() public for ADDR-Modul.
123 * Revision 1.73 2002/08/08 16:26:24 rschmidt
124 * Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac().
125 * Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM.
128 * Revision 1.72 2002/07/24 15:11:19 rschmidt
129 * Fixed wrong placement of parenthesis.
132 * Revision 1.71 2002/07/23 16:05:18 rschmidt
133 * Added global functions for PHY: SkGePhyRead(), SkGePhyWrite().
134 * Fixed Tx Counter Overflow IRQ (Bug ID #10730).
137 * Revision 1.70 2002/07/18 14:27:27 rwahl
138 * Fixed syntax error.
140 * Revision 1.69 2002/07/17 17:08:47 rwahl
141 * Fixed check in SkXmMacStatistic().
143 * Revision 1.68 2002/07/16 07:35:24 rwahl
144 * Removed check for cleared mib counter in SkGmResetCounter().
146 * Revision 1.67 2002/07/15 18:35:56 rwahl
147 * Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(),
148 * SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(),
149 * SkXmOverflowStatus(), SkGmOverflowStatus().
150 * Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both
152 * Changes to SkGmInitMac(): call to SkGmResetCounter().
155 * Revision 1.66 2002/07/15 15:59:30 rschmidt
156 * Added PHY Address in SkXmPhyRead(), SkXmPhyWrite().
157 * Added MIB Clear Counter in SkGmInitMac().
158 * Added Duplex and Flow-Control settings.
159 * Reset all Multicast filtering Hash reg. in SkGmInitMac().
160 * Added new function: SkGmGetMuxConfig().
163 * Revision 1.65 2002/06/10 09:35:39 rschmidt
164 * Replaced C++ comments (//).
165 * Added #define VCPU around VCPUwaitTime.
168 * Revision 1.64 2002/06/05 08:41:10 rschmidt
169 * Added function for XMAC2: SkXmTimeStamp().
170 * Added function for YUKON: SkGmSetRxCmd().
171 * Changed SkGmInitMac() resp. SkGmHardRst().
172 * Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode).
173 * SkXmRxTxEnable() replaced by SkMacRxTxEnable().
176 * Revision 1.63 2002/04/25 13:04:44 rschmidt
177 * Changes for handling YUKON.
178 * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types.
179 * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced
180 * by functions SkXmPhyRead(), SkXmPhyWrite();
181 * Removed use of PRxCmd to setup XMAC.
182 * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res.
183 * Added setting of XM_RX_DIS_CEXT in SkXmInitMac().
184 * Removed status parameter from MAC IRQ handler SkMacIrq(),
185 * SkXmIrq() and SkGmIrq().
186 * SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy().
187 * Added SkMac...() functions to handle both XMAC and GMAC.
188 * Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(),
189 * SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(),
190 * SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite().
191 * Changes for V-CPU support.
194 * Revision 1.62 2001/08/06 09:50:14 rschmidt
195 * Workaround BCOM Errata #1 for the C5 type.
198 * Revision 1.61 2001/02/09 15:40:59 rassmann
201 * Revision 1.60 2001/02/07 15:02:01 cgoos
202 * Added workaround for Fujitsu switch link down.
204 * Revision 1.59 2001/01/10 09:38:06 cgoos
205 * Fixed Broadcom C0/A1 Id check for workaround.
207 * Revision 1.58 2000/11/29 11:30:38 cgoos
208 * Changed DEBUG sections with NW output to xDEBUG
210 * Revision 1.57 2000/11/27 12:40:40 rassmann
211 * Suppressing preamble after first access to BCom, not before (#10556).
213 * Revision 1.56 2000/11/09 12:32:48 rassmann
216 * Revision 1.55 2000/11/09 11:30:10 rassmann
217 * WA: Waiting after releasing reset until BCom chip is accessible.
219 * Revision 1.54 2000/10/02 14:10:27 rassmann
220 * Reading BCOM PHY after releasing reset until it returns a valid value.
222 * Revision 1.53 2000/07/27 12:22:11 gklug
223 * fix: possible endless loop in XmHardRst.
225 * Revision 1.52 2000/05/22 08:48:31 malthoff
226 * Fix: #10523 errata valid for all BCOM PHYs.
228 * Revision 1.51 2000/05/17 12:52:18 malthoff
229 * Fixes BCom link errata (#10523).
231 * Revision 1.50 1999/11/22 13:40:14 cgoos
232 * Changed license header to GPL.
234 * Revision 1.49 1999/11/22 08:12:13 malthoff
235 * Add workaround for power consumption feature of BCom C0 chip.
237 * Revision 1.48 1999/11/16 08:39:01 malthoff
238 * Fix: MDIO preamble suppression is port dependent.
240 * Revision 1.47 1999/08/27 08:55:35 malthoff
241 * 1000BT: Optimizing MDIO transfer by oppressing MDIO preamble.
243 * Revision 1.46 1999/08/13 11:01:12 malthoff
244 * Fix for 1000BT: pFlowCtrlMode was not set correctly.
246 * Revision 1.45 1999/08/12 19:18:28 malthoff
247 * 1000BT Fixes: Do not owerwrite XM_MMU_CMD.
248 * Do not execute BCOM A1 workaround for B1 chips.
249 * Fix pause frame setting.
250 * Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL.
252 * Revision 1.44 1999/08/03 15:23:48 cgoos
253 * Fixed setting of PHY interrupt mask in half duplex mode.
255 * Revision 1.43 1999/08/03 15:22:17 cgoos
256 * Added some debug output.
257 * Disabled XMac GP0 interrupt for external PHYs.
259 * Revision 1.42 1999/08/02 08:39:23 malthoff
260 * BCOM PHY: TX LED: To get the mono flop behaviour it is required
261 * to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL.
263 * Revision 1.41 1999/07/30 06:54:31 malthoff
264 * Add temp. workarounds for the BCOM Phy revision A1.
266 * Revision 1.40 1999/06/01 07:43:26 cgoos
267 * Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to
270 * Revision 1.39 1999/05/19 07:29:51 cgoos
271 * Changes for 1000Base-T.
273 * Revision 1.38 1999/04/08 14:35:10 malthoff
274 * Add code for enabling signal detect. Enabling signal detect is disabled.
276 * Revision 1.37 1999/03/12 13:42:54 malthoff
277 * Add: Jumbo Frame Support.
278 * Add: Receive modes SK_LENERR_OK_ON/OFF and
279 * SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd().
281 * Revision 1.36 1999/03/08 10:10:55 gklug
282 * fix: AutoSensing did switch to next mode even if LiPa indicated offline
284 * Revision 1.35 1999/02/22 15:16:41 malthoff
285 * Remove some compiler warnings.
287 * Revision 1.34 1999/01/22 09:19:59 gklug
288 * fix: Init DupMode and InitPauseMd are now called in RxTxEnable
290 * Revision 1.33 1998/12/11 15:19:11 gklug
291 * chg: lipa autoneg stati
292 * chg: debug messages
293 * chg: do NOT use spurious XmIrq
295 * Revision 1.32 1998/12/10 11:08:44 malthoff
296 * bug fix: pAC has been used for IOs in SkXmHardRst().
297 * SkXmInitPhy() is also called for the Diag in SkXmInitMac().
299 * Revision 1.31 1998/12/10 10:39:11 gklug
300 * fix: do 4 RESETS of the XMAC at the beginning
301 * fix: dummy read interrupt source register BEFORE initializing the Phy
302 * add: debug messages
303 * fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt
305 * Revision 1.30 1998/12/07 12:18:32 gklug
306 * add: refinement of autosense mode: take into account the autoneg cap of LiPa
308 * Revision 1.29 1998/12/07 07:12:29 gklug
309 * fix: if page is received the link is down.
311 * Revision 1.28 1998/12/01 10:12:47 gklug
312 * chg: if spurious IRQ from XMAC encountered, save it
314 * Revision 1.27 1998/11/26 07:33:38 gklug
315 * add: InitPhy call is now in XmInit function
317 * Revision 1.26 1998/11/18 13:38:24 malthoff
318 * 'Imsk' is also unused in SkXmAutoNegDone.
320 * Revision 1.25 1998/11/18 13:28:01 malthoff
321 * Remove unused variable 'Reg' in SkXmAutoNegDone().
323 * Revision 1.24 1998/11/18 13:18:45 gklug
324 * add: workaround for xmac errata #1
325 * add: detect Link Down also when Link partner requested config
326 * chg: XMIrq is only used when link is up
328 * Revision 1.23 1998/11/04 07:07:04 cgoos
329 * Added function SkXmRxTxEnable.
331 * Revision 1.22 1998/10/30 07:35:54 gklug
332 * fix: serve LinkDown interrupt when link is already down
334 * Revision 1.21 1998/10/29 15:32:03 gklug
335 * fix: Link Down signaling
337 * Revision 1.20 1998/10/29 11:17:27 gklug
338 * fix: AutoNegDone bug
340 * Revision 1.19 1998/10/29 10:14:43 malthoff
341 * Add endainesss comment for reading/writing MAC addresses.
343 * Revision 1.18 1998/10/28 07:48:55 cgoos
344 * Fix: ASS somtimes signaled although link is up.
346 * Revision 1.17 1998/10/26 07:55:39 malthoff
347 * Fix in SkXmInitPauseMd(): Pause Mode
348 * was disabled and not enabled.
349 * Fix in SkXmAutoNegDone(): Checking Mode bits
350 * always failed, becaues of some missing braces.
352 * Revision 1.16 1998/10/22 09:46:52 gklug
353 * fix SysKonnectFileId typo
355 * Revision 1.15 1998/10/21 05:51:37 gklug
356 * add: para DoLoop to InitPhy function for loopback set-up
358 * Revision 1.14 1998/10/16 10:59:23 malthoff
359 * Remove Lint warning for dummy reads.
361 * Revision 1.13 1998/10/15 14:01:20 malthoff
362 * Fix: SkXmAutoNegDone() is (int) but does not return a value.
364 * Revision 1.12 1998/10/14 14:45:04 malthoff
365 * Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by
366 * SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent
367 * from the Sirq module.
369 * Revision 1.11 1998/10/14 13:59:01 gklug
370 * add: InitPhy function
372 * Revision 1.10 1998/10/14 11:20:57 malthoff
373 * Make SkXmAutoNegDone() public, because it's
374 * used in diagnostics, too.
375 * The Link Up event to the RLMT is issued in SkXmIrq().
376 * SkXmIrq() is not available in diagnostics.
377 * Use PHY_READ when reading PHY registers.
379 * Revision 1.9 1998/10/14 05:50:10 cgoos
380 * Added definition for Para.
382 * Revision 1.8 1998/10/14 05:41:28 gklug
384 * add: auto-negotiation done function
386 * Revision 1.7 1998/10/09 06:55:20 malthoff
387 * The configuration of the XMACs Tx Request Threshold
388 * depends from the drivers port usage now. The port
389 * usage is configured in GIPortUsage.
391 * Revision 1.6 1998/10/05 07:48:00 malthoff
394 * Revision 1.5 1998/10/01 07:03:54 gklug
395 * add: dummy function for XMAC ISR
397 * Revision 1.4 1998/09/30 12:37:44 malthoff
398 * Add SkXmSetRxCmd() and related code.
400 * Revision 1.3 1998/09/28 13:26:40 malthoff
401 * Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd()
403 * Revision 1.2 1998/09/16 14:34:21 malthoff
404 * Add SkXmClrExactAddr(), SkXmClrSrcCheck(),
405 * SkXmClrHashAddr(), SkXmFlushTxFifo(),
406 * SkXmFlushRxFifo(), and SkXmHardRst().
407 * Finish Coding of SkXmSoftRst().
408 * The sources may be compiled now.
410 * Revision 1.1 1998/09/04 10:05:56 malthoff
414 ******************************************************************************/
418 #include "h/skdrv1st.h"
419 #include "h/skdrv2nd.h"
421 /* typedefs *******************************************************************/
423 /* BCOM PHY magic pattern list */
424 typedef struct s_PhyHack {
425 int PhyReg; /* Phy register */
426 SK_U16 PhyVal; /* Value to write */
429 /* local variables ************************************************************/
430 static const char SysKonnectFileId[] =
433 BCOM_HACK BcomRegA1Hack[] = {
434 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
435 { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
436 { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
439 BCOM_HACK BcomRegC0Hack[] = {
440 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
441 { 0x15, 0x0A04 }, { 0x18, 0x0420 },
445 /* function prototypes ********************************************************/
446 static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
447 static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
448 static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
449 static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
450 static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
451 static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
453 static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
454 static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
455 static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
456 static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
457 #endif /* OTHER_PHY */
460 /******************************************************************************
462 * SkXmPhyRead() - Read from XMAC PHY register
464 * Description: reads a 16-bit word from XMAC PHY or ext. PHY
470 SK_AC *pAC, /* Adapter Context */
471 SK_IOC IoC, /* I/O Context */
472 int Port, /* Port Index (MAC_1 + n) */
473 int PhyReg, /* Register Address (Offset) */
474 SK_U16 *pVal) /* Pointer to Value */
479 pPrt = &pAC->GIni.GP[Port];
481 /* write the PHY register's address */
482 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
484 /* get the PHY register's value */
485 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
487 if (pPrt->PhyType != SK_PHY_XMAC) {
489 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
490 /* wait until 'Ready' is set */
491 } while ((Mmu & XM_MMU_PHY_RDY) == 0);
493 /* get the PHY register's value */
494 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
499 /******************************************************************************
501 * SkXmPhyWrite() - Write to XMAC PHY register
503 * Description: writes a 16-bit word to XMAC PHY or ext. PHY
509 SK_AC *pAC, /* Adapter Context */
510 SK_IOC IoC, /* I/O Context */
511 int Port, /* Port Index (MAC_1 + n) */
512 int PhyReg, /* Register Address (Offset) */
513 SK_U16 Val) /* Value */
518 pPrt = &pAC->GIni.GP[Port];
520 if (pPrt->PhyType != SK_PHY_XMAC) {
522 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
523 /* wait until 'Busy' is cleared */
524 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
527 /* write the PHY register's address */
528 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
530 /* write the PHY register's value */
531 XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
533 if (pPrt->PhyType != SK_PHY_XMAC) {
535 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
536 /* wait until 'Busy' is cleared */
537 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
542 /******************************************************************************
544 * SkGmPhyRead() - Read from GPHY register
546 * Description: reads a 16-bit word from GPHY through MDIO
552 SK_AC *pAC, /* Adapter Context */
553 SK_IOC IoC, /* I/O Context */
554 int Port, /* Port Index (MAC_1 + n) */
555 int PhyReg, /* Register Address (Offset) */
556 SK_U16 *pVal) /* Pointer to Value */
564 VCPUgetTime(&SimCyle, &SimLowTime);
565 VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
566 PhyReg, SimCyle, SimLowTime);
569 pPrt = &pAC->GIni.GP[Port];
571 /* set PHY-Register offset and 'Read' OpCode (= 1) */
572 *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
573 GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
575 GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
577 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
579 /* additional check for MDC/MDIO activity */
580 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
585 *pVal |= GM_SMI_CT_BUSY;
592 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
594 /* wait until 'ReadValid' is set */
595 } while (Ctrl == *pVal);
597 /* get the PHY register's value */
598 GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
601 VCPUgetTime(&SimCyle, &SimLowTime);
602 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
603 SimCyle, SimLowTime);
608 /******************************************************************************
610 * SkGmPhyWrite() - Write to GPHY register
612 * Description: writes a 16-bit word to GPHY through MDIO
618 SK_AC *pAC, /* Adapter Context */
619 SK_IOC IoC, /* I/O Context */
620 int Port, /* Port Index (MAC_1 + n) */
621 int PhyReg, /* Register Address (Offset) */
622 SK_U16 Val) /* Value */
631 VCPUgetTime(&SimCyle, &SimLowTime);
632 VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
633 PhyReg, Val, SimCyle, SimLowTime);
636 pPrt = &pAC->GIni.GP[Port];
638 /* write the PHY register's value */
639 GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
641 /* set PHY-Register offset and 'Write' OpCode (= 0) */
642 Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
644 GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
646 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
648 /* additional check for MDC/MDIO activity */
649 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
653 Val |= GM_SMI_CT_BUSY;
657 /* read Timer value */
658 SK_IN32(IoC, B2_TI_VAL, &DWord);
663 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
665 /* wait until 'Busy' is cleared */
666 } while (Ctrl == Val);
669 VCPUgetTime(&SimCyle, &SimLowTime);
670 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
671 SimCyle, SimLowTime);
676 /******************************************************************************
678 * SkGePhyRead() - Read from PHY register
680 * Description: calls a read PHY routine dep. on board type
686 SK_AC *pAC, /* Adapter Context */
687 SK_IOC IoC, /* I/O Context */
688 int Port, /* Port Index (MAC_1 + n) */
689 int PhyReg, /* Register Address (Offset) */
690 SK_U16 *pVal) /* Pointer to Value */
692 void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
694 if (pAC->GIni.GIGenesis) {
695 r_func = SkXmPhyRead;
698 r_func = SkGmPhyRead;
701 r_func(pAC, IoC, Port, PhyReg, pVal);
705 /******************************************************************************
707 * SkGePhyWrite() - Write to PHY register
709 * Description: calls a write PHY routine dep. on board type
715 SK_AC *pAC, /* Adapter Context */
716 SK_IOC IoC, /* I/O Context */
717 int Port, /* Port Index (MAC_1 + n) */
718 int PhyReg, /* Register Address (Offset) */
719 SK_U16 Val) /* Value */
721 void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
723 if (pAC->GIni.GIGenesis) {
724 w_func = SkXmPhyWrite;
727 w_func = SkGmPhyWrite;
730 w_func(pAC, IoC, Port, PhyReg, Val);
734 /******************************************************************************
736 * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
739 * enables / disables promiscuous mode by setting Mode Register (XMAC) or
740 * Receive Control Register (GMAC) dep. on board type
745 void SkMacPromiscMode(
746 SK_AC *pAC, /* adapter context */
747 SK_IOC IoC, /* IO context */
748 int Port, /* Port Index (MAC_1 + n) */
749 SK_BOOL Enable) /* Enable / Disable */
754 if (pAC->GIni.GIGenesis) {
756 XM_IN32(IoC, Port, XM_MODE, &MdReg);
757 /* enable or disable promiscuous mode */
759 MdReg |= XM_MD_ENA_PROM;
762 MdReg &= ~XM_MD_ENA_PROM;
764 /* setup Mode Register */
765 XM_OUT32(IoC, Port, XM_MODE, MdReg);
769 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
771 /* enable or disable unicast and multicast filtering */
773 RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
776 RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
778 /* setup Receive Control Register */
779 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
781 } /* SkMacPromiscMode*/
784 /******************************************************************************
786 * SkMacHashing() - Enable / Disable Hashing
789 * enables / disables hashing by setting Mode Register (XMAC) or
790 * Receive Control Register (GMAC) dep. on board type
796 SK_AC *pAC, /* adapter context */
797 SK_IOC IoC, /* IO context */
798 int Port, /* Port Index (MAC_1 + n) */
799 SK_BOOL Enable) /* Enable / Disable */
804 if (pAC->GIni.GIGenesis) {
806 XM_IN32(IoC, Port, XM_MODE, &MdReg);
807 /* enable or disable hashing */
809 MdReg |= XM_MD_ENA_HASH;
812 MdReg &= ~XM_MD_ENA_HASH;
814 /* setup Mode Register */
815 XM_OUT32(IoC, Port, XM_MODE, MdReg);
819 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
821 /* enable or disable multicast filtering */
823 RcReg |= GM_RXCR_MCF_ENA;
826 RcReg &= ~GM_RXCR_MCF_ENA;
828 /* setup Receive Control Register */
829 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
835 /******************************************************************************
837 * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
841 * - FCS stripping, SK_STRIP_FCS_ON/OFF
842 * - pad byte stripping, SK_STRIP_PAD_ON/OFF
843 * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
844 * for inrange length error frames
845 * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
846 * for frames > 1514 bytes
847 * - enable Rx of own packets SK_SELF_RX_ON/OFF
849 * for incoming packets may be enabled/disabled by this function.
850 * Additional modes may be added later.
851 * Multiple modes can be enabled/disabled at the same time.
852 * The new configuration is written to the Rx Command register immediately.
857 static void SkXmSetRxCmd(
858 SK_AC *pAC, /* adapter context */
859 SK_IOC IoC, /* IO context */
860 int Port, /* Port Index (MAC_1 + n) */
861 int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
862 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
867 XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
871 switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
872 case SK_STRIP_FCS_ON:
873 RxCmd |= XM_RX_STRIP_FCS;
875 case SK_STRIP_FCS_OFF:
876 RxCmd &= ~XM_RX_STRIP_FCS;
880 switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
881 case SK_STRIP_PAD_ON:
882 RxCmd |= XM_RX_STRIP_PAD;
884 case SK_STRIP_PAD_OFF:
885 RxCmd &= ~XM_RX_STRIP_PAD;
889 switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
890 case SK_LENERR_OK_ON:
891 RxCmd |= XM_RX_LENERR_OK;
893 case SK_LENERR_OK_OFF:
894 RxCmd &= ~XM_RX_LENERR_OK;
898 switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
899 case SK_BIG_PK_OK_ON:
900 RxCmd |= XM_RX_BIG_PK_OK;
902 case SK_BIG_PK_OK_OFF:
903 RxCmd &= ~XM_RX_BIG_PK_OK;
907 switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
909 RxCmd |= XM_RX_SELF_RX;
912 RxCmd &= ~XM_RX_SELF_RX;
916 /* Write the new mode to the Rx command register if required */
917 if (OldRxCmd != RxCmd) {
918 XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
923 /******************************************************************************
925 * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
929 * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
930 * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
931 * for frames > 1514 bytes
932 * - enable Rx of own packets SK_SELF_RX_ON/OFF
934 * for incoming packets may be enabled/disabled by this function.
935 * Additional modes may be added later.
936 * Multiple modes can be enabled/disabled at the same time.
937 * The new configuration is written to the Rx Command register immediately.
942 static void SkGmSetRxCmd(
943 SK_AC *pAC, /* adapter context */
944 SK_IOC IoC, /* IO context */
945 int Port, /* Port Index (MAC_1 + n) */
946 int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
947 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
952 if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
954 GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
958 if ((Mode & SK_STRIP_FCS_ON) != 0) {
959 RxCmd |= GM_RXCR_CRC_DIS;
962 RxCmd &= ~GM_RXCR_CRC_DIS;
964 /* Write the new mode to the Rx control register if required */
965 if (OldRxCmd != RxCmd) {
966 GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
970 if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
972 GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
976 if ((Mode & SK_BIG_PK_OK_ON) != 0) {
977 RxCmd |= GM_SMOD_JUMBO_ENA;
980 RxCmd &= ~GM_SMOD_JUMBO_ENA;
982 /* Write the new mode to the Rx control register if required */
983 if (OldRxCmd != RxCmd) {
984 GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
990 /******************************************************************************
992 * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
994 * Description: modifies the MAC's Rx Control reg. dep. on board type
1000 SK_AC *pAC, /* adapter context */
1001 SK_IOC IoC, /* IO context */
1002 int Port, /* Port Index (MAC_1 + n) */
1003 int Mode) /* Rx Mode */
1005 if (pAC->GIni.GIGenesis) {
1007 SkXmSetRxCmd(pAC, IoC, Port, Mode);
1011 SkGmSetRxCmd(pAC, IoC, Port, Mode);
1013 } /* SkMacSetRxCmd */
1016 /******************************************************************************
1018 * SkMacCrcGener() - Enable / Disable CRC Generation
1020 * Description: enables / disables CRC generation dep. on board type
1026 SK_AC *pAC, /* adapter context */
1027 SK_IOC IoC, /* IO context */
1028 int Port, /* Port Index (MAC_1 + n) */
1029 SK_BOOL Enable) /* Enable / Disable */
1033 if (pAC->GIni.GIGenesis) {
1035 XM_IN16(IoC, Port, XM_TX_CMD, &Word);
1038 Word &= ~XM_TX_NO_CRC;
1041 Word |= XM_TX_NO_CRC;
1043 /* setup Tx Command Register */
1044 XM_OUT16(pAC, Port, XM_TX_CMD, Word);
1048 GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
1051 Word &= ~GM_TXCR_CRC_DIS;
1054 Word |= GM_TXCR_CRC_DIS;
1056 /* setup Tx Control Register */
1057 GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
1059 } /* SkMacCrcGener*/
1061 #endif /* SK_DIAG */
1064 /******************************************************************************
1066 * SkXmClrExactAddr() - Clear Exact Match Address Registers
1069 * All Exact Match Address registers of the XMAC 'Port' will be
1070 * cleared starting with 'StartNum' up to (and including) the
1071 * Exact Match address number of 'StopNum'.
1076 void SkXmClrExactAddr(
1077 SK_AC *pAC, /* adapter context */
1078 SK_IOC IoC, /* IO context */
1079 int Port, /* Port Index (MAC_1 + n) */
1080 int StartNum, /* Begin with this Address Register Index (0..15) */
1081 int StopNum) /* Stop after finished with this Register Idx (0..15) */
1084 SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
1086 if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
1087 StartNum > StopNum) {
1089 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
1093 for (i = StartNum; i <= StopNum; i++) {
1094 XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
1096 } /* SkXmClrExactAddr */
1099 /******************************************************************************
1101 * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
1104 * Flush the transmit FIFO of the MAC specified by the index 'Port'
1109 void SkMacFlushTxFifo(
1110 SK_AC *pAC, /* adapter context */
1111 SK_IOC IoC, /* IO context */
1112 int Port) /* Port Index (MAC_1 + n) */
1116 if (pAC->GIni.GIGenesis) {
1118 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1120 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
1123 /* no way to flush the FIFO we have to issue a reset */
1126 } /* SkMacFlushTxFifo */
1129 /******************************************************************************
1131 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
1134 * Flush the receive FIFO of the MAC specified by the index 'Port'
1139 void SkMacFlushRxFifo(
1140 SK_AC *pAC, /* adapter context */
1141 SK_IOC IoC, /* IO context */
1142 int Port) /* Port Index (MAC_1 + n) */
1146 if (pAC->GIni.GIGenesis) {
1148 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1150 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
1153 /* no way to flush the FIFO we have to issue a reset */
1156 } /* SkMacFlushRxFifo */
1159 /******************************************************************************
1161 * SkXmSoftRst() - Do a XMAC software reset
1164 * The PHY registers should not be destroyed during this
1165 * kind of software reset. Therefore the XMAC Software Reset
1166 * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
1168 * The software reset is done by
1169 * - disabling the Rx and Tx state machine,
1170 * - resetting the statistics module,
1171 * - clear all other significant XMAC Mode,
1172 * Command, and Control Registers
1173 * - clearing the Hash Register and the
1174 * Exact Match Address registers, and
1175 * - flushing the XMAC's Rx and Tx FIFOs.
1178 * Another requirement when stopping the XMAC is to
1179 * avoid sending corrupted frames on the network.
1180 * Disabling the Tx state machine will NOT interrupt
1181 * the currently transmitted frame. But we must take care
1182 * that the Tx FIFO is cleared AFTER the current frame
1183 * is complete sent to the network.
1185 * It takes about 12ns to send a frame with 1538 bytes.
1186 * One PCI clock goes at least 15ns (66MHz). Therefore
1187 * after reading XM_GP_PORT back, we are sure that the
1188 * transmitter is disabled AND idle. And this means
1189 * we may flush the transmit FIFO now.
1194 static void SkXmSoftRst(
1195 SK_AC *pAC, /* adapter context */
1196 SK_IOC IoC, /* IO context */
1197 int Port) /* Port Index (MAC_1 + n) */
1199 SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1201 /* reset the statistics module */
1202 XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
1204 /* disable all XMAC IRQs */
1205 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
1207 XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
1209 XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
1210 XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
1212 /* disable all PHY IRQs */
1213 switch (pAC->GIni.GP[Port].PhyType) {
1215 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
1219 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
1223 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
1225 #endif /* OTHER_PHY */
1228 /* clear the Hash Register */
1229 XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
1231 /* clear the Exact Match Address registers */
1232 SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
1234 /* clear the Source Check Address registers */
1235 XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
1240 /******************************************************************************
1242 * SkXmHardRst() - Do a XMAC hardware reset
1245 * The XMAC of the specified 'Port' and all connected devices
1246 * (PHY and SERDES) will receive a reset signal on its *Reset pins.
1247 * External PHYs must be reset be clearing a bit in the GPIO register
1248 * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
1251 * It is absolutely necessary to reset the SW_RST Bit first
1252 * before calling this function.
1257 static void SkXmHardRst(
1258 SK_AC *pAC, /* adapter context */
1259 SK_IOC IoC, /* IO context */
1260 int Port) /* Port Index (MAC_1 + n) */
1267 for (i = 0; i < 4; i++) {
1268 /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
1269 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1273 if (TOut++ > 10000) {
1275 * Adapter seems to be in RESET state.
1276 * Registers cannot be written.
1281 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
1283 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
1285 } while ((Word & MFF_SET_MAC_RST) == 0);
1288 /* For external PHYs there must be special handling */
1289 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
1290 /* reset external PHY */
1291 SK_IN32(IoC, B2_GP_IO, &Reg);
1293 Reg |= GP_DIR_0; /* set to output */
1297 Reg |= GP_DIR_2; /* set to output */
1300 SK_OUT32(IoC, B2_GP_IO, Reg);
1303 SK_IN32(IoC, B2_GP_IO, &Reg);
1309 /******************************************************************************
1311 * SkGmSoftRst() - Do a GMAC software reset
1314 * The GPHY registers should not be destroyed during this
1315 * kind of software reset.
1320 static void SkGmSoftRst(
1321 SK_AC *pAC, /* adapter context */
1322 SK_IOC IoC, /* IO context */
1323 int Port) /* Port Index (MAC_1 + n) */
1325 SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1328 /* reset the statistics module */
1330 /* disable all GMAC IRQs */
1331 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
1333 /* disable all PHY IRQs */
1334 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
1336 /* clear the Hash Register */
1337 GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
1339 /* Enable Unicast and Multicast filtering */
1340 GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
1342 GM_OUT16(IoC, Port, GM_RX_CTRL,
1343 RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
1348 /******************************************************************************
1350 * SkGmHardRst() - Do a GMAC hardware reset
1355 * It is absolutely necessary to reset the SW_RST Bit first
1356 * before calling this function.
1361 static void SkGmHardRst(
1362 SK_AC *pAC, /* adapter context */
1363 SK_IOC IoC, /* IO context */
1364 int Port) /* Port Index (MAC_1 + n) */
1366 /* set GPHY Control reset */
1367 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1369 /* set GMAC Control reset */
1370 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1375 /******************************************************************************
1377 * SkMacSoftRst() - Do a MAC software reset
1379 * Description: calls a MAC software reset routine dep. on board type
1385 SK_AC *pAC, /* adapter context */
1386 SK_IOC IoC, /* IO context */
1387 int Port) /* Port Index (MAC_1 + n) */
1391 pPrt = &pAC->GIni.GP[Port];
1393 /* disable receiver and transmitter */
1394 SkMacRxTxDisable(pAC, IoC, Port);
1396 if (pAC->GIni.GIGenesis) {
1398 SkXmSoftRst(pAC, IoC, Port);
1402 SkGmSoftRst(pAC, IoC, Port);
1405 /* flush the MAC's Rx and Tx FIFOs */
1406 SkMacFlushTxFifo(pAC, IoC, Port);
1408 SkMacFlushRxFifo(pAC, IoC, Port);
1410 pPrt->PState = SK_PRT_STOP;
1412 } /* SkMacSoftRst */
1415 /******************************************************************************
1417 * SkMacHardRst() - Do a MAC hardware reset
1419 * Description: calls a MAC hardware reset routine dep. on board type
1425 SK_AC *pAC, /* adapter context */
1426 SK_IOC IoC, /* IO context */
1427 int Port) /* Port Index (MAC_1 + n) */
1430 if (pAC->GIni.GIGenesis) {
1432 SkXmHardRst(pAC, IoC, Port);
1436 SkGmHardRst(pAC, IoC, Port);
1439 pAC->GIni.GP[Port].PState = SK_PRT_RESET;
1441 } /* SkMacHardRst */
1444 /******************************************************************************
1446 * SkXmInitMac() - Initialize the XMAC II
1449 * Initialize the XMAC of the specified port.
1450 * The XMAC must be reset or stopped before calling this function.
1453 * The XMAC's Rx and Tx state machine is still disabled when returning.
1459 SK_AC *pAC, /* adapter context */
1460 SK_IOC IoC, /* IO context */
1461 int Port) /* Port Index (MAC_1 + n) */
1468 pPrt = &pAC->GIni.GP[Port];
1470 if (pPrt->PState == SK_PRT_STOP) {
1471 /* Port State: SK_PRT_STOP */
1472 /* Verify that the reset bit is cleared */
1473 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1475 if ((SWord & MFF_SET_MAC_RST) != 0) {
1476 /* PState does not match HW state */
1477 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1479 pPrt->PState = SK_PRT_RESET;
1483 if (pPrt->PState == SK_PRT_RESET) {
1486 * Note: The SW reset is self clearing, therefore there is
1487 * nothing to do here.
1489 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1491 /* Ensure that XMAC reset release is done (errata from LReinbold?) */
1492 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1494 /* Clear PHY reset */
1495 if (pPrt->PhyType != SK_PHY_XMAC) {
1497 SK_IN32(IoC, B2_GP_IO, &Reg);
1500 Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */
1503 Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */
1505 SK_OUT32(IoC, B2_GP_IO, Reg);
1507 /* Enable GMII interface */
1508 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
1510 /* read Id from external PHY (all have the same address) */
1511 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1514 * Optimize MDIO transfer by suppressing preamble.
1515 * Must be done AFTER first access to BCOM chip.
1517 XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
1519 XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1521 if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1523 * Workaround BCOM Errata for the C0 type.
1524 * Write magic patterns to reserved registers.
1527 while (BcomRegC0Hack[i].PhyReg != 0) {
1528 SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1529 BcomRegC0Hack[i].PhyVal);
1533 else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1535 * Workaround BCOM Errata for the A1 type.
1536 * Write magic patterns to reserved registers.
1539 while (BcomRegA1Hack[i].PhyReg != 0) {
1540 SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1541 BcomRegA1Hack[i].PhyVal);
1547 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1548 * Disable Power Management after reset.
1550 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
1552 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1553 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
1555 /* PHY LED initialization is done in SkGeXmitLED() */
1558 /* Dummy read the Interrupt source register */
1559 XM_IN16(IoC, Port, XM_ISRC, &SWord);
1562 * The auto-negotiation process starts immediately after
1563 * clearing the reset. The auto-negotiation process should be
1564 * started by the SIRQ, therefore stop it here immediately.
1566 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1569 /* temp. code: enable signal detect */
1570 /* WARNING: do not override GMII setting above */
1571 XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1576 * configure the XMACs Station Address
1577 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1578 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1580 for (i = 0; i < 3; i++) {
1582 * The following 2 statements are together endianess
1583 * independent. Remember this when changing.
1585 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1587 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1590 /* Tx Inter Packet Gap (XM_TX_IPG): use default */
1591 /* Tx High Water Mark (XM_TX_HI_WM): use default */
1592 /* Tx Low Water Mark (XM_TX_LO_WM): use default */
1593 /* Host Request Threshold (XM_HT_THR): use default */
1594 /* Rx Request Threshold (XM_RX_THR): use default */
1595 /* Rx Low Water Mark (XM_RX_LO_WM): use default */
1597 /* configure Rx High Water Mark (XM_RX_HI_WM) */
1598 XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1600 /* Configure Tx Request Threshold */
1601 SWord = SK_XM_THR_SL; /* for single port */
1603 if (pAC->GIni.GIMacsFound > 1) {
1604 switch (pAC->GIni.GIPortUsage) {
1606 SWord = SK_XM_THR_REDL; /* redundant link */
1609 SWord = SK_XM_THR_MULL; /* load balancing */
1612 SWord = SK_XM_THR_JUMBO; /* jumbo frames */
1615 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1619 XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1621 /* setup register defaults for the Tx Command Register */
1622 XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1624 /* setup register defaults for the Rx Command Register */
1625 SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1627 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1628 SWord |= XM_RX_BIG_PK_OK;
1631 if (pPrt->PLinkModeConf == SK_LMODE_HALF) {
1633 * If in manual half duplex mode the other side might be in
1634 * full duplex mode, so ignore if a carrier extension is not seen
1635 * on frames received
1637 SWord |= XM_RX_DIS_CEXT;
1640 XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1643 * setup register defaults for the Mode Register
1644 * - Don't strip error frames to avoid Store & Forward
1646 * - Enable 'Check Station Address' bit
1647 * - Enable 'Check Address Array' bit
1649 XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1652 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1653 * - Enable all bits excepting 'Octets Rx OK Low CntOv'
1654 * and 'Octets Rx OK Hi Cnt Ov'.
1656 XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1659 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1660 * - Enable all bits excepting 'Octets Tx OK Low CntOv'
1661 * and 'Octets Tx OK Hi Cnt Ov'.
1663 XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1666 * Do NOT init XMAC interrupt mask here.
1667 * All interrupts remain disable until link comes up!
1671 * Any additional configuration changes may be done now.
1672 * The last action is to enable the Rx and Tx state machine.
1673 * This should be done after the auto-negotiation process
1674 * has been completed successfully.
1678 /******************************************************************************
1680 * SkGmInitMac() - Initialize the GMAC
1683 * Initialize the GMAC of the specified port.
1684 * The GMAC must be reset or stopped before calling this function.
1687 * The GMAC's Rx and Tx state machine is still disabled when returning.
1693 SK_AC *pAC, /* adapter context */
1694 SK_IOC IoC, /* IO context */
1695 int Port) /* Port Index (MAC_1 + n) */
1702 pPrt = &pAC->GIni.GP[Port];
1704 if (pPrt->PState == SK_PRT_STOP) {
1705 /* Port State: SK_PRT_STOP */
1706 /* Verify that the reset bit is cleared */
1707 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
1709 if ((DWord & GMC_RST_SET) != 0) {
1710 /* PState does not match HW state */
1711 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1713 pPrt->PState = SK_PRT_RESET;
1717 if (pPrt->PState == SK_PRT_RESET) {
1718 /* set GPHY Control reset */
1719 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1721 /* set GMAC Control reset */
1722 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1724 /* clear GMAC Control reset */
1725 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
1727 /* set GMAC Control reset */
1728 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1730 /* set HWCFG_MODE */
1731 DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
1732 GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
1733 (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
1734 GPC_HWCFG_GMII_FIB);
1736 /* set GPHY Control reset */
1737 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
1739 /* release GPHY Control reset */
1740 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
1742 /* clear GMAC Control reset */
1743 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
1745 /* Dummy read the Interrupt source register */
1746 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
1749 /* read Id from PHY */
1750 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
1752 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1756 (void)SkGmResetCounter(pAC, IoC, Port);
1760 /* speed settings */
1761 switch (pPrt->PLinkSpeed) {
1762 case SK_LSPEED_AUTO:
1763 case SK_LSPEED_1000MBPS:
1764 SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1766 case SK_LSPEED_100MBPS:
1767 SWord |= GM_GPCR_SPEED_100;
1769 case SK_LSPEED_10MBPS:
1773 /* duplex settings */
1774 if (pPrt->PLinkMode != SK_LMODE_HALF) {
1775 /* set full duplex */
1776 SWord |= GM_GPCR_DUP_FULL;
1779 /* flow control settings */
1780 switch (pPrt->PFlowCtrlMode) {
1781 case SK_FLOW_MODE_NONE:
1782 /* disable auto-negotiation for flow-control */
1783 SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS;
1785 case SK_FLOW_MODE_LOC_SEND:
1786 SWord |= GM_GPCR_FC_RX_DIS;
1788 case SK_FLOW_MODE_SYMMETRIC:
1790 case SK_FLOW_MODE_SYM_OR_REM:
1791 /* enable auto-negotiation for flow-control and */
1792 /* enable Rx and Tx of pause frames */
1796 /* Auto-negotiation ? */
1797 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1798 /* disable auto-update for speed, duplex and flow-control */
1799 SWord |= GM_GPCR_AU_ALL_DIS;
1802 /* setup General Purpose Control Register */
1803 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1805 /* setup Transmit Control Register */
1806 GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR);
1808 /* setup Receive Control Register */
1809 GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1812 /* setup Transmit Flow Control Register */
1813 GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1815 /* setup Transmit Parameter Register */
1817 GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1820 SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26);
1822 GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1824 /* configure the Serial Mode Register */
1826 GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1829 SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH;
1831 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1832 /* enable jumbo mode (Max. Frame Length = 9018) */
1833 SWord |= GM_SMOD_JUMBO_ENA;
1836 GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
1839 * configure the GMACs Station Addresses
1840 * in PROM you can find our addresses at:
1841 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1842 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1843 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1846 for (i = 0; i < 3; i++) {
1848 * The following 2 statements are together endianess
1849 * independent. Remember this when changing.
1851 /* physical address: will be used for pause frames */
1852 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1855 /* WA for deviation #16 */
1856 if (pAC->GIni.GIChipRev == 0) {
1857 /* swap the address bytes */
1858 SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
1860 /* write to register in reversed order */
1861 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
1864 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1867 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1868 #endif /* WA_DEV_16 */
1870 /* virtual address: will be used for data */
1871 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
1873 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
1875 /* reset Multicast filtering Hash registers 1-3 */
1876 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
1879 /* reset Multicast filtering Hash register 4 */
1880 GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
1882 /* enable interrupt mask for counter overflows */
1883 GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
1884 GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
1885 GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
1887 /* read General Purpose Status */
1888 GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
1890 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1891 ("MAC Stat Reg=0x%04X\n", SWord));
1894 c_print("MAC Stat Reg=0x%04X\n", SWord);
1895 #endif /* SK_DIAG */
1900 /******************************************************************************
1902 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1905 * This function initializes the XMACs Duplex Mode.
1906 * It should be called after successfully finishing
1907 * the Auto-negotiation Process
1913 SK_AC *pAC, /* adapter context */
1914 SK_IOC IoC, /* IO context */
1915 int Port) /* Port Index (MAC_1 + n) */
1917 switch (pAC->GIni.GP[Port].PLinkModeStatus) {
1918 case SK_LMODE_STAT_AUTOHALF:
1919 case SK_LMODE_STAT_HALF:
1920 /* Configuration Actions for Half Duplex Mode */
1922 * XM_BURST = default value. We are probable not quick
1923 * enough at the 'XMAC' bus to burst 8kB.
1924 * The XMAC stops bursting if no transmit frames
1925 * are available or the burst limit is exceeded.
1927 /* XM_TX_RT_LIM = default value (15) */
1928 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
1930 case SK_LMODE_STAT_AUTOFULL:
1931 case SK_LMODE_STAT_FULL:
1932 /* Configuration Actions for Full Duplex Mode */
1934 * The duplex mode is configured by the PHY,
1935 * therefore it seems to be that there is nothing
1939 case SK_LMODE_STAT_UNKNOWN:
1941 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
1944 } /* SkXmInitDupMd */
1947 /******************************************************************************
1949 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1952 * This function initializes the Pause Mode which should
1953 * be used for this port.
1954 * It should be called after successfully finishing
1955 * the Auto-negotiation Process
1960 void SkXmInitPauseMd(
1961 SK_AC *pAC, /* adapter context */
1962 SK_IOC IoC, /* IO context */
1963 int Port) /* Port Index (MAC_1 + n) */
1969 pPrt = &pAC->GIni.GP[Port];
1971 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
1973 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
1974 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1976 /* Disable Pause Frame Reception */
1977 Word |= XM_MMU_IGN_PF;
1981 * enabling pause frame reception is required for 1000BT
1982 * because the XMAC is not reset if the link is going down
1984 /* Enable Pause Frame Reception */
1985 Word &= ~XM_MMU_IGN_PF;
1988 XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
1990 XM_IN32(IoC, Port, XM_MODE, &DWord);
1992 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
1993 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1996 * Configure Pause Frame Generation
1997 * Use internal and external Pause Frame Generation.
1998 * Sending pause frames is edge triggered.
1999 * Send a Pause frame with the maximum pause time if
2000 * internal oder external FIFO full condition occurs.
2001 * Send a zero pause time frame to re-start transmission.
2004 /* XM_PAUSE_DA = '010000C28001' (default) */
2006 /* XM_MAC_PTIME = 0xffff (maximum) */
2007 /* remember this value is defined in big endian (!) */
2008 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
2010 /* Set Pause Mode in Mode Register */
2011 DWord |= XM_PAUSE_MODE;
2013 /* Set Pause Mode in MAC Rx FIFO */
2014 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
2018 * disable pause frame generation is required for 1000BT
2019 * because the XMAC is not reset if the link is going down
2021 /* Disable Pause Mode in Mode Register */
2022 DWord &= ~XM_PAUSE_MODE;
2024 /* Disable Pause Mode in MAC Rx FIFO */
2025 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
2028 XM_OUT32(IoC, Port, XM_MODE, DWord);
2029 } /* SkXmInitPauseMd*/
2032 /******************************************************************************
2034 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
2036 * Description: initializes all the XMACs Phy registers
2043 static void SkXmInitPhyXmac(
2044 SK_AC *pAC, /* adapter context */
2045 SK_IOC IoC, /* IO context */
2046 int Port, /* Port Index (MAC_1 + n) */
2047 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2052 pPrt = &pAC->GIni.GP[Port];
2055 /* Auto-negotiation ? */
2056 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2057 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2058 ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
2059 /* Set DuplexMode in Config register */
2060 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2061 Ctrl |= PHY_CT_DUP_MD;
2065 * Do NOT enable Auto-negotiation here. This would hold
2066 * the link down because no IDLEs are transmitted
2070 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2071 ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
2072 /* Set Auto-negotiation advertisement */
2074 /* Set Full/half duplex capabilities */
2075 switch (pPrt->PLinkMode) {
2076 case SK_LMODE_AUTOHALF:
2077 Ctrl |= PHY_X_AN_HD;
2079 case SK_LMODE_AUTOFULL:
2080 Ctrl |= PHY_X_AN_FD;
2082 case SK_LMODE_AUTOBOTH:
2083 Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
2086 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2090 switch (pPrt->PFlowCtrlMode) {
2091 case SK_FLOW_MODE_NONE:
2092 Ctrl |= PHY_X_P_NO_PAUSE;
2094 case SK_FLOW_MODE_LOC_SEND:
2095 Ctrl |= PHY_X_P_ASYM_MD;
2097 case SK_FLOW_MODE_SYMMETRIC:
2098 Ctrl |= PHY_X_P_SYM_MD;
2100 case SK_FLOW_MODE_SYM_OR_REM:
2101 Ctrl |= PHY_X_P_BOTH_MD;
2104 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2108 /* Write AutoNeg Advertisement Register */
2109 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
2111 /* Restart Auto-negotiation */
2112 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
2116 /* Set the Phy Loopback bit, too */
2117 Ctrl |= PHY_CT_LOOP;
2120 /* Write to the Phy control register */
2121 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
2122 } /* SkXmInitPhyXmac */
2125 /******************************************************************************
2127 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
2129 * Description: initializes all the Broadcom Phy registers
2136 static void SkXmInitPhyBcom(
2137 SK_AC *pAC, /* adapter context */
2138 SK_IOC IoC, /* IO context */
2139 int Port, /* Port Index (MAC_1 + n) */
2140 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2149 Ctrl1 = PHY_CT_SP1000;
2151 Ctrl3 = PHY_SEL_TYPE;
2152 Ctrl4 = PHY_B_PEC_EN_LTR;
2153 Ctrl5 = PHY_B_AC_TX_TST;
2155 pPrt = &pAC->GIni.GP[Port];
2157 /* manually Master/Slave ? */
2158 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2159 Ctrl2 |= PHY_B_1000C_MSE;
2161 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2162 Ctrl2 |= PHY_B_1000C_MSC;
2165 /* Auto-negotiation ? */
2166 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2167 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2168 ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
2169 /* Set DuplexMode in Config register */
2170 Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2172 /* Determine Master/Slave manually if not already done */
2173 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2174 Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
2178 * Do NOT enable Auto-negotiation here. This would hold
2179 * the link down because no IDLES are transmitted
2183 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2184 ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
2185 /* Set Auto-negotiation advertisement */
2188 * Workaround BCOM Errata #1 for the C5 type.
2189 * 1000Base-T Link Acquisition Failure in Slave Mode
2190 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
2192 Ctrl2 |= PHY_B_1000C_RD;
2194 /* Set Full/half duplex capabilities */
2195 switch (pPrt->PLinkMode) {
2196 case SK_LMODE_AUTOHALF:
2197 Ctrl2 |= PHY_B_1000C_AHD;
2199 case SK_LMODE_AUTOFULL:
2200 Ctrl2 |= PHY_B_1000C_AFD;
2202 case SK_LMODE_AUTOBOTH:
2203 Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
2206 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2210 switch (pPrt->PFlowCtrlMode) {
2211 case SK_FLOW_MODE_NONE:
2212 Ctrl3 |= PHY_B_P_NO_PAUSE;
2214 case SK_FLOW_MODE_LOC_SEND:
2215 Ctrl3 |= PHY_B_P_ASYM_MD;
2217 case SK_FLOW_MODE_SYMMETRIC:
2218 Ctrl3 |= PHY_B_P_SYM_MD;
2220 case SK_FLOW_MODE_SYM_OR_REM:
2221 Ctrl3 |= PHY_B_P_BOTH_MD;
2224 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2228 /* Restart Auto-negotiation */
2229 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2232 /* Initialize LED register here? */
2233 /* No. Please do it in SkDgXmitLed() (if required) and swap
2234 init order of LEDs and XMAC. (MAl) */
2236 /* Write 1000Base-T Control Register */
2237 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2238 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2239 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2241 /* Write AutoNeg Advertisement Register */
2242 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2243 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2244 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
2247 /* Set the Phy Loopback bit, too */
2248 Ctrl1 |= PHY_CT_LOOP;
2251 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2252 /* configure FIFO to high latency for transmission of ext. packets */
2253 Ctrl4 |= PHY_B_PEC_HIGH_LA;
2255 /* configure reception of extended packets */
2256 Ctrl5 |= PHY_B_AC_LONG_PACK;
2258 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2261 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2262 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
2264 /* Write to the Phy control register */
2265 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2266 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2267 ("PHY Control Reg=0x%04X\n", Ctrl1));
2268 } /* SkXmInitPhyBcom */
2271 /******************************************************************************
2273 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2275 * Description: initializes all the Marvell Phy registers
2282 static void SkGmInitPhyMarv(
2283 SK_AC *pAC, /* adapter context */
2284 SK_IOC IoC, /* IO context */
2285 int Port, /* Port Index (MAC_1 + n) */
2286 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2300 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2304 pPrt = &pAC->GIni.GP[Port];
2306 /* Auto-negotiation ? */
2307 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2315 /* Read Ext. PHY Specific Control */
2316 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2318 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2319 PHY_M_EC_MAC_S_MSK);
2321 ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) |
2322 PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
2324 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2325 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2326 ("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl));
2328 /* Read PHY Control */
2329 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2331 /* Assert software reset */
2332 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL,
2333 (SK_U16)(PhyCtrl | PHY_CT_RESET));
2337 PhyCtrl = 0 /* PHY_CT_COL_TST */;
2339 AutoNegAdv = PHY_SEL_TYPE;
2341 /* manually Master/Slave ? */
2342 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2343 /* enable Manual Master/Slave */
2344 C1000BaseT |= PHY_M_1000C_MSE;
2346 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2347 C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
2351 /* Auto-negotiation ? */
2353 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2354 ("InitPhyMarv: no auto-negotiation Port %d\n", Port));
2356 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2357 /* Set Full Duplex Mode */
2358 PhyCtrl |= PHY_CT_DUP_MD;
2361 /* Set Master/Slave manually if not already done */
2362 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2363 C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
2367 switch (pPrt->PLinkSpeed) {
2368 case SK_LSPEED_AUTO:
2369 case SK_LSPEED_1000MBPS:
2370 PhyCtrl |= PHY_CT_SP1000;
2372 case SK_LSPEED_100MBPS:
2373 PhyCtrl |= PHY_CT_SP100;
2375 case SK_LSPEED_10MBPS:
2378 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2383 PhyCtrl |= PHY_CT_RESET;
2386 * Do NOT enable Auto-negotiation here. This would hold
2387 * the link down because no IDLES are transmitted
2391 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2392 ("InitPhyMarv: with auto-negotiation Port %d\n", Port));
2394 PhyCtrl |= PHY_CT_ANE;
2396 if (pAC->GIni.GICopperType) {
2397 /* Set Speed capabilities */
2398 switch (pPrt->PLinkSpeed) {
2399 case SK_LSPEED_AUTO:
2400 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2401 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2402 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2404 case SK_LSPEED_1000MBPS:
2405 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2407 case SK_LSPEED_100MBPS:
2408 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2409 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2411 case SK_LSPEED_10MBPS:
2412 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2415 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2419 /* Set Full/half duplex capabilities */
2420 switch (pPrt->PLinkMode) {
2421 case SK_LMODE_AUTOHALF:
2422 C1000BaseT &= ~PHY_M_1000C_AFD;
2423 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2425 case SK_LMODE_AUTOFULL:
2426 C1000BaseT &= ~PHY_M_1000C_AHD;
2427 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2429 case SK_LMODE_AUTOBOTH:
2432 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2436 /* Set Auto-negotiation advertisement */
2437 switch (pPrt->PFlowCtrlMode) {
2438 case SK_FLOW_MODE_NONE:
2439 AutoNegAdv |= PHY_B_P_NO_PAUSE;
2441 case SK_FLOW_MODE_LOC_SEND:
2442 AutoNegAdv |= PHY_B_P_ASYM_MD;
2444 case SK_FLOW_MODE_SYMMETRIC:
2445 AutoNegAdv |= PHY_B_P_SYM_MD;
2447 case SK_FLOW_MODE_SYM_OR_REM:
2448 AutoNegAdv |= PHY_B_P_BOTH_MD;
2451 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2455 else { /* special defines for FIBER (88E1011S only) */
2457 /* Set Full/half duplex capabilities */
2458 switch (pPrt->PLinkMode) {
2459 case SK_LMODE_AUTOHALF:
2460 AutoNegAdv |= PHY_M_AN_1000X_AHD;
2462 case SK_LMODE_AUTOFULL:
2463 AutoNegAdv |= PHY_M_AN_1000X_AFD;
2465 case SK_LMODE_AUTOBOTH:
2466 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2469 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2473 /* Set Auto-negotiation advertisement */
2474 switch (pPrt->PFlowCtrlMode) {
2475 case SK_FLOW_MODE_NONE:
2476 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2478 case SK_FLOW_MODE_LOC_SEND:
2479 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2481 case SK_FLOW_MODE_SYMMETRIC:
2482 AutoNegAdv |= PHY_M_P_SYM_MD_X;
2484 case SK_FLOW_MODE_SYM_OR_REM:
2485 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2488 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2494 /* Restart Auto-negotiation */
2495 PhyCtrl |= PHY_CT_RE_CFG;
2501 * E-mail from Gu Lin (08-03-2002):
2504 /* Program PHY register 30 as 16'h0708 for simulation speed up */
2505 SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708);
2511 /* Write 1000Base-T Control Register */
2512 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2513 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2514 ("1000B-T Ctrl=0x%04X\n", C1000BaseT));
2516 /* Write AutoNeg Advertisement Register */
2517 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2518 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2519 ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv));
2523 /* Set the PHY Loopback bit */
2524 PhyCtrl |= PHY_CT_LOOP;
2526 /* Program PHY register 16 as 16'h0400 to force link good */
2527 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2530 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2531 /* Write Ext. PHY Specific Control */
2532 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2533 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2536 else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2537 /* Write PHY Specific Control */
2538 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK);
2543 /* Write to the PHY Control register */
2544 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2550 LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2552 #ifdef ACT_LED_BLINK
2553 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2554 #endif /* ACT_LED_BLINK */
2556 #ifdef DUP_LED_NORMAL
2557 LedCtrl |= PHY_M_LEDC_DP_CTRL;
2558 #endif /* DUP_LED_NORMAL */
2560 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2565 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2566 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2567 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2568 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2569 #endif /* SK_DIAG */
2572 /* Read PHY Control */
2573 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2574 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2575 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2577 /* Read 1000Base-T Control Register */
2578 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2579 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2580 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
2582 /* Read AutoNeg Advertisement Register */
2583 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2584 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2585 ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv));
2587 /* Read Ext. PHY Specific Control */
2588 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2589 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2590 ("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2592 /* Read PHY Status */
2593 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2594 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2595 ("PHY Stat Reg.=0x%04X\n", PhyStat));
2596 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2597 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2598 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
2600 /* Read PHY Specific Status */
2601 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2602 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2603 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
2607 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2608 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2609 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2610 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2611 c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2612 c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2613 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2614 #endif /* SK_DIAG */
2616 } /* SkGmInitPhyMarv */
2620 /******************************************************************************
2622 * SkXmInitPhyLone() - Initialize the Level One Phy registers
2624 * Description: initializes all the Level One Phy registers
2631 static void SkXmInitPhyLone(
2632 SK_AC *pAC, /* adapter context */
2633 SK_IOC IoC, /* IO context */
2634 int Port, /* Port Index (MAC_1 + n) */
2635 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2642 Ctrl1 = PHY_CT_SP1000;
2644 Ctrl3 = PHY_SEL_TYPE;
2646 pPrt = &pAC->GIni.GP[Port];
2648 /* manually Master/Slave ? */
2649 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2650 Ctrl2 |= PHY_L_1000C_MSE;
2652 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2653 Ctrl2 |= PHY_L_1000C_MSC;
2656 /* Auto-negotiation ? */
2657 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2659 * level one spec say: "1000Mbps: manual mode not allowed"
2660 * but lets see what happens...
2662 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2663 ("InitPhyLone: no auto-negotiation Port %d\n", Port));
2664 /* Set DuplexMode in Config register */
2665 Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2667 /* Determine Master/Slave manually if not already done */
2668 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2669 Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
2673 * Do NOT enable Auto-negotiation here. This would hold
2674 * the link down because no IDLES are transmitted
2678 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2679 ("InitPhyLone: with auto-negotiation Port %d\n", Port));
2680 /* Set Auto-negotiation advertisement */
2682 /* Set Full/half duplex capabilities */
2683 switch (pPrt->PLinkMode) {
2684 case SK_LMODE_AUTOHALF:
2685 Ctrl2 |= PHY_L_1000C_AHD;
2687 case SK_LMODE_AUTOFULL:
2688 Ctrl2 |= PHY_L_1000C_AFD;
2690 case SK_LMODE_AUTOBOTH:
2691 Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2694 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2698 switch (pPrt->PFlowCtrlMode) {
2699 case SK_FLOW_MODE_NONE:
2700 Ctrl3 |= PHY_L_P_NO_PAUSE;
2702 case SK_FLOW_MODE_LOC_SEND:
2703 Ctrl3 |= PHY_L_P_ASYM_MD;
2705 case SK_FLOW_MODE_SYMMETRIC:
2706 Ctrl3 |= PHY_L_P_SYM_MD;
2708 case SK_FLOW_MODE_SYM_OR_REM:
2709 Ctrl3 |= PHY_L_P_BOTH_MD;
2712 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2716 /* Restart Auto-negotiation */
2717 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2721 /* Initialize LED register here ? */
2722 /* No. Please do it in SkDgXmitLed() (if required) and swap
2723 init order of LEDs and XMAC. (MAl) */
2725 /* Write 1000Base-T Control Register */
2726 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2727 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2728 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2730 /* Write AutoNeg Advertisement Register */
2731 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2732 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2733 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
2737 /* Set the Phy Loopback bit, too */
2738 Ctrl1 |= PHY_CT_LOOP;
2741 /* Write to the Phy control register */
2742 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2743 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2744 ("PHY Control Reg=0x%04X\n", Ctrl1));
2745 } /* SkXmInitPhyLone */
2748 /******************************************************************************
2750 * SkXmInitPhyNat() - Initialize the National Phy registers
2752 * Description: initializes all the National Phy registers
2759 static void SkXmInitPhyNat(
2760 SK_AC *pAC, /* adapter context */
2761 SK_IOC IoC, /* IO context */
2762 int Port, /* Port Index (MAC_1 + n) */
2763 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2765 /* todo: National */
2766 } /* SkXmInitPhyNat */
2767 #endif /* OTHER_PHY */
2770 /******************************************************************************
2772 * SkMacInitPhy() - Initialize the PHY registers
2774 * Description: calls the Init PHY routines dep. on board type
2782 SK_AC *pAC, /* adapter context */
2783 SK_IOC IoC, /* IO context */
2784 int Port, /* Port Index (MAC_1 + n) */
2785 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2789 pPrt = &pAC->GIni.GP[Port];
2791 switch (pPrt->PhyType) {
2793 SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2796 SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2798 case SK_PHY_MARV_COPPER:
2799 case SK_PHY_MARV_FIBER:
2800 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2804 SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2807 SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2809 #endif /* OTHER_PHY */
2811 } /* SkMacInitPhy */
2815 /******************************************************************************
2817 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
2819 * This function analyses the Interrupt status word. If any of the
2820 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
2823 void SkXmAutoNegLipaXmac(
2824 SK_AC *pAC, /* adapter context */
2825 SK_IOC IoC, /* IO context */
2826 int Port, /* Port Index (MAC_1 + n) */
2827 SK_U16 IStatus) /* Interrupt Status word to analyse */
2831 pPrt = &pAC->GIni.GP[Port];
2833 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2834 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
2836 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2837 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n",
2839 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2841 } /* SkXmAutoNegLipaXmac */
2844 /******************************************************************************
2846 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
2848 * This function analyses the PHY status word.
2849 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
2852 void SkMacAutoNegLipaPhy(
2853 SK_AC *pAC, /* adapter context */
2854 SK_IOC IoC, /* IO context */
2855 int Port, /* Port Index (MAC_1 + n) */
2856 SK_U16 PhyStat) /* PHY Status word to analyse */
2860 pPrt = &pAC->GIni.GP[Port];
2862 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2863 (PhyStat & PHY_ST_AN_OVER) != 0) {
2865 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2866 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\n",
2868 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2870 } /* SkMacAutoNegLipaPhy */
2871 #endif /* SK_DIAG */
2874 /******************************************************************************
2876 * SkXmAutoNegDoneXmac() - Auto-negotiation handling
2879 * This function handles the auto-negotiation if the Done bit is set.
2883 * SK_AND_DUP_CAP Duplex capability error happened
2884 * SK_AND_OTHER Other error happened
2886 static int SkXmAutoNegDoneXmac(
2887 SK_AC *pAC, /* adapter context */
2888 SK_IOC IoC, /* IO context */
2889 int Port) /* Port Index (MAC_1 + n) */
2892 SK_U16 ResAb; /* Resolved Ability */
2893 SK_U16 LPAb; /* Link Partner Ability */
2895 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2896 ("AutoNegDoneXmac, Port %d\n",Port));
2898 pPrt = &pAC->GIni.GP[Port];
2900 /* Get PHY parameters */
2901 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
2902 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
2904 if ((LPAb & PHY_X_AN_RFB) != 0) {
2905 /* At least one of the remote fault bit is set */
2907 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2908 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2909 pPrt->PAutoNegFail = SK_TRUE;
2910 return(SK_AND_OTHER);
2913 /* Check Duplex mismatch */
2914 if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
2915 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
2917 else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
2918 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
2922 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2923 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2924 pPrt->PAutoNegFail = SK_TRUE;
2925 return(SK_AND_DUP_CAP);
2928 /* Check PAUSE mismatch */
2929 /* We are NOT using chapter 4.23 of the Xaqti manual */
2930 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2931 if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
2932 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
2933 (LPAb & PHY_X_P_SYM_MD) != 0) {
2934 /* Symmetric PAUSE */
2935 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2937 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
2938 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
2939 /* Enable PAUSE receive, disable PAUSE transmit */
2940 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2942 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
2943 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
2944 /* Disable PAUSE receive, enable PAUSE transmit */
2945 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2948 /* PAUSE mismatch -> no PAUSE */
2949 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2951 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
2954 } /* SkXmAutoNegDoneXmac */
2957 /******************************************************************************
2959 * SkXmAutoNegDoneBcom() - Auto-negotiation handling
2962 * This function handles the auto-negotiation if the Done bit is set.
2966 * SK_AND_DUP_CAP Duplex capability error happened
2967 * SK_AND_OTHER Other error happened
2969 static int SkXmAutoNegDoneBcom(
2970 SK_AC *pAC, /* adapter context */
2971 SK_IOC IoC, /* IO context */
2972 int Port) /* Port Index (MAC_1 + n) */
2975 SK_U16 LPAb; /* Link Partner Ability */
2976 SK_U16 AuxStat; /* Auxiliary Status */
2980 SK_U16 ResAb; /* Resolved Ability */
2983 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2984 ("AutoNegDoneBcom, Port %d\n", Port));
2985 pPrt = &pAC->GIni.GP[Port];
2987 /* Get PHY parameters */
2988 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
2991 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
2994 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
2996 if ((LPAb & PHY_B_AN_RF) != 0) {
2997 /* Remote fault bit is set: Error */
2998 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2999 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3000 pPrt->PAutoNegFail = SK_TRUE;
3001 return(SK_AND_OTHER);
3004 /* Check Duplex mismatch */
3005 if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
3006 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3008 else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
3009 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3013 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3014 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3015 pPrt->PAutoNegFail = SK_TRUE;
3016 return(SK_AND_DUP_CAP);
3021 /* Check Master/Slave resolution */
3022 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3023 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3024 ("Master/Slave Fault Port %d\n", Port));
3025 pPrt->PAutoNegFail = SK_TRUE;
3026 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3027 return(SK_AND_OTHER);
3030 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3031 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
3034 /* Check PAUSE mismatch */
3035 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3036 if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
3037 /* Symmetric PAUSE */
3038 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3040 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
3041 /* Enable PAUSE receive, disable PAUSE transmit */
3042 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3044 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
3045 /* Disable PAUSE receive, enable PAUSE transmit */
3046 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3049 /* PAUSE mismatch -> no PAUSE */
3050 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3052 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3055 } /* SkXmAutoNegDoneBcom */
3058 /******************************************************************************
3060 * SkGmAutoNegDoneMarv() - Auto-negotiation handling
3063 * This function handles the auto-negotiation if the Done bit is set.
3067 * SK_AND_DUP_CAP Duplex capability error happened
3068 * SK_AND_OTHER Other error happened
3070 static int SkGmAutoNegDoneMarv(
3071 SK_AC *pAC, /* adapter context */
3072 SK_IOC IoC, /* IO context */
3073 int Port) /* Port Index (MAC_1 + n) */
3076 SK_U16 LPAb; /* Link Partner Ability */
3077 SK_U16 ResAb; /* Resolved Ability */
3078 SK_U16 AuxStat; /* Auxiliary Status */
3080 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3081 ("AutoNegDoneMarv, Port %d\n", Port));
3082 pPrt = &pAC->GIni.GP[Port];
3084 /* Get PHY parameters */
3085 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
3087 if ((LPAb & PHY_M_AN_RF) != 0) {
3088 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3089 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3090 pPrt->PAutoNegFail = SK_TRUE;
3091 return(SK_AND_OTHER);
3094 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
3096 /* Check Master/Slave resolution */
3097 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3098 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3099 ("Master/Slave Fault Port %d\n", Port));
3100 pPrt->PAutoNegFail = SK_TRUE;
3101 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3102 return(SK_AND_OTHER);
3105 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3106 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
3108 /* Read PHY Specific Status */
3109 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
3111 /* Check Speed & Duplex resolved */
3112 if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
3113 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3114 ("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port));
3115 pPrt->PAutoNegFail = SK_TRUE;
3116 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
3117 return(SK_AND_DUP_CAP);
3120 if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
3121 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3124 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3127 /* Check PAUSE mismatch */
3128 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3129 if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
3130 /* Symmetric PAUSE */
3131 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3133 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
3134 /* Enable PAUSE receive, disable PAUSE transmit */
3135 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3137 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
3138 /* Disable PAUSE receive, enable PAUSE transmit */
3139 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3142 /* PAUSE mismatch -> no PAUSE */
3143 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3146 /* set used link speed */
3147 switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
3148 case (unsigned)PHY_M_PS_SPEED_1000:
3149 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3151 case PHY_M_PS_SPEED_100:
3152 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
3155 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
3159 } /* SkGmAutoNegDoneMarv */
3163 /******************************************************************************
3165 * SkXmAutoNegDoneLone() - Auto-negotiation handling
3168 * This function handles the auto-negotiation if the Done bit is set.
3172 * SK_AND_DUP_CAP Duplex capability error happened
3173 * SK_AND_OTHER Other error happened
3175 static int SkXmAutoNegDoneLone(
3176 SK_AC *pAC, /* adapter context */
3177 SK_IOC IoC, /* IO context */
3178 int Port) /* Port Index (MAC_1 + n) */
3181 SK_U16 ResAb; /* Resolved Ability */
3182 SK_U16 LPAb; /* Link Partner Ability */
3183 SK_U16 QuickStat; /* Auxiliary Status */
3185 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3186 ("AutoNegDoneLone, Port %d\n",Port));
3187 pPrt = &pAC->GIni.GP[Port];
3189 /* Get PHY parameters */
3190 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
3191 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
3192 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
3194 if ((LPAb & PHY_L_AN_RF) != 0) {
3195 /* Remote fault bit is set */
3197 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3198 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3199 pPrt->PAutoNegFail = SK_TRUE;
3200 return(SK_AND_OTHER);
3203 /* Check Duplex mismatch */
3204 if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
3205 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3208 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3211 /* Check Master/Slave resolution */
3212 if ((ResAb & PHY_L_1000S_MSF) != 0) {
3214 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3215 ("Master/Slave Fault Port %d\n", Port));
3216 pPrt->PAutoNegFail = SK_TRUE;
3217 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3218 return(SK_AND_OTHER);
3220 else if (ResAb & PHY_L_1000S_MSR) {
3221 pPrt->PMSStatus = SK_MS_STAT_MASTER;
3224 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
3227 /* Check PAUSE mismatch */
3228 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3229 /* we must manually resolve the abilities here */
3230 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3231 switch (pPrt->PFlowCtrlMode) {
3232 case SK_FLOW_MODE_NONE:
3235 case SK_FLOW_MODE_LOC_SEND:
3236 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3237 (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
3238 /* Disable PAUSE receive, enable PAUSE transmit */
3239 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3242 case SK_FLOW_MODE_SYMMETRIC:
3243 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3244 /* Symmetric PAUSE */
3245 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3248 case SK_FLOW_MODE_SYM_OR_REM:
3249 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3250 PHY_L_QS_AS_PAUSE) {
3251 /* Enable PAUSE receive, disable PAUSE transmit */
3252 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3254 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3255 /* Symmetric PAUSE */
3256 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3260 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3265 } /* SkXmAutoNegDoneLone */
3268 /******************************************************************************
3270 * SkXmAutoNegDoneNat() - Auto-negotiation handling
3273 * This function handles the auto-negotiation if the Done bit is set.
3277 * SK_AND_DUP_CAP Duplex capability error happened
3278 * SK_AND_OTHER Other error happened
3280 static int SkXmAutoNegDoneNat(
3281 SK_AC *pAC, /* adapter context */
3282 SK_IOC IoC, /* IO context */
3283 int Port) /* Port Index (MAC_1 + n) */
3285 /* todo: National */
3287 } /* SkXmAutoNegDoneNat */
3288 #endif /* OTHER_PHY */
3291 /******************************************************************************
3293 * SkMacAutoNegDone() - Auto-negotiation handling
3295 * Description: calls the auto-negotiation done routines dep. on board type
3299 * SK_AND_DUP_CAP Duplex capability error happened
3300 * SK_AND_OTHER Other error happened
3302 int SkMacAutoNegDone(
3303 SK_AC *pAC, /* adapter context */
3304 SK_IOC IoC, /* IO context */
3305 int Port) /* Port Index (MAC_1 + n) */
3310 pPrt = &pAC->GIni.GP[Port];
3312 switch (pPrt->PhyType) {
3314 Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3317 Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3319 case SK_PHY_MARV_COPPER:
3320 case SK_PHY_MARV_FIBER:
3321 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3325 Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3328 Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3330 #endif /* OTHER_PHY */
3332 return(SK_AND_OTHER);
3335 if (Rtv != SK_AND_OK) {
3339 /* We checked everything and may now enable the link */
3340 pPrt->PAutoNegFail = SK_FALSE;
3342 SkMacRxTxEnable(pAC, IoC, Port);
3345 } /* SkMacAutoNegDone */
3348 /******************************************************************************
3350 * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3353 * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3358 static void SkXmSetRxTxEn(
3359 SK_AC *pAC, /* Adapter Context */
3360 SK_IOC IoC, /* IO context */
3361 int Port, /* Port Index (MAC_1 + n) */
3362 int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3366 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3368 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3369 case SK_MAC_LOOPB_ON:
3370 Word |= XM_MMU_MAC_LB;
3372 case SK_MAC_LOOPB_OFF:
3373 Word &= ~XM_MMU_MAC_LB;
3377 switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
3378 case SK_PHY_LOOPB_ON:
3379 Word |= XM_MMU_GMII_LOOP;
3381 case SK_PHY_LOOPB_OFF:
3382 Word &= ~XM_MMU_GMII_LOOP;
3386 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3387 case SK_PHY_FULLD_ON:
3388 Word |= XM_MMU_GMII_FD;
3390 case SK_PHY_FULLD_OFF:
3391 Word &= ~XM_MMU_GMII_FD;
3395 XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3397 /* dummy read to ensure writing */
3398 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3400 } /* SkXmSetRxTxEn */
3403 /******************************************************************************
3405 * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3408 * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3413 static void SkGmSetRxTxEn(
3414 SK_AC *pAC, /* Adapter Context */
3415 SK_IOC IoC, /* IO context */
3416 int Port, /* Port Index (MAC_1 + n) */
3417 int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */
3421 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3423 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3424 case SK_MAC_LOOPB_ON:
3425 Ctrl |= GM_GPCR_LOOP_ENA;
3427 case SK_MAC_LOOPB_OFF:
3428 Ctrl &= ~GM_GPCR_LOOP_ENA;
3432 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3433 case SK_PHY_FULLD_ON:
3434 Ctrl |= GM_GPCR_DUP_FULL;
3436 case SK_PHY_FULLD_OFF:
3437 Ctrl &= ~GM_GPCR_DUP_FULL;
3441 GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3443 /* dummy read to ensure writing */
3444 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3446 } /* SkGmSetRxTxEn */
3449 /******************************************************************************
3451 * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3453 * Description: calls the Special Set Rx/Tx Enable routines dep. on board type
3457 void SkMacSetRxTxEn(
3458 SK_AC *pAC, /* Adapter Context */
3459 SK_IOC IoC, /* IO context */
3460 int Port, /* Port Index (MAC_1 + n) */
3463 if (pAC->GIni.GIGenesis) {
3465 SkXmSetRxTxEn(pAC, IoC, Port, Para);
3469 SkGmSetRxTxEn(pAC, IoC, Port, Para);
3472 } /* SkMacSetRxTxEn */
3475 /******************************************************************************
3477 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3479 * Description: enables Rx/Tx dep. on board type
3483 * != 0 Error happened
3485 int SkMacRxTxEnable(
3486 SK_AC *pAC, /* adapter context */
3487 SK_IOC IoC, /* IO context */
3488 int Port) /* Port Index (MAC_1 + n) */
3491 SK_U16 Reg; /* 16-bit register value */
3492 SK_U16 IntMask; /* MAC interrupt mask */
3495 pPrt = &pAC->GIni.GP[Port];
3497 if (!pPrt->PHWLinkUp) {
3498 /* The Hardware link is NOT up */
3502 if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3503 pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3504 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3505 pPrt->PAutoNegFail) {
3506 /* Auto-negotiation is not done or failed */
3510 if (pAC->GIni.GIGenesis) {
3511 /* set Duplex Mode and Pause Mode */
3512 SkXmInitDupMd(pAC, IoC, Port);
3514 SkXmInitPauseMd(pAC, IoC, Port);
3517 * Initialize the Interrupt Mask Register. Default IRQs are...
3518 * - Link Asynchronous Event
3519 * - Link Partner requests config
3520 * - Auto Negotiation Done
3521 * - Rx Counter Event Overflow
3522 * - Tx Counter Event Overflow
3523 * - Transmit FIFO Underrun
3525 IntMask = XM_DEF_MSK;
3528 /* add IRQ for Receive FIFO Overflow */
3529 IntMask &= ~XM_IS_RXF_OV;
3532 if (pPrt->PhyType != SK_PHY_XMAC) {
3533 /* disable GP0 interrupt bit */
3534 IntMask |= XM_IS_INP_ASS;
3536 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
3538 /* get MMU Command Reg. */
3539 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
3541 if (pPrt->PhyType != SK_PHY_XMAC &&
3542 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3543 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3544 /* set to Full Duplex */
3545 Reg |= XM_MMU_GMII_FD;
3548 switch (pPrt->PhyType) {
3551 * Workaround BCOM Errata (#10523) for all BCom Phys
3552 * Enable Power Management after link up
3554 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3555 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3556 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3557 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
3561 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3565 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3566 /* no interrupts possible from National ??? */
3568 #endif /* OTHER_PHY */
3572 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3576 * Initialize the Interrupt Mask Register. Default IRQs are...
3577 * - Rx Counter Event Overflow
3578 * - Tx Counter Event Overflow
3579 * - Transmit FIFO Underrun
3581 IntMask = GMAC_DEF_MSK;
3584 /* add IRQ for Receive FIFO Overrun */
3585 IntMask |= GM_IS_RX_FF_OR;
3588 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
3590 /* get General Purpose Control */
3591 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
3593 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3594 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3595 /* set to Full Duplex */
3596 Reg |= GM_GPCR_DUP_FULL;
3600 GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3603 /* Enable all PHY interrupts */
3604 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
3610 } /* SkMacRxTxEnable */
3613 /******************************************************************************
3615 * SkMacRxTxDisable() - Disable Receiver and Transmitter
3617 * Description: disables Rx/Tx dep. on board type
3621 void SkMacRxTxDisable(
3622 SK_AC *pAC, /* Adapter Context */
3623 SK_IOC IoC, /* IO context */
3624 int Port) /* Port Index (MAC_1 + n) */
3628 if (pAC->GIni.GIGenesis) {
3630 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3632 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
3634 /* dummy read to ensure writing */
3635 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3639 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3641 GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
3643 /* dummy read to ensure writing */
3644 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3646 } /* SkMacRxTxDisable */
3649 /******************************************************************************
3651 * SkMacIrqDisable() - Disable IRQ from MAC
3653 * Description: sets the IRQ-mask to disable IRQ dep. on board type
3657 void SkMacIrqDisable(
3658 SK_AC *pAC, /* Adapter Context */
3659 SK_IOC IoC, /* IO context */
3660 int Port) /* Port Index (MAC_1 + n) */
3665 pPrt = &pAC->GIni.GP[Port];
3667 if (pAC->GIni.GIGenesis) {
3669 /* disable all XMAC IRQs */
3670 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
3672 /* Disable all PHY interrupts */
3673 switch (pPrt->PhyType) {
3675 /* Make sure that PHY is initialized */
3676 if (pPrt->PState != SK_PRT_RESET) {
3677 /* NOT allowed if BCOM is in RESET state */
3678 /* Workaround BCOM Errata (#10523) all BCom */
3679 /* Disable Power Management if link is down */
3680 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3681 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3682 (SK_U16)(Word | PHY_B_AC_DIS_PM));
3683 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3688 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3692 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3694 #endif /* OTHER_PHY */
3698 /* disable all GMAC IRQs */
3699 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
3702 /* Disable all PHY interrupts */
3703 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3706 } /* SkMacIrqDisable */
3710 /******************************************************************************
3712 * SkXmSendCont() - Enable / Disable Send Continuous Mode
3714 * Description: enable / disable Send Continuous Mode on XMAC
3720 SK_AC *pAC, /* adapter context */
3721 SK_IOC IoC, /* IO context */
3722 int Port, /* Port Index (MAC_1 + n) */
3723 SK_BOOL Enable) /* Enable / Disable */
3727 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3730 MdReg |= XM_MD_TX_CONT;
3733 MdReg &= ~XM_MD_TX_CONT;
3735 /* setup Mode Register */
3736 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3740 /******************************************************************************
3742 * SkMacTimeStamp() - Enable / Disable Time Stamp
3744 * Description: enable / disable Time Stamp generation for Rx packets
3749 void SkMacTimeStamp(
3750 SK_AC *pAC, /* adapter context */
3751 SK_IOC IoC, /* IO context */
3752 int Port, /* Port Index (MAC_1 + n) */
3753 SK_BOOL Enable) /* Enable / Disable */
3758 if (pAC->GIni.GIGenesis) {
3760 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3766 MdReg &= ~XM_MD_ATS;
3768 /* setup Mode Register */
3769 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3773 TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3776 TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3778 /* Start/Stop Time Stamp Timer */
3779 SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl);
3781 } /* SkMacTimeStamp*/
3785 /******************************************************************************
3787 * SkXmIrq() - Interrupt Service Routine
3789 * Description: services an Interrupt Request of the XMAC
3792 * With an external PHY, some interrupt bits are not meaningfull any more:
3793 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
3794 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
3795 * - Page Received (bit #9) XM_IS_RX_PAGE
3796 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
3797 * - AutoNegDone (bit #7) XM_IS_AND
3798 * Also probably not valid any more is the GP0 input bit:
3799 * - GPRegisterBit0set XM_IS_INP_ASS
3805 SK_AC *pAC, /* adapter context */
3806 SK_IOC IoC, /* IO context */
3807 int Port) /* Port Index (MAC_1 + n) */
3811 SK_U16 IStatus; /* Interrupt status read from the XMAC */
3814 pPrt = &pAC->GIni.GP[Port];
3816 XM_IN16(IoC, Port, XM_ISRC, &IStatus);
3818 /* LinkPartner Auto-negable? */
3819 if (pPrt->PhyType == SK_PHY_XMAC) {
3820 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
3823 /* mask bits that are not used with ext. PHY */
3824 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
3825 XM_IS_RX_PAGE | XM_IS_TX_PAGE |
3826 XM_IS_AND | XM_IS_INP_ASS);
3829 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3830 ("XmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3832 if (!pPrt->PHWLinkUp) {
3833 /* Spurious XMAC interrupt */
3834 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3835 ("SkXmIrq: spurious interrupt on Port %d\n", Port));
3839 if ((IStatus & XM_IS_INP_ASS) != 0) {
3840 /* Reread ISR Register if link is not in sync */
3841 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
3843 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3844 ("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\n",
3845 Port, IStatus, IStatus2));
3846 IStatus &= ~XM_IS_INP_ASS;
3847 IStatus |= IStatus2;
3850 if ((IStatus & XM_IS_LNK_AE) != 0) {
3851 /* not used, GP0 is used instead */
3854 if ((IStatus & XM_IS_TX_ABORT) != 0) {
3858 if ((IStatus & XM_IS_FRC_INT) != 0) {
3859 /* not used, use ASIC IRQ instead if needed */
3862 if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
3863 SkHWLinkDown(pAC, IoC, Port);
3865 /* Signal to RLMT */
3866 Para.Para32[0] = (SK_U32)Port;
3867 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
3869 /* Start workaround Errata #2 timer */
3870 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
3871 SKGE_HWAC, SK_HWEV_WATIM, Para);
3874 if ((IStatus & XM_IS_RX_PAGE) != 0) {
3878 if ((IStatus & XM_IS_TX_PAGE) != 0) {
3882 if ((IStatus & XM_IS_AND) != 0) {
3883 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3884 ("SkXmIrq: AND on link that is up Port %d\n", Port));
3887 if ((IStatus & XM_IS_TSC_OV) != 0) {
3891 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3892 if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
3893 Para.Para32[0] = (SK_U32)Port;
3894 Para.Para32[1] = (SK_U32)IStatus;
3895 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3898 if ((IStatus & XM_IS_RXF_OV) != 0) {
3899 /* normal situation -> no effect */
3905 if ((IStatus & XM_IS_TXF_UR) != 0) {
3906 /* may NOT happen -> error log */
3907 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3910 if ((IStatus & XM_IS_TX_COMP) != 0) {
3911 /* not served here */
3914 if ((IStatus & XM_IS_RX_COMP) != 0) {
3915 /* not served here */
3920 /******************************************************************************
3922 * SkGmIrq() - Interrupt Service Routine
3924 * Description: services an Interrupt Request of the GMAC
3932 SK_AC *pAC, /* adapter context */
3933 SK_IOC IoC, /* IO context */
3934 int Port) /* Port Index (MAC_1 + n) */
3938 SK_U8 IStatus; /* Interrupt status */
3940 pPrt = &pAC->GIni.GP[Port];
3942 SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
3944 /* LinkPartner Auto-negable? */
3945 SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
3947 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3948 ("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3950 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3951 if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
3952 /* these IRQs will be cleared by reading GMACs register */
3953 Para.Para32[0] = (SK_U32)Port;
3954 Para.Para32[1] = (SK_U32)IStatus;
3955 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3958 if (IStatus & GM_IS_RX_FF_OR) {
3959 /* clear GMAC Rx FIFO Overrun IRQ */
3960 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
3966 if (IStatus & GM_IS_TX_FF_UR) {
3967 /* clear GMAC Tx FIFO Underrun IRQ */
3968 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
3969 /* may NOT happen -> error log */
3970 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3973 if (IStatus & GM_IS_TX_COMPL) {
3974 /* not served here */
3977 if (IStatus & GM_IS_RX_COMPL) {
3978 /* not served here */
3982 /******************************************************************************
3984 * SkMacIrq() - Interrupt Service Routine for MAC
3986 * Description: calls the Interrupt Service Routine dep. on board type
3992 SK_AC *pAC, /* adapter context */
3993 SK_IOC IoC, /* IO context */
3994 int Port) /* Port Index (MAC_1 + n) */
3997 if (pAC->GIni.GIGenesis) {
3999 SkXmIrq(pAC, IoC, Port);
4003 SkGmIrq(pAC, IoC, Port);
4007 #endif /* !SK_DIAG */
4009 /******************************************************************************
4011 * SkXmUpdateStats() - Force the XMAC to output the current statistic
4014 * The XMAC holds its statistic internally. To obtain the current
4015 * values a command must be sent so that the statistic data will
4016 * be written to a predefined memory area on the adapter.
4020 * 1: something went wrong
4022 int SkXmUpdateStats(
4023 SK_AC *pAC, /* adapter context */
4024 SK_IOC IoC, /* IO context */
4025 unsigned int Port) /* Port Index (MAC_1 + n) */
4031 pPrt = &pAC->GIni.GP[Port];
4034 /* Send an update command to XMAC specified */
4035 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
4038 * It is an auto-clearing register. If the command bits
4039 * went to zero again, the statistics are transferred.
4040 * Normally the command should be executed immediately.
4041 * But just to be sure we execute a loop.
4045 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
4047 if (++WaitIndex > 10) {
4049 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
4053 } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
4056 } /* SkXmUpdateStats */
4058 /******************************************************************************
4060 * SkGmUpdateStats() - Force the GMAC to output the current statistic
4063 * Empty function for GMAC. Statistic data is accessible in direct way.
4067 * 1: something went wrong
4069 int SkGmUpdateStats(
4070 SK_AC *pAC, /* adapter context */
4071 SK_IOC IoC, /* IO context */
4072 unsigned int Port) /* Port Index (MAC_1 + n) */
4077 /******************************************************************************
4079 * SkXmMacStatistic() - Get XMAC counter value
4082 * Gets the 32bit counter value. Except for the octet counters
4083 * the lower 32bit are counted in hardware and the upper 32bit
4084 * must be counted in software by monitoring counter overflow interrupts.
4088 * 1: something went wrong
4090 int SkXmMacStatistic(
4091 SK_AC *pAC, /* adapter context */
4092 SK_IOC IoC, /* IO context */
4093 unsigned int Port, /* Port Index (MAC_1 + n) */
4094 SK_U16 StatAddr, /* MIB counter base address */
4095 SK_U32 *pVal) /* ptr to return statistic value */
4097 if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
4099 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4104 XM_IN32(IoC, Port, StatAddr, pVal);
4107 } /* SkXmMacStatistic */
4109 /******************************************************************************
4111 * SkGmMacStatistic() - Get GMAC counter value
4114 * Gets the 32bit counter value. Except for the octet counters
4115 * the lower 32bit are counted in hardware and the upper 32bit
4116 * must be counted in software by monitoring counter overflow interrupts.
4120 * 1: something went wrong
4122 int SkGmMacStatistic(
4123 SK_AC *pAC, /* adapter context */
4124 SK_IOC IoC, /* IO context */
4125 unsigned int Port, /* Port Index (MAC_1 + n) */
4126 SK_U16 StatAddr, /* MIB counter base address */
4127 SK_U32 *pVal) /* ptr to return statistic value */
4130 if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
4132 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4134 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4135 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
4139 GM_IN32(IoC, Port, StatAddr, pVal);
4142 } /* SkGmMacStatistic */
4144 /******************************************************************************
4146 * SkXmResetCounter() - Clear MAC statistic counter
4149 * Force the XMAC to clear its statistic counter.
4153 * 1: something went wrong
4155 int SkXmResetCounter(
4156 SK_AC *pAC, /* adapter context */
4157 SK_IOC IoC, /* IO context */
4158 unsigned int Port) /* Port Index (MAC_1 + n) */
4160 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4161 /* Clear two times according to Errata #3 */
4162 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4165 } /* SkXmResetCounter */
4167 /******************************************************************************
4169 * SkGmResetCounter() - Clear MAC statistic counter
4172 * Force GMAC to clear its statistic counter.
4176 * 1: something went wrong
4178 int SkGmResetCounter(
4179 SK_AC *pAC, /* adapter context */
4180 SK_IOC IoC, /* IO context */
4181 unsigned int Port) /* Port Index (MAC_1 + n) */
4183 SK_U16 Reg; /* Phy Address Register */
4187 GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4190 /* set MIB Clear Counter Mode */
4191 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
4193 /* read all MIB Counters with Clear Mode set */
4194 for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4195 /* the reset is performed only when the lower 16 bits are read */
4196 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4199 /* clear MIB Clear Counter Mode */
4200 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4204 } /* SkGmResetCounter */
4206 /******************************************************************************
4208 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4211 * Checks the source causing an counter overflow interrupt. On success the
4212 * resulting counter overflow status is written to <pStatus>, whereas the
4213 * upper dword stores the XMAC ReceiveCounterEvent register and the lower
4214 * dword the XMAC TransmitCounterEvent register.
4217 * For XMAC the interrupt source is a self-clearing register, so the source
4218 * must be checked only once. SIRQ module does another check to be sure
4219 * that no interrupt get lost during process time.
4223 * 1: something went wrong
4225 int SkXmOverflowStatus(
4226 SK_AC *pAC, /* adapter context */
4227 SK_IOC IoC, /* IO context */
4228 unsigned int Port, /* Port Index (MAC_1 + n) */
4229 SK_U16 IStatus, /* Interupt Status from MAC */
4230 SK_U64 *pStatus) /* ptr for return overflow status value */
4232 SK_U64 Status; /* Overflow status */
4237 if ((IStatus & XM_IS_RXC_OV) != 0) {
4239 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
4240 Status |= (SK_U64)RegVal << 32;
4243 if ((IStatus & XM_IS_TXC_OV) != 0) {
4245 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
4246 Status |= (SK_U64)RegVal;
4252 } /* SkXmOverflowStatus */
4255 /******************************************************************************
4257 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4260 * Checks the source causing an counter overflow interrupt. On success the
4261 * resulting counter overflow status is written to <pStatus>, whereas the
4262 * the following bit coding is used:
4264 * 55:48 - TxRx interrupt register bit7:0
4265 * 32:47 - Rx interrupt register
4267 * 23:16 - TxRx interrupt register bit15:8
4268 * 15:0 - Tx interrupt register
4272 * 1: something went wrong
4274 int SkGmOverflowStatus(
4275 SK_AC *pAC, /* adapter context */
4276 SK_IOC IoC, /* IO context */
4277 unsigned int Port, /* Port Index (MAC_1 + n) */
4278 SK_U16 IStatus, /* Interupt Status from MAC */
4279 SK_U64 *pStatus) /* ptr for return overflow status value */
4281 SK_U64 Status; /* Overflow status */
4286 if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4287 /* this register is self-clearing after read */
4288 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4289 Status |= (SK_U64)RegVal << 32;
4292 if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4293 /* this register is self-clearing after read */
4294 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4295 Status |= (SK_U64)RegVal;
4298 /* this register is self-clearing after read */
4299 GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4300 /* Rx overflow interrupt register bits (LoByte)*/
4301 Status |= (SK_U64)((SK_U8)RegVal) << 48;
4302 /* Tx overflow interrupt register bits (HiByte)*/
4303 Status |= (SK_U64)(RegVal >> 8) << 16;
4308 } /* SkGmOverflowStatus */
4310 /******************************************************************************
4312 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4315 * starts the cable diagnostic test if 'StartTest' is true
4316 * gets the results if 'StartTest' is true
4318 * NOTE: this test is meaningful only when link is down
4322 * 1: no YUKON copper
4323 * 2: test in progress
4325 int SkGmCableDiagStatus(
4326 SK_AC *pAC, /* adapter context */
4327 SK_IOC IoC, /* IO context */
4328 int Port, /* Port Index (MAC_1 + n) */
4329 SK_BOOL StartTest) /* flag for start / get result */
4335 pPrt = &pAC->GIni.GP[Port];
4337 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
4343 /* only start the cable test */
4344 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4345 /* apply TDR workaround from Marvell */
4346 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
4348 SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4349 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4350 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4351 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4352 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4355 /* set address to 0 for MDI[0] */
4356 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4358 /* Read Cable Diagnostic Reg */
4359 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4361 /* start Cable Diagnostic Test */
4362 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4363 (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
4368 /* Read Cable Diagnostic Reg */
4369 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4371 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4372 ("PHY Cable Diag.=0x%04X\n", RegVal));
4374 if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4375 /* test is running */
4379 /* get the test results */
4380 for (i = 0; i < 4; i++) {
4381 /* set address to i for MDI[i] */
4382 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4384 /* get Cable Diagnostic values */
4385 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4387 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4389 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4393 } /* SkGmCableDiagStatus */