blob: e6b5a95d4a78348dc787cbe6bc14e4d753ad5ea6 [file] [log] [blame]
wdenkeb20ad32003-09-05 23:19:14 +00001/******************************************************************************
2 *
3 * Name: skxmac2.c
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.91 $
6 * Date: $Date: 2003/02/05 15:09:34 $
7 * Purpose: Contains functions to initialize the MACs and PHYs
8 *
9 ******************************************************************************/
10
11/******************************************************************************
12 *
13 * (C)Copyright 1998-2003 SysKonnect GmbH.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * The information in this file is provided "AS IS" without warranty.
21 *
22 ******************************************************************************/
23
24/******************************************************************************
25 *
26 * History:
27 *
28 * $Log: skxmac2.c,v $
29 * Revision 1.91 2003/02/05 15:09:34 rschmidt
30 * Removed setting of 'Collision Test'-bit in SkGmInitPhyMarv().
31 * Disabled auto-update for speed, duplex and flow-control when
32 * auto-negotiation is not enabled (Bug Id #10766).
33 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000034 *
wdenkeb20ad32003-09-05 23:19:14 +000035 * Revision 1.90 2003/01/29 13:35:19 rschmidt
36 * Increment Rx FIFO Overflow counter only in DEBUG-mode.
37 * Corrected define for blinking active LED.
wdenk9c53f402003-10-15 23:53:47 +000038 *
wdenkeb20ad32003-09-05 23:19:14 +000039 * Revision 1.89 2003/01/28 16:37:45 rschmidt
40 * Changed init for blinking active LED
wdenk9c53f402003-10-15 23:53:47 +000041 *
wdenkeb20ad32003-09-05 23:19:14 +000042 * Revision 1.88 2003/01/28 10:09:38 rschmidt
43 * Added debug outputs in SkGmInitMac().
44 * Added customized init of LED registers in SkGmInitPhyMarv(),
45 * for blinking active LED (#ifdef ACT_LED_BLINK) and
46 * for normal duplex LED (#ifdef DUP_LED_NORMAL).
47 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000048 *
wdenkeb20ad32003-09-05 23:19:14 +000049 * Revision 1.87 2002/12/10 14:39:05 rschmidt
50 * Improved initialization of GPHY in SkGmInitPhyMarv().
51 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000052 *
wdenkeb20ad32003-09-05 23:19:14 +000053 * Revision 1.86 2002/12/09 15:01:12 rschmidt
54 * Added setup of Ext. PHY Specific Ctrl Reg (downshift feature).
wdenk9c53f402003-10-15 23:53:47 +000055 *
wdenkeb20ad32003-09-05 23:19:14 +000056 * Revision 1.85 2002/12/05 14:09:16 rschmidt
57 * Improved avoiding endless loop in SkGmPhyWrite(), SkGmPhyWrite().
58 * Added additional advertising for 10Base-T when 100Base-T is selected.
59 * Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter.
60 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000061 *
wdenkeb20ad32003-09-05 23:19:14 +000062 * Revision 1.84 2002/11/15 12:50:09 rschmidt
63 * Changed SkGmCableDiagStatus() when getting results.
wdenk9c53f402003-10-15 23:53:47 +000064 *
wdenkeb20ad32003-09-05 23:19:14 +000065 * Revision 1.83 2002/11/13 10:28:29 rschmidt
66 * Added some typecasts to avoid compiler warnings.
wdenk9c53f402003-10-15 23:53:47 +000067 *
wdenkeb20ad32003-09-05 23:19:14 +000068 * Revision 1.82 2002/11/13 09:20:46 rschmidt
69 * Replaced for(..) with do {} while (...) in SkXmUpdateStats().
70 * Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic().
71 * Added SkGmCableDiagStatus() for Virtual Cable Test (VCT).
72 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000073 *
wdenkeb20ad32003-09-05 23:19:14 +000074 * Revision 1.81 2002/10/28 14:28:08 rschmidt
75 * Changed MAC address setup for GMAC in SkGmInitMac().
76 * Optimized handling of counter overflow IRQ in SkGmOverflowStatus().
77 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000078 *
wdenkeb20ad32003-09-05 23:19:14 +000079 * Revision 1.80 2002/10/14 15:29:44 rschmidt
80 * Corrected disabling of all PHY IRQs.
81 * Added WA for deviation #16 (address used for pause packets).
82 * Set Pause Mode in SkMacRxTxEnable() only for Genesis.
83 * Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode.
84 * SkXmTimeStamp() replaced by SkMacTimeStamp().
85 * Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq().
86 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000087 *
wdenkeb20ad32003-09-05 23:19:14 +000088 * Revision 1.79 2002/10/10 15:55:36 mkarl
89 * changes for PLinkSpeedUsed
wdenk9c53f402003-10-15 23:53:47 +000090 *
wdenkeb20ad32003-09-05 23:19:14 +000091 * Revision 1.78 2002/09/12 09:39:51 rwahl
92 * Removed deactivate code for SIRQ overflow event separate for TX/RX.
wdenk9c53f402003-10-15 23:53:47 +000093 *
wdenkeb20ad32003-09-05 23:19:14 +000094 * Revision 1.77 2002/09/09 12:26:37 mkarl
95 * added handling for Yukon to SkXmTimeStamp
wdenk9c53f402003-10-15 23:53:47 +000096 *
wdenkeb20ad32003-09-05 23:19:14 +000097 * Revision 1.76 2002/08/21 16:41:16 rschmidt
98 * Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE.
99 * Added forced speed settings in SkGmInitPhyMarv().
100 * Added settings of full/half duplex capabilities for YUKON Fiber.
101 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000102 *
wdenkeb20ad32003-09-05 23:19:14 +0000103 * Revision 1.75 2002/08/16 15:12:01 rschmidt
104 * Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
105 * Added function SkMacHashing() for ADDR-Module.
106 * Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced
107 * with macros).
108 * Removed functions SkGmGetMuxConfig().
109 * Added HWCFG_MODE init for YUKON Fiber.
110 * Changed initialization of GPHY in SkGmInitPhyMarv().
111 * Changed check of parameter in SkXmMacStatistic().
112 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000113 *
wdenkeb20ad32003-09-05 23:19:14 +0000114 * Revision 1.74 2002/08/12 14:00:17 rschmidt
115 * Replaced usage of Broadcom PHY Ids with defines.
116 * Corrected error messages in SkGmMacStatistic().
117 * Made SkMacPromiscMode() public for ADDR-Modul.
118 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000119 *
wdenkeb20ad32003-09-05 23:19:14 +0000120 * Revision 1.73 2002/08/08 16:26:24 rschmidt
121 * Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac().
122 * Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM.
123 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000124 *
wdenkeb20ad32003-09-05 23:19:14 +0000125 * Revision 1.72 2002/07/24 15:11:19 rschmidt
126 * Fixed wrong placement of parenthesis.
127 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000128 *
wdenkeb20ad32003-09-05 23:19:14 +0000129 * Revision 1.71 2002/07/23 16:05:18 rschmidt
130 * Added global functions for PHY: SkGePhyRead(), SkGePhyWrite().
131 * Fixed Tx Counter Overflow IRQ (Bug ID #10730).
132 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000133 *
wdenkeb20ad32003-09-05 23:19:14 +0000134 * Revision 1.70 2002/07/18 14:27:27 rwahl
135 * Fixed syntax error.
wdenk9c53f402003-10-15 23:53:47 +0000136 *
wdenkeb20ad32003-09-05 23:19:14 +0000137 * Revision 1.69 2002/07/17 17:08:47 rwahl
138 * Fixed check in SkXmMacStatistic().
wdenk9c53f402003-10-15 23:53:47 +0000139 *
wdenkeb20ad32003-09-05 23:19:14 +0000140 * Revision 1.68 2002/07/16 07:35:24 rwahl
141 * Removed check for cleared mib counter in SkGmResetCounter().
wdenk9c53f402003-10-15 23:53:47 +0000142 *
wdenkeb20ad32003-09-05 23:19:14 +0000143 * Revision 1.67 2002/07/15 18:35:56 rwahl
144 * Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(),
145 * SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(),
146 * SkXmOverflowStatus(), SkGmOverflowStatus().
147 * Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both
148 * RX & TX.
149 * Changes to SkGmInitMac(): call to SkGmResetCounter().
150 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000151 *
wdenkeb20ad32003-09-05 23:19:14 +0000152 * Revision 1.66 2002/07/15 15:59:30 rschmidt
153 * Added PHY Address in SkXmPhyRead(), SkXmPhyWrite().
154 * Added MIB Clear Counter in SkGmInitMac().
155 * Added Duplex and Flow-Control settings.
156 * Reset all Multicast filtering Hash reg. in SkGmInitMac().
157 * Added new function: SkGmGetMuxConfig().
158 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000159 *
wdenkeb20ad32003-09-05 23:19:14 +0000160 * Revision 1.65 2002/06/10 09:35:39 rschmidt
161 * Replaced C++ comments (//).
162 * Added #define VCPU around VCPUwaitTime.
163 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000164 *
wdenkeb20ad32003-09-05 23:19:14 +0000165 * Revision 1.64 2002/06/05 08:41:10 rschmidt
166 * Added function for XMAC2: SkXmTimeStamp().
167 * Added function for YUKON: SkGmSetRxCmd().
168 * Changed SkGmInitMac() resp. SkGmHardRst().
169 * Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode).
170 * SkXmRxTxEnable() replaced by SkMacRxTxEnable().
171 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000172 *
wdenkeb20ad32003-09-05 23:19:14 +0000173 * Revision 1.63 2002/04/25 13:04:44 rschmidt
174 * Changes for handling YUKON.
175 * Use of #ifdef OTHER_PHY to eliminate code for unused Phy types.
176 * Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced
177 * by functions SkXmPhyRead(), SkXmPhyWrite();
178 * Removed use of PRxCmd to setup XMAC.
179 * Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res.
180 * Added setting of XM_RX_DIS_CEXT in SkXmInitMac().
181 * Removed status parameter from MAC IRQ handler SkMacIrq(),
182 * SkXmIrq() and SkGmIrq().
183 * SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy().
184 * Added SkMac...() functions to handle both XMAC and GMAC.
185 * Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(),
186 * SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(),
187 * SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite().
188 * Changes for V-CPU support.
189 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000190 *
wdenkeb20ad32003-09-05 23:19:14 +0000191 * Revision 1.62 2001/08/06 09:50:14 rschmidt
192 * Workaround BCOM Errata #1 for the C5 type.
193 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000194 *
wdenkeb20ad32003-09-05 23:19:14 +0000195 * Revision 1.61 2001/02/09 15:40:59 rassmann
196 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +0000197 *
wdenkeb20ad32003-09-05 23:19:14 +0000198 * Revision 1.60 2001/02/07 15:02:01 cgoos
199 * Added workaround for Fujitsu switch link down.
wdenk9c53f402003-10-15 23:53:47 +0000200 *
wdenkeb20ad32003-09-05 23:19:14 +0000201 * Revision 1.59 2001/01/10 09:38:06 cgoos
202 * Fixed Broadcom C0/A1 Id check for workaround.
wdenk9c53f402003-10-15 23:53:47 +0000203 *
wdenkeb20ad32003-09-05 23:19:14 +0000204 * Revision 1.58 2000/11/29 11:30:38 cgoos
205 * Changed DEBUG sections with NW output to xDEBUG
wdenk9c53f402003-10-15 23:53:47 +0000206 *
wdenkeb20ad32003-09-05 23:19:14 +0000207 * Revision 1.57 2000/11/27 12:40:40 rassmann
208 * Suppressing preamble after first access to BCom, not before (#10556).
wdenk9c53f402003-10-15 23:53:47 +0000209 *
wdenkeb20ad32003-09-05 23:19:14 +0000210 * Revision 1.56 2000/11/09 12:32:48 rassmann
211 * Renamed variables.
wdenk9c53f402003-10-15 23:53:47 +0000212 *
wdenkeb20ad32003-09-05 23:19:14 +0000213 * Revision 1.55 2000/11/09 11:30:10 rassmann
214 * WA: Waiting after releasing reset until BCom chip is accessible.
wdenk9c53f402003-10-15 23:53:47 +0000215 *
wdenkeb20ad32003-09-05 23:19:14 +0000216 * Revision 1.54 2000/10/02 14:10:27 rassmann
217 * Reading BCOM PHY after releasing reset until it returns a valid value.
wdenk9c53f402003-10-15 23:53:47 +0000218 *
wdenkeb20ad32003-09-05 23:19:14 +0000219 * Revision 1.53 2000/07/27 12:22:11 gklug
220 * fix: possible endless loop in XmHardRst.
wdenk9c53f402003-10-15 23:53:47 +0000221 *
wdenkeb20ad32003-09-05 23:19:14 +0000222 * Revision 1.52 2000/05/22 08:48:31 malthoff
223 * Fix: #10523 errata valid for all BCOM PHYs.
wdenk9c53f402003-10-15 23:53:47 +0000224 *
wdenkeb20ad32003-09-05 23:19:14 +0000225 * Revision 1.51 2000/05/17 12:52:18 malthoff
226 * Fixes BCom link errata (#10523).
wdenk9c53f402003-10-15 23:53:47 +0000227 *
wdenkeb20ad32003-09-05 23:19:14 +0000228 * Revision 1.50 1999/11/22 13:40:14 cgoos
229 * Changed license header to GPL.
wdenk9c53f402003-10-15 23:53:47 +0000230 *
wdenkeb20ad32003-09-05 23:19:14 +0000231 * Revision 1.49 1999/11/22 08:12:13 malthoff
232 * Add workaround for power consumption feature of BCom C0 chip.
wdenk9c53f402003-10-15 23:53:47 +0000233 *
wdenkeb20ad32003-09-05 23:19:14 +0000234 * Revision 1.48 1999/11/16 08:39:01 malthoff
235 * Fix: MDIO preamble suppression is port dependent.
wdenk9c53f402003-10-15 23:53:47 +0000236 *
wdenkeb20ad32003-09-05 23:19:14 +0000237 * Revision 1.47 1999/08/27 08:55:35 malthoff
238 * 1000BT: Optimizing MDIO transfer by oppressing MDIO preamble.
wdenk9c53f402003-10-15 23:53:47 +0000239 *
wdenkeb20ad32003-09-05 23:19:14 +0000240 * Revision 1.46 1999/08/13 11:01:12 malthoff
241 * Fix for 1000BT: pFlowCtrlMode was not set correctly.
wdenk9c53f402003-10-15 23:53:47 +0000242 *
wdenkeb20ad32003-09-05 23:19:14 +0000243 * Revision 1.45 1999/08/12 19:18:28 malthoff
244 * 1000BT Fixes: Do not owerwrite XM_MMU_CMD.
245 * Do not execute BCOM A1 workaround for B1 chips.
246 * Fix pause frame setting.
247 * Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL.
wdenk9c53f402003-10-15 23:53:47 +0000248 *
wdenkeb20ad32003-09-05 23:19:14 +0000249 * Revision 1.44 1999/08/03 15:23:48 cgoos
250 * Fixed setting of PHY interrupt mask in half duplex mode.
wdenk9c53f402003-10-15 23:53:47 +0000251 *
wdenkeb20ad32003-09-05 23:19:14 +0000252 * Revision 1.43 1999/08/03 15:22:17 cgoos
253 * Added some debug output.
254 * Disabled XMac GP0 interrupt for external PHYs.
wdenk9c53f402003-10-15 23:53:47 +0000255 *
wdenkeb20ad32003-09-05 23:19:14 +0000256 * Revision 1.42 1999/08/02 08:39:23 malthoff
257 * BCOM PHY: TX LED: To get the mono flop behaviour it is required
258 * to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL.
wdenk9c53f402003-10-15 23:53:47 +0000259 *
wdenkeb20ad32003-09-05 23:19:14 +0000260 * Revision 1.41 1999/07/30 06:54:31 malthoff
261 * Add temp. workarounds for the BCOM Phy revision A1.
wdenk9c53f402003-10-15 23:53:47 +0000262 *
wdenkeb20ad32003-09-05 23:19:14 +0000263 * Revision 1.40 1999/06/01 07:43:26 cgoos
264 * Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to
265 * AUTOFULL/AUTOHALF.
wdenk9c53f402003-10-15 23:53:47 +0000266 *
wdenkeb20ad32003-09-05 23:19:14 +0000267 * Revision 1.39 1999/05/19 07:29:51 cgoos
268 * Changes for 1000Base-T.
wdenk9c53f402003-10-15 23:53:47 +0000269 *
wdenkeb20ad32003-09-05 23:19:14 +0000270 * Revision 1.38 1999/04/08 14:35:10 malthoff
271 * Add code for enabling signal detect. Enabling signal detect is disabled.
wdenk9c53f402003-10-15 23:53:47 +0000272 *
wdenkeb20ad32003-09-05 23:19:14 +0000273 * Revision 1.37 1999/03/12 13:42:54 malthoff
274 * Add: Jumbo Frame Support.
275 * Add: Receive modes SK_LENERR_OK_ON/OFF and
276 * SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd().
wdenk9c53f402003-10-15 23:53:47 +0000277 *
wdenkeb20ad32003-09-05 23:19:14 +0000278 * Revision 1.36 1999/03/08 10:10:55 gklug
279 * fix: AutoSensing did switch to next mode even if LiPa indicated offline
280 *
281 * Revision 1.35 1999/02/22 15:16:41 malthoff
282 * Remove some compiler warnings.
283 *
284 * Revision 1.34 1999/01/22 09:19:59 gklug
285 * fix: Init DupMode and InitPauseMd are now called in RxTxEnable
286 *
287 * Revision 1.33 1998/12/11 15:19:11 gklug
288 * chg: lipa autoneg stati
289 * chg: debug messages
290 * chg: do NOT use spurious XmIrq
291 *
292 * Revision 1.32 1998/12/10 11:08:44 malthoff
293 * bug fix: pAC has been used for IOs in SkXmHardRst().
294 * SkXmInitPhy() is also called for the Diag in SkXmInitMac().
295 *
296 * Revision 1.31 1998/12/10 10:39:11 gklug
297 * fix: do 4 RESETS of the XMAC at the beginning
298 * fix: dummy read interrupt source register BEFORE initializing the Phy
299 * add: debug messages
300 * fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt
301 *
302 * Revision 1.30 1998/12/07 12:18:32 gklug
303 * add: refinement of autosense mode: take into account the autoneg cap of LiPa
304 *
305 * Revision 1.29 1998/12/07 07:12:29 gklug
306 * fix: if page is received the link is down.
307 *
308 * Revision 1.28 1998/12/01 10:12:47 gklug
309 * chg: if spurious IRQ from XMAC encountered, save it
310 *
311 * Revision 1.27 1998/11/26 07:33:38 gklug
312 * add: InitPhy call is now in XmInit function
313 *
314 * Revision 1.26 1998/11/18 13:38:24 malthoff
315 * 'Imsk' is also unused in SkXmAutoNegDone.
316 *
317 * Revision 1.25 1998/11/18 13:28:01 malthoff
318 * Remove unused variable 'Reg' in SkXmAutoNegDone().
319 *
320 * Revision 1.24 1998/11/18 13:18:45 gklug
321 * add: workaround for xmac errata #1
322 * add: detect Link Down also when Link partner requested config
323 * chg: XMIrq is only used when link is up
324 *
325 * Revision 1.23 1998/11/04 07:07:04 cgoos
326 * Added function SkXmRxTxEnable.
327 *
328 * Revision 1.22 1998/10/30 07:35:54 gklug
329 * fix: serve LinkDown interrupt when link is already down
330 *
331 * Revision 1.21 1998/10/29 15:32:03 gklug
332 * fix: Link Down signaling
333 *
334 * Revision 1.20 1998/10/29 11:17:27 gklug
335 * fix: AutoNegDone bug
336 *
337 * Revision 1.19 1998/10/29 10:14:43 malthoff
338 * Add endainesss comment for reading/writing MAC addresses.
339 *
340 * Revision 1.18 1998/10/28 07:48:55 cgoos
341 * Fix: ASS somtimes signaled although link is up.
342 *
343 * Revision 1.17 1998/10/26 07:55:39 malthoff
344 * Fix in SkXmInitPauseMd(): Pause Mode
345 * was disabled and not enabled.
346 * Fix in SkXmAutoNegDone(): Checking Mode bits
347 * always failed, becaues of some missing braces.
348 *
349 * Revision 1.16 1998/10/22 09:46:52 gklug
350 * fix SysKonnectFileId typo
351 *
352 * Revision 1.15 1998/10/21 05:51:37 gklug
353 * add: para DoLoop to InitPhy function for loopback set-up
354 *
355 * Revision 1.14 1998/10/16 10:59:23 malthoff
356 * Remove Lint warning for dummy reads.
357 *
358 * Revision 1.13 1998/10/15 14:01:20 malthoff
359 * Fix: SkXmAutoNegDone() is (int) but does not return a value.
360 *
361 * Revision 1.12 1998/10/14 14:45:04 malthoff
362 * Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by
363 * SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent
364 * from the Sirq module.
365 *
366 * Revision 1.11 1998/10/14 13:59:01 gklug
367 * add: InitPhy function
368 *
369 * Revision 1.10 1998/10/14 11:20:57 malthoff
370 * Make SkXmAutoNegDone() public, because it's
371 * used in diagnostics, too.
372 * The Link Up event to the RLMT is issued in SkXmIrq().
373 * SkXmIrq() is not available in diagnostics.
374 * Use PHY_READ when reading PHY registers.
375 *
376 * Revision 1.9 1998/10/14 05:50:10 cgoos
377 * Added definition for Para.
378 *
379 * Revision 1.8 1998/10/14 05:41:28 gklug
380 * add: Xmac IRQ
381 * add: auto-negotiation done function
382 *
383 * Revision 1.7 1998/10/09 06:55:20 malthoff
384 * The configuration of the XMACs Tx Request Threshold
385 * depends from the drivers port usage now. The port
386 * usage is configured in GIPortUsage.
387 *
388 * Revision 1.6 1998/10/05 07:48:00 malthoff
389 * minor changes
390 *
391 * Revision 1.5 1998/10/01 07:03:54 gklug
392 * add: dummy function for XMAC ISR
393 *
394 * Revision 1.4 1998/09/30 12:37:44 malthoff
395 * Add SkXmSetRxCmd() and related code.
396 *
397 * Revision 1.3 1998/09/28 13:26:40 malthoff
398 * Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd()
399 *
400 * Revision 1.2 1998/09/16 14:34:21 malthoff
401 * Add SkXmClrExactAddr(), SkXmClrSrcCheck(),
402 * SkXmClrHashAddr(), SkXmFlushTxFifo(),
403 * SkXmFlushRxFifo(), and SkXmHardRst().
404 * Finish Coding of SkXmSoftRst().
405 * The sources may be compiled now.
406 *
407 * Revision 1.1 1998/09/04 10:05:56 malthoff
408 * Created.
409 *
410 *
411 ******************************************************************************/
412
wdenkde887eb2003-09-10 18:20:28 +0000413#include <config.h>
414
415#ifdef CONFIG_SK98
416
wdenkeb20ad32003-09-05 23:19:14 +0000417#include "h/skdrv1st.h"
418#include "h/skdrv2nd.h"
419
420/* typedefs *******************************************************************/
421
422/* BCOM PHY magic pattern list */
423typedef struct s_PhyHack {
424 int PhyReg; /* Phy register */
425 SK_U16 PhyVal; /* Value to write */
426} BCOM_HACK;
427
428/* local variables ************************************************************/
429static const char SysKonnectFileId[] =
430 "@(#)$Id: skxmac2.c,v 1.91 2003/02/05 15:09:34 rschmidt Exp $ (C) SK ";
431
432BCOM_HACK BcomRegA1Hack[] = {
433 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
434 { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
435 { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
436 { 0, 0 }
437};
438BCOM_HACK BcomRegC0Hack[] = {
439 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
440 { 0x15, 0x0A04 }, { 0x18, 0x0420 },
441 { 0, 0 }
442};
443
444/* function prototypes ********************************************************/
445static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
446static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
447static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
448static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
449static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
450static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
451#ifdef OTHER_PHY
452static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
453static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
454static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
455static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
456#endif /* OTHER_PHY */
457
458
wdenkeb20ad32003-09-05 23:19:14 +0000459/******************************************************************************
460 *
461 * SkXmPhyRead() - Read from XMAC PHY register
462 *
463 * Description: reads a 16-bit word from XMAC PHY or ext. PHY
464 *
465 * Returns:
466 * nothing
467 */
468void SkXmPhyRead(
469SK_AC *pAC, /* Adapter Context */
470SK_IOC IoC, /* I/O Context */
471int Port, /* Port Index (MAC_1 + n) */
472int PhyReg, /* Register Address (Offset) */
473SK_U16 *pVal) /* Pointer to Value */
474{
475 SK_U16 Mmu;
476 SK_GEPORT *pPrt;
477
478 pPrt = &pAC->GIni.GP[Port];
wdenk9c53f402003-10-15 23:53:47 +0000479
wdenkeb20ad32003-09-05 23:19:14 +0000480 /* write the PHY register's address */
481 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
wdenk9c53f402003-10-15 23:53:47 +0000482
wdenkeb20ad32003-09-05 23:19:14 +0000483 /* get the PHY register's value */
484 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
wdenk9c53f402003-10-15 23:53:47 +0000485
wdenkeb20ad32003-09-05 23:19:14 +0000486 if (pPrt->PhyType != SK_PHY_XMAC) {
487 do {
488 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
489 /* wait until 'Ready' is set */
490 } while ((Mmu & XM_MMU_PHY_RDY) == 0);
491
492 /* get the PHY register's value */
493 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
494 }
495} /* SkXmPhyRead */
496
497
498/******************************************************************************
499 *
500 * SkXmPhyWrite() - Write to XMAC PHY register
501 *
502 * Description: writes a 16-bit word to XMAC PHY or ext. PHY
503 *
504 * Returns:
505 * nothing
506 */
507void SkXmPhyWrite(
508SK_AC *pAC, /* Adapter Context */
509SK_IOC IoC, /* I/O Context */
510int Port, /* Port Index (MAC_1 + n) */
511int PhyReg, /* Register Address (Offset) */
512SK_U16 Val) /* Value */
513{
514 SK_U16 Mmu;
515 SK_GEPORT *pPrt;
516
517 pPrt = &pAC->GIni.GP[Port];
wdenk9c53f402003-10-15 23:53:47 +0000518
wdenkeb20ad32003-09-05 23:19:14 +0000519 if (pPrt->PhyType != SK_PHY_XMAC) {
520 do {
521 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
522 /* wait until 'Busy' is cleared */
523 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
524 }
wdenk9c53f402003-10-15 23:53:47 +0000525
wdenkeb20ad32003-09-05 23:19:14 +0000526 /* write the PHY register's address */
527 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
wdenk9c53f402003-10-15 23:53:47 +0000528
wdenkeb20ad32003-09-05 23:19:14 +0000529 /* write the PHY register's value */
530 XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
wdenk9c53f402003-10-15 23:53:47 +0000531
wdenkeb20ad32003-09-05 23:19:14 +0000532 if (pPrt->PhyType != SK_PHY_XMAC) {
533 do {
534 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
535 /* wait until 'Busy' is cleared */
536 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
537 }
538} /* SkXmPhyWrite */
539
540
541/******************************************************************************
542 *
543 * SkGmPhyRead() - Read from GPHY register
544 *
545 * Description: reads a 16-bit word from GPHY through MDIO
546 *
547 * Returns:
548 * nothing
549 */
550void SkGmPhyRead(
551SK_AC *pAC, /* Adapter Context */
552SK_IOC IoC, /* I/O Context */
553int Port, /* Port Index (MAC_1 + n) */
554int PhyReg, /* Register Address (Offset) */
555SK_U16 *pVal) /* Pointer to Value */
556{
557 SK_U16 Ctrl;
558 SK_GEPORT *pPrt;
559#ifdef VCPU
560 u_long SimCyle;
561 u_long SimLowTime;
wdenk9c53f402003-10-15 23:53:47 +0000562
wdenkeb20ad32003-09-05 23:19:14 +0000563 VCPUgetTime(&SimCyle, &SimLowTime);
564 VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
565 PhyReg, SimCyle, SimLowTime);
566#endif /* VCPU */
wdenk9c53f402003-10-15 23:53:47 +0000567
wdenkeb20ad32003-09-05 23:19:14 +0000568 pPrt = &pAC->GIni.GP[Port];
wdenk9c53f402003-10-15 23:53:47 +0000569
wdenkeb20ad32003-09-05 23:19:14 +0000570 /* set PHY-Register offset and 'Read' OpCode (= 1) */
571 *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
572 GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
573
574 GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
575
576 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
wdenk9c53f402003-10-15 23:53:47 +0000577
wdenkeb20ad32003-09-05 23:19:14 +0000578 /* additional check for MDC/MDIO activity */
579 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
580 *pVal = 0;
581 return;
582 }
583
584 *pVal |= GM_SMI_CT_BUSY;
wdenk9c53f402003-10-15 23:53:47 +0000585
wdenkeb20ad32003-09-05 23:19:14 +0000586 do {
587#ifdef VCPU
588 VCPUwaitTime(1000);
589#endif /* VCPU */
590
591 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
592
593 /* wait until 'ReadValid' is set */
594 } while (Ctrl == *pVal);
wdenk9c53f402003-10-15 23:53:47 +0000595
wdenkeb20ad32003-09-05 23:19:14 +0000596 /* get the PHY register's value */
597 GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
598
599#ifdef VCPU
600 VCPUgetTime(&SimCyle, &SimLowTime);
601 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
602 SimCyle, SimLowTime);
603#endif /* VCPU */
604} /* SkGmPhyRead */
605
606
607/******************************************************************************
608 *
609 * SkGmPhyWrite() - Write to GPHY register
610 *
611 * Description: writes a 16-bit word to GPHY through MDIO
612 *
613 * Returns:
614 * nothing
615 */
616void SkGmPhyWrite(
617SK_AC *pAC, /* Adapter Context */
618SK_IOC IoC, /* I/O Context */
619int Port, /* Port Index (MAC_1 + n) */
620int PhyReg, /* Register Address (Offset) */
621SK_U16 Val) /* Value */
622{
623 SK_U16 Ctrl;
624 SK_GEPORT *pPrt;
625#ifdef VCPU
626 SK_U32 DWord;
627 u_long SimCyle;
628 u_long SimLowTime;
wdenk9c53f402003-10-15 23:53:47 +0000629
wdenkeb20ad32003-09-05 23:19:14 +0000630 VCPUgetTime(&SimCyle, &SimLowTime);
631 VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
632 PhyReg, Val, SimCyle, SimLowTime);
633#endif /* VCPU */
wdenk9c53f402003-10-15 23:53:47 +0000634
wdenkeb20ad32003-09-05 23:19:14 +0000635 pPrt = &pAC->GIni.GP[Port];
wdenk9c53f402003-10-15 23:53:47 +0000636
wdenkeb20ad32003-09-05 23:19:14 +0000637 /* write the PHY register's value */
638 GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
wdenk9c53f402003-10-15 23:53:47 +0000639
wdenkeb20ad32003-09-05 23:19:14 +0000640 /* set PHY-Register offset and 'Write' OpCode (= 0) */
641 Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
642
643 GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
644
645 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
wdenk9c53f402003-10-15 23:53:47 +0000646
wdenkeb20ad32003-09-05 23:19:14 +0000647 /* additional check for MDC/MDIO activity */
648 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
649 return;
650 }
wdenk9c53f402003-10-15 23:53:47 +0000651
wdenkeb20ad32003-09-05 23:19:14 +0000652 Val |= GM_SMI_CT_BUSY;
653
654 do {
655#ifdef VCPU
656 /* read Timer value */
657 SK_IN32(IoC, B2_TI_VAL, &DWord);
658
659 VCPUwaitTime(1000);
660#endif /* VCPU */
661
662 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
663
664 /* wait until 'Busy' is cleared */
665 } while (Ctrl == Val);
wdenk9c53f402003-10-15 23:53:47 +0000666
wdenkeb20ad32003-09-05 23:19:14 +0000667#ifdef VCPU
668 VCPUgetTime(&SimCyle, &SimLowTime);
669 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
670 SimCyle, SimLowTime);
671#endif /* VCPU */
672} /* SkGmPhyWrite */
673
674
675/******************************************************************************
676 *
677 * SkGePhyRead() - Read from PHY register
678 *
679 * Description: calls a read PHY routine dep. on board type
680 *
681 * Returns:
682 * nothing
683 */
684void SkGePhyRead(
685SK_AC *pAC, /* Adapter Context */
686SK_IOC IoC, /* I/O Context */
687int Port, /* Port Index (MAC_1 + n) */
688int PhyReg, /* Register Address (Offset) */
689SK_U16 *pVal) /* Pointer to Value */
690{
691 void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
692
693 if (pAC->GIni.GIGenesis) {
694 r_func = SkXmPhyRead;
695 }
696 else {
697 r_func = SkGmPhyRead;
698 }
wdenk9c53f402003-10-15 23:53:47 +0000699
wdenkeb20ad32003-09-05 23:19:14 +0000700 r_func(pAC, IoC, Port, PhyReg, pVal);
701} /* SkGePhyRead */
702
703
704/******************************************************************************
705 *
706 * SkGePhyWrite() - Write to PHY register
707 *
708 * Description: calls a write PHY routine dep. on board type
709 *
710 * Returns:
711 * nothing
712 */
713void SkGePhyWrite(
714SK_AC *pAC, /* Adapter Context */
715SK_IOC IoC, /* I/O Context */
716int Port, /* Port Index (MAC_1 + n) */
717int PhyReg, /* Register Address (Offset) */
718SK_U16 Val) /* Value */
719{
720 void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
721
722 if (pAC->GIni.GIGenesis) {
723 w_func = SkXmPhyWrite;
724 }
725 else {
726 w_func = SkGmPhyWrite;
727 }
wdenk9c53f402003-10-15 23:53:47 +0000728
wdenkeb20ad32003-09-05 23:19:14 +0000729 w_func(pAC, IoC, Port, PhyReg, Val);
730} /* SkGePhyWrite */
731
732
733/******************************************************************************
734 *
735 * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
736 *
737 * Description:
738 * enables / disables promiscuous mode by setting Mode Register (XMAC) or
wdenk9c53f402003-10-15 23:53:47 +0000739 * Receive Control Register (GMAC) dep. on board type
wdenkeb20ad32003-09-05 23:19:14 +0000740 *
741 * Returns:
742 * nothing
743 */
744void SkMacPromiscMode(
745SK_AC *pAC, /* adapter context */
746SK_IOC IoC, /* IO context */
747int Port, /* Port Index (MAC_1 + n) */
748SK_BOOL Enable) /* Enable / Disable */
749{
750 SK_U16 RcReg;
751 SK_U32 MdReg;
752
753 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +0000754
wdenkeb20ad32003-09-05 23:19:14 +0000755 XM_IN32(IoC, Port, XM_MODE, &MdReg);
756 /* enable or disable promiscuous mode */
757 if (Enable) {
758 MdReg |= XM_MD_ENA_PROM;
759 }
760 else {
761 MdReg &= ~XM_MD_ENA_PROM;
762 }
763 /* setup Mode Register */
764 XM_OUT32(IoC, Port, XM_MODE, MdReg);
765 }
766 else {
wdenk9c53f402003-10-15 23:53:47 +0000767
wdenkeb20ad32003-09-05 23:19:14 +0000768 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
wdenk9c53f402003-10-15 23:53:47 +0000769
wdenkeb20ad32003-09-05 23:19:14 +0000770 /* enable or disable unicast and multicast filtering */
771 if (Enable) {
772 RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
773 }
774 else {
775 RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
776 }
777 /* setup Receive Control Register */
778 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
779 }
780} /* SkMacPromiscMode*/
781
782
783/******************************************************************************
784 *
785 * SkMacHashing() - Enable / Disable Hashing
786 *
787 * Description:
788 * enables / disables hashing by setting Mode Register (XMAC) or
wdenk9c53f402003-10-15 23:53:47 +0000789 * Receive Control Register (GMAC) dep. on board type
wdenkeb20ad32003-09-05 23:19:14 +0000790 *
791 * Returns:
792 * nothing
793 */
794void SkMacHashing(
795SK_AC *pAC, /* adapter context */
796SK_IOC IoC, /* IO context */
797int Port, /* Port Index (MAC_1 + n) */
798SK_BOOL Enable) /* Enable / Disable */
799{
800 SK_U16 RcReg;
801 SK_U32 MdReg;
802
803 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +0000804
wdenkeb20ad32003-09-05 23:19:14 +0000805 XM_IN32(IoC, Port, XM_MODE, &MdReg);
806 /* enable or disable hashing */
807 if (Enable) {
808 MdReg |= XM_MD_ENA_HASH;
809 }
810 else {
811 MdReg &= ~XM_MD_ENA_HASH;
812 }
813 /* setup Mode Register */
814 XM_OUT32(IoC, Port, XM_MODE, MdReg);
815 }
816 else {
wdenk9c53f402003-10-15 23:53:47 +0000817
wdenkeb20ad32003-09-05 23:19:14 +0000818 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
wdenk9c53f402003-10-15 23:53:47 +0000819
wdenkeb20ad32003-09-05 23:19:14 +0000820 /* enable or disable multicast filtering */
821 if (Enable) {
822 RcReg |= GM_RXCR_MCF_ENA;
823 }
824 else {
825 RcReg &= ~GM_RXCR_MCF_ENA;
826 }
827 /* setup Receive Control Register */
828 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
829 }
830} /* SkMacHashing*/
831
832
833#ifdef SK_DIAG
834/******************************************************************************
835 *
836 * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
837 *
838 * Description:
839 * The features
840 * - FCS stripping, SK_STRIP_FCS_ON/OFF
841 * - pad byte stripping, SK_STRIP_PAD_ON/OFF
842 * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
843 * for inrange length error frames
844 * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
845 * for frames > 1514 bytes
846 * - enable Rx of own packets SK_SELF_RX_ON/OFF
847 *
848 * for incoming packets may be enabled/disabled by this function.
849 * Additional modes may be added later.
850 * Multiple modes can be enabled/disabled at the same time.
851 * The new configuration is written to the Rx Command register immediately.
852 *
853 * Returns:
854 * nothing
855 */
856static void SkXmSetRxCmd(
857SK_AC *pAC, /* adapter context */
858SK_IOC IoC, /* IO context */
859int Port, /* Port Index (MAC_1 + n) */
860int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
861 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
862{
863 SK_U16 OldRxCmd;
864 SK_U16 RxCmd;
865
866 XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
867
868 RxCmd = OldRxCmd;
wdenk9c53f402003-10-15 23:53:47 +0000869
wdenkeb20ad32003-09-05 23:19:14 +0000870 switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
871 case SK_STRIP_FCS_ON:
872 RxCmd |= XM_RX_STRIP_FCS;
873 break;
874 case SK_STRIP_FCS_OFF:
875 RxCmd &= ~XM_RX_STRIP_FCS;
876 break;
877 }
878
879 switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
880 case SK_STRIP_PAD_ON:
881 RxCmd |= XM_RX_STRIP_PAD;
882 break;
883 case SK_STRIP_PAD_OFF:
884 RxCmd &= ~XM_RX_STRIP_PAD;
885 break;
886 }
887
888 switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
889 case SK_LENERR_OK_ON:
890 RxCmd |= XM_RX_LENERR_OK;
891 break;
892 case SK_LENERR_OK_OFF:
893 RxCmd &= ~XM_RX_LENERR_OK;
894 break;
895 }
896
897 switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
898 case SK_BIG_PK_OK_ON:
899 RxCmd |= XM_RX_BIG_PK_OK;
900 break;
901 case SK_BIG_PK_OK_OFF:
902 RxCmd &= ~XM_RX_BIG_PK_OK;
903 break;
904 }
905
906 switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
907 case SK_SELF_RX_ON:
908 RxCmd |= XM_RX_SELF_RX;
909 break;
910 case SK_SELF_RX_OFF:
911 RxCmd &= ~XM_RX_SELF_RX;
912 break;
913 }
914
915 /* Write the new mode to the Rx command register if required */
916 if (OldRxCmd != RxCmd) {
917 XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
918 }
919} /* SkXmSetRxCmd */
920
921
922/******************************************************************************
923 *
924 * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
925 *
926 * Description:
927 * The features
928 * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
929 * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
930 * for frames > 1514 bytes
931 * - enable Rx of own packets SK_SELF_RX_ON/OFF
932 *
933 * for incoming packets may be enabled/disabled by this function.
934 * Additional modes may be added later.
935 * Multiple modes can be enabled/disabled at the same time.
936 * The new configuration is written to the Rx Command register immediately.
937 *
938 * Returns:
939 * nothing
940 */
941static void SkGmSetRxCmd(
942SK_AC *pAC, /* adapter context */
943SK_IOC IoC, /* IO context */
944int Port, /* Port Index (MAC_1 + n) */
945int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
946 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
947{
948 SK_U16 OldRxCmd;
949 SK_U16 RxCmd;
950
951 if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
wdenk9c53f402003-10-15 23:53:47 +0000952
wdenkeb20ad32003-09-05 23:19:14 +0000953 GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
954
955 RxCmd = OldRxCmd;
956
957 if ((Mode & SK_STRIP_FCS_ON) != 0) {
958 RxCmd |= GM_RXCR_CRC_DIS;
959 }
960 else {
961 RxCmd &= ~GM_RXCR_CRC_DIS;
962 }
963 /* Write the new mode to the Rx control register if required */
964 if (OldRxCmd != RxCmd) {
965 GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
966 }
967 }
968
969 if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
wdenk9c53f402003-10-15 23:53:47 +0000970
wdenkeb20ad32003-09-05 23:19:14 +0000971 GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
972
973 RxCmd = OldRxCmd;
974
975 if ((Mode & SK_BIG_PK_OK_ON) != 0) {
976 RxCmd |= GM_SMOD_JUMBO_ENA;
977 }
978 else {
979 RxCmd &= ~GM_SMOD_JUMBO_ENA;
980 }
981 /* Write the new mode to the Rx control register if required */
982 if (OldRxCmd != RxCmd) {
983 GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
984 }
985 }
986} /* SkGmSetRxCmd */
987
988
989/******************************************************************************
990 *
991 * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
992 *
993 * Description: modifies the MAC's Rx Control reg. dep. on board type
994 *
995 * Returns:
996 * nothing
997 */
998void SkMacSetRxCmd(
999SK_AC *pAC, /* adapter context */
1000SK_IOC IoC, /* IO context */
1001int Port, /* Port Index (MAC_1 + n) */
1002int Mode) /* Rx Mode */
1003{
1004 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00001005
wdenkeb20ad32003-09-05 23:19:14 +00001006 SkXmSetRxCmd(pAC, IoC, Port, Mode);
1007 }
1008 else {
wdenk9c53f402003-10-15 23:53:47 +00001009
wdenkeb20ad32003-09-05 23:19:14 +00001010 SkGmSetRxCmd(pAC, IoC, Port, Mode);
1011 }
1012} /* SkMacSetRxCmd */
1013
1014
1015/******************************************************************************
1016 *
1017 * SkMacCrcGener() - Enable / Disable CRC Generation
1018 *
1019 * Description: enables / disables CRC generation dep. on board type
1020 *
1021 * Returns:
1022 * nothing
1023 */
1024void SkMacCrcGener(
1025SK_AC *pAC, /* adapter context */
1026SK_IOC IoC, /* IO context */
1027int Port, /* Port Index (MAC_1 + n) */
1028SK_BOOL Enable) /* Enable / Disable */
1029{
1030 SK_U16 Word;
1031
1032 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00001033
wdenkeb20ad32003-09-05 23:19:14 +00001034 XM_IN16(IoC, Port, XM_TX_CMD, &Word);
1035
1036 if (Enable) {
1037 Word &= ~XM_TX_NO_CRC;
1038 }
1039 else {
1040 Word |= XM_TX_NO_CRC;
1041 }
1042 /* setup Tx Command Register */
1043 XM_OUT16(pAC, Port, XM_TX_CMD, Word);
1044 }
1045 else {
wdenk9c53f402003-10-15 23:53:47 +00001046
wdenkeb20ad32003-09-05 23:19:14 +00001047 GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
wdenk9c53f402003-10-15 23:53:47 +00001048
wdenkeb20ad32003-09-05 23:19:14 +00001049 if (Enable) {
1050 Word &= ~GM_TXCR_CRC_DIS;
1051 }
1052 else {
1053 Word |= GM_TXCR_CRC_DIS;
1054 }
1055 /* setup Tx Control Register */
1056 GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
1057 }
1058} /* SkMacCrcGener*/
1059
1060#endif /* SK_DIAG */
1061
1062
1063/******************************************************************************
1064 *
1065 * SkXmClrExactAddr() - Clear Exact Match Address Registers
1066 *
1067 * Description:
1068 * All Exact Match Address registers of the XMAC 'Port' will be
1069 * cleared starting with 'StartNum' up to (and including) the
1070 * Exact Match address number of 'StopNum'.
1071 *
1072 * Returns:
1073 * nothing
1074 */
1075void SkXmClrExactAddr(
1076SK_AC *pAC, /* adapter context */
1077SK_IOC IoC, /* IO context */
1078int Port, /* Port Index (MAC_1 + n) */
1079int StartNum, /* Begin with this Address Register Index (0..15) */
1080int StopNum) /* Stop after finished with this Register Idx (0..15) */
1081{
1082 int i;
1083 SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
1084
1085 if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
1086 StartNum > StopNum) {
1087
1088 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
1089 return;
1090 }
1091
1092 for (i = StartNum; i <= StopNum; i++) {
1093 XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
1094 }
1095} /* SkXmClrExactAddr */
1096
1097
1098/******************************************************************************
1099 *
1100 * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
1101 *
1102 * Description:
1103 * Flush the transmit FIFO of the MAC specified by the index 'Port'
1104 *
1105 * Returns:
1106 * nothing
1107 */
1108void SkMacFlushTxFifo(
1109SK_AC *pAC, /* adapter context */
1110SK_IOC IoC, /* IO context */
1111int Port) /* Port Index (MAC_1 + n) */
1112{
1113 SK_U32 MdReg;
1114
1115 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00001116
wdenkeb20ad32003-09-05 23:19:14 +00001117 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1118
1119 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
1120 }
1121 else {
1122 /* no way to flush the FIFO we have to issue a reset */
1123 /* TBD */
1124 }
1125} /* SkMacFlushTxFifo */
1126
1127
1128/******************************************************************************
1129 *
1130 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
1131 *
1132 * Description:
1133 * Flush the receive FIFO of the MAC specified by the index 'Port'
1134 *
1135 * Returns:
1136 * nothing
1137 */
1138void SkMacFlushRxFifo(
1139SK_AC *pAC, /* adapter context */
1140SK_IOC IoC, /* IO context */
1141int Port) /* Port Index (MAC_1 + n) */
1142{
1143 SK_U32 MdReg;
1144
1145 if (pAC->GIni.GIGenesis) {
1146
1147 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1148
1149 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
1150 }
1151 else {
1152 /* no way to flush the FIFO we have to issue a reset */
1153 /* TBD */
1154 }
1155} /* SkMacFlushRxFifo */
1156
1157
1158/******************************************************************************
1159 *
1160 * SkXmSoftRst() - Do a XMAC software reset
1161 *
1162 * Description:
1163 * The PHY registers should not be destroyed during this
1164 * kind of software reset. Therefore the XMAC Software Reset
1165 * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
1166 *
1167 * The software reset is done by
1168 * - disabling the Rx and Tx state machine,
1169 * - resetting the statistics module,
1170 * - clear all other significant XMAC Mode,
1171 * Command, and Control Registers
1172 * - clearing the Hash Register and the
1173 * Exact Match Address registers, and
1174 * - flushing the XMAC's Rx and Tx FIFOs.
1175 *
1176 * Note:
1177 * Another requirement when stopping the XMAC is to
1178 * avoid sending corrupted frames on the network.
1179 * Disabling the Tx state machine will NOT interrupt
1180 * the currently transmitted frame. But we must take care
1181 * that the Tx FIFO is cleared AFTER the current frame
1182 * is complete sent to the network.
1183 *
1184 * It takes about 12ns to send a frame with 1538 bytes.
1185 * One PCI clock goes at least 15ns (66MHz). Therefore
1186 * after reading XM_GP_PORT back, we are sure that the
1187 * transmitter is disabled AND idle. And this means
1188 * we may flush the transmit FIFO now.
1189 *
1190 * Returns:
1191 * nothing
1192 */
1193static void SkXmSoftRst(
1194SK_AC *pAC, /* adapter context */
1195SK_IOC IoC, /* IO context */
1196int Port) /* Port Index (MAC_1 + n) */
1197{
1198 SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
wdenk9c53f402003-10-15 23:53:47 +00001199
wdenkeb20ad32003-09-05 23:19:14 +00001200 /* reset the statistics module */
1201 XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
1202
1203 /* disable all XMAC IRQs */
1204 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
wdenk9c53f402003-10-15 23:53:47 +00001205
wdenkeb20ad32003-09-05 23:19:14 +00001206 XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
wdenk9c53f402003-10-15 23:53:47 +00001207
wdenkeb20ad32003-09-05 23:19:14 +00001208 XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
1209 XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
wdenk9c53f402003-10-15 23:53:47 +00001210
wdenkeb20ad32003-09-05 23:19:14 +00001211 /* disable all PHY IRQs */
1212 switch (pAC->GIni.GP[Port].PhyType) {
1213 case SK_PHY_BCOM:
1214 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
1215 break;
1216#ifdef OTHER_PHY
1217 case SK_PHY_LONE:
1218 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
1219 break;
1220 case SK_PHY_NAT:
1221 /* todo: National
1222 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
1223 break;
1224#endif /* OTHER_PHY */
1225 }
1226
1227 /* clear the Hash Register */
1228 XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
1229
1230 /* clear the Exact Match Address registers */
1231 SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
wdenk9c53f402003-10-15 23:53:47 +00001232
wdenkeb20ad32003-09-05 23:19:14 +00001233 /* clear the Source Check Address registers */
1234 XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
1235
1236} /* SkXmSoftRst */
1237
1238
1239/******************************************************************************
1240 *
1241 * SkXmHardRst() - Do a XMAC hardware reset
1242 *
1243 * Description:
1244 * The XMAC of the specified 'Port' and all connected devices
1245 * (PHY and SERDES) will receive a reset signal on its *Reset pins.
1246 * External PHYs must be reset be clearing a bit in the GPIO register
1247 * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
1248 *
1249 * ATTENTION:
1250 * It is absolutely necessary to reset the SW_RST Bit first
1251 * before calling this function.
1252 *
1253 * Returns:
1254 * nothing
1255 */
1256static void SkXmHardRst(
1257SK_AC *pAC, /* adapter context */
1258SK_IOC IoC, /* IO context */
1259int Port) /* Port Index (MAC_1 + n) */
1260{
1261 SK_U32 Reg;
1262 int i;
1263 int TOut;
1264 SK_U16 Word;
1265
1266 for (i = 0; i < 4; i++) {
1267 /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
1268 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1269
1270 TOut = 0;
1271 do {
1272 if (TOut++ > 10000) {
1273 /*
1274 * Adapter seems to be in RESET state.
1275 * Registers cannot be written.
1276 */
1277 return;
1278 }
1279
1280 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
wdenk9c53f402003-10-15 23:53:47 +00001281
wdenkeb20ad32003-09-05 23:19:14 +00001282 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
wdenk9c53f402003-10-15 23:53:47 +00001283
wdenkeb20ad32003-09-05 23:19:14 +00001284 } while ((Word & MFF_SET_MAC_RST) == 0);
1285 }
1286
1287 /* For external PHYs there must be special handling */
1288 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
1289 /* reset external PHY */
1290 SK_IN32(IoC, B2_GP_IO, &Reg);
1291 if (Port == 0) {
1292 Reg |= GP_DIR_0; /* set to output */
1293 Reg &= ~GP_IO_0;
1294 }
1295 else {
1296 Reg |= GP_DIR_2; /* set to output */
1297 Reg &= ~GP_IO_2;
1298 }
1299 SK_OUT32(IoC, B2_GP_IO, Reg);
1300
1301 /* short delay */
1302 SK_IN32(IoC, B2_GP_IO, &Reg);
1303 }
1304
1305} /* SkXmHardRst */
1306
1307
1308/******************************************************************************
1309 *
1310 * SkGmSoftRst() - Do a GMAC software reset
1311 *
1312 * Description:
1313 * The GPHY registers should not be destroyed during this
1314 * kind of software reset.
1315 *
1316 * Returns:
1317 * nothing
1318 */
1319static void SkGmSoftRst(
1320SK_AC *pAC, /* adapter context */
1321SK_IOC IoC, /* IO context */
1322int Port) /* Port Index (MAC_1 + n) */
1323{
1324 SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1325 SK_U16 RxCtrl;
1326
1327 /* reset the statistics module */
1328
1329 /* disable all GMAC IRQs */
1330 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
wdenk9c53f402003-10-15 23:53:47 +00001331
wdenkeb20ad32003-09-05 23:19:14 +00001332 /* disable all PHY IRQs */
1333 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
wdenk9c53f402003-10-15 23:53:47 +00001334
wdenkeb20ad32003-09-05 23:19:14 +00001335 /* clear the Hash Register */
1336 GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
1337
1338 /* Enable Unicast and Multicast filtering */
1339 GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
wdenk9c53f402003-10-15 23:53:47 +00001340
wdenkeb20ad32003-09-05 23:19:14 +00001341 GM_OUT16(IoC, Port, GM_RX_CTRL,
1342 RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
1343
1344} /* SkGmSoftRst */
1345
1346
1347/******************************************************************************
1348 *
1349 * SkGmHardRst() - Do a GMAC hardware reset
1350 *
1351 * Description:
1352 *
1353 * ATTENTION:
1354 * It is absolutely necessary to reset the SW_RST Bit first
1355 * before calling this function.
1356 *
1357 * Returns:
1358 * nothing
1359 */
1360static void SkGmHardRst(
1361SK_AC *pAC, /* adapter context */
1362SK_IOC IoC, /* IO context */
1363int Port) /* Port Index (MAC_1 + n) */
1364{
1365 /* set GPHY Control reset */
1366 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1367
1368 /* set GMAC Control reset */
1369 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1370
1371} /* SkGmHardRst */
1372
1373
1374/******************************************************************************
1375 *
1376 * SkMacSoftRst() - Do a MAC software reset
1377 *
1378 * Description: calls a MAC software reset routine dep. on board type
1379 *
1380 * Returns:
1381 * nothing
1382 */
1383void SkMacSoftRst(
1384SK_AC *pAC, /* adapter context */
1385SK_IOC IoC, /* IO context */
1386int Port) /* Port Index (MAC_1 + n) */
1387{
1388 SK_GEPORT *pPrt;
1389
1390 pPrt = &pAC->GIni.GP[Port];
1391
1392 /* disable receiver and transmitter */
1393 SkMacRxTxDisable(pAC, IoC, Port);
1394
1395 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00001396
wdenkeb20ad32003-09-05 23:19:14 +00001397 SkXmSoftRst(pAC, IoC, Port);
1398 }
1399 else {
wdenk9c53f402003-10-15 23:53:47 +00001400
wdenkeb20ad32003-09-05 23:19:14 +00001401 SkGmSoftRst(pAC, IoC, Port);
1402 }
1403
1404 /* flush the MAC's Rx and Tx FIFOs */
1405 SkMacFlushTxFifo(pAC, IoC, Port);
wdenk9c53f402003-10-15 23:53:47 +00001406
wdenkeb20ad32003-09-05 23:19:14 +00001407 SkMacFlushRxFifo(pAC, IoC, Port);
1408
1409 pPrt->PState = SK_PRT_STOP;
1410
1411} /* SkMacSoftRst */
1412
1413
1414/******************************************************************************
1415 *
1416 * SkMacHardRst() - Do a MAC hardware reset
1417 *
1418 * Description: calls a MAC hardware reset routine dep. on board type
1419 *
1420 * Returns:
1421 * nothing
1422 */
1423void SkMacHardRst(
1424SK_AC *pAC, /* adapter context */
1425SK_IOC IoC, /* IO context */
1426int Port) /* Port Index (MAC_1 + n) */
1427{
wdenk9c53f402003-10-15 23:53:47 +00001428
wdenkeb20ad32003-09-05 23:19:14 +00001429 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00001430
wdenkeb20ad32003-09-05 23:19:14 +00001431 SkXmHardRst(pAC, IoC, Port);
1432 }
1433 else {
wdenk9c53f402003-10-15 23:53:47 +00001434
wdenkeb20ad32003-09-05 23:19:14 +00001435 SkGmHardRst(pAC, IoC, Port);
1436 }
1437
1438 pAC->GIni.GP[Port].PState = SK_PRT_RESET;
1439
1440} /* SkMacHardRst */
1441
1442
wdenkeb20ad32003-09-05 23:19:14 +00001443/******************************************************************************
1444 *
1445 * SkXmInitMac() - Initialize the XMAC II
1446 *
1447 * Description:
1448 * Initialize the XMAC of the specified port.
1449 * The XMAC must be reset or stopped before calling this function.
1450 *
1451 * Note:
1452 * The XMAC's Rx and Tx state machine is still disabled when returning.
1453 *
1454 * Returns:
1455 * nothing
1456 */
1457void SkXmInitMac(
1458SK_AC *pAC, /* adapter context */
1459SK_IOC IoC, /* IO context */
1460int Port) /* Port Index (MAC_1 + n) */
1461{
1462 SK_GEPORT *pPrt;
1463 SK_U32 Reg;
1464 int i;
1465 SK_U16 SWord;
1466
1467 pPrt = &pAC->GIni.GP[Port];
1468
1469 if (pPrt->PState == SK_PRT_STOP) {
1470 /* Port State: SK_PRT_STOP */
1471 /* Verify that the reset bit is cleared */
1472 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1473
1474 if ((SWord & MFF_SET_MAC_RST) != 0) {
1475 /* PState does not match HW state */
1476 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1477 /* Correct it */
1478 pPrt->PState = SK_PRT_RESET;
1479 }
1480 }
1481
1482 if (pPrt->PState == SK_PRT_RESET) {
1483 /*
1484 * clear HW reset
1485 * Note: The SW reset is self clearing, therefore there is
1486 * nothing to do here.
1487 */
1488 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1489
1490 /* Ensure that XMAC reset release is done (errata from LReinbold?) */
1491 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1492
1493 /* Clear PHY reset */
1494 if (pPrt->PhyType != SK_PHY_XMAC) {
1495
1496 SK_IN32(IoC, B2_GP_IO, &Reg);
wdenk9c53f402003-10-15 23:53:47 +00001497
wdenkeb20ad32003-09-05 23:19:14 +00001498 if (Port == 0) {
1499 Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */
1500 }
1501 else {
1502 Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */
1503 }
1504 SK_OUT32(IoC, B2_GP_IO, Reg);
1505
1506 /* Enable GMII interface */
1507 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
1508
1509 /* read Id from external PHY (all have the same address) */
1510 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1511
1512 /*
1513 * Optimize MDIO transfer by suppressing preamble.
1514 * Must be done AFTER first access to BCOM chip.
1515 */
1516 XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
wdenk9c53f402003-10-15 23:53:47 +00001517
wdenkeb20ad32003-09-05 23:19:14 +00001518 XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1519
1520 if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1521 /*
1522 * Workaround BCOM Errata for the C0 type.
1523 * Write magic patterns to reserved registers.
1524 */
1525 i = 0;
1526 while (BcomRegC0Hack[i].PhyReg != 0) {
1527 SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1528 BcomRegC0Hack[i].PhyVal);
1529 i++;
1530 }
1531 }
1532 else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1533 /*
1534 * Workaround BCOM Errata for the A1 type.
1535 * Write magic patterns to reserved registers.
1536 */
1537 i = 0;
1538 while (BcomRegA1Hack[i].PhyReg != 0) {
1539 SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1540 BcomRegA1Hack[i].PhyVal);
1541 i++;
1542 }
1543 }
1544
1545 /*
1546 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1547 * Disable Power Management after reset.
1548 */
1549 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
wdenk9c53f402003-10-15 23:53:47 +00001550
wdenkeb20ad32003-09-05 23:19:14 +00001551 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1552 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
1553
1554 /* PHY LED initialization is done in SkGeXmitLED() */
1555 }
1556
1557 /* Dummy read the Interrupt source register */
1558 XM_IN16(IoC, Port, XM_ISRC, &SWord);
wdenk9c53f402003-10-15 23:53:47 +00001559
wdenkeb20ad32003-09-05 23:19:14 +00001560 /*
1561 * The auto-negotiation process starts immediately after
1562 * clearing the reset. The auto-negotiation process should be
1563 * started by the SIRQ, therefore stop it here immediately.
1564 */
1565 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1566
1567#if 0
1568 /* temp. code: enable signal detect */
1569 /* WARNING: do not override GMII setting above */
1570 XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1571#endif
1572 }
1573
1574 /*
1575 * configure the XMACs Station Address
1576 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1577 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1578 */
1579 for (i = 0; i < 3; i++) {
1580 /*
1581 * The following 2 statements are together endianess
1582 * independent. Remember this when changing.
1583 */
1584 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
wdenk9c53f402003-10-15 23:53:47 +00001585
wdenkeb20ad32003-09-05 23:19:14 +00001586 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1587 }
1588
1589 /* Tx Inter Packet Gap (XM_TX_IPG): use default */
1590 /* Tx High Water Mark (XM_TX_HI_WM): use default */
1591 /* Tx Low Water Mark (XM_TX_LO_WM): use default */
1592 /* Host Request Threshold (XM_HT_THR): use default */
1593 /* Rx Request Threshold (XM_RX_THR): use default */
1594 /* Rx Low Water Mark (XM_RX_LO_WM): use default */
1595
1596 /* configure Rx High Water Mark (XM_RX_HI_WM) */
1597 XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1598
1599 /* Configure Tx Request Threshold */
1600 SWord = SK_XM_THR_SL; /* for single port */
1601
1602 if (pAC->GIni.GIMacsFound > 1) {
1603 switch (pAC->GIni.GIPortUsage) {
1604 case SK_RED_LINK:
1605 SWord = SK_XM_THR_REDL; /* redundant link */
1606 break;
1607 case SK_MUL_LINK:
1608 SWord = SK_XM_THR_MULL; /* load balancing */
1609 break;
1610 case SK_JUMBO_LINK:
1611 SWord = SK_XM_THR_JUMBO; /* jumbo frames */
1612 break;
1613 default:
1614 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1615 break;
1616 }
1617 }
1618 XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1619
1620 /* setup register defaults for the Tx Command Register */
1621 XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1622
1623 /* setup register defaults for the Rx Command Register */
1624 SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1625
1626 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1627 SWord |= XM_RX_BIG_PK_OK;
1628 }
1629
1630 if (pPrt->PLinkModeConf == SK_LMODE_HALF) {
1631 /*
1632 * If in manual half duplex mode the other side might be in
1633 * full duplex mode, so ignore if a carrier extension is not seen
1634 * on frames received
1635 */
1636 SWord |= XM_RX_DIS_CEXT;
1637 }
wdenk9c53f402003-10-15 23:53:47 +00001638
wdenkeb20ad32003-09-05 23:19:14 +00001639 XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1640
1641 /*
1642 * setup register defaults for the Mode Register
1643 * - Don't strip error frames to avoid Store & Forward
1644 * on the Rx side.
1645 * - Enable 'Check Station Address' bit
1646 * - Enable 'Check Address Array' bit
1647 */
1648 XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1649
1650 /*
1651 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1652 * - Enable all bits excepting 'Octets Rx OK Low CntOv'
1653 * and 'Octets Rx OK Hi Cnt Ov'.
1654 */
1655 XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1656
1657 /*
1658 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1659 * - Enable all bits excepting 'Octets Tx OK Low CntOv'
1660 * and 'Octets Tx OK Hi Cnt Ov'.
1661 */
1662 XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1663
1664 /*
1665 * Do NOT init XMAC interrupt mask here.
1666 * All interrupts remain disable until link comes up!
1667 */
1668
1669 /*
1670 * Any additional configuration changes may be done now.
1671 * The last action is to enable the Rx and Tx state machine.
1672 * This should be done after the auto-negotiation process
1673 * has been completed successfully.
1674 */
1675} /* SkXmInitMac */
1676
1677/******************************************************************************
1678 *
1679 * SkGmInitMac() - Initialize the GMAC
1680 *
1681 * Description:
1682 * Initialize the GMAC of the specified port.
1683 * The GMAC must be reset or stopped before calling this function.
1684 *
1685 * Note:
1686 * The GMAC's Rx and Tx state machine is still disabled when returning.
1687 *
1688 * Returns:
1689 * nothing
1690 */
1691void SkGmInitMac(
1692SK_AC *pAC, /* adapter context */
1693SK_IOC IoC, /* IO context */
1694int Port) /* Port Index (MAC_1 + n) */
1695{
1696 SK_GEPORT *pPrt;
1697 int i;
1698 SK_U16 SWord;
1699 SK_U32 DWord;
1700
1701 pPrt = &pAC->GIni.GP[Port];
1702
1703 if (pPrt->PState == SK_PRT_STOP) {
1704 /* Port State: SK_PRT_STOP */
1705 /* Verify that the reset bit is cleared */
1706 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
wdenk9c53f402003-10-15 23:53:47 +00001707
wdenkeb20ad32003-09-05 23:19:14 +00001708 if ((DWord & GMC_RST_SET) != 0) {
1709 /* PState does not match HW state */
1710 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1711 /* Correct it */
1712 pPrt->PState = SK_PRT_RESET;
1713 }
1714 }
1715
1716 if (pPrt->PState == SK_PRT_RESET) {
1717 /* set GPHY Control reset */
1718 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1719
1720 /* set GMAC Control reset */
1721 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1722
1723 /* clear GMAC Control reset */
1724 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
1725
1726 /* set GMAC Control reset */
1727 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1728
1729 /* set HWCFG_MODE */
1730 DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
1731 GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
1732 (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
1733 GPC_HWCFG_GMII_FIB);
1734
1735 /* set GPHY Control reset */
1736 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
1737
1738 /* release GPHY Control reset */
1739 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
1740
1741 /* clear GMAC Control reset */
1742 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
1743
1744 /* Dummy read the Interrupt source register */
1745 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
wdenk9c53f402003-10-15 23:53:47 +00001746
wdenkeb20ad32003-09-05 23:19:14 +00001747#ifndef VCPU
1748 /* read Id from PHY */
1749 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
wdenk9c53f402003-10-15 23:53:47 +00001750
wdenkeb20ad32003-09-05 23:19:14 +00001751 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1752#endif /* VCPU */
1753 }
1754
1755 (void)SkGmResetCounter(pAC, IoC, Port);
1756
1757 SWord = 0;
1758
1759 /* speed settings */
1760 switch (pPrt->PLinkSpeed) {
1761 case SK_LSPEED_AUTO:
1762 case SK_LSPEED_1000MBPS:
1763 SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1764 break;
1765 case SK_LSPEED_100MBPS:
1766 SWord |= GM_GPCR_SPEED_100;
1767 break;
1768 case SK_LSPEED_10MBPS:
1769 break;
1770 }
wdenk9c53f402003-10-15 23:53:47 +00001771
wdenkeb20ad32003-09-05 23:19:14 +00001772 /* duplex settings */
1773 if (pPrt->PLinkMode != SK_LMODE_HALF) {
1774 /* set full duplex */
1775 SWord |= GM_GPCR_DUP_FULL;
1776 }
1777
1778 /* flow control settings */
1779 switch (pPrt->PFlowCtrlMode) {
1780 case SK_FLOW_MODE_NONE:
1781 /* disable auto-negotiation for flow-control */
1782 SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS;
1783 break;
1784 case SK_FLOW_MODE_LOC_SEND:
1785 SWord |= GM_GPCR_FC_RX_DIS;
1786 break;
1787 case SK_FLOW_MODE_SYMMETRIC:
1788 /* TBD */
1789 case SK_FLOW_MODE_SYM_OR_REM:
1790 /* enable auto-negotiation for flow-control and */
1791 /* enable Rx and Tx of pause frames */
1792 break;
1793 }
1794
1795 /* Auto-negotiation ? */
1796 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1797 /* disable auto-update for speed, duplex and flow-control */
1798 SWord |= GM_GPCR_AU_ALL_DIS;
1799 }
wdenk9c53f402003-10-15 23:53:47 +00001800
wdenkeb20ad32003-09-05 23:19:14 +00001801 /* setup General Purpose Control Register */
1802 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1803
1804 /* setup Transmit Control Register */
1805 GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR);
1806
1807 /* setup Receive Control Register */
1808 GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1809 GM_RXCR_CRC_DIS);
1810
1811 /* setup Transmit Flow Control Register */
1812 GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1813
1814 /* setup Transmit Parameter Register */
1815#ifdef VCPU
1816 GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1817#endif /* VCPU */
1818
1819 SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26);
wdenk9c53f402003-10-15 23:53:47 +00001820
wdenkeb20ad32003-09-05 23:19:14 +00001821 GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1822
1823 /* configure the Serial Mode Register */
1824#ifdef VCPU
1825 GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1826#endif /* VCPU */
wdenk9c53f402003-10-15 23:53:47 +00001827
wdenkeb20ad32003-09-05 23:19:14 +00001828 SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH;
1829
1830 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1831 /* enable jumbo mode (Max. Frame Length = 9018) */
1832 SWord |= GM_SMOD_JUMBO_ENA;
1833 }
wdenk9c53f402003-10-15 23:53:47 +00001834
wdenkeb20ad32003-09-05 23:19:14 +00001835 GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
wdenk9c53f402003-10-15 23:53:47 +00001836
wdenkeb20ad32003-09-05 23:19:14 +00001837 /*
1838 * configure the GMACs Station Addresses
1839 * in PROM you can find our addresses at:
1840 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1841 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1842 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1843 */
1844
1845 for (i = 0; i < 3; i++) {
1846 /*
1847 * The following 2 statements are together endianess
1848 * independent. Remember this when changing.
1849 */
1850 /* physical address: will be used for pause frames */
1851 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1852
1853#ifdef WA_DEV_16
1854 /* WA for deviation #16 */
1855 if (pAC->GIni.GIChipRev == 0) {
1856 /* swap the address bytes */
1857 SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
1858
1859 /* write to register in reversed order */
1860 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
1861 }
1862 else {
1863 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1864 }
wdenk9c53f402003-10-15 23:53:47 +00001865#else
wdenkeb20ad32003-09-05 23:19:14 +00001866 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1867#endif /* WA_DEV_16 */
wdenk9c53f402003-10-15 23:53:47 +00001868
wdenkeb20ad32003-09-05 23:19:14 +00001869 /* virtual address: will be used for data */
1870 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
1871
1872 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
wdenk9c53f402003-10-15 23:53:47 +00001873
wdenkeb20ad32003-09-05 23:19:14 +00001874 /* reset Multicast filtering Hash registers 1-3 */
1875 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
1876 }
1877
1878 /* reset Multicast filtering Hash register 4 */
1879 GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
1880
1881 /* enable interrupt mask for counter overflows */
1882 GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
1883 GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
1884 GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
1885
1886 /* read General Purpose Status */
1887 GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
wdenk9c53f402003-10-15 23:53:47 +00001888
wdenkeb20ad32003-09-05 23:19:14 +00001889 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1890 ("MAC Stat Reg=0x%04X\n", SWord));
1891
1892#ifdef SK_DIAG
1893 c_print("MAC Stat Reg=0x%04X\n", SWord);
1894#endif /* SK_DIAG */
1895
1896} /* SkGmInitMac */
1897
1898
1899/******************************************************************************
1900 *
1901 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1902 *
1903 * Description:
1904 * This function initializes the XMACs Duplex Mode.
1905 * It should be called after successfully finishing
1906 * the Auto-negotiation Process
1907 *
1908 * Returns:
1909 * nothing
1910 */
1911void SkXmInitDupMd(
1912SK_AC *pAC, /* adapter context */
1913SK_IOC IoC, /* IO context */
1914int Port) /* Port Index (MAC_1 + n) */
1915{
1916 switch (pAC->GIni.GP[Port].PLinkModeStatus) {
1917 case SK_LMODE_STAT_AUTOHALF:
1918 case SK_LMODE_STAT_HALF:
1919 /* Configuration Actions for Half Duplex Mode */
1920 /*
1921 * XM_BURST = default value. We are probable not quick
1922 * enough at the 'XMAC' bus to burst 8kB.
1923 * The XMAC stops bursting if no transmit frames
1924 * are available or the burst limit is exceeded.
1925 */
1926 /* XM_TX_RT_LIM = default value (15) */
1927 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
1928 break;
1929 case SK_LMODE_STAT_AUTOFULL:
1930 case SK_LMODE_STAT_FULL:
1931 /* Configuration Actions for Full Duplex Mode */
1932 /*
1933 * The duplex mode is configured by the PHY,
1934 * therefore it seems to be that there is nothing
1935 * to do here.
1936 */
1937 break;
1938 case SK_LMODE_STAT_UNKNOWN:
1939 default:
1940 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
1941 break;
1942 }
1943} /* SkXmInitDupMd */
1944
1945
1946/******************************************************************************
1947 *
1948 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1949 *
1950 * Description:
1951 * This function initializes the Pause Mode which should
1952 * be used for this port.
1953 * It should be called after successfully finishing
1954 * the Auto-negotiation Process
1955 *
1956 * Returns:
1957 * nothing
1958 */
1959void SkXmInitPauseMd(
1960SK_AC *pAC, /* adapter context */
1961SK_IOC IoC, /* IO context */
1962int Port) /* Port Index (MAC_1 + n) */
1963{
1964 SK_GEPORT *pPrt;
1965 SK_U32 DWord;
1966 SK_U16 Word;
1967
1968 pPrt = &pAC->GIni.GP[Port];
1969
1970 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
wdenk9c53f402003-10-15 23:53:47 +00001971
wdenkeb20ad32003-09-05 23:19:14 +00001972 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
1973 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1974
1975 /* Disable Pause Frame Reception */
1976 Word |= XM_MMU_IGN_PF;
1977 }
1978 else {
1979 /*
1980 * enabling pause frame reception is required for 1000BT
1981 * because the XMAC is not reset if the link is going down
1982 */
1983 /* Enable Pause Frame Reception */
1984 Word &= ~XM_MMU_IGN_PF;
wdenk9c53f402003-10-15 23:53:47 +00001985 }
1986
wdenkeb20ad32003-09-05 23:19:14 +00001987 XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
1988
1989 XM_IN32(IoC, Port, XM_MODE, &DWord);
1990
1991 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
1992 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1993
1994 /*
1995 * Configure Pause Frame Generation
1996 * Use internal and external Pause Frame Generation.
1997 * Sending pause frames is edge triggered.
1998 * Send a Pause frame with the maximum pause time if
1999 * internal oder external FIFO full condition occurs.
2000 * Send a zero pause time frame to re-start transmission.
2001 */
2002
2003 /* XM_PAUSE_DA = '010000C28001' (default) */
2004
2005 /* XM_MAC_PTIME = 0xffff (maximum) */
2006 /* remember this value is defined in big endian (!) */
2007 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
2008
2009 /* Set Pause Mode in Mode Register */
2010 DWord |= XM_PAUSE_MODE;
2011
2012 /* Set Pause Mode in MAC Rx FIFO */
2013 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
2014 }
2015 else {
2016 /*
2017 * disable pause frame generation is required for 1000BT
2018 * because the XMAC is not reset if the link is going down
2019 */
2020 /* Disable Pause Mode in Mode Register */
2021 DWord &= ~XM_PAUSE_MODE;
2022
2023 /* Disable Pause Mode in MAC Rx FIFO */
2024 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
2025 }
wdenk9c53f402003-10-15 23:53:47 +00002026
wdenkeb20ad32003-09-05 23:19:14 +00002027 XM_OUT32(IoC, Port, XM_MODE, DWord);
2028} /* SkXmInitPauseMd*/
2029
2030
2031/******************************************************************************
2032 *
2033 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
2034 *
2035 * Description: initializes all the XMACs Phy registers
2036 *
2037 * Note:
2038 *
2039 * Returns:
2040 * nothing
2041 */
2042static void SkXmInitPhyXmac(
2043SK_AC *pAC, /* adapter context */
2044SK_IOC IoC, /* IO context */
2045int Port, /* Port Index (MAC_1 + n) */
2046SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2047{
2048 SK_GEPORT *pPrt;
2049 SK_U16 Ctrl;
2050
2051 pPrt = &pAC->GIni.GP[Port];
2052 Ctrl = 0;
wdenk9c53f402003-10-15 23:53:47 +00002053
wdenkeb20ad32003-09-05 23:19:14 +00002054 /* Auto-negotiation ? */
2055 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2056 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2057 ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
2058 /* Set DuplexMode in Config register */
2059 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2060 Ctrl |= PHY_CT_DUP_MD;
2061 }
2062
2063 /*
2064 * Do NOT enable Auto-negotiation here. This would hold
2065 * the link down because no IDLEs are transmitted
2066 */
2067 }
2068 else {
2069 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2070 ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
2071 /* Set Auto-negotiation advertisement */
2072
2073 /* Set Full/half duplex capabilities */
2074 switch (pPrt->PLinkMode) {
2075 case SK_LMODE_AUTOHALF:
2076 Ctrl |= PHY_X_AN_HD;
2077 break;
2078 case SK_LMODE_AUTOFULL:
2079 Ctrl |= PHY_X_AN_FD;
2080 break;
2081 case SK_LMODE_AUTOBOTH:
2082 Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
2083 break;
2084 default:
2085 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2086 SKERR_HWI_E015MSG);
2087 }
2088
2089 switch (pPrt->PFlowCtrlMode) {
2090 case SK_FLOW_MODE_NONE:
2091 Ctrl |= PHY_X_P_NO_PAUSE;
2092 break;
2093 case SK_FLOW_MODE_LOC_SEND:
2094 Ctrl |= PHY_X_P_ASYM_MD;
2095 break;
2096 case SK_FLOW_MODE_SYMMETRIC:
2097 Ctrl |= PHY_X_P_SYM_MD;
2098 break;
2099 case SK_FLOW_MODE_SYM_OR_REM:
2100 Ctrl |= PHY_X_P_BOTH_MD;
2101 break;
2102 default:
2103 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2104 SKERR_HWI_E016MSG);
2105 }
2106
2107 /* Write AutoNeg Advertisement Register */
2108 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
2109
2110 /* Restart Auto-negotiation */
2111 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
2112 }
2113
2114 if (DoLoop) {
2115 /* Set the Phy Loopback bit, too */
2116 Ctrl |= PHY_CT_LOOP;
2117 }
2118
2119 /* Write to the Phy control register */
2120 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
2121} /* SkXmInitPhyXmac */
2122
2123
2124/******************************************************************************
2125 *
2126 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
2127 *
2128 * Description: initializes all the Broadcom Phy registers
2129 *
2130 * Note:
2131 *
2132 * Returns:
2133 * nothing
2134 */
2135static void SkXmInitPhyBcom(
2136SK_AC *pAC, /* adapter context */
2137SK_IOC IoC, /* IO context */
2138int Port, /* Port Index (MAC_1 + n) */
2139SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2140{
2141 SK_GEPORT *pPrt;
2142 SK_U16 Ctrl1;
2143 SK_U16 Ctrl2;
2144 SK_U16 Ctrl3;
2145 SK_U16 Ctrl4;
2146 SK_U16 Ctrl5;
2147
2148 Ctrl1 = PHY_CT_SP1000;
2149 Ctrl2 = 0;
2150 Ctrl3 = PHY_SEL_TYPE;
2151 Ctrl4 = PHY_B_PEC_EN_LTR;
2152 Ctrl5 = PHY_B_AC_TX_TST;
2153
2154 pPrt = &pAC->GIni.GP[Port];
2155
2156 /* manually Master/Slave ? */
2157 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2158 Ctrl2 |= PHY_B_1000C_MSE;
wdenk9c53f402003-10-15 23:53:47 +00002159
wdenkeb20ad32003-09-05 23:19:14 +00002160 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2161 Ctrl2 |= PHY_B_1000C_MSC;
2162 }
2163 }
2164 /* Auto-negotiation ? */
2165 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2166 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2167 ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
2168 /* Set DuplexMode in Config register */
2169 Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2170
2171 /* Determine Master/Slave manually if not already done */
2172 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2173 Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
2174 }
2175
2176 /*
2177 * Do NOT enable Auto-negotiation here. This would hold
2178 * the link down because no IDLES are transmitted
2179 */
2180 }
2181 else {
2182 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2183 ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
2184 /* Set Auto-negotiation advertisement */
2185
2186 /*
2187 * Workaround BCOM Errata #1 for the C5 type.
2188 * 1000Base-T Link Acquisition Failure in Slave Mode
2189 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
2190 */
2191 Ctrl2 |= PHY_B_1000C_RD;
wdenk9c53f402003-10-15 23:53:47 +00002192
wdenkeb20ad32003-09-05 23:19:14 +00002193 /* Set Full/half duplex capabilities */
2194 switch (pPrt->PLinkMode) {
2195 case SK_LMODE_AUTOHALF:
2196 Ctrl2 |= PHY_B_1000C_AHD;
2197 break;
2198 case SK_LMODE_AUTOFULL:
2199 Ctrl2 |= PHY_B_1000C_AFD;
2200 break;
2201 case SK_LMODE_AUTOBOTH:
2202 Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
2203 break;
2204 default:
2205 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2206 SKERR_HWI_E015MSG);
2207 }
2208
2209 switch (pPrt->PFlowCtrlMode) {
2210 case SK_FLOW_MODE_NONE:
2211 Ctrl3 |= PHY_B_P_NO_PAUSE;
2212 break;
2213 case SK_FLOW_MODE_LOC_SEND:
2214 Ctrl3 |= PHY_B_P_ASYM_MD;
2215 break;
2216 case SK_FLOW_MODE_SYMMETRIC:
2217 Ctrl3 |= PHY_B_P_SYM_MD;
2218 break;
2219 case SK_FLOW_MODE_SYM_OR_REM:
2220 Ctrl3 |= PHY_B_P_BOTH_MD;
2221 break;
2222 default:
2223 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2224 SKERR_HWI_E016MSG);
2225 }
2226
2227 /* Restart Auto-negotiation */
2228 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2229 }
wdenk9c53f402003-10-15 23:53:47 +00002230
wdenkeb20ad32003-09-05 23:19:14 +00002231 /* Initialize LED register here? */
2232 /* No. Please do it in SkDgXmitLed() (if required) and swap
2233 init order of LEDs and XMAC. (MAl) */
wdenk9c53f402003-10-15 23:53:47 +00002234
wdenkeb20ad32003-09-05 23:19:14 +00002235 /* Write 1000Base-T Control Register */
2236 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2237 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2238 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
wdenk9c53f402003-10-15 23:53:47 +00002239
wdenkeb20ad32003-09-05 23:19:14 +00002240 /* Write AutoNeg Advertisement Register */
2241 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2242 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2243 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
wdenk9c53f402003-10-15 23:53:47 +00002244
wdenkeb20ad32003-09-05 23:19:14 +00002245 if (DoLoop) {
2246 /* Set the Phy Loopback bit, too */
2247 Ctrl1 |= PHY_CT_LOOP;
2248 }
2249
2250 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2251 /* configure FIFO to high latency for transmission of ext. packets */
2252 Ctrl4 |= PHY_B_PEC_HIGH_LA;
2253
2254 /* configure reception of extended packets */
2255 Ctrl5 |= PHY_B_AC_LONG_PACK;
2256
2257 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2258 }
2259
2260 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2261 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
wdenk9c53f402003-10-15 23:53:47 +00002262
wdenkeb20ad32003-09-05 23:19:14 +00002263 /* Write to the Phy control register */
2264 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2265 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2266 ("PHY Control Reg=0x%04X\n", Ctrl1));
2267} /* SkXmInitPhyBcom */
2268
2269
2270/******************************************************************************
2271 *
2272 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2273 *
2274 * Description: initializes all the Marvell Phy registers
2275 *
2276 * Note:
2277 *
2278 * Returns:
2279 * nothing
2280 */
2281static void SkGmInitPhyMarv(
2282SK_AC *pAC, /* adapter context */
2283SK_IOC IoC, /* IO context */
2284int Port, /* Port Index (MAC_1 + n) */
2285SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2286{
2287 SK_GEPORT *pPrt;
2288 SK_U16 PhyCtrl;
2289 SK_U16 C1000BaseT;
2290 SK_U16 AutoNegAdv;
2291 SK_U16 ExtPhyCtrl;
2292 SK_U16 PhyStat;
2293 SK_U16 PhyStat1;
2294 SK_U16 PhySpecStat;
2295 SK_U16 LedCtrl;
2296 SK_BOOL AutoNeg;
2297
2298#ifdef VCPU
2299 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2300 Port, DoLoop);
2301#else /* VCPU */
wdenk9c53f402003-10-15 23:53:47 +00002302
wdenkeb20ad32003-09-05 23:19:14 +00002303 pPrt = &pAC->GIni.GP[Port];
2304
2305 /* Auto-negotiation ? */
2306 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2307 AutoNeg = SK_FALSE;
2308 }
2309 else {
2310 AutoNeg = SK_TRUE;
2311 }
wdenk9c53f402003-10-15 23:53:47 +00002312
wdenkeb20ad32003-09-05 23:19:14 +00002313 if (!DoLoop) {
2314 /* Read Ext. PHY Specific Control */
2315 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
wdenk9c53f402003-10-15 23:53:47 +00002316
wdenkeb20ad32003-09-05 23:19:14 +00002317 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2318 PHY_M_EC_MAC_S_MSK);
wdenk9c53f402003-10-15 23:53:47 +00002319
wdenkeb20ad32003-09-05 23:19:14 +00002320 ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) |
2321 PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
wdenk9c53f402003-10-15 23:53:47 +00002322
wdenkeb20ad32003-09-05 23:19:14 +00002323 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2324 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2325 ("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl));
wdenk9c53f402003-10-15 23:53:47 +00002326
wdenkeb20ad32003-09-05 23:19:14 +00002327 /* Read PHY Control */
2328 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
wdenk9c53f402003-10-15 23:53:47 +00002329
wdenkeb20ad32003-09-05 23:19:14 +00002330 /* Assert software reset */
2331 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL,
2332 (SK_U16)(PhyCtrl | PHY_CT_RESET));
2333 }
2334#endif /* VCPU */
2335
2336 PhyCtrl = 0 /* PHY_CT_COL_TST */;
2337 C1000BaseT = 0;
2338 AutoNegAdv = PHY_SEL_TYPE;
2339
2340 /* manually Master/Slave ? */
2341 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2342 /* enable Manual Master/Slave */
2343 C1000BaseT |= PHY_M_1000C_MSE;
wdenk9c53f402003-10-15 23:53:47 +00002344
wdenkeb20ad32003-09-05 23:19:14 +00002345 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2346 C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
2347 }
2348 }
wdenk9c53f402003-10-15 23:53:47 +00002349
wdenkeb20ad32003-09-05 23:19:14 +00002350 /* Auto-negotiation ? */
2351 if (!AutoNeg) {
2352 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2353 ("InitPhyMarv: no auto-negotiation Port %d\n", Port));
wdenk9c53f402003-10-15 23:53:47 +00002354
wdenkeb20ad32003-09-05 23:19:14 +00002355 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2356 /* Set Full Duplex Mode */
2357 PhyCtrl |= PHY_CT_DUP_MD;
2358 }
2359
2360 /* Set Master/Slave manually if not already done */
2361 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2362 C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
2363 }
2364
2365 /* Set Speed */
2366 switch (pPrt->PLinkSpeed) {
2367 case SK_LSPEED_AUTO:
2368 case SK_LSPEED_1000MBPS:
2369 PhyCtrl |= PHY_CT_SP1000;
2370 break;
2371 case SK_LSPEED_100MBPS:
2372 PhyCtrl |= PHY_CT_SP100;
2373 break;
2374 case SK_LSPEED_10MBPS:
2375 break;
2376 default:
2377 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2378 SKERR_HWI_E019MSG);
2379 }
2380
2381 if (!DoLoop) {
2382 PhyCtrl |= PHY_CT_RESET;
2383 }
2384 /*
2385 * Do NOT enable Auto-negotiation here. This would hold
2386 * the link down because no IDLES are transmitted
2387 */
2388 }
2389 else {
2390 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2391 ("InitPhyMarv: with auto-negotiation Port %d\n", Port));
wdenk9c53f402003-10-15 23:53:47 +00002392
wdenkeb20ad32003-09-05 23:19:14 +00002393 PhyCtrl |= PHY_CT_ANE;
wdenk9c53f402003-10-15 23:53:47 +00002394
wdenkeb20ad32003-09-05 23:19:14 +00002395 if (pAC->GIni.GICopperType) {
2396 /* Set Speed capabilities */
2397 switch (pPrt->PLinkSpeed) {
2398 case SK_LSPEED_AUTO:
2399 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2400 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2401 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2402 break;
2403 case SK_LSPEED_1000MBPS:
2404 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2405 break;
2406 case SK_LSPEED_100MBPS:
2407 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2408 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2409 break;
2410 case SK_LSPEED_10MBPS:
2411 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2412 break;
2413 default:
2414 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2415 SKERR_HWI_E019MSG);
2416 }
2417
2418 /* Set Full/half duplex capabilities */
2419 switch (pPrt->PLinkMode) {
2420 case SK_LMODE_AUTOHALF:
2421 C1000BaseT &= ~PHY_M_1000C_AFD;
2422 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2423 break;
2424 case SK_LMODE_AUTOFULL:
2425 C1000BaseT &= ~PHY_M_1000C_AHD;
2426 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2427 break;
2428 case SK_LMODE_AUTOBOTH:
2429 break;
2430 default:
2431 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2432 SKERR_HWI_E015MSG);
2433 }
wdenk9c53f402003-10-15 23:53:47 +00002434
wdenkeb20ad32003-09-05 23:19:14 +00002435 /* Set Auto-negotiation advertisement */
2436 switch (pPrt->PFlowCtrlMode) {
2437 case SK_FLOW_MODE_NONE:
2438 AutoNegAdv |= PHY_B_P_NO_PAUSE;
2439 break;
2440 case SK_FLOW_MODE_LOC_SEND:
2441 AutoNegAdv |= PHY_B_P_ASYM_MD;
2442 break;
2443 case SK_FLOW_MODE_SYMMETRIC:
2444 AutoNegAdv |= PHY_B_P_SYM_MD;
2445 break;
2446 case SK_FLOW_MODE_SYM_OR_REM:
2447 AutoNegAdv |= PHY_B_P_BOTH_MD;
2448 break;
2449 default:
2450 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2451 SKERR_HWI_E016MSG);
2452 }
2453 }
2454 else { /* special defines for FIBER (88E1011S only) */
wdenk9c53f402003-10-15 23:53:47 +00002455
wdenkeb20ad32003-09-05 23:19:14 +00002456 /* Set Full/half duplex capabilities */
2457 switch (pPrt->PLinkMode) {
2458 case SK_LMODE_AUTOHALF:
2459 AutoNegAdv |= PHY_M_AN_1000X_AHD;
2460 break;
2461 case SK_LMODE_AUTOFULL:
2462 AutoNegAdv |= PHY_M_AN_1000X_AFD;
2463 break;
2464 case SK_LMODE_AUTOBOTH:
2465 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2466 break;
2467 default:
2468 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2469 SKERR_HWI_E015MSG);
2470 }
wdenk9c53f402003-10-15 23:53:47 +00002471
wdenkeb20ad32003-09-05 23:19:14 +00002472 /* Set Auto-negotiation advertisement */
2473 switch (pPrt->PFlowCtrlMode) {
2474 case SK_FLOW_MODE_NONE:
2475 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2476 break;
2477 case SK_FLOW_MODE_LOC_SEND:
2478 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2479 break;
2480 case SK_FLOW_MODE_SYMMETRIC:
2481 AutoNegAdv |= PHY_M_P_SYM_MD_X;
2482 break;
2483 case SK_FLOW_MODE_SYM_OR_REM:
2484 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2485 break;
2486 default:
2487 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2488 SKERR_HWI_E016MSG);
2489 }
2490 }
2491
2492 if (!DoLoop) {
2493 /* Restart Auto-negotiation */
2494 PhyCtrl |= PHY_CT_RE_CFG;
2495 }
2496 }
wdenk9c53f402003-10-15 23:53:47 +00002497
wdenkeb20ad32003-09-05 23:19:14 +00002498#ifdef VCPU
2499 /*
2500 * E-mail from Gu Lin (08-03-2002):
2501 */
wdenk9c53f402003-10-15 23:53:47 +00002502
wdenkeb20ad32003-09-05 23:19:14 +00002503 /* Program PHY register 30 as 16'h0708 for simulation speed up */
2504 SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708);
wdenk9c53f402003-10-15 23:53:47 +00002505
wdenkeb20ad32003-09-05 23:19:14 +00002506 VCpuWait(2000);
2507
2508#else /* VCPU */
wdenk9c53f402003-10-15 23:53:47 +00002509
wdenkeb20ad32003-09-05 23:19:14 +00002510 /* Write 1000Base-T Control Register */
2511 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2512 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2513 ("1000B-T Ctrl=0x%04X\n", C1000BaseT));
wdenk9c53f402003-10-15 23:53:47 +00002514
wdenkeb20ad32003-09-05 23:19:14 +00002515 /* Write AutoNeg Advertisement Register */
2516 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2517 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2518 ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv));
2519#endif /* VCPU */
wdenk9c53f402003-10-15 23:53:47 +00002520
wdenkeb20ad32003-09-05 23:19:14 +00002521 if (DoLoop) {
2522 /* Set the PHY Loopback bit */
2523 PhyCtrl |= PHY_CT_LOOP;
2524
2525 /* Program PHY register 16 as 16'h0400 to force link good */
2526 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2527
2528#if 0
2529 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2530 /* Write Ext. PHY Specific Control */
2531 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2532 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2533 }
2534 }
2535 else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2536 /* Write PHY Specific Control */
2537 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK);
2538 }
2539#endif /* 0 */
2540 }
2541
2542 /* Write to the PHY Control register */
2543 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2544
2545#ifdef VCPU
2546 VCpuWait(2000);
2547#else
2548
2549 LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2550
2551#ifdef ACT_LED_BLINK
2552 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2553#endif /* ACT_LED_BLINK */
2554
2555#ifdef DUP_LED_NORMAL
2556 LedCtrl |= PHY_M_LEDC_DP_CTRL;
2557#endif /* DUP_LED_NORMAL */
2558
2559 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2560
2561#endif /* VCPU */
2562
2563#ifdef SK_DIAG
2564 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2565 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2566 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2567 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2568#endif /* SK_DIAG */
2569
2570#ifndef xDEBUG
2571 /* Read PHY Control */
2572 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2573 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2574 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
wdenk9c53f402003-10-15 23:53:47 +00002575
wdenkeb20ad32003-09-05 23:19:14 +00002576 /* Read 1000Base-T Control Register */
2577 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2578 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2579 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
wdenk9c53f402003-10-15 23:53:47 +00002580
wdenkeb20ad32003-09-05 23:19:14 +00002581 /* Read AutoNeg Advertisement Register */
2582 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2583 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2584 ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv));
wdenk9c53f402003-10-15 23:53:47 +00002585
wdenkeb20ad32003-09-05 23:19:14 +00002586 /* Read Ext. PHY Specific Control */
2587 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2588 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2589 ("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl));
wdenk9c53f402003-10-15 23:53:47 +00002590
wdenkeb20ad32003-09-05 23:19:14 +00002591 /* Read PHY Status */
2592 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2593 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2594 ("PHY Stat Reg.=0x%04X\n", PhyStat));
2595 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2596 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2597 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
wdenk9c53f402003-10-15 23:53:47 +00002598
wdenkeb20ad32003-09-05 23:19:14 +00002599 /* Read PHY Specific Status */
2600 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2601 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2602 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
2603#endif /* DEBUG */
2604
2605#ifdef SK_DIAG
2606 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2607 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2608 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2609 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2610 c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2611 c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2612 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2613#endif /* SK_DIAG */
2614
2615} /* SkGmInitPhyMarv */
2616
2617
2618#ifdef OTHER_PHY
2619/******************************************************************************
2620 *
2621 * SkXmInitPhyLone() - Initialize the Level One Phy registers
2622 *
2623 * Description: initializes all the Level One Phy registers
2624 *
2625 * Note:
2626 *
2627 * Returns:
2628 * nothing
2629 */
2630static void SkXmInitPhyLone(
2631SK_AC *pAC, /* adapter context */
2632SK_IOC IoC, /* IO context */
2633int Port, /* Port Index (MAC_1 + n) */
2634SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2635{
2636 SK_GEPORT *pPrt;
2637 SK_U16 Ctrl1;
2638 SK_U16 Ctrl2;
2639 SK_U16 Ctrl3;
2640
2641 Ctrl1 = PHY_CT_SP1000;
2642 Ctrl2 = 0;
2643 Ctrl3 = PHY_SEL_TYPE;
2644
2645 pPrt = &pAC->GIni.GP[Port];
2646
2647 /* manually Master/Slave ? */
2648 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2649 Ctrl2 |= PHY_L_1000C_MSE;
wdenk9c53f402003-10-15 23:53:47 +00002650
wdenkeb20ad32003-09-05 23:19:14 +00002651 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2652 Ctrl2 |= PHY_L_1000C_MSC;
2653 }
2654 }
2655 /* Auto-negotiation ? */
2656 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2657 /*
2658 * level one spec say: "1000Mbps: manual mode not allowed"
2659 * but lets see what happens...
2660 */
2661 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2662 ("InitPhyLone: no auto-negotiation Port %d\n", Port));
2663 /* Set DuplexMode in Config register */
2664 Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2665
2666 /* Determine Master/Slave manually if not already done */
2667 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2668 Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
2669 }
2670
2671 /*
2672 * Do NOT enable Auto-negotiation here. This would hold
2673 * the link down because no IDLES are transmitted
2674 */
2675 }
2676 else {
2677 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2678 ("InitPhyLone: with auto-negotiation Port %d\n", Port));
2679 /* Set Auto-negotiation advertisement */
2680
2681 /* Set Full/half duplex capabilities */
2682 switch (pPrt->PLinkMode) {
2683 case SK_LMODE_AUTOHALF:
2684 Ctrl2 |= PHY_L_1000C_AHD;
2685 break;
2686 case SK_LMODE_AUTOFULL:
2687 Ctrl2 |= PHY_L_1000C_AFD;
2688 break;
2689 case SK_LMODE_AUTOBOTH:
2690 Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2691 break;
2692 default:
2693 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2694 SKERR_HWI_E015MSG);
2695 }
2696
2697 switch (pPrt->PFlowCtrlMode) {
2698 case SK_FLOW_MODE_NONE:
2699 Ctrl3 |= PHY_L_P_NO_PAUSE;
2700 break;
2701 case SK_FLOW_MODE_LOC_SEND:
2702 Ctrl3 |= PHY_L_P_ASYM_MD;
2703 break;
2704 case SK_FLOW_MODE_SYMMETRIC:
2705 Ctrl3 |= PHY_L_P_SYM_MD;
2706 break;
2707 case SK_FLOW_MODE_SYM_OR_REM:
2708 Ctrl3 |= PHY_L_P_BOTH_MD;
2709 break;
2710 default:
2711 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2712 SKERR_HWI_E016MSG);
2713 }
2714
2715 /* Restart Auto-negotiation */
2716 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2717
2718 }
wdenk9c53f402003-10-15 23:53:47 +00002719
wdenkeb20ad32003-09-05 23:19:14 +00002720 /* Initialize LED register here ? */
2721 /* No. Please do it in SkDgXmitLed() (if required) and swap
2722 init order of LEDs and XMAC. (MAl) */
wdenk9c53f402003-10-15 23:53:47 +00002723
wdenkeb20ad32003-09-05 23:19:14 +00002724 /* Write 1000Base-T Control Register */
2725 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2726 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2727 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
wdenk9c53f402003-10-15 23:53:47 +00002728
wdenkeb20ad32003-09-05 23:19:14 +00002729 /* Write AutoNeg Advertisement Register */
2730 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2731 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2732 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
wdenk9c53f402003-10-15 23:53:47 +00002733
wdenkeb20ad32003-09-05 23:19:14 +00002734
2735 if (DoLoop) {
2736 /* Set the Phy Loopback bit, too */
2737 Ctrl1 |= PHY_CT_LOOP;
2738 }
2739
2740 /* Write to the Phy control register */
2741 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2742 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2743 ("PHY Control Reg=0x%04X\n", Ctrl1));
2744} /* SkXmInitPhyLone */
2745
2746
2747/******************************************************************************
2748 *
2749 * SkXmInitPhyNat() - Initialize the National Phy registers
2750 *
2751 * Description: initializes all the National Phy registers
2752 *
2753 * Note:
2754 *
2755 * Returns:
2756 * nothing
2757 */
2758static void SkXmInitPhyNat(
2759SK_AC *pAC, /* adapter context */
2760SK_IOC IoC, /* IO context */
2761int Port, /* Port Index (MAC_1 + n) */
2762SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2763{
2764/* todo: National */
2765} /* SkXmInitPhyNat */
2766#endif /* OTHER_PHY */
2767
2768
2769/******************************************************************************
2770 *
2771 * SkMacInitPhy() - Initialize the PHY registers
2772 *
2773 * Description: calls the Init PHY routines dep. on board type
2774 *
2775 * Note:
2776 *
2777 * Returns:
2778 * nothing
2779 */
2780void SkMacInitPhy(
2781SK_AC *pAC, /* adapter context */
2782SK_IOC IoC, /* IO context */
2783int Port, /* Port Index (MAC_1 + n) */
2784SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2785{
2786 SK_GEPORT *pPrt;
2787
2788 pPrt = &pAC->GIni.GP[Port];
2789
2790 switch (pPrt->PhyType) {
2791 case SK_PHY_XMAC:
2792 SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2793 break;
2794 case SK_PHY_BCOM:
2795 SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2796 break;
2797 case SK_PHY_MARV_COPPER:
2798 case SK_PHY_MARV_FIBER:
2799 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2800 break;
2801#ifdef OTHER_PHY
2802 case SK_PHY_LONE:
2803 SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2804 break;
2805 case SK_PHY_NAT:
2806 SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2807 break;
2808#endif /* OTHER_PHY */
2809 }
2810} /* SkMacInitPhy */
2811
2812
2813#ifndef SK_DIAG
2814/******************************************************************************
2815 *
2816 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
2817 *
2818 * This function analyses the Interrupt status word. If any of the
2819 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
2820 * is set true.
2821 */
2822void SkXmAutoNegLipaXmac(
2823SK_AC *pAC, /* adapter context */
2824SK_IOC IoC, /* IO context */
2825int Port, /* Port Index (MAC_1 + n) */
2826SK_U16 IStatus) /* Interrupt Status word to analyse */
2827{
2828 SK_GEPORT *pPrt;
2829
2830 pPrt = &pAC->GIni.GP[Port];
2831
2832 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2833 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
2834
2835 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2836 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n",
2837 Port, IStatus));
2838 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2839 }
2840} /* SkXmAutoNegLipaXmac */
2841
2842
2843/******************************************************************************
2844 *
2845 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
2846 *
2847 * This function analyses the PHY status word.
2848 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
2849 * is set true.
2850 */
2851void SkMacAutoNegLipaPhy(
2852SK_AC *pAC, /* adapter context */
2853SK_IOC IoC, /* IO context */
2854int Port, /* Port Index (MAC_1 + n) */
2855SK_U16 PhyStat) /* PHY Status word to analyse */
2856{
2857 SK_GEPORT *pPrt;
2858
2859 pPrt = &pAC->GIni.GP[Port];
2860
2861 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2862 (PhyStat & PHY_ST_AN_OVER) != 0) {
2863
2864 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2865 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\n",
2866 Port, PhyStat));
2867 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2868 }
2869} /* SkMacAutoNegLipaPhy */
2870#endif /* SK_DIAG */
2871
2872
2873/******************************************************************************
2874 *
2875 * SkXmAutoNegDoneXmac() - Auto-negotiation handling
2876 *
2877 * Description:
2878 * This function handles the auto-negotiation if the Done bit is set.
2879 *
2880 * Returns:
2881 * SK_AND_OK o.k.
2882 * SK_AND_DUP_CAP Duplex capability error happened
2883 * SK_AND_OTHER Other error happened
2884 */
2885static int SkXmAutoNegDoneXmac(
2886SK_AC *pAC, /* adapter context */
2887SK_IOC IoC, /* IO context */
2888int Port) /* Port Index (MAC_1 + n) */
2889{
2890 SK_GEPORT *pPrt;
2891 SK_U16 ResAb; /* Resolved Ability */
2892 SK_U16 LPAb; /* Link Partner Ability */
2893
2894 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2895 ("AutoNegDoneXmac, Port %d\n",Port));
2896
2897 pPrt = &pAC->GIni.GP[Port];
2898
2899 /* Get PHY parameters */
2900 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
2901 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
2902
2903 if ((LPAb & PHY_X_AN_RFB) != 0) {
2904 /* At least one of the remote fault bit is set */
2905 /* Error */
2906 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2907 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2908 pPrt->PAutoNegFail = SK_TRUE;
2909 return(SK_AND_OTHER);
2910 }
2911
2912 /* Check Duplex mismatch */
2913 if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
2914 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
2915 }
2916 else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
2917 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
2918 }
2919 else {
2920 /* Error */
2921 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2922 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2923 pPrt->PAutoNegFail = SK_TRUE;
2924 return(SK_AND_DUP_CAP);
2925 }
2926
2927 /* Check PAUSE mismatch */
2928 /* We are NOT using chapter 4.23 of the Xaqti manual */
2929 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2930 if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
2931 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
2932 (LPAb & PHY_X_P_SYM_MD) != 0) {
2933 /* Symmetric PAUSE */
2934 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2935 }
2936 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
2937 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
2938 /* Enable PAUSE receive, disable PAUSE transmit */
2939 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2940 }
2941 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
2942 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
2943 /* Disable PAUSE receive, enable PAUSE transmit */
2944 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2945 }
2946 else {
2947 /* PAUSE mismatch -> no PAUSE */
2948 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2949 }
2950 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
2951
2952 return(SK_AND_OK);
2953} /* SkXmAutoNegDoneXmac */
2954
2955
2956/******************************************************************************
2957 *
2958 * SkXmAutoNegDoneBcom() - Auto-negotiation handling
2959 *
2960 * Description:
2961 * This function handles the auto-negotiation if the Done bit is set.
2962 *
2963 * Returns:
2964 * SK_AND_OK o.k.
2965 * SK_AND_DUP_CAP Duplex capability error happened
2966 * SK_AND_OTHER Other error happened
2967 */
2968static int SkXmAutoNegDoneBcom(
2969SK_AC *pAC, /* adapter context */
2970SK_IOC IoC, /* IO context */
2971int Port) /* Port Index (MAC_1 + n) */
2972{
2973 SK_GEPORT *pPrt;
2974 SK_U16 LPAb; /* Link Partner Ability */
2975 SK_U16 AuxStat; /* Auxiliary Status */
2976
2977#if 0
297801-Sep-2000 RA;:;:
2979 SK_U16 ResAb; /* Resolved Ability */
2980#endif /* 0 */
2981
2982 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2983 ("AutoNegDoneBcom, Port %d\n", Port));
2984 pPrt = &pAC->GIni.GP[Port];
2985
2986 /* Get PHY parameters */
2987 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
2988#if 0
298901-Sep-2000 RA;:;:
2990 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
2991#endif /* 0 */
wdenk9c53f402003-10-15 23:53:47 +00002992
wdenkeb20ad32003-09-05 23:19:14 +00002993 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
2994
2995 if ((LPAb & PHY_B_AN_RF) != 0) {
2996 /* Remote fault bit is set: Error */
2997 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2998 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2999 pPrt->PAutoNegFail = SK_TRUE;
3000 return(SK_AND_OTHER);
3001 }
3002
3003 /* Check Duplex mismatch */
3004 if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
3005 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3006 }
3007 else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
3008 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3009 }
3010 else {
3011 /* Error */
3012 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3013 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3014 pPrt->PAutoNegFail = SK_TRUE;
3015 return(SK_AND_DUP_CAP);
3016 }
wdenk9c53f402003-10-15 23:53:47 +00003017
wdenkeb20ad32003-09-05 23:19:14 +00003018#if 0
301901-Sep-2000 RA;:;:
3020 /* Check Master/Slave resolution */
3021 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3022 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3023 ("Master/Slave Fault Port %d\n", Port));
3024 pPrt->PAutoNegFail = SK_TRUE;
3025 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3026 return(SK_AND_OTHER);
3027 }
wdenk9c53f402003-10-15 23:53:47 +00003028
wdenkeb20ad32003-09-05 23:19:14 +00003029 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3030 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
3031#endif /* 0 */
3032
3033 /* Check PAUSE mismatch */
3034 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3035 if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
3036 /* Symmetric PAUSE */
3037 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3038 }
3039 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
3040 /* Enable PAUSE receive, disable PAUSE transmit */
3041 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3042 }
3043 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
3044 /* Disable PAUSE receive, enable PAUSE transmit */
3045 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3046 }
3047 else {
3048 /* PAUSE mismatch -> no PAUSE */
3049 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3050 }
3051 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3052
3053 return(SK_AND_OK);
3054} /* SkXmAutoNegDoneBcom */
3055
3056
3057/******************************************************************************
3058 *
3059 * SkGmAutoNegDoneMarv() - Auto-negotiation handling
3060 *
3061 * Description:
3062 * This function handles the auto-negotiation if the Done bit is set.
3063 *
3064 * Returns:
3065 * SK_AND_OK o.k.
3066 * SK_AND_DUP_CAP Duplex capability error happened
3067 * SK_AND_OTHER Other error happened
3068 */
3069static int SkGmAutoNegDoneMarv(
3070SK_AC *pAC, /* adapter context */
3071SK_IOC IoC, /* IO context */
3072int Port) /* Port Index (MAC_1 + n) */
3073{
3074 SK_GEPORT *pPrt;
3075 SK_U16 LPAb; /* Link Partner Ability */
3076 SK_U16 ResAb; /* Resolved Ability */
3077 SK_U16 AuxStat; /* Auxiliary Status */
3078
3079 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3080 ("AutoNegDoneMarv, Port %d\n", Port));
3081 pPrt = &pAC->GIni.GP[Port];
3082
3083 /* Get PHY parameters */
3084 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
wdenk9c53f402003-10-15 23:53:47 +00003085
wdenkeb20ad32003-09-05 23:19:14 +00003086 if ((LPAb & PHY_M_AN_RF) != 0) {
3087 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3088 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3089 pPrt->PAutoNegFail = SK_TRUE;
3090 return(SK_AND_OTHER);
3091 }
3092
3093 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
wdenk9c53f402003-10-15 23:53:47 +00003094
wdenkeb20ad32003-09-05 23:19:14 +00003095 /* Check Master/Slave resolution */
3096 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3097 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3098 ("Master/Slave Fault Port %d\n", Port));
3099 pPrt->PAutoNegFail = SK_TRUE;
3100 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3101 return(SK_AND_OTHER);
3102 }
wdenk9c53f402003-10-15 23:53:47 +00003103
wdenkeb20ad32003-09-05 23:19:14 +00003104 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3105 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
wdenk9c53f402003-10-15 23:53:47 +00003106
wdenkeb20ad32003-09-05 23:19:14 +00003107 /* Read PHY Specific Status */
3108 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
wdenk9c53f402003-10-15 23:53:47 +00003109
wdenkeb20ad32003-09-05 23:19:14 +00003110 /* Check Speed & Duplex resolved */
3111 if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
3112 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3113 ("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port));
3114 pPrt->PAutoNegFail = SK_TRUE;
3115 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
3116 return(SK_AND_DUP_CAP);
3117 }
wdenk9c53f402003-10-15 23:53:47 +00003118
wdenkeb20ad32003-09-05 23:19:14 +00003119 if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
3120 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3121 }
3122 else {
3123 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3124 }
wdenk9c53f402003-10-15 23:53:47 +00003125
wdenkeb20ad32003-09-05 23:19:14 +00003126 /* Check PAUSE mismatch */
3127 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3128 if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
3129 /* Symmetric PAUSE */
3130 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3131 }
3132 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
3133 /* Enable PAUSE receive, disable PAUSE transmit */
3134 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3135 }
3136 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
3137 /* Disable PAUSE receive, enable PAUSE transmit */
3138 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3139 }
3140 else {
3141 /* PAUSE mismatch -> no PAUSE */
3142 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3143 }
wdenk9c53f402003-10-15 23:53:47 +00003144
wdenkeb20ad32003-09-05 23:19:14 +00003145 /* set used link speed */
3146 switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
3147 case (unsigned)PHY_M_PS_SPEED_1000:
3148 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3149 break;
3150 case PHY_M_PS_SPEED_100:
3151 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
3152 break;
3153 default:
3154 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
3155 }
3156
3157 return(SK_AND_OK);
3158} /* SkGmAutoNegDoneMarv */
3159
3160
3161#ifdef OTHER_PHY
3162/******************************************************************************
3163 *
3164 * SkXmAutoNegDoneLone() - Auto-negotiation handling
3165 *
3166 * Description:
3167 * This function handles the auto-negotiation if the Done bit is set.
3168 *
3169 * Returns:
3170 * SK_AND_OK o.k.
3171 * SK_AND_DUP_CAP Duplex capability error happened
3172 * SK_AND_OTHER Other error happened
3173 */
3174static int SkXmAutoNegDoneLone(
3175SK_AC *pAC, /* adapter context */
3176SK_IOC IoC, /* IO context */
3177int Port) /* Port Index (MAC_1 + n) */
3178{
3179 SK_GEPORT *pPrt;
3180 SK_U16 ResAb; /* Resolved Ability */
3181 SK_U16 LPAb; /* Link Partner Ability */
3182 SK_U16 QuickStat; /* Auxiliary Status */
3183
3184 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3185 ("AutoNegDoneLone, Port %d\n",Port));
3186 pPrt = &pAC->GIni.GP[Port];
3187
3188 /* Get PHY parameters */
3189 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
3190 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
3191 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
3192
3193 if ((LPAb & PHY_L_AN_RF) != 0) {
3194 /* Remote fault bit is set */
3195 /* Error */
3196 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3197 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3198 pPrt->PAutoNegFail = SK_TRUE;
3199 return(SK_AND_OTHER);
3200 }
3201
3202 /* Check Duplex mismatch */
3203 if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
3204 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3205 }
3206 else {
3207 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3208 }
wdenk9c53f402003-10-15 23:53:47 +00003209
wdenkeb20ad32003-09-05 23:19:14 +00003210 /* Check Master/Slave resolution */
3211 if ((ResAb & PHY_L_1000S_MSF) != 0) {
3212 /* Error */
3213 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3214 ("Master/Slave Fault Port %d\n", Port));
3215 pPrt->PAutoNegFail = SK_TRUE;
3216 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3217 return(SK_AND_OTHER);
3218 }
3219 else if (ResAb & PHY_L_1000S_MSR) {
3220 pPrt->PMSStatus = SK_MS_STAT_MASTER;
3221 }
3222 else {
3223 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
3224 }
3225
3226 /* Check PAUSE mismatch */
3227 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3228 /* we must manually resolve the abilities here */
3229 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3230 switch (pPrt->PFlowCtrlMode) {
3231 case SK_FLOW_MODE_NONE:
3232 /* default */
3233 break;
3234 case SK_FLOW_MODE_LOC_SEND:
3235 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3236 (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
3237 /* Disable PAUSE receive, enable PAUSE transmit */
3238 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3239 }
3240 break;
3241 case SK_FLOW_MODE_SYMMETRIC:
3242 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3243 /* Symmetric PAUSE */
3244 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3245 }
3246 break;
3247 case SK_FLOW_MODE_SYM_OR_REM:
3248 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3249 PHY_L_QS_AS_PAUSE) {
3250 /* Enable PAUSE receive, disable PAUSE transmit */
3251 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3252 }
3253 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3254 /* Symmetric PAUSE */
3255 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3256 }
3257 break;
3258 default:
3259 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3260 SKERR_HWI_E016MSG);
3261 }
wdenk9c53f402003-10-15 23:53:47 +00003262
wdenkeb20ad32003-09-05 23:19:14 +00003263 return(SK_AND_OK);
3264} /* SkXmAutoNegDoneLone */
3265
3266
3267/******************************************************************************
3268 *
3269 * SkXmAutoNegDoneNat() - Auto-negotiation handling
3270 *
3271 * Description:
3272 * This function handles the auto-negotiation if the Done bit is set.
3273 *
3274 * Returns:
3275 * SK_AND_OK o.k.
3276 * SK_AND_DUP_CAP Duplex capability error happened
3277 * SK_AND_OTHER Other error happened
3278 */
3279static int SkXmAutoNegDoneNat(
3280SK_AC *pAC, /* adapter context */
3281SK_IOC IoC, /* IO context */
3282int Port) /* Port Index (MAC_1 + n) */
3283{
3284/* todo: National */
3285 return(SK_AND_OK);
3286} /* SkXmAutoNegDoneNat */
3287#endif /* OTHER_PHY */
3288
3289
3290/******************************************************************************
3291 *
3292 * SkMacAutoNegDone() - Auto-negotiation handling
3293 *
3294 * Description: calls the auto-negotiation done routines dep. on board type
3295 *
3296 * Returns:
3297 * SK_AND_OK o.k.
3298 * SK_AND_DUP_CAP Duplex capability error happened
3299 * SK_AND_OTHER Other error happened
3300 */
3301int SkMacAutoNegDone(
3302SK_AC *pAC, /* adapter context */
3303SK_IOC IoC, /* IO context */
3304int Port) /* Port Index (MAC_1 + n) */
3305{
3306 SK_GEPORT *pPrt;
3307 int Rtv;
3308
3309 pPrt = &pAC->GIni.GP[Port];
3310
3311 switch (pPrt->PhyType) {
3312 case SK_PHY_XMAC:
3313 Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3314 break;
3315 case SK_PHY_BCOM:
3316 Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3317 break;
3318 case SK_PHY_MARV_COPPER:
3319 case SK_PHY_MARV_FIBER:
3320 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3321 break;
3322#ifdef OTHER_PHY
3323 case SK_PHY_LONE:
3324 Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3325 break;
3326 case SK_PHY_NAT:
3327 Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3328 break;
3329#endif /* OTHER_PHY */
3330 default:
3331 return(SK_AND_OTHER);
3332 }
wdenk9c53f402003-10-15 23:53:47 +00003333
wdenkeb20ad32003-09-05 23:19:14 +00003334 if (Rtv != SK_AND_OK) {
3335 return(Rtv);
3336 }
3337
3338 /* We checked everything and may now enable the link */
3339 pPrt->PAutoNegFail = SK_FALSE;
3340
3341 SkMacRxTxEnable(pAC, IoC, Port);
wdenk9c53f402003-10-15 23:53:47 +00003342
wdenkeb20ad32003-09-05 23:19:14 +00003343 return(SK_AND_OK);
3344} /* SkMacAutoNegDone */
3345
3346
3347/******************************************************************************
3348 *
3349 * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3350 *
3351 * Description:
3352 * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3353 * enables Rx/Tx
3354 *
3355 * Returns: N/A
3356 */
3357static void SkXmSetRxTxEn(
3358SK_AC *pAC, /* Adapter Context */
3359SK_IOC IoC, /* IO context */
3360int Port, /* Port Index (MAC_1 + n) */
3361int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3362{
3363 SK_U16 Word;
3364
3365 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3366
3367 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3368 case SK_MAC_LOOPB_ON:
3369 Word |= XM_MMU_MAC_LB;
3370 break;
3371 case SK_MAC_LOOPB_OFF:
3372 Word &= ~XM_MMU_MAC_LB;
3373 break;
3374 }
3375
3376 switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
3377 case SK_PHY_LOOPB_ON:
3378 Word |= XM_MMU_GMII_LOOP;
3379 break;
3380 case SK_PHY_LOOPB_OFF:
3381 Word &= ~XM_MMU_GMII_LOOP;
3382 break;
3383 }
wdenk9c53f402003-10-15 23:53:47 +00003384
wdenkeb20ad32003-09-05 23:19:14 +00003385 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3386 case SK_PHY_FULLD_ON:
3387 Word |= XM_MMU_GMII_FD;
3388 break;
3389 case SK_PHY_FULLD_OFF:
3390 Word &= ~XM_MMU_GMII_FD;
3391 break;
3392 }
wdenk9c53f402003-10-15 23:53:47 +00003393
wdenkeb20ad32003-09-05 23:19:14 +00003394 XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3395
3396 /* dummy read to ensure writing */
3397 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3398
3399} /* SkXmSetRxTxEn */
3400
3401
3402/******************************************************************************
3403 *
3404 * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3405 *
3406 * Description:
3407 * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3408 * enables Rx/Tx
3409 *
3410 * Returns: N/A
3411 */
3412static void SkGmSetRxTxEn(
3413SK_AC *pAC, /* Adapter Context */
3414SK_IOC IoC, /* IO context */
3415int Port, /* Port Index (MAC_1 + n) */
3416int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */
3417{
3418 SK_U16 Ctrl;
wdenk9c53f402003-10-15 23:53:47 +00003419
wdenkeb20ad32003-09-05 23:19:14 +00003420 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3421
3422 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3423 case SK_MAC_LOOPB_ON:
3424 Ctrl |= GM_GPCR_LOOP_ENA;
3425 break;
3426 case SK_MAC_LOOPB_OFF:
3427 Ctrl &= ~GM_GPCR_LOOP_ENA;
3428 break;
3429 }
3430
3431 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3432 case SK_PHY_FULLD_ON:
3433 Ctrl |= GM_GPCR_DUP_FULL;
3434 break;
3435 case SK_PHY_FULLD_OFF:
3436 Ctrl &= ~GM_GPCR_DUP_FULL;
3437 break;
3438 }
wdenk9c53f402003-10-15 23:53:47 +00003439
wdenkeb20ad32003-09-05 23:19:14 +00003440 GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3441
3442 /* dummy read to ensure writing */
3443 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3444
3445} /* SkGmSetRxTxEn */
3446
3447
3448/******************************************************************************
3449 *
3450 * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3451 *
3452 * Description: calls the Special Set Rx/Tx Enable routines dep. on board type
3453 *
3454 * Returns: N/A
3455 */
3456void SkMacSetRxTxEn(
3457SK_AC *pAC, /* Adapter Context */
3458SK_IOC IoC, /* IO context */
3459int Port, /* Port Index (MAC_1 + n) */
3460int Para)
3461{
3462 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00003463
wdenkeb20ad32003-09-05 23:19:14 +00003464 SkXmSetRxTxEn(pAC, IoC, Port, Para);
3465 }
3466 else {
wdenk9c53f402003-10-15 23:53:47 +00003467
wdenkeb20ad32003-09-05 23:19:14 +00003468 SkGmSetRxTxEn(pAC, IoC, Port, Para);
3469 }
3470
3471} /* SkMacSetRxTxEn */
3472
3473
3474/******************************************************************************
3475 *
3476 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3477 *
3478 * Description: enables Rx/Tx dep. on board type
3479 *
3480 * Returns:
3481 * 0 o.k.
3482 * != 0 Error happened
3483 */
3484int SkMacRxTxEnable(
3485SK_AC *pAC, /* adapter context */
3486SK_IOC IoC, /* IO context */
3487int Port) /* Port Index (MAC_1 + n) */
3488{
3489 SK_GEPORT *pPrt;
3490 SK_U16 Reg; /* 16-bit register value */
3491 SK_U16 IntMask; /* MAC interrupt mask */
3492 SK_U16 SWord;
3493
3494 pPrt = &pAC->GIni.GP[Port];
3495
3496 if (!pPrt->PHWLinkUp) {
3497 /* The Hardware link is NOT up */
3498 return(0);
3499 }
3500
3501 if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3502 pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3503 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3504 pPrt->PAutoNegFail) {
3505 /* Auto-negotiation is not done or failed */
3506 return(0);
3507 }
3508
3509 if (pAC->GIni.GIGenesis) {
3510 /* set Duplex Mode and Pause Mode */
3511 SkXmInitDupMd(pAC, IoC, Port);
wdenk9c53f402003-10-15 23:53:47 +00003512
wdenkeb20ad32003-09-05 23:19:14 +00003513 SkXmInitPauseMd(pAC, IoC, Port);
wdenk9c53f402003-10-15 23:53:47 +00003514
wdenkeb20ad32003-09-05 23:19:14 +00003515 /*
3516 * Initialize the Interrupt Mask Register. Default IRQs are...
3517 * - Link Asynchronous Event
3518 * - Link Partner requests config
3519 * - Auto Negotiation Done
3520 * - Rx Counter Event Overflow
3521 * - Tx Counter Event Overflow
3522 * - Transmit FIFO Underrun
3523 */
3524 IntMask = XM_DEF_MSK;
3525
3526#ifdef DEBUG
3527 /* add IRQ for Receive FIFO Overflow */
3528 IntMask &= ~XM_IS_RXF_OV;
3529#endif /* DEBUG */
wdenk9c53f402003-10-15 23:53:47 +00003530
wdenkeb20ad32003-09-05 23:19:14 +00003531 if (pPrt->PhyType != SK_PHY_XMAC) {
3532 /* disable GP0 interrupt bit */
3533 IntMask |= XM_IS_INP_ASS;
3534 }
3535 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
wdenk9c53f402003-10-15 23:53:47 +00003536
wdenkeb20ad32003-09-05 23:19:14 +00003537 /* get MMU Command Reg. */
3538 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
wdenk9c53f402003-10-15 23:53:47 +00003539
wdenkeb20ad32003-09-05 23:19:14 +00003540 if (pPrt->PhyType != SK_PHY_XMAC &&
3541 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3542 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3543 /* set to Full Duplex */
3544 Reg |= XM_MMU_GMII_FD;
3545 }
wdenk9c53f402003-10-15 23:53:47 +00003546
wdenkeb20ad32003-09-05 23:19:14 +00003547 switch (pPrt->PhyType) {
3548 case SK_PHY_BCOM:
3549 /*
3550 * Workaround BCOM Errata (#10523) for all BCom Phys
3551 * Enable Power Management after link up
3552 */
3553 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3554 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3555 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3556 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
3557 break;
3558#ifdef OTHER_PHY
3559 case SK_PHY_LONE:
3560 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3561 break;
3562 case SK_PHY_NAT:
3563 /* todo National:
3564 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3565 /* no interrupts possible from National ??? */
3566 break;
3567#endif /* OTHER_PHY */
3568 }
wdenk9c53f402003-10-15 23:53:47 +00003569
wdenkeb20ad32003-09-05 23:19:14 +00003570 /* enable Rx/Tx */
3571 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3572 }
3573 else {
3574 /*
3575 * Initialize the Interrupt Mask Register. Default IRQs are...
3576 * - Rx Counter Event Overflow
3577 * - Tx Counter Event Overflow
3578 * - Transmit FIFO Underrun
3579 */
3580 IntMask = GMAC_DEF_MSK;
3581
3582#ifdef DEBUG
3583 /* add IRQ for Receive FIFO Overrun */
3584 IntMask |= GM_IS_RX_FF_OR;
3585#endif /* DEBUG */
wdenk9c53f402003-10-15 23:53:47 +00003586
wdenkeb20ad32003-09-05 23:19:14 +00003587 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
wdenk9c53f402003-10-15 23:53:47 +00003588
wdenkeb20ad32003-09-05 23:19:14 +00003589 /* get General Purpose Control */
3590 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
wdenk9c53f402003-10-15 23:53:47 +00003591
wdenkeb20ad32003-09-05 23:19:14 +00003592 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3593 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3594 /* set to Full Duplex */
3595 Reg |= GM_GPCR_DUP_FULL;
3596 }
wdenk9c53f402003-10-15 23:53:47 +00003597
wdenkeb20ad32003-09-05 23:19:14 +00003598 /* enable Rx/Tx */
3599 GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3600
3601#ifndef VCPU
3602 /* Enable all PHY interrupts */
3603 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
3604#endif /* VCPU */
3605 }
wdenk9c53f402003-10-15 23:53:47 +00003606
wdenkeb20ad32003-09-05 23:19:14 +00003607 return(0);
3608
3609} /* SkMacRxTxEnable */
3610
3611
3612/******************************************************************************
3613 *
3614 * SkMacRxTxDisable() - Disable Receiver and Transmitter
3615 *
3616 * Description: disables Rx/Tx dep. on board type
3617 *
3618 * Returns: N/A
3619 */
3620void SkMacRxTxDisable(
3621SK_AC *pAC, /* Adapter Context */
3622SK_IOC IoC, /* IO context */
3623int Port) /* Port Index (MAC_1 + n) */
3624{
3625 SK_U16 Word;
3626
3627 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00003628
wdenkeb20ad32003-09-05 23:19:14 +00003629 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
wdenk9c53f402003-10-15 23:53:47 +00003630
wdenkeb20ad32003-09-05 23:19:14 +00003631 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
wdenk9c53f402003-10-15 23:53:47 +00003632
wdenkeb20ad32003-09-05 23:19:14 +00003633 /* dummy read to ensure writing */
3634 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3635 }
3636 else {
wdenk9c53f402003-10-15 23:53:47 +00003637
wdenkeb20ad32003-09-05 23:19:14 +00003638 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3639
3640 GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
3641
3642 /* dummy read to ensure writing */
3643 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3644 }
3645} /* SkMacRxTxDisable */
3646
3647
3648/******************************************************************************
3649 *
3650 * SkMacIrqDisable() - Disable IRQ from MAC
3651 *
3652 * Description: sets the IRQ-mask to disable IRQ dep. on board type
3653 *
3654 * Returns: N/A
3655 */
3656void SkMacIrqDisable(
3657SK_AC *pAC, /* Adapter Context */
3658SK_IOC IoC, /* IO context */
3659int Port) /* Port Index (MAC_1 + n) */
3660{
3661 SK_GEPORT *pPrt;
3662 SK_U16 Word;
3663
3664 pPrt = &pAC->GIni.GP[Port];
3665
3666 if (pAC->GIni.GIGenesis) {
wdenk9c53f402003-10-15 23:53:47 +00003667
wdenkeb20ad32003-09-05 23:19:14 +00003668 /* disable all XMAC IRQs */
wdenk9c53f402003-10-15 23:53:47 +00003669 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
3670
wdenkeb20ad32003-09-05 23:19:14 +00003671 /* Disable all PHY interrupts */
3672 switch (pPrt->PhyType) {
3673 case SK_PHY_BCOM:
3674 /* Make sure that PHY is initialized */
3675 if (pPrt->PState != SK_PRT_RESET) {
3676 /* NOT allowed if BCOM is in RESET state */
3677 /* Workaround BCOM Errata (#10523) all BCom */
3678 /* Disable Power Management if link is down */
3679 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3680 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3681 (SK_U16)(Word | PHY_B_AC_DIS_PM));
3682 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3683 }
3684 break;
3685#ifdef OTHER_PHY
3686 case SK_PHY_LONE:
3687 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3688 break;
3689 case SK_PHY_NAT:
3690 /* todo: National
3691 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3692 break;
3693#endif /* OTHER_PHY */
3694 }
3695 }
3696 else {
3697 /* disable all GMAC IRQs */
3698 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
wdenk9c53f402003-10-15 23:53:47 +00003699
wdenkeb20ad32003-09-05 23:19:14 +00003700#ifndef VCPU
3701 /* Disable all PHY interrupts */
3702 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3703#endif /* VCPU */
3704 }
3705} /* SkMacIrqDisable */
3706
3707
3708#ifdef SK_DIAG
3709/******************************************************************************
3710 *
3711 * SkXmSendCont() - Enable / Disable Send Continuous Mode
3712 *
3713 * Description: enable / disable Send Continuous Mode on XMAC
3714 *
3715 * Returns:
3716 * nothing
3717 */
3718void SkXmSendCont(
3719SK_AC *pAC, /* adapter context */
3720SK_IOC IoC, /* IO context */
3721int Port, /* Port Index (MAC_1 + n) */
3722SK_BOOL Enable) /* Enable / Disable */
3723{
3724 SK_U32 MdReg;
3725
3726 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3727
3728 if (Enable) {
3729 MdReg |= XM_MD_TX_CONT;
3730 }
3731 else {
3732 MdReg &= ~XM_MD_TX_CONT;
3733 }
3734 /* setup Mode Register */
3735 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3736
3737} /* SkXmSendCont*/
3738
3739/******************************************************************************
3740 *
3741 * SkMacTimeStamp() - Enable / Disable Time Stamp
3742 *
3743 * Description: enable / disable Time Stamp generation for Rx packets
3744 *
3745 * Returns:
3746 * nothing
3747 */
3748void SkMacTimeStamp(
3749SK_AC *pAC, /* adapter context */
3750SK_IOC IoC, /* IO context */
3751int Port, /* Port Index (MAC_1 + n) */
3752SK_BOOL Enable) /* Enable / Disable */
3753{
3754 SK_U32 MdReg;
3755 SK_U8 TimeCtrl;
3756
3757 if (pAC->GIni.GIGenesis) {
3758
3759 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3760
3761 if (Enable) {
3762 MdReg |= XM_MD_ATS;
3763 }
3764 else {
3765 MdReg &= ~XM_MD_ATS;
3766 }
3767 /* setup Mode Register */
3768 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3769 }
3770 else {
3771 if (Enable) {
3772 TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3773 }
3774 else {
3775 TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3776 }
3777 /* Start/Stop Time Stamp Timer */
3778 SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl);
3779 }
3780} /* SkMacTimeStamp*/
3781
3782#else /* SK_DIAG */
3783
3784/******************************************************************************
3785 *
3786 * SkXmIrq() - Interrupt Service Routine
3787 *
3788 * Description: services an Interrupt Request of the XMAC
3789 *
3790 * Note:
3791 * With an external PHY, some interrupt bits are not meaningfull any more:
3792 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
3793 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
3794 * - Page Received (bit #9) XM_IS_RX_PAGE
3795 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
3796 * - AutoNegDone (bit #7) XM_IS_AND
3797 * Also probably not valid any more is the GP0 input bit:
3798 * - GPRegisterBit0set XM_IS_INP_ASS
3799 *
3800 * Returns:
3801 * nothing
3802 */
3803void SkXmIrq(
3804SK_AC *pAC, /* adapter context */
3805SK_IOC IoC, /* IO context */
3806int Port) /* Port Index (MAC_1 + n) */
3807{
3808 SK_GEPORT *pPrt;
3809 SK_EVPARA Para;
3810 SK_U16 IStatus; /* Interrupt status read from the XMAC */
3811 SK_U16 IStatus2;
3812
3813 pPrt = &pAC->GIni.GP[Port];
wdenk9c53f402003-10-15 23:53:47 +00003814
wdenkeb20ad32003-09-05 23:19:14 +00003815 XM_IN16(IoC, Port, XM_ISRC, &IStatus);
wdenk9c53f402003-10-15 23:53:47 +00003816
wdenkeb20ad32003-09-05 23:19:14 +00003817 /* LinkPartner Auto-negable? */
3818 if (pPrt->PhyType == SK_PHY_XMAC) {
3819 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
3820 }
3821 else {
3822 /* mask bits that are not used with ext. PHY */
3823 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
3824 XM_IS_RX_PAGE | XM_IS_TX_PAGE |
3825 XM_IS_AND | XM_IS_INP_ASS);
3826 }
wdenk9c53f402003-10-15 23:53:47 +00003827
wdenkeb20ad32003-09-05 23:19:14 +00003828 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3829 ("XmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3830
3831 if (!pPrt->PHWLinkUp) {
3832 /* Spurious XMAC interrupt */
3833 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3834 ("SkXmIrq: spurious interrupt on Port %d\n", Port));
3835 return;
3836 }
3837
3838 if ((IStatus & XM_IS_INP_ASS) != 0) {
3839 /* Reread ISR Register if link is not in sync */
3840 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
3841
3842 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3843 ("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\n",
3844 Port, IStatus, IStatus2));
3845 IStatus &= ~XM_IS_INP_ASS;
3846 IStatus |= IStatus2;
3847 }
3848
3849 if ((IStatus & XM_IS_LNK_AE) != 0) {
3850 /* not used, GP0 is used instead */
3851 }
3852
3853 if ((IStatus & XM_IS_TX_ABORT) != 0) {
3854 /* not used */
3855 }
3856
3857 if ((IStatus & XM_IS_FRC_INT) != 0) {
3858 /* not used, use ASIC IRQ instead if needed */
3859 }
3860
3861 if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
3862 SkHWLinkDown(pAC, IoC, Port);
3863
3864 /* Signal to RLMT */
3865 Para.Para32[0] = (SK_U32)Port;
3866 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
3867
3868 /* Start workaround Errata #2 timer */
3869 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
3870 SKGE_HWAC, SK_HWEV_WATIM, Para);
3871 }
3872
3873 if ((IStatus & XM_IS_RX_PAGE) != 0) {
3874 /* not used */
3875 }
3876
3877 if ((IStatus & XM_IS_TX_PAGE) != 0) {
3878 /* not used */
3879 }
3880
3881 if ((IStatus & XM_IS_AND) != 0) {
3882 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3883 ("SkXmIrq: AND on link that is up Port %d\n", Port));
3884 }
3885
3886 if ((IStatus & XM_IS_TSC_OV) != 0) {
3887 /* not used */
3888 }
3889
3890 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3891 if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
3892 Para.Para32[0] = (SK_U32)Port;
3893 Para.Para32[1] = (SK_U32)IStatus;
3894 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3895 }
3896
3897 if ((IStatus & XM_IS_RXF_OV) != 0) {
3898 /* normal situation -> no effect */
3899#ifdef DEBUG
3900 pPrt->PRxOverCnt++;
3901#endif /* DEBUG */
3902 }
3903
3904 if ((IStatus & XM_IS_TXF_UR) != 0) {
3905 /* may NOT happen -> error log */
3906 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3907 }
3908
3909 if ((IStatus & XM_IS_TX_COMP) != 0) {
3910 /* not served here */
3911 }
3912
3913 if ((IStatus & XM_IS_RX_COMP) != 0) {
3914 /* not served here */
3915 }
3916} /* SkXmIrq */
3917
3918
3919/******************************************************************************
3920 *
3921 * SkGmIrq() - Interrupt Service Routine
3922 *
3923 * Description: services an Interrupt Request of the GMAC
3924 *
3925 * Note:
3926 *
3927 * Returns:
3928 * nothing
3929 */
3930void SkGmIrq(
3931SK_AC *pAC, /* adapter context */
3932SK_IOC IoC, /* IO context */
3933int Port) /* Port Index (MAC_1 + n) */
3934{
3935 SK_GEPORT *pPrt;
3936 SK_EVPARA Para;
3937 SK_U8 IStatus; /* Interrupt status */
3938
3939 pPrt = &pAC->GIni.GP[Port];
wdenk9c53f402003-10-15 23:53:47 +00003940
wdenkeb20ad32003-09-05 23:19:14 +00003941 SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
wdenk9c53f402003-10-15 23:53:47 +00003942
wdenkeb20ad32003-09-05 23:19:14 +00003943 /* LinkPartner Auto-negable? */
3944 SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
wdenk9c53f402003-10-15 23:53:47 +00003945
wdenkeb20ad32003-09-05 23:19:14 +00003946 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3947 ("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3948
3949 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3950 if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
3951 /* these IRQs will be cleared by reading GMACs register */
3952 Para.Para32[0] = (SK_U32)Port;
3953 Para.Para32[1] = (SK_U32)IStatus;
3954 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3955 }
3956
3957 if (IStatus & GM_IS_RX_FF_OR) {
3958 /* clear GMAC Rx FIFO Overrun IRQ */
3959 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
3960#ifdef DEBUG
3961 pPrt->PRxOverCnt++;
3962#endif /* DEBUG */
3963 }
3964
3965 if (IStatus & GM_IS_TX_FF_UR) {
3966 /* clear GMAC Tx FIFO Underrun IRQ */
3967 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
3968 /* may NOT happen -> error log */
3969 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3970 }
3971
3972 if (IStatus & GM_IS_TX_COMPL) {
3973 /* not served here */
3974 }
3975
3976 if (IStatus & GM_IS_RX_COMPL) {
3977 /* not served here */
3978 }
3979} /* SkGmIrq */
3980
3981/******************************************************************************
3982 *
3983 * SkMacIrq() - Interrupt Service Routine for MAC
3984 *
3985 * Description: calls the Interrupt Service Routine dep. on board type
3986 *
3987 * Returns:
3988 * nothing
3989 */
3990void SkMacIrq(
3991SK_AC *pAC, /* adapter context */
3992SK_IOC IoC, /* IO context */
3993int Port) /* Port Index (MAC_1 + n) */
3994{
3995
3996 if (pAC->GIni.GIGenesis) {
3997 /* IRQ from XMAC */
3998 SkXmIrq(pAC, IoC, Port);
3999 }
4000 else {
4001 /* IRQ from GMAC */
4002 SkGmIrq(pAC, IoC, Port);
4003 }
4004} /* SkMacIrq */
4005
4006#endif /* !SK_DIAG */
4007
4008/******************************************************************************
4009 *
4010 * SkXmUpdateStats() - Force the XMAC to output the current statistic
4011 *
4012 * Description:
4013 * The XMAC holds its statistic internally. To obtain the current
4014 * values a command must be sent so that the statistic data will
4015 * be written to a predefined memory area on the adapter.
4016 *
4017 * Returns:
4018 * 0: success
4019 * 1: something went wrong
4020 */
4021int SkXmUpdateStats(
4022SK_AC *pAC, /* adapter context */
4023SK_IOC IoC, /* IO context */
4024unsigned int Port) /* Port Index (MAC_1 + n) */
4025{
4026 SK_GEPORT *pPrt;
4027 SK_U16 StatReg;
4028 int WaitIndex;
4029
4030 pPrt = &pAC->GIni.GP[Port];
4031 WaitIndex = 0;
4032
4033 /* Send an update command to XMAC specified */
4034 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
4035
4036 /*
4037 * It is an auto-clearing register. If the command bits
4038 * went to zero again, the statistics are transferred.
4039 * Normally the command should be executed immediately.
4040 * But just to be sure we execute a loop.
4041 */
4042 do {
4043
4044 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
wdenk9c53f402003-10-15 23:53:47 +00004045
wdenkeb20ad32003-09-05 23:19:14 +00004046 if (++WaitIndex > 10) {
4047
4048 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
4049
4050 return(1);
4051 }
4052 } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
wdenk9c53f402003-10-15 23:53:47 +00004053
wdenkeb20ad32003-09-05 23:19:14 +00004054 return(0);
4055} /* SkXmUpdateStats */
4056
4057/******************************************************************************
4058 *
4059 * SkGmUpdateStats() - Force the GMAC to output the current statistic
4060 *
4061 * Description:
4062 * Empty function for GMAC. Statistic data is accessible in direct way.
4063 *
4064 * Returns:
4065 * 0: success
4066 * 1: something went wrong
4067 */
4068int SkGmUpdateStats(
4069SK_AC *pAC, /* adapter context */
4070SK_IOC IoC, /* IO context */
4071unsigned int Port) /* Port Index (MAC_1 + n) */
4072{
4073 return(0);
4074}
4075
4076/******************************************************************************
4077 *
4078 * SkXmMacStatistic() - Get XMAC counter value
4079 *
4080 * Description:
4081 * Gets the 32bit counter value. Except for the octet counters
4082 * the lower 32bit are counted in hardware and the upper 32bit
4083 * must be counted in software by monitoring counter overflow interrupts.
4084 *
4085 * Returns:
4086 * 0: success
4087 * 1: something went wrong
4088 */
4089int SkXmMacStatistic(
4090SK_AC *pAC, /* adapter context */
4091SK_IOC IoC, /* IO context */
4092unsigned int Port, /* Port Index (MAC_1 + n) */
4093SK_U16 StatAddr, /* MIB counter base address */
4094SK_U32 *pVal) /* ptr to return statistic value */
4095{
4096 if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
wdenk9c53f402003-10-15 23:53:47 +00004097
wdenkeb20ad32003-09-05 23:19:14 +00004098 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
wdenk9c53f402003-10-15 23:53:47 +00004099
wdenkeb20ad32003-09-05 23:19:14 +00004100 return(1);
4101 }
wdenk9c53f402003-10-15 23:53:47 +00004102
wdenkeb20ad32003-09-05 23:19:14 +00004103 XM_IN32(IoC, Port, StatAddr, pVal);
4104
4105 return(0);
4106} /* SkXmMacStatistic */
4107
4108/******************************************************************************
4109 *
4110 * SkGmMacStatistic() - Get GMAC counter value
4111 *
4112 * Description:
4113 * Gets the 32bit counter value. Except for the octet counters
4114 * the lower 32bit are counted in hardware and the upper 32bit
4115 * must be counted in software by monitoring counter overflow interrupts.
4116 *
4117 * Returns:
4118 * 0: success
4119 * 1: something went wrong
4120 */
4121int SkGmMacStatistic(
4122SK_AC *pAC, /* adapter context */
4123SK_IOC IoC, /* IO context */
4124unsigned int Port, /* Port Index (MAC_1 + n) */
4125SK_U16 StatAddr, /* MIB counter base address */
4126SK_U32 *pVal) /* ptr to return statistic value */
4127{
4128
4129 if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
wdenk9c53f402003-10-15 23:53:47 +00004130
wdenkeb20ad32003-09-05 23:19:14 +00004131 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
wdenk9c53f402003-10-15 23:53:47 +00004132
wdenkeb20ad32003-09-05 23:19:14 +00004133 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4134 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
4135 return(1);
4136 }
wdenk9c53f402003-10-15 23:53:47 +00004137
wdenkeb20ad32003-09-05 23:19:14 +00004138 GM_IN32(IoC, Port, StatAddr, pVal);
4139
4140 return(0);
4141} /* SkGmMacStatistic */
4142
4143/******************************************************************************
4144 *
4145 * SkXmResetCounter() - Clear MAC statistic counter
4146 *
4147 * Description:
4148 * Force the XMAC to clear its statistic counter.
4149 *
4150 * Returns:
4151 * 0: success
4152 * 1: something went wrong
4153 */
4154int SkXmResetCounter(
4155SK_AC *pAC, /* adapter context */
4156SK_IOC IoC, /* IO context */
4157unsigned int Port) /* Port Index (MAC_1 + n) */
4158{
4159 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4160 /* Clear two times according to Errata #3 */
4161 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4162
4163 return(0);
4164} /* SkXmResetCounter */
4165
4166/******************************************************************************
4167 *
4168 * SkGmResetCounter() - Clear MAC statistic counter
4169 *
4170 * Description:
4171 * Force GMAC to clear its statistic counter.
4172 *
4173 * Returns:
4174 * 0: success
4175 * 1: something went wrong
4176 */
4177int SkGmResetCounter(
4178SK_AC *pAC, /* adapter context */
4179SK_IOC IoC, /* IO context */
4180unsigned int Port) /* Port Index (MAC_1 + n) */
4181{
4182 SK_U16 Reg; /* Phy Address Register */
4183 SK_U16 Word;
4184 int i;
4185
4186 GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4187
4188#ifndef VCPU
4189 /* set MIB Clear Counter Mode */
4190 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
wdenk9c53f402003-10-15 23:53:47 +00004191
wdenkeb20ad32003-09-05 23:19:14 +00004192 /* read all MIB Counters with Clear Mode set */
4193 for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4194 /* the reset is performed only when the lower 16 bits are read */
4195 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4196 }
wdenk9c53f402003-10-15 23:53:47 +00004197
wdenkeb20ad32003-09-05 23:19:14 +00004198 /* clear MIB Clear Counter Mode */
4199 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4200#endif /* !VCPU */
wdenk9c53f402003-10-15 23:53:47 +00004201
wdenkeb20ad32003-09-05 23:19:14 +00004202 return(0);
4203} /* SkGmResetCounter */
4204
4205/******************************************************************************
4206 *
4207 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4208 *
4209 * Description:
4210 * Checks the source causing an counter overflow interrupt. On success the
4211 * resulting counter overflow status is written to <pStatus>, whereas the
4212 * upper dword stores the XMAC ReceiveCounterEvent register and the lower
4213 * dword the XMAC TransmitCounterEvent register.
4214 *
4215 * Note:
4216 * For XMAC the interrupt source is a self-clearing register, so the source
4217 * must be checked only once. SIRQ module does another check to be sure
4218 * that no interrupt get lost during process time.
4219 *
4220 * Returns:
4221 * 0: success
4222 * 1: something went wrong
4223 */
4224int SkXmOverflowStatus(
4225SK_AC *pAC, /* adapter context */
4226SK_IOC IoC, /* IO context */
4227unsigned int Port, /* Port Index (MAC_1 + n) */
4228SK_U16 IStatus, /* Interupt Status from MAC */
4229SK_U64 *pStatus) /* ptr for return overflow status value */
4230{
4231 SK_U64 Status; /* Overflow status */
4232 SK_U32 RegVal;
4233
4234 Status = 0;
4235
4236 if ((IStatus & XM_IS_RXC_OV) != 0) {
4237
4238 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
4239 Status |= (SK_U64)RegVal << 32;
4240 }
wdenk9c53f402003-10-15 23:53:47 +00004241
wdenkeb20ad32003-09-05 23:19:14 +00004242 if ((IStatus & XM_IS_TXC_OV) != 0) {
4243
4244 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
4245 Status |= (SK_U64)RegVal;
4246 }
4247
4248 *pStatus = Status;
4249
4250 return(0);
4251} /* SkXmOverflowStatus */
4252
4253
4254/******************************************************************************
4255 *
4256 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4257 *
4258 * Description:
4259 * Checks the source causing an counter overflow interrupt. On success the
4260 * resulting counter overflow status is written to <pStatus>, whereas the
4261 * the following bit coding is used:
4262 * 63:56 - unused
4263 * 55:48 - TxRx interrupt register bit7:0
4264 * 32:47 - Rx interrupt register
4265 * 31:24 - unused
4266 * 23:16 - TxRx interrupt register bit15:8
4267 * 15:0 - Tx interrupt register
4268 *
4269 * Returns:
4270 * 0: success
4271 * 1: something went wrong
4272 */
4273int SkGmOverflowStatus(
4274SK_AC *pAC, /* adapter context */
4275SK_IOC IoC, /* IO context */
4276unsigned int Port, /* Port Index (MAC_1 + n) */
4277SK_U16 IStatus, /* Interupt Status from MAC */
4278SK_U64 *pStatus) /* ptr for return overflow status value */
4279{
4280 SK_U64 Status; /* Overflow status */
4281 SK_U16 RegVal;
4282
4283 Status = 0;
4284
4285 if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4286 /* this register is self-clearing after read */
4287 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4288 Status |= (SK_U64)RegVal << 32;
4289 }
wdenk9c53f402003-10-15 23:53:47 +00004290
wdenkeb20ad32003-09-05 23:19:14 +00004291 if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4292 /* this register is self-clearing after read */
4293 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4294 Status |= (SK_U64)RegVal;
4295 }
wdenk9c53f402003-10-15 23:53:47 +00004296
wdenkeb20ad32003-09-05 23:19:14 +00004297 /* this register is self-clearing after read */
4298 GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4299 /* Rx overflow interrupt register bits (LoByte)*/
4300 Status |= (SK_U64)((SK_U8)RegVal) << 48;
4301 /* Tx overflow interrupt register bits (HiByte)*/
4302 Status |= (SK_U64)(RegVal >> 8) << 16;
4303
4304 *pStatus = Status;
4305
4306 return(0);
4307} /* SkGmOverflowStatus */
4308
4309/******************************************************************************
4310 *
4311 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4312 *
4313 * Description:
4314 * starts the cable diagnostic test if 'StartTest' is true
4315 * gets the results if 'StartTest' is true
4316 *
4317 * NOTE: this test is meaningful only when link is down
wdenk9c53f402003-10-15 23:53:47 +00004318 *
wdenkeb20ad32003-09-05 23:19:14 +00004319 * Returns:
4320 * 0: success
4321 * 1: no YUKON copper
4322 * 2: test in progress
4323 */
4324int SkGmCableDiagStatus(
4325SK_AC *pAC, /* adapter context */
4326SK_IOC IoC, /* IO context */
4327int Port, /* Port Index (MAC_1 + n) */
4328SK_BOOL StartTest) /* flag for start / get result */
4329{
4330 int i;
4331 SK_U16 RegVal;
4332 SK_GEPORT *pPrt;
4333
4334 pPrt = &pAC->GIni.GP[Port];
4335
4336 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
wdenk9c53f402003-10-15 23:53:47 +00004337
wdenkeb20ad32003-09-05 23:19:14 +00004338 return(1);
4339 }
4340
4341 if (StartTest) {
4342 /* only start the cable test */
4343 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4344 /* apply TDR workaround from Marvell */
4345 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
wdenk9c53f402003-10-15 23:53:47 +00004346
wdenkeb20ad32003-09-05 23:19:14 +00004347 SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4348 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4349 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4350 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4351 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4352 }
4353
4354 /* set address to 0 for MDI[0] */
4355 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4356
4357 /* Read Cable Diagnostic Reg */
4358 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4359
4360 /* start Cable Diagnostic Test */
4361 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4362 (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
wdenk9c53f402003-10-15 23:53:47 +00004363
wdenkeb20ad32003-09-05 23:19:14 +00004364 return(0);
4365 }
wdenk9c53f402003-10-15 23:53:47 +00004366
wdenkeb20ad32003-09-05 23:19:14 +00004367 /* Read Cable Diagnostic Reg */
4368 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4369
4370 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4371 ("PHY Cable Diag.=0x%04X\n", RegVal));
4372
4373 if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4374 /* test is running */
4375 return(2);
4376 }
4377
4378 /* get the test results */
4379 for (i = 0; i < 4; i++) {
4380 /* set address to i for MDI[i] */
4381 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4382
4383 /* get Cable Diagnostic values */
4384 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4385
4386 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4387
4388 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4389 }
4390
4391 return(0);
4392} /* SkGmCableDiagStatus */
4393
wdenkde887eb2003-09-10 18:20:28 +00004394#endif /* CONFIG_SK98 */
4395
wdenkeb20ad32003-09-05 23:19:14 +00004396/* End of file */