1 /******************************************************************************
4 * Project: Gigabit Ethernet Adapters, Common Modules
5 * Version: $Revision: 1.99 $
6 * Date: $Date: 2003/07/11 12:19:33 $
7 * Purpose: Contains functions to initialize the MACs and PHYs
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect.
14 * (C)Copyright 2002-2003 Marvell.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
25 /******************************************************************************
30 * Revision 1.99 2003/07/11 12:19:33 rschmidt
31 * Reduced init values for Master & Slave downshift counters to
35 * Revision 1.98 2003/07/04 12:53:56 rschmidt
36 * Changed setting of downshift feature in SkGmInitPhyMarv().
37 * Enabled downshift feature only for para 'Speed' set to 'Auto'.
38 * Changed init values for Master & Slave downshift counters.
41 * Revision 1.97 2003/05/28 15:53:47 rschmidt
42 * Removed setting of Yukon PHY's 'force link good' in loopback mode.
43 * Replaced call pFnMacOverflow() with SkXmOverflowStatus() resp.
44 * SkGmOverflowStatus().
47 * Revision 1.96 2003/05/13 17:37:11 mkarl
48 * Removed calls to PNMI for SLIM driver.
49 * Added SK_FAR for PXE.
50 * Separated code pathes not used for SLIM driver.
51 * Some further separations for YUKON and GENESIS.
54 * Revision 1.95 2003/05/06 13:09:53 rschmidt
55 * Changed init sequence for auto-negotiation disabled in SkGmInitMac().
56 * Added defines around GENESIS resp. YUKON branches to reduce
60 * Revision 1.94 2003/04/10 14:36:40 rschmidt
61 * Fixed define for debug code in SkGmInitPhyMarv().
63 * Revision 1.93 2003/04/08 16:58:16 rschmidt
64 * Changed initialisation of GMAC and GPHY for disabling
65 * Flow-Control with parameter 'none' (Bug Id #10769).
66 * Changed init for blinking active LED and normal duplex LED
67 * depending on value from GILedBlinkCtrl (LED Blink Control).
68 * Added control for Link100 LED.
69 * Changed handling for different PhyTypes for source code
70 * portability to PXE, UNDI.
73 * Revision 1.92 2003/03/31 07:12:33 mkarl
74 * Restore PHY_MARV_AUNE_ADV after writing to GM_GP_CTRL in order to make
75 * auto-negotiation of limited flow-control possible.
76 * Corrected Copyright.
79 * Revision 1.91 2003/02/05 15:09:34 rschmidt
80 * Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv().
81 * Disabled auto-update for speed, duplex and flow-control when
82 * auto-negotiation is not enabled (Bug Id #10766).
85 * Revision 1.90 2003/01/29 13:35:19 rschmidt
86 * Increment Rx FIFO Overflow counter only in DEBUG-mode.
87 * Corrected define for blinking active LED.
89 * Revision 1.89 2003/01/28 16:37:45 rschmidt
90 * Changed init for blinking active LED
92 * Revision 1.88 2003/01/28 10:09:38 rschmidt
93 * Added debug outputs in SkGmInitMac().
94 * Added customized init of LED registers in SkGmInitPhyMarv(),
95 * for blinking active LED (#ifdef ACT_LED_BLINK) and
96 * for normal duplex LED (#ifdef DUP_LED_NORMAL).
99 * Revision 1.87 2002/12/10 14:39:05 rschmidt
100 * Improved initialization of GPHY in SkGmInitPhyMarv().
103 * Revision 1.86 2002/12/09 15:01:12 rschmidt
104 * Added setup of Ext. PHY Specific Ctrl Reg (downshift feature).
106 * Revision 1.85 2002/12/05 14:09:16 rschmidt
107 * Improved avoiding endless loop in SkGmPhyRead(), SkGmPhyWrite().
108 * Added additional advertising for 10Base-T when 100Base-T is selected.
109 * Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter.
112 * Revision 1.84 2002/11/15 12:50:09 rschmidt
113 * Changed SkGmCableDiagStatus() when getting results.
115 * Revision 1.83 2002/11/13 10:28:29 rschmidt
116 * Added some typecasts to avoid compiler warnings.
118 * Revision 1.82 2002/11/13 09:20:46 rschmidt
119 * Replaced for(..) with do {} while (...) in SkXmUpdateStats().
120 * Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic().
121 * Added SkGmCableDiagStatus() for Virtual Cable Test (VCT).
124 * Revision 1.81 2002/10/28 14:28:08 rschmidt
125 * Changed MAC address setup for GMAC in SkGmInitMac().
126 * Optimized handling of counter overflow IRQ in SkGmOverflowStatus().
129 * Revision 1.80 2002/10/14 15:29:44 rschmidt
130 * Corrected disabling of all PHY IRQs.
131 * Added WA for deviation #16 (address used for pause packets).
132 * Set Pause Mode in SkMacRxTxEnable() only for Genesis.
133 * Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode.
134 * SkXmTimeStamp() replaced by SkMacTimeStamp().
135 * Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq().
138 * Revision 1.79 2002/10/10 15:55:36 mkarl
139 * changes for PLinkSpeedUsed
141 * Revision 1.78 2002/09/12 09:39:51 rwahl
142 * Removed deactivate code for SIRQ overflow event separate for TX/RX.
144 * Revision 1.77 2002/09/09 12:26:37 mkarl
145 * added handling for Yukon to SkXmTimeStamp
147 * Revision 1.76 2002/08/21 16:41:16 rschmidt
148 * Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE.
149 * Added forced speed settings in SkGmInitPhyMarv().
150 * Added settings of full/half duplex capabilities for YUKON Fiber.
153 * Revision 1.75 2002/08/16 15:12:01 rschmidt
154 * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
155 * Added function SkMacHashing() for ADDR-Module.
156 * Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced
158 * Removed functions SkGmGetMuxConfig().
159 * Added HWCFG_MODE init for YUKON Fiber.
160 * Changed initialization of GPHY in SkGmInitPhyMarv().
161 * Changed check of parameter in SkXmMacStatistic().
164 * Revision 1.74 2002/08/12 14:00:17 rschmidt
165 * Replaced usage of Broadcom PHY Ids with defines.
166 * Corrected error messages in SkGmMacStatistic().
167 * Made SkMacPromiscMode() public for ADDR-Modul.
170 * Revision 1.73 2002/08/08 16:26:24 rschmidt
171 * Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac().
172 * Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM.
175 * Revision 1.72 2002/07/24 15:11:19 rschmidt
176 * Fixed wrong placement of parenthesis.
179 * Revision 1.71 2002/07/23 16:05:18 rschmidt
180 * Added global functions for PHY: SkGePhyRead(), SkGePhyWrite().
181 * Fixed Tx Counter Overflow IRQ (Bug ID #10730).
184 * Revision 1.70 2002/07/18 14:27:27 rwahl
185 * Fixed syntax error.
187 * Revision 1.69 2002/07/17 17:08:47 rwahl
188 * Fixed check in SkXmMacStatistic().
190 * Revision 1.68 2002/07/16 07:35:24 rwahl
191 * Removed check for cleared mib counter in SkGmResetCounter().
193 * Revision 1.67 2002/07/15 18:35:56 rwahl
194 * Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(),
195 * SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(),
196 * SkXmOverflowStatus(), SkGmOverflowStatus().
197 * Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both
199 * Changes to SkGmInitMac(): call to SkGmResetCounter().
202 * Revision 1.66 2002/07/15 15:59:30 rschmidt
203 * Added PHY Address in SkXmPhyRead(), SkXmPhyWrite().
204 * Added MIB Clear Counter in SkGmInitMac().
205 * Added Duplex and Flow-Control settings.
206 * Reset all Multicast filtering Hash reg. in SkGmInitMac().
207 * Added new function: SkGmGetMuxConfig().
210 * Revision 1.65 2002/06/10 09:35:39 rschmidt
211 * Replaced C++ comments (//).
212 * Added #define VCPU around VCPUwaitTime.
215 * Revision 1.64 2002/06/05 08:41:10 rschmidt
216 * Added function for XMAC2: SkXmTimeStamp().
217 * Added function for YUKON: SkGmSetRxCmd().
218 * Changed SkGmInitMac() resp. SkGmHardRst().
219 * Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode).
220 * SkXmRxTxEnable() replaced by SkMacRxTxEnable().
223 * Revision 1.63 2002/04/25 13:04:44 rschmidt
224 * Changes for handling YUKON.
225 * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types.
226 * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced
227 * by functions SkXmPhyRead(), SkXmPhyWrite();
228 * Removed use of PRxCmd to setup XMAC.
229 * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res.
230 * Added setting of XM_RX_DIS_CEXT in SkXmInitMac().
231 * Removed status parameter from MAC IRQ handler SkMacIrq(),
232 * SkXmIrq() and SkGmIrq().
233 * SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy().
234 * Added SkMac...() functions to handle both XMAC and GMAC.
235 * Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(),
236 * SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(),
237 * SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite().
238 * Changes for V-CPU support.
241 * Revision 1.62 2001/08/06 09:50:14 rschmidt
242 * Workaround BCOM Errata #1 for the C5 type.
245 * Revision 1.61 2001/02/09 15:40:59 rassmann
248 * Revision 1.60 2001/02/07 15:02:01 cgoos
249 * Added workaround for Fujitsu switch link down.
251 * Revision 1.59 2001/01/10 09:38:06 cgoos
252 * Fixed Broadcom C0/A1 Id check for workaround.
254 * Revision 1.58 2000/11/29 11:30:38 cgoos
255 * Changed DEBUG sections with NW output to xDEBUG
257 * Revision 1.57 2000/11/27 12:40:40 rassmann
258 * Suppressing preamble after first access to BCom, not before (#10556).
260 * Revision 1.56 2000/11/09 12:32:48 rassmann
263 * Revision 1.55 2000/11/09 11:30:10 rassmann
264 * WA: Waiting after releasing reset until BCom chip is accessible.
266 * Revision 1.54 2000/10/02 14:10:27 rassmann
267 * Reading BCOM PHY after releasing reset until it returns a valid value.
269 * Revision 1.53 2000/07/27 12:22:11 gklug
270 * fix: possible endless loop in XmHardRst.
272 * Revision 1.52 2000/05/22 08:48:31 malthoff
273 * Fix: #10523 errata valid for all BCOM PHYs.
275 * Revision 1.51 2000/05/17 12:52:18 malthoff
276 * Fixes BCom link errata (#10523).
278 * Revision 1.50 1999/11/22 13:40:14 cgoos
279 * Changed license header to GPL.
281 * Revision 1.49 1999/11/22 08:12:13 malthoff
282 * Add workaround for power consumption feature of BCom C0 chip.
284 * Revision 1.48 1999/11/16 08:39:01 malthoff
285 * Fix: MDIO preamble suppression is port dependent.
287 * Revision 1.47 1999/08/27 08:55:35 malthoff
288 * 1000BT: Optimizing MDIO transfer by oppressing MDIO preamble.
290 * Revision 1.46 1999/08/13 11:01:12 malthoff
291 * Fix for 1000BT: pFlowCtrlMode was not set correctly.
293 * Revision 1.45 1999/08/12 19:18:28 malthoff
294 * 1000BT Fixes: Do not owerwrite XM_MMU_CMD.
295 * Do not execute BCOM A1 workaround for B1 chips.
296 * Fix pause frame setting.
297 * Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL.
299 * Revision 1.44 1999/08/03 15:23:48 cgoos
300 * Fixed setting of PHY interrupt mask in half duplex mode.
302 * Revision 1.43 1999/08/03 15:22:17 cgoos
303 * Added some debug output.
304 * Disabled XMac GP0 interrupt for external PHYs.
306 * Revision 1.42 1999/08/02 08:39:23 malthoff
307 * BCOM PHY: TX LED: To get the mono flop behaviour it is required
308 * to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL.
310 * Revision 1.41 1999/07/30 06:54:31 malthoff
311 * Add temp. workarounds for the BCOM Phy revision A1.
313 * Revision 1.40 1999/06/01 07:43:26 cgoos
314 * Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to
317 * Revision 1.39 1999/05/19 07:29:51 cgoos
318 * Changes for 1000Base-T.
320 * Revision 1.38 1999/04/08 14:35:10 malthoff
321 * Add code for enabling signal detect. Enabling signal detect is disabled.
323 * Revision 1.37 1999/03/12 13:42:54 malthoff
324 * Add: Jumbo Frame Support.
325 * Add: Receive modes SK_LENERR_OK_ON/OFF and
326 * SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd().
328 * Revision 1.36 1999/03/08 10:10:55 gklug
329 * fix: AutoSensing did switch to next mode even if LiPa indicated offline
331 * Revision 1.35 1999/02/22 15:16:41 malthoff
332 * Remove some compiler warnings.
334 * Revision 1.34 1999/01/22 09:19:59 gklug
335 * fix: Init DupMode and InitPauseMd are now called in RxTxEnable
337 * Revision 1.33 1998/12/11 15:19:11 gklug
338 * chg: lipa autoneg stati
339 * chg: debug messages
340 * chg: do NOT use spurious XmIrq
342 * Revision 1.32 1998/12/10 11:08:44 malthoff
343 * bug fix: pAC has been used for IOs in SkXmHardRst().
344 * SkXmInitPhy() is also called for the Diag in SkXmInitMac().
346 * Revision 1.31 1998/12/10 10:39:11 gklug
347 * fix: do 4 RESETS of the XMAC at the beginning
348 * fix: dummy read interrupt source register BEFORE initializing the Phy
349 * add: debug messages
350 * fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt
352 * Revision 1.30 1998/12/07 12:18:32 gklug
353 * add: refinement of autosense mode: take into account the autoneg cap of LiPa
355 * Revision 1.29 1998/12/07 07:12:29 gklug
356 * fix: if page is received the link is down.
358 * Revision 1.28 1998/12/01 10:12:47 gklug
359 * chg: if spurious IRQ from XMAC encountered, save it
361 * Revision 1.27 1998/11/26 07:33:38 gklug
362 * add: InitPhy call is now in XmInit function
364 * Revision 1.26 1998/11/18 13:38:24 malthoff
365 * 'Imsk' is also unused in SkXmAutoNegDone.
367 * Revision 1.25 1998/11/18 13:28:01 malthoff
368 * Remove unused variable 'Reg' in SkXmAutoNegDone().
370 * Revision 1.24 1998/11/18 13:18:45 gklug
371 * add: workaround for xmac errata #1
372 * add: detect Link Down also when Link partner requested config
373 * chg: XMIrq is only used when link is up
375 * Revision 1.23 1998/11/04 07:07:04 cgoos
376 * Added function SkXmRxTxEnable.
378 * Revision 1.22 1998/10/30 07:35:54 gklug
379 * fix: serve LinkDown interrupt when link is already down
381 * Revision 1.21 1998/10/29 15:32:03 gklug
382 * fix: Link Down signaling
384 * Revision 1.20 1998/10/29 11:17:27 gklug
385 * fix: AutoNegDone bug
387 * Revision 1.19 1998/10/29 10:14:43 malthoff
388 * Add endainesss comment for reading/writing MAC addresses.
390 * Revision 1.18 1998/10/28 07:48:55 cgoos
391 * Fix: ASS somtimes signaled although link is up.
393 * Revision 1.17 1998/10/26 07:55:39 malthoff
394 * Fix in SkXmInitPauseMd(): Pause Mode
395 * was disabled and not enabled.
396 * Fix in SkXmAutoNegDone(): Checking Mode bits
397 * always failed, becaues of some missing braces.
399 * Revision 1.16 1998/10/22 09:46:52 gklug
400 * fix SysKonnectFileId typo
402 * Revision 1.15 1998/10/21 05:51:37 gklug
403 * add: para DoLoop to InitPhy function for loopback set-up
405 * Revision 1.14 1998/10/16 10:59:23 malthoff
406 * Remove Lint warning for dummy reads.
408 * Revision 1.13 1998/10/15 14:01:20 malthoff
409 * Fix: SkXmAutoNegDone() is (int) but does not return a value.
411 * Revision 1.12 1998/10/14 14:45:04 malthoff
412 * Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by
413 * SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent
414 * from the Sirq module.
416 * Revision 1.11 1998/10/14 13:59:01 gklug
417 * add: InitPhy function
419 * Revision 1.10 1998/10/14 11:20:57 malthoff
420 * Make SkXmAutoNegDone() public, because it's
421 * used in diagnostics, too.
422 * The Link Up event to the RLMT is issued in SkXmIrq().
423 * SkXmIrq() is not available in diagnostics.
424 * Use PHY_READ when reading PHY registers.
426 * Revision 1.9 1998/10/14 05:50:10 cgoos
427 * Added definition for Para.
429 * Revision 1.8 1998/10/14 05:41:28 gklug
431 * add: auto-negotiation done function
433 * Revision 1.7 1998/10/09 06:55:20 malthoff
434 * The configuration of the XMACs Tx Request Threshold
435 * depends from the drivers port usage now. The port
436 * usage is configured in GIPortUsage.
438 * Revision 1.6 1998/10/05 07:48:00 malthoff
441 * Revision 1.5 1998/10/01 07:03:54 gklug
442 * add: dummy function for XMAC ISR
444 * Revision 1.4 1998/09/30 12:37:44 malthoff
445 * Add SkXmSetRxCmd() and related code.
447 * Revision 1.3 1998/09/28 13:26:40 malthoff
448 * Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd()
450 * Revision 1.2 1998/09/16 14:34:21 malthoff
451 * Add SkXmClrExactAddr(), SkXmClrSrcCheck(),
452 * SkXmClrHashAddr(), SkXmFlushTxFifo(),
453 * SkXmFlushRxFifo(), and SkXmHardRst().
454 * Finish Coding of SkXmSoftRst().
455 * The sources may be compiled now.
457 * Revision 1.1 1998/09/04 10:05:56 malthoff
461 ******************************************************************************/
463 #include "h/skdrv1st.h"
464 #include "h/skdrv2nd.h"
466 /* typedefs *******************************************************************/
468 /* BCOM PHY magic pattern list */
469 typedef struct s_PhyHack {
470 int PhyReg; /* Phy register */
471 SK_U16 PhyVal; /* Value to write */
474 /* local variables ************************************************************/
476 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
477 static const char SysKonnectFileId[] =
478 "@(#) $Id: skxmac2.c,v 1.99 2003/07/11 12:19:33 rschmidt Exp $ (C) Marvell.";
482 BCOM_HACK BcomRegA1Hack[] = {
483 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
484 { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
485 { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
488 BCOM_HACK BcomRegC0Hack[] = {
489 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
490 { 0x15, 0x0A04 }, { 0x18, 0x0420 },
495 /* function prototypes ********************************************************/
497 static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
498 static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
499 static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
500 static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
503 static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
504 static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
507 static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
508 static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
509 static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
510 static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
511 #endif /* OTHER_PHY */
515 /******************************************************************************
517 * SkXmPhyRead() - Read from XMAC PHY register
519 * Description: reads a 16-bit word from XMAC PHY or ext. PHY
525 SK_AC *pAC, /* Adapter Context */
526 SK_IOC IoC, /* I/O Context */
527 int Port, /* Port Index (MAC_1 + n) */
528 int PhyReg, /* Register Address (Offset) */
529 SK_U16 SK_FAR *pVal) /* Pointer to Value */
534 pPrt = &pAC->GIni.GP[Port];
536 /* write the PHY register's address */
537 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
539 /* get the PHY register's value */
540 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
542 if (pPrt->PhyType != SK_PHY_XMAC) {
544 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
545 /* wait until 'Ready' is set */
546 } while ((Mmu & XM_MMU_PHY_RDY) == 0);
548 /* get the PHY register's value */
549 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
554 /******************************************************************************
556 * SkXmPhyWrite() - Write to XMAC PHY register
558 * Description: writes a 16-bit word to XMAC PHY or ext. PHY
564 SK_AC *pAC, /* Adapter Context */
565 SK_IOC IoC, /* I/O Context */
566 int Port, /* Port Index (MAC_1 + n) */
567 int PhyReg, /* Register Address (Offset) */
568 SK_U16 Val) /* Value */
573 pPrt = &pAC->GIni.GP[Port];
575 if (pPrt->PhyType != SK_PHY_XMAC) {
577 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
578 /* wait until 'Busy' is cleared */
579 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
582 /* write the PHY register's address */
583 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
585 /* write the PHY register's value */
586 XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
588 if (pPrt->PhyType != SK_PHY_XMAC) {
590 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
591 /* wait until 'Busy' is cleared */
592 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
599 /******************************************************************************
601 * SkGmPhyRead() - Read from GPHY register
603 * Description: reads a 16-bit word from GPHY through MDIO
609 SK_AC *pAC, /* Adapter Context */
610 SK_IOC IoC, /* I/O Context */
611 int Port, /* Port Index (MAC_1 + n) */
612 int PhyReg, /* Register Address (Offset) */
613 SK_U16 SK_FAR *pVal) /* Pointer to Value */
621 VCPUgetTime(&SimCyle, &SimLowTime);
622 VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
623 PhyReg, SimCyle, SimLowTime);
626 pPrt = &pAC->GIni.GP[Port];
628 /* set PHY-Register offset and 'Read' OpCode (= 1) */
629 *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
630 GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
632 GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
634 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
636 /* additional check for MDC/MDIO activity */
637 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
642 *pVal |= GM_SMI_CT_BUSY;
649 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
651 /* wait until 'ReadValid' is set */
652 } while (Ctrl == *pVal);
654 /* get the PHY register's value */
655 GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
658 VCPUgetTime(&SimCyle, &SimLowTime);
659 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
660 SimCyle, SimLowTime);
666 /******************************************************************************
668 * SkGmPhyWrite() - Write to GPHY register
670 * Description: writes a 16-bit word to GPHY through MDIO
676 SK_AC *pAC, /* Adapter Context */
677 SK_IOC IoC, /* I/O Context */
678 int Port, /* Port Index (MAC_1 + n) */
679 int PhyReg, /* Register Address (Offset) */
680 SK_U16 Val) /* Value */
689 VCPUgetTime(&SimCyle, &SimLowTime);
690 VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
691 PhyReg, Val, SimCyle, SimLowTime);
694 pPrt = &pAC->GIni.GP[Port];
696 /* write the PHY register's value */
697 GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
699 /* set PHY-Register offset and 'Write' OpCode (= 0) */
700 Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
702 GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
704 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
706 /* additional check for MDC/MDIO activity */
707 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
711 Val |= GM_SMI_CT_BUSY;
715 /* read Timer value */
716 SK_IN32(IoC, B2_TI_VAL, &DWord);
721 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
723 /* wait until 'Busy' is cleared */
724 } while (Ctrl == Val);
727 VCPUgetTime(&SimCyle, &SimLowTime);
728 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
729 SimCyle, SimLowTime);
737 /******************************************************************************
739 * SkGePhyRead() - Read from PHY register
741 * Description: calls a read PHY routine dep. on board type
747 SK_AC *pAC, /* Adapter Context */
748 SK_IOC IoC, /* I/O Context */
749 int Port, /* Port Index (MAC_1 + n) */
750 int PhyReg, /* Register Address (Offset) */
751 SK_U16 *pVal) /* Pointer to Value */
753 void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
755 if (pAC->GIni.GIGenesis) {
756 r_func = SkXmPhyRead;
759 r_func = SkGmPhyRead;
762 r_func(pAC, IoC, Port, PhyReg, pVal);
766 /******************************************************************************
768 * SkGePhyWrite() - Write to PHY register
770 * Description: calls a write PHY routine dep. on board type
776 SK_AC *pAC, /* Adapter Context */
777 SK_IOC IoC, /* I/O Context */
778 int Port, /* Port Index (MAC_1 + n) */
779 int PhyReg, /* Register Address (Offset) */
780 SK_U16 Val) /* Value */
782 void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
784 if (pAC->GIni.GIGenesis) {
785 w_func = SkXmPhyWrite;
788 w_func = SkGmPhyWrite;
791 w_func(pAC, IoC, Port, PhyReg, Val);
796 /******************************************************************************
798 * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
801 * enables / disables promiscuous mode by setting Mode Register (XMAC) or
802 * Receive Control Register (GMAC) dep. on board type
807 void SkMacPromiscMode(
808 SK_AC *pAC, /* adapter context */
809 SK_IOC IoC, /* IO context */
810 int Port, /* Port Index (MAC_1 + n) */
811 SK_BOOL Enable) /* Enable / Disable */
821 if (pAC->GIni.GIGenesis) {
823 XM_IN32(IoC, Port, XM_MODE, &MdReg);
824 /* enable or disable promiscuous mode */
826 MdReg |= XM_MD_ENA_PROM;
829 MdReg &= ~XM_MD_ENA_PROM;
831 /* setup Mode Register */
832 XM_OUT32(IoC, Port, XM_MODE, MdReg);
837 if (pAC->GIni.GIYukon) {
839 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
841 /* enable or disable unicast and multicast filtering */
843 RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
846 RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
848 /* setup Receive Control Register */
849 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
853 } /* SkMacPromiscMode*/
856 /******************************************************************************
858 * SkMacHashing() - Enable / Disable Hashing
861 * enables / disables hashing by setting Mode Register (XMAC) or
862 * Receive Control Register (GMAC) dep. on board type
868 SK_AC *pAC, /* adapter context */
869 SK_IOC IoC, /* IO context */
870 int Port, /* Port Index (MAC_1 + n) */
871 SK_BOOL Enable) /* Enable / Disable */
881 if (pAC->GIni.GIGenesis) {
883 XM_IN32(IoC, Port, XM_MODE, &MdReg);
884 /* enable or disable hashing */
886 MdReg |= XM_MD_ENA_HASH;
889 MdReg &= ~XM_MD_ENA_HASH;
891 /* setup Mode Register */
892 XM_OUT32(IoC, Port, XM_MODE, MdReg);
897 if (pAC->GIni.GIYukon) {
899 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
901 /* enable or disable multicast filtering */
903 RcReg |= GM_RXCR_MCF_ENA;
906 RcReg &= ~GM_RXCR_MCF_ENA;
908 /* setup Receive Control Register */
909 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
917 /******************************************************************************
919 * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
923 * - FCS stripping, SK_STRIP_FCS_ON/OFF
924 * - pad byte stripping, SK_STRIP_PAD_ON/OFF
925 * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
926 * for inrange length error frames
927 * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
928 * for frames > 1514 bytes
929 * - enable Rx of own packets SK_SELF_RX_ON/OFF
931 * for incoming packets may be enabled/disabled by this function.
932 * Additional modes may be added later.
933 * Multiple modes can be enabled/disabled at the same time.
934 * The new configuration is written to the Rx Command register immediately.
939 static void SkXmSetRxCmd(
940 SK_AC *pAC, /* adapter context */
941 SK_IOC IoC, /* IO context */
942 int Port, /* Port Index (MAC_1 + n) */
943 int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
944 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
949 XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
953 switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
954 case SK_STRIP_FCS_ON:
955 RxCmd |= XM_RX_STRIP_FCS;
957 case SK_STRIP_FCS_OFF:
958 RxCmd &= ~XM_RX_STRIP_FCS;
962 switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
963 case SK_STRIP_PAD_ON:
964 RxCmd |= XM_RX_STRIP_PAD;
966 case SK_STRIP_PAD_OFF:
967 RxCmd &= ~XM_RX_STRIP_PAD;
971 switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
972 case SK_LENERR_OK_ON:
973 RxCmd |= XM_RX_LENERR_OK;
975 case SK_LENERR_OK_OFF:
976 RxCmd &= ~XM_RX_LENERR_OK;
980 switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
981 case SK_BIG_PK_OK_ON:
982 RxCmd |= XM_RX_BIG_PK_OK;
984 case SK_BIG_PK_OK_OFF:
985 RxCmd &= ~XM_RX_BIG_PK_OK;
989 switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
991 RxCmd |= XM_RX_SELF_RX;
994 RxCmd &= ~XM_RX_SELF_RX;
998 /* Write the new mode to the Rx command register if required */
999 if (OldRxCmd != RxCmd) {
1000 XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
1002 } /* SkXmSetRxCmd */
1005 /******************************************************************************
1007 * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
1011 * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
1012 * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
1013 * for frames > 1514 bytes
1014 * - enable Rx of own packets SK_SELF_RX_ON/OFF
1016 * for incoming packets may be enabled/disabled by this function.
1017 * Additional modes may be added later.
1018 * Multiple modes can be enabled/disabled at the same time.
1019 * The new configuration is written to the Rx Command register immediately.
1024 static void SkGmSetRxCmd(
1025 SK_AC *pAC, /* adapter context */
1026 SK_IOC IoC, /* IO context */
1027 int Port, /* Port Index (MAC_1 + n) */
1028 int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
1029 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
1034 if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
1036 GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
1040 if ((Mode & SK_STRIP_FCS_ON) != 0) {
1041 RxCmd |= GM_RXCR_CRC_DIS;
1044 RxCmd &= ~GM_RXCR_CRC_DIS;
1046 /* Write the new mode to the Rx control register if required */
1047 if (OldRxCmd != RxCmd) {
1048 GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
1052 if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
1054 GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
1058 if ((Mode & SK_BIG_PK_OK_ON) != 0) {
1059 RxCmd |= GM_SMOD_JUMBO_ENA;
1062 RxCmd &= ~GM_SMOD_JUMBO_ENA;
1064 /* Write the new mode to the Rx control register if required */
1065 if (OldRxCmd != RxCmd) {
1066 GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
1069 } /* SkGmSetRxCmd */
1072 /******************************************************************************
1074 * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
1076 * Description: modifies the MAC's Rx Control reg. dep. on board type
1082 SK_AC *pAC, /* adapter context */
1083 SK_IOC IoC, /* IO context */
1084 int Port, /* Port Index (MAC_1 + n) */
1085 int Mode) /* Rx Mode */
1087 if (pAC->GIni.GIGenesis) {
1089 SkXmSetRxCmd(pAC, IoC, Port, Mode);
1093 SkGmSetRxCmd(pAC, IoC, Port, Mode);
1096 } /* SkMacSetRxCmd */
1099 /******************************************************************************
1101 * SkMacCrcGener() - Enable / Disable CRC Generation
1103 * Description: enables / disables CRC generation dep. on board type
1109 SK_AC *pAC, /* adapter context */
1110 SK_IOC IoC, /* IO context */
1111 int Port, /* Port Index (MAC_1 + n) */
1112 SK_BOOL Enable) /* Enable / Disable */
1116 if (pAC->GIni.GIGenesis) {
1118 XM_IN16(IoC, Port, XM_TX_CMD, &Word);
1121 Word &= ~XM_TX_NO_CRC;
1124 Word |= XM_TX_NO_CRC;
1126 /* setup Tx Command Register */
1127 XM_OUT16(IoC, Port, XM_TX_CMD, Word);
1131 GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
1134 Word &= ~GM_TXCR_CRC_DIS;
1137 Word |= GM_TXCR_CRC_DIS;
1139 /* setup Tx Control Register */
1140 GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
1143 } /* SkMacCrcGener*/
1145 #endif /* SK_DIAG */
1149 /******************************************************************************
1151 * SkXmClrExactAddr() - Clear Exact Match Address Registers
1154 * All Exact Match Address registers of the XMAC 'Port' will be
1155 * cleared starting with 'StartNum' up to (and including) the
1156 * Exact Match address number of 'StopNum'.
1161 void SkXmClrExactAddr(
1162 SK_AC *pAC, /* adapter context */
1163 SK_IOC IoC, /* IO context */
1164 int Port, /* Port Index (MAC_1 + n) */
1165 int StartNum, /* Begin with this Address Register Index (0..15) */
1166 int StopNum) /* Stop after finished with this Register Idx (0..15) */
1169 SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
1171 if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
1172 StartNum > StopNum) {
1174 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
1178 for (i = StartNum; i <= StopNum; i++) {
1179 XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
1181 } /* SkXmClrExactAddr */
1182 #endif /* GENESIS */
1185 /******************************************************************************
1187 * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
1190 * Flush the transmit FIFO of the MAC specified by the index 'Port'
1195 void SkMacFlushTxFifo(
1196 SK_AC *pAC, /* adapter context */
1197 SK_IOC IoC, /* IO context */
1198 int Port) /* Port Index (MAC_1 + n) */
1203 if (pAC->GIni.GIGenesis) {
1205 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1207 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
1209 #endif /* GENESIS */
1212 if (pAC->GIni.GIYukon) {
1213 /* no way to flush the FIFO we have to issue a reset */
1218 } /* SkMacFlushTxFifo */
1221 /******************************************************************************
1223 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
1226 * Flush the receive FIFO of the MAC specified by the index 'Port'
1231 void SkMacFlushRxFifo(
1232 SK_AC *pAC, /* adapter context */
1233 SK_IOC IoC, /* IO context */
1234 int Port) /* Port Index (MAC_1 + n) */
1239 if (pAC->GIni.GIGenesis) {
1241 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1243 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
1245 #endif /* GENESIS */
1248 if (pAC->GIni.GIYukon) {
1249 /* no way to flush the FIFO we have to issue a reset */
1254 } /* SkMacFlushRxFifo */
1258 /******************************************************************************
1260 * SkXmSoftRst() - Do a XMAC software reset
1263 * The PHY registers should not be destroyed during this
1264 * kind of software reset. Therefore the XMAC Software Reset
1265 * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
1267 * The software reset is done by
1268 * - disabling the Rx and Tx state machine,
1269 * - resetting the statistics module,
1270 * - clear all other significant XMAC Mode,
1271 * Command, and Control Registers
1272 * - clearing the Hash Register and the
1273 * Exact Match Address registers, and
1274 * - flushing the XMAC's Rx and Tx FIFOs.
1277 * Another requirement when stopping the XMAC is to
1278 * avoid sending corrupted frames on the network.
1279 * Disabling the Tx state machine will NOT interrupt
1280 * the currently transmitted frame. But we must take care
1281 * that the Tx FIFO is cleared AFTER the current frame
1282 * is complete sent to the network.
1284 * It takes about 12ns to send a frame with 1538 bytes.
1285 * One PCI clock goes at least 15ns (66MHz). Therefore
1286 * after reading XM_GP_PORT back, we are sure that the
1287 * transmitter is disabled AND idle. And this means
1288 * we may flush the transmit FIFO now.
1293 static void SkXmSoftRst(
1294 SK_AC *pAC, /* adapter context */
1295 SK_IOC IoC, /* IO context */
1296 int Port) /* Port Index (MAC_1 + n) */
1298 SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1300 /* reset the statistics module */
1301 XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
1303 /* disable all XMAC IRQs */
1304 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
1306 XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
1308 XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
1309 XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
1311 /* disable all PHY IRQs */
1312 switch (pAC->GIni.GP[Port].PhyType) {
1314 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
1318 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
1322 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
1324 #endif /* OTHER_PHY */
1327 /* clear the Hash Register */
1328 XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
1330 /* clear the Exact Match Address registers */
1331 SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
1333 /* clear the Source Check Address registers */
1334 XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
1339 /******************************************************************************
1341 * SkXmHardRst() - Do a XMAC hardware reset
1344 * The XMAC of the specified 'Port' and all connected devices
1345 * (PHY and SERDES) will receive a reset signal on its *Reset pins.
1346 * External PHYs must be reset be clearing a bit in the GPIO register
1347 * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
1350 * It is absolutely necessary to reset the SW_RST Bit first
1351 * before calling this function.
1356 static void SkXmHardRst(
1357 SK_AC *pAC, /* adapter context */
1358 SK_IOC IoC, /* IO context */
1359 int Port) /* Port Index (MAC_1 + n) */
1366 for (i = 0; i < 4; i++) {
1367 /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
1368 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1372 if (TOut++ > 10000) {
1374 * Adapter seems to be in RESET state.
1375 * Registers cannot be written.
1380 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
1382 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
1384 } while ((Word & MFF_SET_MAC_RST) == 0);
1387 /* For external PHYs there must be special handling */
1388 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
1389 /* reset external PHY */
1390 SK_IN32(IoC, B2_GP_IO, &Reg);
1392 Reg |= GP_DIR_0; /* set to output */
1396 Reg |= GP_DIR_2; /* set to output */
1399 SK_OUT32(IoC, B2_GP_IO, Reg);
1402 SK_IN32(IoC, B2_GP_IO, &Reg);
1406 #endif /* GENESIS */
1410 /******************************************************************************
1412 * SkGmSoftRst() - Do a GMAC software reset
1415 * The GPHY registers should not be destroyed during this
1416 * kind of software reset.
1421 static void SkGmSoftRst(
1422 SK_AC *pAC, /* adapter context */
1423 SK_IOC IoC, /* IO context */
1424 int Port) /* Port Index (MAC_1 + n) */
1426 SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1429 /* reset the statistics module */
1431 /* disable all GMAC IRQs */
1432 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
1434 /* disable all PHY IRQs */
1435 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
1437 /* clear the Hash Register */
1438 GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
1440 /* Enable Unicast and Multicast filtering */
1441 GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
1443 GM_OUT16(IoC, Port, GM_RX_CTRL,
1444 (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
1449 /******************************************************************************
1451 * SkGmHardRst() - Do a GMAC hardware reset
1456 * It is absolutely necessary to reset the SW_RST Bit first
1457 * before calling this function.
1462 static void SkGmHardRst(
1463 SK_AC *pAC, /* adapter context */
1464 SK_IOC IoC, /* IO context */
1465 int Port) /* Port Index (MAC_1 + n) */
1467 /* set GPHY Control reset */
1468 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1470 /* set GMAC Control reset */
1471 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1477 /******************************************************************************
1479 * SkMacSoftRst() - Do a MAC software reset
1481 * Description: calls a MAC software reset routine dep. on board type
1487 SK_AC *pAC, /* adapter context */
1488 SK_IOC IoC, /* IO context */
1489 int Port) /* Port Index (MAC_1 + n) */
1493 pPrt = &pAC->GIni.GP[Port];
1495 /* disable receiver and transmitter */
1496 SkMacRxTxDisable(pAC, IoC, Port);
1499 if (pAC->GIni.GIGenesis) {
1501 SkXmSoftRst(pAC, IoC, Port);
1503 #endif /* GENESIS */
1506 if (pAC->GIni.GIYukon) {
1508 SkGmSoftRst(pAC, IoC, Port);
1512 /* flush the MAC's Rx and Tx FIFOs */
1513 SkMacFlushTxFifo(pAC, IoC, Port);
1515 SkMacFlushRxFifo(pAC, IoC, Port);
1517 pPrt->PState = SK_PRT_STOP;
1519 } /* SkMacSoftRst */
1522 /******************************************************************************
1524 * SkMacHardRst() - Do a MAC hardware reset
1526 * Description: calls a MAC hardware reset routine dep. on board type
1532 SK_AC *pAC, /* adapter context */
1533 SK_IOC IoC, /* IO context */
1534 int Port) /* Port Index (MAC_1 + n) */
1538 if (pAC->GIni.GIGenesis) {
1540 SkXmHardRst(pAC, IoC, Port);
1542 #endif /* GENESIS */
1545 if (pAC->GIni.GIYukon) {
1547 SkGmHardRst(pAC, IoC, Port);
1551 pAC->GIni.GP[Port].PState = SK_PRT_RESET;
1553 } /* SkMacHardRst */
1557 /******************************************************************************
1559 * SkXmInitMac() - Initialize the XMAC II
1562 * Initialize the XMAC of the specified port.
1563 * The XMAC must be reset or stopped before calling this function.
1566 * The XMAC's Rx and Tx state machine is still disabled when returning.
1572 SK_AC *pAC, /* adapter context */
1573 SK_IOC IoC, /* IO context */
1574 int Port) /* Port Index (MAC_1 + n) */
1581 pPrt = &pAC->GIni.GP[Port];
1583 if (pPrt->PState == SK_PRT_STOP) {
1584 /* Port State: SK_PRT_STOP */
1585 /* Verify that the reset bit is cleared */
1586 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1588 if ((SWord & MFF_SET_MAC_RST) != 0) {
1589 /* PState does not match HW state */
1590 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1592 pPrt->PState = SK_PRT_RESET;
1596 if (pPrt->PState == SK_PRT_RESET) {
1599 * Note: The SW reset is self clearing, therefore there is
1600 * nothing to do here.
1602 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1604 /* Ensure that XMAC reset release is done (errata from LReinbold?) */
1605 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1607 /* Clear PHY reset */
1608 if (pPrt->PhyType != SK_PHY_XMAC) {
1610 SK_IN32(IoC, B2_GP_IO, &Reg);
1613 Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */
1616 Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */
1618 SK_OUT32(IoC, B2_GP_IO, Reg);
1620 /* Enable GMII interface */
1621 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
1623 /* read Id from external PHY (all have the same address) */
1624 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1627 * Optimize MDIO transfer by suppressing preamble.
1628 * Must be done AFTER first access to BCOM chip.
1630 XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
1632 XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1634 if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1636 * Workaround BCOM Errata for the C0 type.
1637 * Write magic patterns to reserved registers.
1640 while (BcomRegC0Hack[i].PhyReg != 0) {
1641 SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1642 BcomRegC0Hack[i].PhyVal);
1646 else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1648 * Workaround BCOM Errata for the A1 type.
1649 * Write magic patterns to reserved registers.
1652 while (BcomRegA1Hack[i].PhyReg != 0) {
1653 SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1654 BcomRegA1Hack[i].PhyVal);
1660 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1661 * Disable Power Management after reset.
1663 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
1665 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1666 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
1668 /* PHY LED initialization is done in SkGeXmitLED() */
1671 /* Dummy read the Interrupt source register */
1672 XM_IN16(IoC, Port, XM_ISRC, &SWord);
1675 * The auto-negotiation process starts immediately after
1676 * clearing the reset. The auto-negotiation process should be
1677 * started by the SIRQ, therefore stop it here immediately.
1679 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1682 /* temp. code: enable signal detect */
1683 /* WARNING: do not override GMII setting above */
1684 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1689 * configure the XMACs Station Address
1690 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1691 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1693 for (i = 0; i < 3; i++) {
1695 * The following 2 statements are together endianess
1696 * independent. Remember this when changing.
1698 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1700 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1703 /* Tx Inter Packet Gap (XM_TX_IPG): use default */
1704 /* Tx High Water Mark (XM_TX_HI_WM): use default */
1705 /* Tx Low Water Mark (XM_TX_LO_WM): use default */
1706 /* Host Request Threshold (XM_HT_THR): use default */
1707 /* Rx Request Threshold (XM_RX_THR): use default */
1708 /* Rx Low Water Mark (XM_RX_LO_WM): use default */
1710 /* configure Rx High Water Mark (XM_RX_HI_WM) */
1711 XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1713 /* Configure Tx Request Threshold */
1714 SWord = SK_XM_THR_SL; /* for single port */
1716 if (pAC->GIni.GIMacsFound > 1) {
1717 switch (pAC->GIni.GIPortUsage) {
1719 SWord = SK_XM_THR_REDL; /* redundant link */
1722 SWord = SK_XM_THR_MULL; /* load balancing */
1725 SWord = SK_XM_THR_JUMBO; /* jumbo frames */
1728 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1732 XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1734 /* setup register defaults for the Tx Command Register */
1735 XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1737 /* setup register defaults for the Rx Command Register */
1738 SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1740 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1741 SWord |= XM_RX_BIG_PK_OK;
1744 if (pPrt->PLinkMode == SK_LMODE_HALF) {
1746 * If in manual half duplex mode the other side might be in
1747 * full duplex mode, so ignore if a carrier extension is not seen
1748 * on frames received
1750 SWord |= XM_RX_DIS_CEXT;
1753 XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1756 * setup register defaults for the Mode Register
1757 * - Don't strip error frames to avoid Store & Forward
1759 * - Enable 'Check Station Address' bit
1760 * - Enable 'Check Address Array' bit
1762 XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1765 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1766 * - Enable all bits excepting 'Octets Rx OK Low CntOv'
1767 * and 'Octets Rx OK Hi Cnt Ov'.
1769 XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1772 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1773 * - Enable all bits excepting 'Octets Tx OK Low CntOv'
1774 * and 'Octets Tx OK Hi Cnt Ov'.
1776 XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1779 * Do NOT init XMAC interrupt mask here.
1780 * All interrupts remain disable until link comes up!
1784 * Any additional configuration changes may be done now.
1785 * The last action is to enable the Rx and Tx state machine.
1786 * This should be done after the auto-negotiation process
1787 * has been completed successfully.
1790 #endif /* GENESIS */
1794 /******************************************************************************
1796 * SkGmInitMac() - Initialize the GMAC
1799 * Initialize the GMAC of the specified port.
1800 * The GMAC must be reset or stopped before calling this function.
1803 * The GMAC's Rx and Tx state machine is still disabled when returning.
1809 SK_AC *pAC, /* adapter context */
1810 SK_IOC IoC, /* IO context */
1811 int Port) /* Port Index (MAC_1 + n) */
1818 pPrt = &pAC->GIni.GP[Port];
1820 if (pPrt->PState == SK_PRT_STOP) {
1821 /* Port State: SK_PRT_STOP */
1822 /* Verify that the reset bit is cleared */
1823 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
1825 if ((DWord & GMC_RST_SET) != 0) {
1826 /* PState does not match HW state */
1827 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1829 pPrt->PState = SK_PRT_RESET;
1833 if (pPrt->PState == SK_PRT_RESET) {
1834 /* set GPHY Control reset */
1835 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1837 /* set GMAC Control reset */
1838 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1841 /* clear GMAC Control reset */
1842 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
1844 /* set GMAC Control reset */
1845 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1848 /* set HWCFG_MODE */
1849 DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
1850 GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
1851 (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
1852 GPC_HWCFG_GMII_FIB);
1854 /* set GPHY Control reset */
1855 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
1857 /* release GPHY Control reset */
1858 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
1864 /* clear GMAC Control reset */
1865 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
1871 /* Auto-negotiation ? */
1872 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1873 /* Auto-negotiation disabled */
1875 /* get General Purpose Control */
1876 GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
1878 /* disable auto-update for speed, duplex and flow-control */
1879 SWord |= GM_GPCR_AU_ALL_DIS;
1881 /* setup General Purpose Control Register */
1882 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1884 SWord = GM_GPCR_AU_ALL_DIS;
1890 /* speed settings */
1891 switch (pPrt->PLinkSpeed) {
1892 case SK_LSPEED_AUTO:
1893 case SK_LSPEED_1000MBPS:
1894 SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1896 case SK_LSPEED_100MBPS:
1897 SWord |= GM_GPCR_SPEED_100;
1899 case SK_LSPEED_10MBPS:
1903 /* duplex settings */
1904 if (pPrt->PLinkMode != SK_LMODE_HALF) {
1905 /* set full duplex */
1906 SWord |= GM_GPCR_DUP_FULL;
1909 switch (pPrt->PFlowCtrlMode) {
1910 case SK_FLOW_MODE_NONE:
1912 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
1913 /* disable Tx & Rx flow-control */
1914 SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1916 case SK_FLOW_MODE_LOC_SEND:
1917 /* disable Rx flow-control */
1918 SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1920 case SK_FLOW_MODE_SYMMETRIC:
1921 case SK_FLOW_MODE_SYM_OR_REM:
1922 /* enable Tx & Rx flow-control */
1926 /* setup General Purpose Control Register */
1927 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1929 /* dummy read the Interrupt Source Register */
1930 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
1933 /* read Id from PHY */
1934 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
1936 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1940 (void)SkGmResetCounter(pAC, IoC, Port);
1942 /* setup Transmit Control Register */
1943 GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR);
1945 /* setup Receive Control Register */
1946 GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1949 /* setup Transmit Flow Control Register */
1950 GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1952 /* setup Transmit Parameter Register */
1954 GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1957 SWord = (SK_U16)(JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26));
1959 GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1961 /* configure the Serial Mode Register */
1963 GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1966 SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH;
1968 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1969 /* enable jumbo mode (Max. Frame Length = 9018) */
1970 SWord |= GM_SMOD_JUMBO_ENA;
1973 GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
1976 * configure the GMACs Station Addresses
1977 * in PROM you can find our addresses at:
1978 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1979 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1980 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1983 for (i = 0; i < 3; i++) {
1985 * The following 2 statements are together endianess
1986 * independent. Remember this when changing.
1988 /* physical address: will be used for pause frames */
1989 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1992 /* WA for deviation #16 */
1993 if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
1994 /* swap the address bytes */
1995 SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
1997 /* write to register in reversed order */
1998 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
2001 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
2004 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
2005 #endif /* WA_DEV_16 */
2007 /* virtual address: will be used for data */
2008 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
2010 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
2012 /* reset Multicast filtering Hash registers 1-3 */
2013 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
2016 /* reset Multicast filtering Hash register 4 */
2017 GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
2019 /* enable interrupt mask for counter overflows */
2020 GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
2021 GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
2022 GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
2024 /* read General Purpose Status */
2025 GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
2027 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2028 ("MAC Stat Reg=0x%04X\n", SWord));
2031 c_print("MAC Stat Reg=0x%04X\n", SWord);
2032 #endif /* SK_DIAG */
2039 /******************************************************************************
2041 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
2044 * This function initializes the XMACs Duplex Mode.
2045 * It should be called after successfully finishing
2046 * the Auto-negotiation Process
2052 SK_AC *pAC, /* adapter context */
2053 SK_IOC IoC, /* IO context */
2054 int Port) /* Port Index (MAC_1 + n) */
2056 switch (pAC->GIni.GP[Port].PLinkModeStatus) {
2057 case SK_LMODE_STAT_AUTOHALF:
2058 case SK_LMODE_STAT_HALF:
2059 /* Configuration Actions for Half Duplex Mode */
2061 * XM_BURST = default value. We are probable not quick
2062 * enough at the 'XMAC' bus to burst 8kB.
2063 * The XMAC stops bursting if no transmit frames
2064 * are available or the burst limit is exceeded.
2066 /* XM_TX_RT_LIM = default value (15) */
2067 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
2069 case SK_LMODE_STAT_AUTOFULL:
2070 case SK_LMODE_STAT_FULL:
2071 /* Configuration Actions for Full Duplex Mode */
2073 * The duplex mode is configured by the PHY,
2074 * therefore it seems to be that there is nothing
2078 case SK_LMODE_STAT_UNKNOWN:
2080 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
2083 } /* SkXmInitDupMd */
2086 /******************************************************************************
2088 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
2091 * This function initializes the Pause Mode which should
2092 * be used for this port.
2093 * It should be called after successfully finishing
2094 * the Auto-negotiation Process
2099 void SkXmInitPauseMd(
2100 SK_AC *pAC, /* adapter context */
2101 SK_IOC IoC, /* IO context */
2102 int Port) /* Port Index (MAC_1 + n) */
2108 pPrt = &pAC->GIni.GP[Port];
2110 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
2112 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
2113 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
2115 /* Disable Pause Frame Reception */
2116 Word |= XM_MMU_IGN_PF;
2120 * enabling pause frame reception is required for 1000BT
2121 * because the XMAC is not reset if the link is going down
2123 /* Enable Pause Frame Reception */
2124 Word &= ~XM_MMU_IGN_PF;
2127 XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
2129 XM_IN32(IoC, Port, XM_MODE, &DWord);
2131 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
2132 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
2135 * Configure Pause Frame Generation
2136 * Use internal and external Pause Frame Generation.
2137 * Sending pause frames is edge triggered.
2138 * Send a Pause frame with the maximum pause time if
2139 * internal oder external FIFO full condition occurs.
2140 * Send a zero pause time frame to re-start transmission.
2143 /* XM_PAUSE_DA = '010000C28001' (default) */
2145 /* XM_MAC_PTIME = 0xffff (maximum) */
2146 /* remember this value is defined in big endian (!) */
2147 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
2149 /* Set Pause Mode in Mode Register */
2150 DWord |= XM_PAUSE_MODE;
2152 /* Set Pause Mode in MAC Rx FIFO */
2153 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
2157 * disable pause frame generation is required for 1000BT
2158 * because the XMAC is not reset if the link is going down
2160 /* Disable Pause Mode in Mode Register */
2161 DWord &= ~XM_PAUSE_MODE;
2163 /* Disable Pause Mode in MAC Rx FIFO */
2164 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
2167 XM_OUT32(IoC, Port, XM_MODE, DWord);
2168 } /* SkXmInitPauseMd*/
2171 /******************************************************************************
2173 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
2175 * Description: initializes all the XMACs Phy registers
2182 static void SkXmInitPhyXmac(
2183 SK_AC *pAC, /* adapter context */
2184 SK_IOC IoC, /* IO context */
2185 int Port, /* Port Index (MAC_1 + n) */
2186 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2191 pPrt = &pAC->GIni.GP[Port];
2194 /* Auto-negotiation ? */
2195 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2196 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2197 ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
2198 /* Set DuplexMode in Config register */
2199 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2200 Ctrl |= PHY_CT_DUP_MD;
2204 * Do NOT enable Auto-negotiation here. This would hold
2205 * the link down because no IDLEs are transmitted
2209 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2210 ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
2211 /* Set Auto-negotiation advertisement */
2213 /* Set Full/half duplex capabilities */
2214 switch (pPrt->PLinkMode) {
2215 case SK_LMODE_AUTOHALF:
2216 Ctrl |= PHY_X_AN_HD;
2218 case SK_LMODE_AUTOFULL:
2219 Ctrl |= PHY_X_AN_FD;
2221 case SK_LMODE_AUTOBOTH:
2222 Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
2225 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2229 switch (pPrt->PFlowCtrlMode) {
2230 case SK_FLOW_MODE_NONE:
2231 Ctrl |= PHY_X_P_NO_PAUSE;
2233 case SK_FLOW_MODE_LOC_SEND:
2234 Ctrl |= PHY_X_P_ASYM_MD;
2236 case SK_FLOW_MODE_SYMMETRIC:
2237 Ctrl |= PHY_X_P_SYM_MD;
2239 case SK_FLOW_MODE_SYM_OR_REM:
2240 Ctrl |= PHY_X_P_BOTH_MD;
2243 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2247 /* Write AutoNeg Advertisement Register */
2248 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
2250 /* Restart Auto-negotiation */
2251 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
2255 /* Set the Phy Loopback bit, too */
2256 Ctrl |= PHY_CT_LOOP;
2259 /* Write to the Phy control register */
2260 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
2261 } /* SkXmInitPhyXmac */
2264 /******************************************************************************
2266 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
2268 * Description: initializes all the Broadcom Phy registers
2275 static void SkXmInitPhyBcom(
2276 SK_AC *pAC, /* adapter context */
2277 SK_IOC IoC, /* IO context */
2278 int Port, /* Port Index (MAC_1 + n) */
2279 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2288 Ctrl1 = PHY_CT_SP1000;
2290 Ctrl3 = PHY_SEL_TYPE;
2291 Ctrl4 = PHY_B_PEC_EN_LTR;
2292 Ctrl5 = PHY_B_AC_TX_TST;
2294 pPrt = &pAC->GIni.GP[Port];
2296 /* manually Master/Slave ? */
2297 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2298 Ctrl2 |= PHY_B_1000C_MSE;
2300 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2301 Ctrl2 |= PHY_B_1000C_MSC;
2304 /* Auto-negotiation ? */
2305 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2306 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2307 ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
2308 /* Set DuplexMode in Config register */
2309 Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2311 /* Determine Master/Slave manually if not already done */
2312 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2313 Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
2317 * Do NOT enable Auto-negotiation here. This would hold
2318 * the link down because no IDLES are transmitted
2322 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2323 ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
2324 /* Set Auto-negotiation advertisement */
2327 * Workaround BCOM Errata #1 for the C5 type.
2328 * 1000Base-T Link Acquisition Failure in Slave Mode
2329 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
2331 Ctrl2 |= PHY_B_1000C_RD;
2333 /* Set Full/half duplex capabilities */
2334 switch (pPrt->PLinkMode) {
2335 case SK_LMODE_AUTOHALF:
2336 Ctrl2 |= PHY_B_1000C_AHD;
2338 case SK_LMODE_AUTOFULL:
2339 Ctrl2 |= PHY_B_1000C_AFD;
2341 case SK_LMODE_AUTOBOTH:
2342 Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
2345 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2349 switch (pPrt->PFlowCtrlMode) {
2350 case SK_FLOW_MODE_NONE:
2351 Ctrl3 |= PHY_B_P_NO_PAUSE;
2353 case SK_FLOW_MODE_LOC_SEND:
2354 Ctrl3 |= PHY_B_P_ASYM_MD;
2356 case SK_FLOW_MODE_SYMMETRIC:
2357 Ctrl3 |= PHY_B_P_SYM_MD;
2359 case SK_FLOW_MODE_SYM_OR_REM:
2360 Ctrl3 |= PHY_B_P_BOTH_MD;
2363 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2367 /* Restart Auto-negotiation */
2368 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2371 /* Initialize LED register here? */
2372 /* No. Please do it in SkDgXmitLed() (if required) and swap
2373 init order of LEDs and XMAC. (MAl) */
2375 /* Write 1000Base-T Control Register */
2376 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2377 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2378 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2380 /* Write AutoNeg Advertisement Register */
2381 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2382 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2383 ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2386 /* Set the Phy Loopback bit, too */
2387 Ctrl1 |= PHY_CT_LOOP;
2390 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2391 /* configure FIFO to high latency for transmission of ext. packets */
2392 Ctrl4 |= PHY_B_PEC_HIGH_LA;
2394 /* configure reception of extended packets */
2395 Ctrl5 |= PHY_B_AC_LONG_PACK;
2397 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2400 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2401 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
2403 /* Write to the Phy control register */
2404 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2405 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2406 ("PHY Control Reg=0x%04X\n", Ctrl1));
2407 } /* SkXmInitPhyBcom */
2408 #endif /* GENESIS */
2412 /******************************************************************************
2414 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2416 * Description: initializes all the Marvell Phy registers
2423 static void SkGmInitPhyMarv(
2424 SK_AC *pAC, /* adapter context */
2425 SK_IOC IoC, /* IO context */
2426 int Port, /* Port Index (MAC_1 + n) */
2427 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2436 #if defined(SK_DIAG) || defined(DEBUG)
2440 #endif /* SK_DIAG || DEBUG */
2442 pPrt = &pAC->GIni.GP[Port];
2444 /* Auto-negotiation ? */
2445 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2452 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2453 ("InitPhyMarv: Port %d, auto-negotiation %s\n",
2454 Port, AutoNeg ? "ON" : "OFF"));
2457 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2462 /* Set 'MAC Power up'-bit, set Manual MDI configuration */
2463 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2464 PHY_M_PC_MAC_POW_UP);
2466 else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
2467 /* Read Ext. PHY Specific Control */
2468 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2470 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2471 PHY_M_EC_MAC_S_MSK);
2473 ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
2474 PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
2476 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2477 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2478 ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2481 /* Read PHY Control */
2482 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2484 PhyCtrl |= PHY_CT_RESET;
2485 /* Assert software reset */
2486 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2490 PhyCtrl = 0 /* PHY_CT_COL_TST */;
2492 AutoNegAdv = PHY_SEL_TYPE;
2494 /* manually Master/Slave ? */
2495 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2496 /* enable Manual Master/Slave */
2497 C1000BaseT |= PHY_M_1000C_MSE;
2499 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2500 C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
2504 /* Auto-negotiation ? */
2507 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2508 /* Set Full Duplex Mode */
2509 PhyCtrl |= PHY_CT_DUP_MD;
2512 /* Set Master/Slave manually if not already done */
2513 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2514 C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
2518 switch (pPrt->PLinkSpeed) {
2519 case SK_LSPEED_AUTO:
2520 case SK_LSPEED_1000MBPS:
2521 PhyCtrl |= PHY_CT_SP1000;
2523 case SK_LSPEED_100MBPS:
2524 PhyCtrl |= PHY_CT_SP100;
2526 case SK_LSPEED_10MBPS:
2529 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2534 PhyCtrl |= PHY_CT_RESET;
2537 * Do NOT enable Auto-negotiation here. This would hold
2538 * the link down because no IDLES are transmitted
2542 PhyCtrl |= PHY_CT_ANE;
2544 if (pAC->GIni.GICopperType) {
2545 /* Set Speed capabilities */
2546 switch (pPrt->PLinkSpeed) {
2547 case SK_LSPEED_AUTO:
2548 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2549 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2550 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2552 case SK_LSPEED_1000MBPS:
2553 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2555 case SK_LSPEED_100MBPS:
2556 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2557 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2559 case SK_LSPEED_10MBPS:
2560 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2563 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2567 /* Set Full/half duplex capabilities */
2568 switch (pPrt->PLinkMode) {
2569 case SK_LMODE_AUTOHALF:
2570 C1000BaseT &= ~PHY_M_1000C_AFD;
2571 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2573 case SK_LMODE_AUTOFULL:
2574 C1000BaseT &= ~PHY_M_1000C_AHD;
2575 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2577 case SK_LMODE_AUTOBOTH:
2580 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2584 /* Set Auto-negotiation advertisement */
2585 switch (pPrt->PFlowCtrlMode) {
2586 case SK_FLOW_MODE_NONE:
2587 AutoNegAdv |= PHY_B_P_NO_PAUSE;
2589 case SK_FLOW_MODE_LOC_SEND:
2590 AutoNegAdv |= PHY_B_P_ASYM_MD;
2592 case SK_FLOW_MODE_SYMMETRIC:
2593 AutoNegAdv |= PHY_B_P_SYM_MD;
2595 case SK_FLOW_MODE_SYM_OR_REM:
2596 AutoNegAdv |= PHY_B_P_BOTH_MD;
2599 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2603 else { /* special defines for FIBER (88E1011S only) */
2605 /* Set Full/half duplex capabilities */
2606 switch (pPrt->PLinkMode) {
2607 case SK_LMODE_AUTOHALF:
2608 AutoNegAdv |= PHY_M_AN_1000X_AHD;
2610 case SK_LMODE_AUTOFULL:
2611 AutoNegAdv |= PHY_M_AN_1000X_AFD;
2613 case SK_LMODE_AUTOBOTH:
2614 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2617 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2621 /* Set Auto-negotiation advertisement */
2622 switch (pPrt->PFlowCtrlMode) {
2623 case SK_FLOW_MODE_NONE:
2624 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2626 case SK_FLOW_MODE_LOC_SEND:
2627 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2629 case SK_FLOW_MODE_SYMMETRIC:
2630 AutoNegAdv |= PHY_M_P_SYM_MD_X;
2632 case SK_FLOW_MODE_SYM_OR_REM:
2633 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2636 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2642 /* Restart Auto-negotiation */
2643 PhyCtrl |= PHY_CT_RE_CFG;
2649 * E-mail from Gu Lin (08-03-2002):
2652 /* Program PHY register 30 as 16'h0708 for simulation speed up */
2653 SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
2659 /* Write 1000Base-T Control Register */
2660 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2661 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2662 ("1000B-T Ctrl=0x%04X\n", C1000BaseT));
2664 /* Write AutoNeg Advertisement Register */
2665 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2666 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2667 ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv));
2671 /* Set the PHY Loopback bit */
2672 PhyCtrl |= PHY_CT_LOOP;
2675 /* Program PHY register 16 as 16'h0400 to force link good */
2676 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2680 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2681 /* Write Ext. PHY Specific Control */
2682 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2683 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2688 else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2689 /* Write PHY Specific Control */
2690 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2691 PHY_M_PC_EN_DET_MSK);
2695 /* Write to the PHY Control register */
2696 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2702 LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2704 if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
2705 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2708 if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
2709 LedCtrl |= PHY_M_LEDC_DP_CTRL;
2712 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2714 if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
2715 /* only in forced 100Mbps mode */
2716 if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
2718 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
2719 PHY_M_LED_MO_100(MO_LED_ON));
2724 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2725 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2726 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2727 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2728 #endif /* SK_DIAG */
2730 #if defined(SK_DIAG) || defined(DEBUG)
2731 /* Read PHY Control */
2732 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2733 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2734 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2736 /* Read 1000Base-T Control Register */
2737 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2738 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2739 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
2741 /* Read AutoNeg Advertisement Register */
2742 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2743 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2744 ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv));
2746 /* Read Ext. PHY Specific Control */
2747 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2748 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2749 ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2751 /* Read PHY Status */
2752 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2753 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2754 ("PHY Stat Reg.=0x%04X\n", PhyStat));
2755 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2756 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2757 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
2759 /* Read PHY Specific Status */
2760 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2761 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2762 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
2763 #endif /* SK_DIAG || DEBUG */
2766 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2767 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2768 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2769 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2770 c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2771 c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2772 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2773 #endif /* SK_DIAG */
2777 } /* SkGmInitPhyMarv */
2782 /******************************************************************************
2784 * SkXmInitPhyLone() - Initialize the Level One Phy registers
2786 * Description: initializes all the Level One Phy registers
2793 static void SkXmInitPhyLone(
2794 SK_AC *pAC, /* adapter context */
2795 SK_IOC IoC, /* IO context */
2796 int Port, /* Port Index (MAC_1 + n) */
2797 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2804 Ctrl1 = PHY_CT_SP1000;
2806 Ctrl3 = PHY_SEL_TYPE;
2808 pPrt = &pAC->GIni.GP[Port];
2810 /* manually Master/Slave ? */
2811 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2812 Ctrl2 |= PHY_L_1000C_MSE;
2814 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2815 Ctrl2 |= PHY_L_1000C_MSC;
2818 /* Auto-negotiation ? */
2819 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2821 * level one spec say: "1000Mbps: manual mode not allowed"
2822 * but lets see what happens...
2824 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2825 ("InitPhyLone: no auto-negotiation Port %d\n", Port));
2826 /* Set DuplexMode in Config register */
2827 Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2829 /* Determine Master/Slave manually if not already done */
2830 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2831 Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
2835 * Do NOT enable Auto-negotiation here. This would hold
2836 * the link down because no IDLES are transmitted
2840 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2841 ("InitPhyLone: with auto-negotiation Port %d\n", Port));
2842 /* Set Auto-negotiation advertisement */
2844 /* Set Full/half duplex capabilities */
2845 switch (pPrt->PLinkMode) {
2846 case SK_LMODE_AUTOHALF:
2847 Ctrl2 |= PHY_L_1000C_AHD;
2849 case SK_LMODE_AUTOFULL:
2850 Ctrl2 |= PHY_L_1000C_AFD;
2852 case SK_LMODE_AUTOBOTH:
2853 Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2856 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2860 switch (pPrt->PFlowCtrlMode) {
2861 case SK_FLOW_MODE_NONE:
2862 Ctrl3 |= PHY_L_P_NO_PAUSE;
2864 case SK_FLOW_MODE_LOC_SEND:
2865 Ctrl3 |= PHY_L_P_ASYM_MD;
2867 case SK_FLOW_MODE_SYMMETRIC:
2868 Ctrl3 |= PHY_L_P_SYM_MD;
2870 case SK_FLOW_MODE_SYM_OR_REM:
2871 Ctrl3 |= PHY_L_P_BOTH_MD;
2874 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2878 /* Restart Auto-negotiation */
2879 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2883 /* Write 1000Base-T Control Register */
2884 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2885 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2886 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2888 /* Write AutoNeg Advertisement Register */
2889 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2890 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2891 ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2894 /* Set the Phy Loopback bit, too */
2895 Ctrl1 |= PHY_CT_LOOP;
2898 /* Write to the Phy control register */
2899 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2900 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2901 ("PHY Control Reg=0x%04X\n", Ctrl1));
2902 } /* SkXmInitPhyLone */
2905 /******************************************************************************
2907 * SkXmInitPhyNat() - Initialize the National Phy registers
2909 * Description: initializes all the National Phy registers
2916 static void SkXmInitPhyNat(
2917 SK_AC *pAC, /* adapter context */
2918 SK_IOC IoC, /* IO context */
2919 int Port, /* Port Index (MAC_1 + n) */
2920 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2922 /* todo: National */
2923 } /* SkXmInitPhyNat */
2924 #endif /* OTHER_PHY */
2927 /******************************************************************************
2929 * SkMacInitPhy() - Initialize the PHY registers
2931 * Description: calls the Init PHY routines dep. on board type
2939 SK_AC *pAC, /* adapter context */
2940 SK_IOC IoC, /* IO context */
2941 int Port, /* Port Index (MAC_1 + n) */
2942 SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2946 pPrt = &pAC->GIni.GP[Port];
2949 if (pAC->GIni.GIGenesis) {
2951 switch (pPrt->PhyType) {
2953 SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2956 SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2960 SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2963 SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2965 #endif /* OTHER_PHY */
2968 #endif /* GENESIS */
2971 if (pAC->GIni.GIYukon) {
2973 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2977 } /* SkMacInitPhy */
2981 /******************************************************************************
2983 * SkXmAutoNegDoneXmac() - Auto-negotiation handling
2986 * This function handles the auto-negotiation if the Done bit is set.
2990 * SK_AND_DUP_CAP Duplex capability error happened
2991 * SK_AND_OTHER Other error happened
2993 static int SkXmAutoNegDoneXmac(
2994 SK_AC *pAC, /* adapter context */
2995 SK_IOC IoC, /* IO context */
2996 int Port) /* Port Index (MAC_1 + n) */
2999 SK_U16 ResAb; /* Resolved Ability */
3000 SK_U16 LPAb; /* Link Partner Ability */
3002 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3003 ("AutoNegDoneXmac, Port %d\n", Port));
3005 pPrt = &pAC->GIni.GP[Port];
3007 /* Get PHY parameters */
3008 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
3009 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
3011 if ((LPAb & PHY_X_AN_RFB) != 0) {
3012 /* At least one of the remote fault bit is set */
3014 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3015 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3016 pPrt->PAutoNegFail = SK_TRUE;
3017 return(SK_AND_OTHER);
3020 /* Check Duplex mismatch */
3021 if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
3022 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3024 else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
3025 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3029 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3030 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3031 pPrt->PAutoNegFail = SK_TRUE;
3032 return(SK_AND_DUP_CAP);
3035 /* Check PAUSE mismatch */
3036 /* We are NOT using chapter 4.23 of the Xaqti manual */
3037 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3038 if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
3039 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
3040 (LPAb & PHY_X_P_SYM_MD) != 0) {
3041 /* Symmetric PAUSE */
3042 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3044 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
3045 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
3046 /* Enable PAUSE receive, disable PAUSE transmit */
3047 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3049 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
3050 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
3051 /* Disable PAUSE receive, enable PAUSE transmit */
3052 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3055 /* PAUSE mismatch -> no PAUSE */
3056 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3058 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3061 } /* SkXmAutoNegDoneXmac */
3064 /******************************************************************************
3066 * SkXmAutoNegDoneBcom() - Auto-negotiation handling
3069 * This function handles the auto-negotiation if the Done bit is set.
3073 * SK_AND_DUP_CAP Duplex capability error happened
3074 * SK_AND_OTHER Other error happened
3076 static int SkXmAutoNegDoneBcom(
3077 SK_AC *pAC, /* adapter context */
3078 SK_IOC IoC, /* IO context */
3079 int Port) /* Port Index (MAC_1 + n) */
3082 SK_U16 LPAb; /* Link Partner Ability */
3083 SK_U16 AuxStat; /* Auxiliary Status */
3087 SK_U16 ResAb; /* Resolved Ability */
3090 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3091 ("AutoNegDoneBcom, Port %d\n", Port));
3092 pPrt = &pAC->GIni.GP[Port];
3094 /* Get PHY parameters */
3095 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
3098 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
3101 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
3103 if ((LPAb & PHY_B_AN_RF) != 0) {
3104 /* Remote fault bit is set: Error */
3105 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3106 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3107 pPrt->PAutoNegFail = SK_TRUE;
3108 return(SK_AND_OTHER);
3111 /* Check Duplex mismatch */
3112 if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
3113 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3115 else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
3116 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3120 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3121 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3122 pPrt->PAutoNegFail = SK_TRUE;
3123 return(SK_AND_DUP_CAP);
3128 /* Check Master/Slave resolution */
3129 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3130 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3131 ("Master/Slave Fault Port %d\n", Port));
3132 pPrt->PAutoNegFail = SK_TRUE;
3133 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3134 return(SK_AND_OTHER);
3137 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3138 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
3141 /* Check PAUSE mismatch ??? */
3142 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3143 if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
3144 /* Symmetric PAUSE */
3145 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3147 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
3148 /* Enable PAUSE receive, disable PAUSE transmit */
3149 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3151 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
3152 /* Disable PAUSE receive, enable PAUSE transmit */
3153 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3156 /* PAUSE mismatch -> no PAUSE */
3157 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3159 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3162 } /* SkXmAutoNegDoneBcom */
3163 #endif /* GENESIS */
3167 /******************************************************************************
3169 * SkGmAutoNegDoneMarv() - Auto-negotiation handling
3172 * This function handles the auto-negotiation if the Done bit is set.
3176 * SK_AND_DUP_CAP Duplex capability error happened
3177 * SK_AND_OTHER Other error happened
3179 static int SkGmAutoNegDoneMarv(
3180 SK_AC *pAC, /* adapter context */
3181 SK_IOC IoC, /* IO context */
3182 int Port) /* Port Index (MAC_1 + n) */
3185 SK_U16 LPAb; /* Link Partner Ability */
3186 SK_U16 ResAb; /* Resolved Ability */
3187 SK_U16 AuxStat; /* Auxiliary Status */
3189 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3190 ("AutoNegDoneMarv, Port %d\n", Port));
3191 pPrt = &pAC->GIni.GP[Port];
3193 /* Get PHY parameters */
3194 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
3196 if ((LPAb & PHY_M_AN_RF) != 0) {
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 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
3205 /* Check Master/Slave resolution */
3206 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3207 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3208 ("Master/Slave Fault Port %d\n", Port));
3209 pPrt->PAutoNegFail = SK_TRUE;
3210 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3211 return(SK_AND_OTHER);
3214 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3215 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
3217 /* Read PHY Specific Status */
3218 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
3220 /* Check Speed & Duplex resolved */
3221 if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
3222 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3223 ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
3224 pPrt->PAutoNegFail = SK_TRUE;
3225 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
3226 return(SK_AND_DUP_CAP);
3229 if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
3230 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3233 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3236 /* Check PAUSE mismatch ??? */
3237 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3238 if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
3239 /* Symmetric PAUSE */
3240 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3242 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
3243 /* Enable PAUSE receive, disable PAUSE transmit */
3244 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3246 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
3247 /* Disable PAUSE receive, enable PAUSE transmit */
3248 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3251 /* PAUSE mismatch -> no PAUSE */
3252 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3255 /* set used link speed */
3256 switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
3257 case (unsigned)PHY_M_PS_SPEED_1000:
3258 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3260 case PHY_M_PS_SPEED_100:
3261 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
3264 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
3268 } /* SkGmAutoNegDoneMarv */
3273 /******************************************************************************
3275 * SkXmAutoNegDoneLone() - Auto-negotiation handling
3278 * This function handles the auto-negotiation if the Done bit is set.
3282 * SK_AND_DUP_CAP Duplex capability error happened
3283 * SK_AND_OTHER Other error happened
3285 static int SkXmAutoNegDoneLone(
3286 SK_AC *pAC, /* adapter context */
3287 SK_IOC IoC, /* IO context */
3288 int Port) /* Port Index (MAC_1 + n) */
3291 SK_U16 ResAb; /* Resolved Ability */
3292 SK_U16 LPAb; /* Link Partner Ability */
3293 SK_U16 QuickStat; /* Auxiliary Status */
3295 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3296 ("AutoNegDoneLone, Port %d\n", Port));
3297 pPrt = &pAC->GIni.GP[Port];
3299 /* Get PHY parameters */
3300 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
3301 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
3302 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
3304 if ((LPAb & PHY_L_AN_RF) != 0) {
3305 /* Remote fault bit is set */
3307 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3308 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3309 pPrt->PAutoNegFail = SK_TRUE;
3310 return(SK_AND_OTHER);
3313 /* Check Duplex mismatch */
3314 if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
3315 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3318 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3321 /* Check Master/Slave resolution */
3322 if ((ResAb & PHY_L_1000S_MSF) != 0) {
3324 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3325 ("Master/Slave Fault Port %d\n", Port));
3326 pPrt->PAutoNegFail = SK_TRUE;
3327 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3328 return(SK_AND_OTHER);
3330 else if (ResAb & PHY_L_1000S_MSR) {
3331 pPrt->PMSStatus = SK_MS_STAT_MASTER;
3334 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
3337 /* Check PAUSE mismatch */
3338 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3339 /* we must manually resolve the abilities here */
3340 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3341 switch (pPrt->PFlowCtrlMode) {
3342 case SK_FLOW_MODE_NONE:
3345 case SK_FLOW_MODE_LOC_SEND:
3346 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3347 (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
3348 /* Disable PAUSE receive, enable PAUSE transmit */
3349 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3352 case SK_FLOW_MODE_SYMMETRIC:
3353 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3354 /* Symmetric PAUSE */
3355 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3358 case SK_FLOW_MODE_SYM_OR_REM:
3359 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3360 PHY_L_QS_AS_PAUSE) {
3361 /* Enable PAUSE receive, disable PAUSE transmit */
3362 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3364 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3365 /* Symmetric PAUSE */
3366 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3370 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3375 } /* SkXmAutoNegDoneLone */
3378 /******************************************************************************
3380 * SkXmAutoNegDoneNat() - Auto-negotiation handling
3383 * This function handles the auto-negotiation if the Done bit is set.
3387 * SK_AND_DUP_CAP Duplex capability error happened
3388 * SK_AND_OTHER Other error happened
3390 static int SkXmAutoNegDoneNat(
3391 SK_AC *pAC, /* adapter context */
3392 SK_IOC IoC, /* IO context */
3393 int Port) /* Port Index (MAC_1 + n) */
3395 /* todo: National */
3397 } /* SkXmAutoNegDoneNat */
3398 #endif /* OTHER_PHY */
3401 /******************************************************************************
3403 * SkMacAutoNegDone() - Auto-negotiation handling
3405 * Description: calls the auto-negotiation done routines dep. on board type
3409 * SK_AND_DUP_CAP Duplex capability error happened
3410 * SK_AND_OTHER Other error happened
3412 int SkMacAutoNegDone(
3413 SK_AC *pAC, /* adapter context */
3414 SK_IOC IoC, /* IO context */
3415 int Port) /* Port Index (MAC_1 + n) */
3422 pPrt = &pAC->GIni.GP[Port];
3425 if (pAC->GIni.GIGenesis) {
3427 switch (pPrt->PhyType) {
3430 Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3433 Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3437 Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3440 Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3442 #endif /* OTHER_PHY */
3444 return(SK_AND_OTHER);
3447 #endif /* GENESIS */
3450 if (pAC->GIni.GIYukon) {
3452 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3456 if (Rtv != SK_AND_OK) {
3460 /* We checked everything and may now enable the link */
3461 pPrt->PAutoNegFail = SK_FALSE;
3463 SkMacRxTxEnable(pAC, IoC, Port);
3466 } /* SkMacAutoNegDone */
3470 /******************************************************************************
3472 * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3475 * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3480 static void SkXmSetRxTxEn(
3481 SK_AC *pAC, /* Adapter Context */
3482 SK_IOC IoC, /* IO context */
3483 int Port, /* Port Index (MAC_1 + n) */
3484 int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3488 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3490 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3491 case SK_MAC_LOOPB_ON:
3492 Word |= XM_MMU_MAC_LB;
3494 case SK_MAC_LOOPB_OFF:
3495 Word &= ~XM_MMU_MAC_LB;
3499 switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
3500 case SK_PHY_LOOPB_ON:
3501 Word |= XM_MMU_GMII_LOOP;
3503 case SK_PHY_LOOPB_OFF:
3504 Word &= ~XM_MMU_GMII_LOOP;
3508 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3509 case SK_PHY_FULLD_ON:
3510 Word |= XM_MMU_GMII_FD;
3512 case SK_PHY_FULLD_OFF:
3513 Word &= ~XM_MMU_GMII_FD;
3517 XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3519 /* dummy read to ensure writing */
3520 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3522 } /* SkXmSetRxTxEn */
3523 #endif /* GENESIS */
3527 /******************************************************************************
3529 * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3532 * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3537 static void SkGmSetRxTxEn(
3538 SK_AC *pAC, /* Adapter Context */
3539 SK_IOC IoC, /* IO context */
3540 int Port, /* Port Index (MAC_1 + n) */
3541 int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */
3545 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3547 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3548 case SK_MAC_LOOPB_ON:
3549 Ctrl |= GM_GPCR_LOOP_ENA;
3551 case SK_MAC_LOOPB_OFF:
3552 Ctrl &= ~GM_GPCR_LOOP_ENA;
3556 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3557 case SK_PHY_FULLD_ON:
3558 Ctrl |= GM_GPCR_DUP_FULL;
3560 case SK_PHY_FULLD_OFF:
3561 Ctrl &= ~GM_GPCR_DUP_FULL;
3565 GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Ctrl | GM_GPCR_RX_ENA |
3568 /* dummy read to ensure writing */
3569 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3571 } /* SkGmSetRxTxEn */
3576 /******************************************************************************
3578 * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3580 * Description: calls the Special Set Rx/Tx Enable routines dep. on board type
3584 void SkMacSetRxTxEn(
3585 SK_AC *pAC, /* Adapter Context */
3586 SK_IOC IoC, /* IO context */
3587 int Port, /* Port Index (MAC_1 + n) */
3591 if (pAC->GIni.GIGenesis) {
3593 SkXmSetRxTxEn(pAC, IoC, Port, Para);
3595 #endif /* GENESIS */
3598 if (pAC->GIni.GIYukon) {
3600 SkGmSetRxTxEn(pAC, IoC, Port, Para);
3604 } /* SkMacSetRxTxEn */
3605 #endif /* !SK_SLIM */
3608 /******************************************************************************
3610 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3612 * Description: enables Rx/Tx dep. on board type
3616 * != 0 Error happened
3618 int SkMacRxTxEnable(
3619 SK_AC *pAC, /* adapter context */
3620 SK_IOC IoC, /* IO context */
3621 int Port) /* Port Index (MAC_1 + n) */
3624 SK_U16 Reg; /* 16-bit register value */
3625 SK_U16 IntMask; /* MAC interrupt mask */
3630 pPrt = &pAC->GIni.GP[Port];
3632 if (!pPrt->PHWLinkUp) {
3633 /* The Hardware link is NOT up */
3637 if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3638 pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3639 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3640 pPrt->PAutoNegFail) {
3641 /* Auto-negotiation is not done or failed */
3646 if (pAC->GIni.GIGenesis) {
3647 /* set Duplex Mode and Pause Mode */
3648 SkXmInitDupMd(pAC, IoC, Port);
3650 SkXmInitPauseMd(pAC, IoC, Port);
3653 * Initialize the Interrupt Mask Register. Default IRQs are...
3654 * - Link Asynchronous Event
3655 * - Link Partner requests config
3656 * - Auto Negotiation Done
3657 * - Rx Counter Event Overflow
3658 * - Tx Counter Event Overflow
3659 * - Transmit FIFO Underrun
3661 IntMask = XM_DEF_MSK;
3664 /* add IRQ for Receive FIFO Overflow */
3665 IntMask &= ~XM_IS_RXF_OV;
3668 if (pPrt->PhyType != SK_PHY_XMAC) {
3669 /* disable GP0 interrupt bit */
3670 IntMask |= XM_IS_INP_ASS;
3672 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
3674 /* get MMU Command Reg. */
3675 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
3677 if (pPrt->PhyType != SK_PHY_XMAC &&
3678 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3679 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3680 /* set to Full Duplex */
3681 Reg |= XM_MMU_GMII_FD;
3684 switch (pPrt->PhyType) {
3687 * Workaround BCOM Errata (#10523) for all BCom Phys
3688 * Enable Power Management after link up
3690 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3691 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3692 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3693 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
3694 (SK_U16)PHY_B_DEF_MSK);
3698 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3702 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3703 /* no interrupts possible from National ??? */
3705 #endif /* OTHER_PHY */
3709 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3711 #endif /* GENESIS */
3714 if (pAC->GIni.GIYukon) {
3716 * Initialize the Interrupt Mask Register. Default IRQs are...
3717 * - Rx Counter Event Overflow
3718 * - Tx Counter Event Overflow
3719 * - Transmit FIFO Underrun
3721 IntMask = GMAC_DEF_MSK;
3724 /* add IRQ for Receive FIFO Overrun */
3725 IntMask |= GM_IS_RX_FF_OR;
3728 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
3730 /* get General Purpose Control */
3731 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
3733 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3734 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3735 /* set to Full Duplex */
3736 Reg |= GM_GPCR_DUP_FULL;
3740 GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
3744 /* Enable all PHY interrupts */
3745 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
3746 (SK_U16)PHY_M_DEF_MSK);
3753 } /* SkMacRxTxEnable */
3756 /******************************************************************************
3758 * SkMacRxTxDisable() - Disable Receiver and Transmitter
3760 * Description: disables Rx/Tx dep. on board type
3764 void SkMacRxTxDisable(
3765 SK_AC *pAC, /* Adapter Context */
3766 SK_IOC IoC, /* IO context */
3767 int Port) /* Port Index (MAC_1 + n) */
3772 if (pAC->GIni.GIGenesis) {
3774 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3776 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
3778 /* dummy read to ensure writing */
3779 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3781 #endif /* GENESIS */
3784 if (pAC->GIni.GIYukon) {
3786 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3788 GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
3791 /* dummy read to ensure writing */
3792 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3796 } /* SkMacRxTxDisable */
3799 /******************************************************************************
3801 * SkMacIrqDisable() - Disable IRQ from MAC
3803 * Description: sets the IRQ-mask to disable IRQ dep. on board type
3807 void SkMacIrqDisable(
3808 SK_AC *pAC, /* Adapter Context */
3809 SK_IOC IoC, /* IO context */
3810 int Port) /* Port Index (MAC_1 + n) */
3817 pPrt = &pAC->GIni.GP[Port];
3820 if (pAC->GIni.GIGenesis) {
3822 /* disable all XMAC IRQs */
3823 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
3825 /* Disable all PHY interrupts */
3826 switch (pPrt->PhyType) {
3828 /* Make sure that PHY is initialized */
3829 if (pPrt->PState != SK_PRT_RESET) {
3830 /* NOT allowed if BCOM is in RESET state */
3831 /* Workaround BCOM Errata (#10523) all BCom */
3832 /* Disable Power Management if link is down */
3833 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3834 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3835 (SK_U16)(Word | PHY_B_AC_DIS_PM));
3836 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3841 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3845 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3847 #endif /* OTHER_PHY */
3850 #endif /* GENESIS */
3853 if (pAC->GIni.GIYukon) {
3854 /* disable all GMAC IRQs */
3855 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
3858 /* Disable all PHY interrupts */
3859 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3864 } /* SkMacIrqDisable */
3868 /******************************************************************************
3870 * SkXmSendCont() - Enable / Disable Send Continuous Mode
3872 * Description: enable / disable Send Continuous Mode on XMAC
3878 SK_AC *pAC, /* adapter context */
3879 SK_IOC IoC, /* IO context */
3880 int Port, /* Port Index (MAC_1 + n) */
3881 SK_BOOL Enable) /* Enable / Disable */
3885 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3888 MdReg |= XM_MD_TX_CONT;
3891 MdReg &= ~XM_MD_TX_CONT;
3893 /* setup Mode Register */
3894 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3896 } /* SkXmSendCont */
3899 /******************************************************************************
3901 * SkMacTimeStamp() - Enable / Disable Time Stamp
3903 * Description: enable / disable Time Stamp generation for Rx packets
3908 void SkMacTimeStamp(
3909 SK_AC *pAC, /* adapter context */
3910 SK_IOC IoC, /* IO context */
3911 int Port, /* Port Index (MAC_1 + n) */
3912 SK_BOOL Enable) /* Enable / Disable */
3917 if (pAC->GIni.GIGenesis) {
3919 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3925 MdReg &= ~XM_MD_ATS;
3927 /* setup Mode Register */
3928 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3932 TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3935 TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3937 /* Start/Stop Time Stamp Timer */
3938 SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
3941 } /* SkMacTimeStamp*/
3943 #else /* !SK_DIAG */
3946 /******************************************************************************
3948 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
3950 * This function analyses the Interrupt status word. If any of the
3951 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
3954 void SkXmAutoNegLipaXmac(
3955 SK_AC *pAC, /* adapter context */
3956 SK_IOC IoC, /* IO context */
3957 int Port, /* Port Index (MAC_1 + n) */
3958 SK_U16 IStatus) /* Interrupt Status word to analyse */
3962 pPrt = &pAC->GIni.GP[Port];
3964 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3965 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
3967 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3968 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
3970 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
3972 } /* SkXmAutoNegLipaXmac */
3973 #endif /* GENESIS */
3976 /******************************************************************************
3978 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
3980 * This function analyses the PHY status word.
3981 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
3984 void SkMacAutoNegLipaPhy(
3985 SK_AC *pAC, /* adapter context */
3986 SK_IOC IoC, /* IO context */
3987 int Port, /* Port Index (MAC_1 + n) */
3988 SK_U16 PhyStat) /* PHY Status word to analyse */
3992 pPrt = &pAC->GIni.GP[Port];
3994 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3995 (PhyStat & PHY_ST_AN_OVER) != 0) {
3997 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3998 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
4000 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
4002 } /* SkMacAutoNegLipaPhy */
4006 /******************************************************************************
4008 * SkXmIrq() - Interrupt Service Routine
4010 * Description: services an Interrupt Request of the XMAC
4013 * With an external PHY, some interrupt bits are not meaningfull any more:
4014 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
4015 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
4016 * - Page Received (bit #9) XM_IS_RX_PAGE
4017 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
4018 * - AutoNegDone (bit #7) XM_IS_AND
4019 * Also probably not valid any more is the GP0 input bit:
4020 * - GPRegisterBit0set XM_IS_INP_ASS
4026 SK_AC *pAC, /* adapter context */
4027 SK_IOC IoC, /* IO context */
4028 int Port) /* Port Index (MAC_1 + n) */
4032 SK_U16 IStatus; /* Interrupt status read from the XMAC */
4035 SK_U64 OverflowStatus;
4038 pPrt = &pAC->GIni.GP[Port];
4040 XM_IN16(IoC, Port, XM_ISRC, &IStatus);
4042 /* LinkPartner Auto-negable? */
4043 if (pPrt->PhyType == SK_PHY_XMAC) {
4044 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
4047 /* mask bits that are not used with ext. PHY */
4048 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
4049 XM_IS_RX_PAGE | XM_IS_TX_PAGE |
4050 XM_IS_AND | XM_IS_INP_ASS);
4053 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4054 ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
4056 if (!pPrt->PHWLinkUp) {
4057 /* Spurious XMAC interrupt */
4058 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4059 ("SkXmIrq: spurious interrupt on Port %d\n", Port));
4063 if ((IStatus & XM_IS_INP_ASS) != 0) {
4064 /* Reread ISR Register if link is not in sync */
4065 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
4067 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4068 ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
4069 Port, IStatus, IStatus2));
4070 IStatus &= ~XM_IS_INP_ASS;
4071 IStatus |= IStatus2;
4074 if ((IStatus & XM_IS_LNK_AE) != 0) {
4075 /* not used, GP0 is used instead */
4078 if ((IStatus & XM_IS_TX_ABORT) != 0) {
4082 if ((IStatus & XM_IS_FRC_INT) != 0) {
4083 /* not used, use ASIC IRQ instead if needed */
4086 if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
4087 SkHWLinkDown(pAC, IoC, Port);
4089 /* Signal to RLMT */
4090 Para.Para32[0] = (SK_U32)Port;
4091 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
4093 /* Start workaround Errata #2 timer */
4094 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
4095 SKGE_HWAC, SK_HWEV_WATIM, Para);
4098 if ((IStatus & XM_IS_RX_PAGE) != 0) {
4102 if ((IStatus & XM_IS_TX_PAGE) != 0) {
4106 if ((IStatus & XM_IS_AND) != 0) {
4107 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4108 ("SkXmIrq: AND on link that is up Port %d\n", Port));
4111 if ((IStatus & XM_IS_TSC_OV) != 0) {
4115 /* Combined Tx & Rx Counter Overflow SIRQ Event */
4116 if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
4118 SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
4120 Para.Para32[0] = (SK_U32)Port;
4121 Para.Para32[1] = (SK_U32)IStatus;
4122 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
4123 #endif /* SK_SLIM */
4126 if ((IStatus & XM_IS_RXF_OV) != 0) {
4127 /* normal situation -> no effect */
4133 if ((IStatus & XM_IS_TXF_UR) != 0) {
4134 /* may NOT happen -> error log */
4135 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
4138 if ((IStatus & XM_IS_TX_COMP) != 0) {
4139 /* not served here */
4142 if ((IStatus & XM_IS_RX_COMP) != 0) {
4143 /* not served here */
4146 #endif /* GENESIS */
4150 /******************************************************************************
4152 * SkGmIrq() - Interrupt Service Routine
4154 * Description: services an Interrupt Request of the GMAC
4162 SK_AC *pAC, /* adapter context */
4163 SK_IOC IoC, /* IO context */
4164 int Port) /* Port Index (MAC_1 + n) */
4167 SK_U8 IStatus; /* Interrupt status */
4169 SK_U64 OverflowStatus;
4174 pPrt = &pAC->GIni.GP[Port];
4176 SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
4179 /* LinkPartner Auto-negable? */
4180 SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
4183 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4184 ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
4186 /* Combined Tx & Rx Counter Overflow SIRQ Event */
4187 if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
4188 /* these IRQs will be cleared by reading GMACs register */
4190 SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
4192 Para.Para32[0] = (SK_U32)Port;
4193 Para.Para32[1] = (SK_U32)IStatus;
4194 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
4198 if (IStatus & GM_IS_RX_FF_OR) {
4199 /* clear GMAC Rx FIFO Overrun IRQ */
4200 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
4206 if (IStatus & GM_IS_TX_FF_UR) {
4207 /* clear GMAC Tx FIFO Underrun IRQ */
4208 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
4209 /* may NOT happen -> error log */
4210 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
4213 if (IStatus & GM_IS_TX_COMPL) {
4214 /* not served here */
4217 if (IStatus & GM_IS_RX_COMPL) {
4218 /* not served here */
4224 /******************************************************************************
4226 * SkMacIrq() - Interrupt Service Routine for MAC
4228 * Description: calls the Interrupt Service Routine dep. on board type
4234 SK_AC *pAC, /* adapter context */
4235 SK_IOC IoC, /* IO context */
4236 int Port) /* Port Index (MAC_1 + n) */
4239 if (pAC->GIni.GIGenesis) {
4241 SkXmIrq(pAC, IoC, Port);
4243 #endif /* GENESIS */
4246 if (pAC->GIni.GIYukon) {
4248 SkGmIrq(pAC, IoC, Port);
4254 #endif /* !SK_DIAG */
4257 /******************************************************************************
4259 * SkXmUpdateStats() - Force the XMAC to output the current statistic
4262 * The XMAC holds its statistic internally. To obtain the current
4263 * values a command must be sent so that the statistic data will
4264 * be written to a predefined memory area on the adapter.
4268 * 1: something went wrong
4270 int SkXmUpdateStats(
4271 SK_AC *pAC, /* adapter context */
4272 SK_IOC IoC, /* IO context */
4273 unsigned int Port) /* Port Index (MAC_1 + n) */
4279 pPrt = &pAC->GIni.GP[Port];
4282 /* Send an update command to XMAC specified */
4283 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
4286 * It is an auto-clearing register. If the command bits
4287 * went to zero again, the statistics are transferred.
4288 * Normally the command should be executed immediately.
4289 * But just to be sure we execute a loop.
4293 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
4295 if (++WaitIndex > 10) {
4297 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
4301 } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
4304 } /* SkXmUpdateStats */
4307 /******************************************************************************
4309 * SkXmMacStatistic() - Get XMAC counter value
4312 * Gets the 32bit counter value. Except for the octet counters
4313 * the lower 32bit are counted in hardware and the upper 32bit
4314 * must be counted in software by monitoring counter overflow interrupts.
4318 * 1: something went wrong
4320 int SkXmMacStatistic(
4321 SK_AC *pAC, /* adapter context */
4322 SK_IOC IoC, /* IO context */
4323 unsigned int Port, /* Port Index (MAC_1 + n) */
4324 SK_U16 StatAddr, /* MIB counter base address */
4325 SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
4327 if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
4329 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4334 XM_IN32(IoC, Port, StatAddr, pVal);
4337 } /* SkXmMacStatistic */
4340 /******************************************************************************
4342 * SkXmResetCounter() - Clear MAC statistic counter
4345 * Force the XMAC to clear its statistic counter.
4349 * 1: something went wrong
4351 int SkXmResetCounter(
4352 SK_AC *pAC, /* adapter context */
4353 SK_IOC IoC, /* IO context */
4354 unsigned int Port) /* Port Index (MAC_1 + n) */
4356 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4357 /* Clear two times according to Errata #3 */
4358 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4361 } /* SkXmResetCounter */
4364 /******************************************************************************
4366 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4369 * Checks the source causing an counter overflow interrupt. On success the
4370 * resulting counter overflow status is written to <pStatus>, whereas the
4371 * upper dword stores the XMAC ReceiveCounterEvent register and the lower
4372 * dword the XMAC TransmitCounterEvent register.
4375 * For XMAC the interrupt source is a self-clearing register, so the source
4376 * must be checked only once. SIRQ module does another check to be sure
4377 * that no interrupt get lost during process time.
4381 * 1: something went wrong
4383 int SkXmOverflowStatus(
4384 SK_AC *pAC, /* adapter context */
4385 SK_IOC IoC, /* IO context */
4386 unsigned int Port, /* Port Index (MAC_1 + n) */
4387 SK_U16 IStatus, /* Interupt Status from MAC */
4388 SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
4390 SK_U64 Status; /* Overflow status */
4395 if ((IStatus & XM_IS_RXC_OV) != 0) {
4397 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
4398 Status |= (SK_U64)RegVal << 32;
4401 if ((IStatus & XM_IS_TXC_OV) != 0) {
4403 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
4404 Status |= (SK_U64)RegVal;
4410 } /* SkXmOverflowStatus */
4411 #endif /* GENESIS */
4415 /******************************************************************************
4417 * SkGmUpdateStats() - Force the GMAC to output the current statistic
4420 * Empty function for GMAC. Statistic data is accessible in direct way.
4424 * 1: something went wrong
4426 int SkGmUpdateStats(
4427 SK_AC *pAC, /* adapter context */
4428 SK_IOC IoC, /* IO context */
4429 unsigned int Port) /* Port Index (MAC_1 + n) */
4435 /******************************************************************************
4437 * SkGmMacStatistic() - Get GMAC counter value
4440 * Gets the 32bit counter value. Except for the octet counters
4441 * the lower 32bit are counted in hardware and the upper 32bit
4442 * must be counted in software by monitoring counter overflow interrupts.
4446 * 1: something went wrong
4448 int SkGmMacStatistic(
4449 SK_AC *pAC, /* adapter context */
4450 SK_IOC IoC, /* IO context */
4451 unsigned int Port, /* Port Index (MAC_1 + n) */
4452 SK_U16 StatAddr, /* MIB counter base address */
4453 SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
4456 if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
4458 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4460 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4461 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
4465 GM_IN32(IoC, Port, StatAddr, pVal);
4468 } /* SkGmMacStatistic */
4471 /******************************************************************************
4473 * SkGmResetCounter() - Clear MAC statistic counter
4476 * Force GMAC to clear its statistic counter.
4480 * 1: something went wrong
4482 int SkGmResetCounter(
4483 SK_AC *pAC, /* adapter context */
4484 SK_IOC IoC, /* IO context */
4485 unsigned int Port) /* Port Index (MAC_1 + n) */
4487 SK_U16 Reg; /* Phy Address Register */
4491 GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4493 /* set MIB Clear Counter Mode */
4494 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
4496 /* read all MIB Counters with Clear Mode set */
4497 for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4498 /* the reset is performed only when the lower 16 bits are read */
4499 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4502 /* clear MIB Clear Counter Mode */
4503 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4506 } /* SkGmResetCounter */
4509 /******************************************************************************
4511 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4514 * Checks the source causing an counter overflow interrupt. On success the
4515 * resulting counter overflow status is written to <pStatus>, whereas the
4516 * the following bit coding is used:
4518 * 55:48 - TxRx interrupt register bit7:0
4519 * 32:47 - Rx interrupt register
4521 * 23:16 - TxRx interrupt register bit15:8
4522 * 15:0 - Tx interrupt register
4526 * 1: something went wrong
4528 int SkGmOverflowStatus(
4529 SK_AC *pAC, /* adapter context */
4530 SK_IOC IoC, /* IO context */
4531 unsigned int Port, /* Port Index (MAC_1 + n) */
4532 SK_U16 IStatus, /* Interupt Status from MAC */
4533 SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
4535 SK_U64 Status; /* Overflow status */
4540 if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4541 /* this register is self-clearing after read */
4542 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4543 Status |= (SK_U64)RegVal << 32;
4546 if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4547 /* this register is self-clearing after read */
4548 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4549 Status |= (SK_U64)RegVal;
4552 /* this register is self-clearing after read */
4553 GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4554 /* Rx overflow interrupt register bits (LoByte)*/
4555 Status |= (SK_U64)((SK_U8)RegVal) << 48;
4556 /* Tx overflow interrupt register bits (HiByte)*/
4557 Status |= (SK_U64)(RegVal >> 8) << 16;
4562 } /* SkGmOverflowStatus */
4566 /******************************************************************************
4568 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4571 * starts the cable diagnostic test if 'StartTest' is true
4572 * gets the results if 'StartTest' is true
4574 * NOTE: this test is meaningful only when link is down
4578 * 1: no YUKON copper
4579 * 2: test in progress
4581 int SkGmCableDiagStatus(
4582 SK_AC *pAC, /* adapter context */
4583 SK_IOC IoC, /* IO context */
4584 int Port, /* Port Index (MAC_1 + n) */
4585 SK_BOOL StartTest) /* flag for start / get result */
4591 pPrt = &pAC->GIni.GP[Port];
4593 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
4599 /* only start the cable test */
4600 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4601 /* apply TDR workaround from Marvell */
4602 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
4604 SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4605 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4606 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4607 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4608 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4611 /* set address to 0 for MDI[0] */
4612 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4614 /* Read Cable Diagnostic Reg */
4615 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4617 /* start Cable Diagnostic Test */
4618 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4619 (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
4624 /* Read Cable Diagnostic Reg */
4625 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4627 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4628 ("PHY Cable Diag.=0x%04X\n", RegVal));
4630 if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4631 /* test is running */
4635 /* get the test results */
4636 for (i = 0; i < 4; i++) {
4637 /* set address to i for MDI[i] */
4638 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4640 /* get Cable Diagnostic values */
4641 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4643 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4645 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4649 } /* SkGmCableDiagStatus */
4650 #endif /* !SK_SLIM */