blob: 2f7c0543f4a3ea142f4ffc79847b75f9dd5f5f53 [file] [log] [blame]
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000034 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000038 *
wdenk7152b1d2003-09-05 23:19:14 +000039 * Revision 1.89 2003/01/28 16:37:45 rschmidt
40 * Changed init for blinking active LED
wdenk42d1f032003-10-15 23:53:47 +000041 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000048 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000052 *
wdenk7152b1d2003-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).
wdenk42d1f032003-10-15 23:53:47 +000055 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000061 *
wdenk7152b1d2003-09-05 23:19:14 +000062 * Revision 1.84 2002/11/15 12:50:09 rschmidt
63 * Changed SkGmCableDiagStatus() when getting results.
wdenk42d1f032003-10-15 23:53:47 +000064 *
wdenk7152b1d2003-09-05 23:19:14 +000065 * Revision 1.83 2002/11/13 10:28:29 rschmidt
66 * Added some typecasts to avoid compiler warnings.
wdenk42d1f032003-10-15 23:53:47 +000067 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000073 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000078 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000087 *
wdenk7152b1d2003-09-05 23:19:14 +000088 * Revision 1.79 2002/10/10 15:55:36 mkarl
89 * changes for PLinkSpeedUsed
wdenk42d1f032003-10-15 23:53:47 +000090 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +000093 *
wdenk7152b1d2003-09-05 23:19:14 +000094 * Revision 1.77 2002/09/09 12:26:37 mkarl
95 * added handling for Yukon to SkXmTimeStamp
wdenk42d1f032003-10-15 23:53:47 +000096 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000102 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000113 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000119 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000124 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000128 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000133 *
wdenk7152b1d2003-09-05 23:19:14 +0000134 * Revision 1.70 2002/07/18 14:27:27 rwahl
135 * Fixed syntax error.
wdenk42d1f032003-10-15 23:53:47 +0000136 *
wdenk7152b1d2003-09-05 23:19:14 +0000137 * Revision 1.69 2002/07/17 17:08:47 rwahl
138 * Fixed check in SkXmMacStatistic().
wdenk42d1f032003-10-15 23:53:47 +0000139 *
wdenk7152b1d2003-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().
wdenk42d1f032003-10-15 23:53:47 +0000142 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000151 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000159 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000164 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000172 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000190 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000194 *
wdenk7152b1d2003-09-05 23:19:14 +0000195 * Revision 1.61 2001/02/09 15:40:59 rassmann
196 * Editorial changes.
wdenk42d1f032003-10-15 23:53:47 +0000197 *
wdenk7152b1d2003-09-05 23:19:14 +0000198 * Revision 1.60 2001/02/07 15:02:01 cgoos
199 * Added workaround for Fujitsu switch link down.
wdenk42d1f032003-10-15 23:53:47 +0000200 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000203 *
wdenk7152b1d2003-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
wdenk42d1f032003-10-15 23:53:47 +0000206 *
wdenk7152b1d2003-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).
wdenk42d1f032003-10-15 23:53:47 +0000209 *
wdenk7152b1d2003-09-05 23:19:14 +0000210 * Revision 1.56 2000/11/09 12:32:48 rassmann
211 * Renamed variables.
wdenk42d1f032003-10-15 23:53:47 +0000212 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000215 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000218 *
wdenk7152b1d2003-09-05 23:19:14 +0000219 * Revision 1.53 2000/07/27 12:22:11 gklug
220 * fix: possible endless loop in XmHardRst.
wdenk42d1f032003-10-15 23:53:47 +0000221 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000224 *
wdenk7152b1d2003-09-05 23:19:14 +0000225 * Revision 1.51 2000/05/17 12:52:18 malthoff
226 * Fixes BCom link errata (#10523).
wdenk42d1f032003-10-15 23:53:47 +0000227 *
wdenk7152b1d2003-09-05 23:19:14 +0000228 * Revision 1.50 1999/11/22 13:40:14 cgoos
229 * Changed license header to GPL.
wdenk42d1f032003-10-15 23:53:47 +0000230 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000233 *
wdenk7152b1d2003-09-05 23:19:14 +0000234 * Revision 1.48 1999/11/16 08:39:01 malthoff
235 * Fix: MDIO preamble suppression is port dependent.
wdenk42d1f032003-10-15 23:53:47 +0000236 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000239 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000242 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000248 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000251 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000255 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000259 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000262 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000266 *
wdenk7152b1d2003-09-05 23:19:14 +0000267 * Revision 1.39 1999/05/19 07:29:51 cgoos
268 * Changes for 1000Base-T.
wdenk42d1f032003-10-15 23:53:47 +0000269 *
wdenk7152b1d2003-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.
wdenk42d1f032003-10-15 23:53:47 +0000272 *
wdenk7152b1d2003-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().
wdenk42d1f032003-10-15 23:53:47 +0000277 *
wdenk7152b1d2003-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
wdenk149dded2003-09-10 18:20:28 +0000413#include <config.h>
414
wdenk7152b1d2003-09-05 23:19:14 +0000415#include "h/skdrv1st.h"
416#include "h/skdrv2nd.h"
417
418/* typedefs *******************************************************************/
419
420/* BCOM PHY magic pattern list */
421typedef struct s_PhyHack {
422 int PhyReg; /* Phy register */
423 SK_U16 PhyVal; /* Value to write */
424} BCOM_HACK;
425
426/* local variables ************************************************************/
427static const char SysKonnectFileId[] =
428 "@(#)$Id: skxmac2.c,v 1.91 2003/02/05 15:09:34 rschmidt Exp $ (C) SK ";
429
430BCOM_HACK BcomRegA1Hack[] = {
431 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
432 { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
433 { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
434 { 0, 0 }
435};
436BCOM_HACK BcomRegC0Hack[] = {
437 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
438 { 0x15, 0x0A04 }, { 0x18, 0x0420 },
439 { 0, 0 }
440};
441
442/* function prototypes ********************************************************/
443static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
444static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
445static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
446static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
447static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
448static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
449#ifdef OTHER_PHY
450static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
451static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
452static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
453static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
454#endif /* OTHER_PHY */
455
456
wdenk7152b1d2003-09-05 23:19:14 +0000457/******************************************************************************
458 *
459 * SkXmPhyRead() - Read from XMAC PHY register
460 *
461 * Description: reads a 16-bit word from XMAC PHY or ext. PHY
462 *
463 * Returns:
464 * nothing
465 */
466void SkXmPhyRead(
467SK_AC *pAC, /* Adapter Context */
468SK_IOC IoC, /* I/O Context */
469int Port, /* Port Index (MAC_1 + n) */
470int PhyReg, /* Register Address (Offset) */
471SK_U16 *pVal) /* Pointer to Value */
472{
473 SK_U16 Mmu;
474 SK_GEPORT *pPrt;
475
476 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +0000477
wdenk7152b1d2003-09-05 23:19:14 +0000478 /* write the PHY register's address */
479 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
wdenk42d1f032003-10-15 23:53:47 +0000480
wdenk7152b1d2003-09-05 23:19:14 +0000481 /* get the PHY register's value */
482 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
wdenk42d1f032003-10-15 23:53:47 +0000483
wdenk7152b1d2003-09-05 23:19:14 +0000484 if (pPrt->PhyType != SK_PHY_XMAC) {
485 do {
486 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
487 /* wait until 'Ready' is set */
488 } while ((Mmu & XM_MMU_PHY_RDY) == 0);
489
490 /* get the PHY register's value */
491 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
492 }
493} /* SkXmPhyRead */
494
495
496/******************************************************************************
497 *
498 * SkXmPhyWrite() - Write to XMAC PHY register
499 *
500 * Description: writes a 16-bit word to XMAC PHY or ext. PHY
501 *
502 * Returns:
503 * nothing
504 */
505void SkXmPhyWrite(
506SK_AC *pAC, /* Adapter Context */
507SK_IOC IoC, /* I/O Context */
508int Port, /* Port Index (MAC_1 + n) */
509int PhyReg, /* Register Address (Offset) */
510SK_U16 Val) /* Value */
511{
512 SK_U16 Mmu;
513 SK_GEPORT *pPrt;
514
515 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +0000516
wdenk7152b1d2003-09-05 23:19:14 +0000517 if (pPrt->PhyType != SK_PHY_XMAC) {
518 do {
519 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
520 /* wait until 'Busy' is cleared */
521 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
522 }
wdenk42d1f032003-10-15 23:53:47 +0000523
wdenk7152b1d2003-09-05 23:19:14 +0000524 /* write the PHY register's address */
525 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
wdenk42d1f032003-10-15 23:53:47 +0000526
wdenk7152b1d2003-09-05 23:19:14 +0000527 /* write the PHY register's value */
528 XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
wdenk42d1f032003-10-15 23:53:47 +0000529
wdenk7152b1d2003-09-05 23:19:14 +0000530 if (pPrt->PhyType != SK_PHY_XMAC) {
531 do {
532 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
533 /* wait until 'Busy' is cleared */
534 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
535 }
536} /* SkXmPhyWrite */
537
538
539/******************************************************************************
540 *
541 * SkGmPhyRead() - Read from GPHY register
542 *
543 * Description: reads a 16-bit word from GPHY through MDIO
544 *
545 * Returns:
546 * nothing
547 */
548void SkGmPhyRead(
549SK_AC *pAC, /* Adapter Context */
550SK_IOC IoC, /* I/O Context */
551int Port, /* Port Index (MAC_1 + n) */
552int PhyReg, /* Register Address (Offset) */
553SK_U16 *pVal) /* Pointer to Value */
554{
555 SK_U16 Ctrl;
556 SK_GEPORT *pPrt;
557#ifdef VCPU
558 u_long SimCyle;
559 u_long SimLowTime;
wdenk42d1f032003-10-15 23:53:47 +0000560
wdenk7152b1d2003-09-05 23:19:14 +0000561 VCPUgetTime(&SimCyle, &SimLowTime);
562 VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
563 PhyReg, SimCyle, SimLowTime);
564#endif /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +0000565
wdenk7152b1d2003-09-05 23:19:14 +0000566 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +0000567
wdenk7152b1d2003-09-05 23:19:14 +0000568 /* set PHY-Register offset and 'Read' OpCode (= 1) */
569 *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
570 GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
571
572 GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
573
574 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
wdenk42d1f032003-10-15 23:53:47 +0000575
wdenk7152b1d2003-09-05 23:19:14 +0000576 /* additional check for MDC/MDIO activity */
577 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
578 *pVal = 0;
579 return;
580 }
581
582 *pVal |= GM_SMI_CT_BUSY;
wdenk42d1f032003-10-15 23:53:47 +0000583
wdenk7152b1d2003-09-05 23:19:14 +0000584 do {
585#ifdef VCPU
586 VCPUwaitTime(1000);
587#endif /* VCPU */
588
589 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
590
591 /* wait until 'ReadValid' is set */
592 } while (Ctrl == *pVal);
wdenk42d1f032003-10-15 23:53:47 +0000593
wdenk7152b1d2003-09-05 23:19:14 +0000594 /* get the PHY register's value */
595 GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
596
597#ifdef VCPU
598 VCPUgetTime(&SimCyle, &SimLowTime);
599 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
600 SimCyle, SimLowTime);
601#endif /* VCPU */
602} /* SkGmPhyRead */
603
604
605/******************************************************************************
606 *
607 * SkGmPhyWrite() - Write to GPHY register
608 *
609 * Description: writes a 16-bit word to GPHY through MDIO
610 *
611 * Returns:
612 * nothing
613 */
614void SkGmPhyWrite(
615SK_AC *pAC, /* Adapter Context */
616SK_IOC IoC, /* I/O Context */
617int Port, /* Port Index (MAC_1 + n) */
618int PhyReg, /* Register Address (Offset) */
619SK_U16 Val) /* Value */
620{
621 SK_U16 Ctrl;
622 SK_GEPORT *pPrt;
623#ifdef VCPU
624 SK_U32 DWord;
625 u_long SimCyle;
626 u_long SimLowTime;
wdenk42d1f032003-10-15 23:53:47 +0000627
wdenk7152b1d2003-09-05 23:19:14 +0000628 VCPUgetTime(&SimCyle, &SimLowTime);
629 VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
630 PhyReg, Val, SimCyle, SimLowTime);
631#endif /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +0000632
wdenk7152b1d2003-09-05 23:19:14 +0000633 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +0000634
wdenk7152b1d2003-09-05 23:19:14 +0000635 /* write the PHY register's value */
636 GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
wdenk42d1f032003-10-15 23:53:47 +0000637
wdenk7152b1d2003-09-05 23:19:14 +0000638 /* set PHY-Register offset and 'Write' OpCode (= 0) */
639 Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
640
641 GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
642
643 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
wdenk42d1f032003-10-15 23:53:47 +0000644
wdenk7152b1d2003-09-05 23:19:14 +0000645 /* additional check for MDC/MDIO activity */
646 if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
647 return;
648 }
wdenk42d1f032003-10-15 23:53:47 +0000649
wdenk7152b1d2003-09-05 23:19:14 +0000650 Val |= GM_SMI_CT_BUSY;
651
652 do {
653#ifdef VCPU
654 /* read Timer value */
655 SK_IN32(IoC, B2_TI_VAL, &DWord);
656
657 VCPUwaitTime(1000);
658#endif /* VCPU */
659
660 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
661
662 /* wait until 'Busy' is cleared */
663 } while (Ctrl == Val);
wdenk42d1f032003-10-15 23:53:47 +0000664
wdenk7152b1d2003-09-05 23:19:14 +0000665#ifdef VCPU
666 VCPUgetTime(&SimCyle, &SimLowTime);
667 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
668 SimCyle, SimLowTime);
669#endif /* VCPU */
670} /* SkGmPhyWrite */
671
672
673/******************************************************************************
674 *
675 * SkGePhyRead() - Read from PHY register
676 *
677 * Description: calls a read PHY routine dep. on board type
678 *
679 * Returns:
680 * nothing
681 */
682void SkGePhyRead(
683SK_AC *pAC, /* Adapter Context */
684SK_IOC IoC, /* I/O Context */
685int Port, /* Port Index (MAC_1 + n) */
686int PhyReg, /* Register Address (Offset) */
687SK_U16 *pVal) /* Pointer to Value */
688{
689 void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
690
691 if (pAC->GIni.GIGenesis) {
692 r_func = SkXmPhyRead;
693 }
694 else {
695 r_func = SkGmPhyRead;
696 }
wdenk42d1f032003-10-15 23:53:47 +0000697
wdenk7152b1d2003-09-05 23:19:14 +0000698 r_func(pAC, IoC, Port, PhyReg, pVal);
699} /* SkGePhyRead */
700
701
702/******************************************************************************
703 *
704 * SkGePhyWrite() - Write to PHY register
705 *
706 * Description: calls a write PHY routine dep. on board type
707 *
708 * Returns:
709 * nothing
710 */
711void SkGePhyWrite(
712SK_AC *pAC, /* Adapter Context */
713SK_IOC IoC, /* I/O Context */
714int Port, /* Port Index (MAC_1 + n) */
715int PhyReg, /* Register Address (Offset) */
716SK_U16 Val) /* Value */
717{
718 void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
719
720 if (pAC->GIni.GIGenesis) {
721 w_func = SkXmPhyWrite;
722 }
723 else {
724 w_func = SkGmPhyWrite;
725 }
wdenk42d1f032003-10-15 23:53:47 +0000726
wdenk7152b1d2003-09-05 23:19:14 +0000727 w_func(pAC, IoC, Port, PhyReg, Val);
728} /* SkGePhyWrite */
729
730
731/******************************************************************************
732 *
733 * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
734 *
735 * Description:
736 * enables / disables promiscuous mode by setting Mode Register (XMAC) or
wdenk42d1f032003-10-15 23:53:47 +0000737 * Receive Control Register (GMAC) dep. on board type
wdenk7152b1d2003-09-05 23:19:14 +0000738 *
739 * Returns:
740 * nothing
741 */
742void SkMacPromiscMode(
743SK_AC *pAC, /* adapter context */
744SK_IOC IoC, /* IO context */
745int Port, /* Port Index (MAC_1 + n) */
746SK_BOOL Enable) /* Enable / Disable */
747{
748 SK_U16 RcReg;
749 SK_U32 MdReg;
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +0200750 SK_U32 *pMdReg = &MdReg;
wdenk7152b1d2003-09-05 23:19:14 +0000751
752 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +0000753
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +0200754 XM_IN32(IoC, Port, XM_MODE, pMdReg);
wdenk7152b1d2003-09-05 23:19:14 +0000755 /* enable or disable promiscuous mode */
756 if (Enable) {
757 MdReg |= XM_MD_ENA_PROM;
758 }
759 else {
760 MdReg &= ~XM_MD_ENA_PROM;
761 }
762 /* setup Mode Register */
763 XM_OUT32(IoC, Port, XM_MODE, MdReg);
764 }
765 else {
wdenk42d1f032003-10-15 23:53:47 +0000766
wdenk7152b1d2003-09-05 23:19:14 +0000767 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
wdenk42d1f032003-10-15 23:53:47 +0000768
wdenk7152b1d2003-09-05 23:19:14 +0000769 /* enable or disable unicast and multicast filtering */
770 if (Enable) {
771 RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
772 }
773 else {
774 RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
775 }
776 /* setup Receive Control Register */
777 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
778 }
779} /* SkMacPromiscMode*/
780
781
782/******************************************************************************
783 *
784 * SkMacHashing() - Enable / Disable Hashing
785 *
786 * Description:
787 * enables / disables hashing by setting Mode Register (XMAC) or
wdenk42d1f032003-10-15 23:53:47 +0000788 * Receive Control Register (GMAC) dep. on board type
wdenk7152b1d2003-09-05 23:19:14 +0000789 *
790 * Returns:
791 * nothing
792 */
793void SkMacHashing(
794SK_AC *pAC, /* adapter context */
795SK_IOC IoC, /* IO context */
796int Port, /* Port Index (MAC_1 + n) */
797SK_BOOL Enable) /* Enable / Disable */
798{
799 SK_U16 RcReg;
800 SK_U32 MdReg;
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +0200801 SK_U32 *pMdReg = &MdReg;
wdenk7152b1d2003-09-05 23:19:14 +0000802
803 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +0000804
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +0200805 XM_IN32(IoC, Port, XM_MODE, pMdReg);
wdenk7152b1d2003-09-05 23:19:14 +0000806 /* 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 {
wdenk42d1f032003-10-15 23:53:47 +0000817
wdenk7152b1d2003-09-05 23:19:14 +0000818 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
wdenk42d1f032003-10-15 23:53:47 +0000819
wdenk7152b1d2003-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;
wdenk42d1f032003-10-15 23:53:47 +0000869
wdenk7152b1d2003-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) {
wdenk42d1f032003-10-15 23:53:47 +0000952
wdenk7152b1d2003-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) {
wdenk42d1f032003-10-15 23:53:47 +0000970
wdenk7152b1d2003-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) {
wdenk42d1f032003-10-15 23:53:47 +00001005
wdenk7152b1d2003-09-05 23:19:14 +00001006 SkXmSetRxCmd(pAC, IoC, Port, Mode);
1007 }
1008 else {
wdenk42d1f032003-10-15 23:53:47 +00001009
wdenk7152b1d2003-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) {
wdenk42d1f032003-10-15 23:53:47 +00001033
wdenk7152b1d2003-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 {
wdenk42d1f032003-10-15 23:53:47 +00001046
wdenk7152b1d2003-09-05 23:19:14 +00001047 GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
wdenk42d1f032003-10-15 23:53:47 +00001048
wdenk7152b1d2003-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;
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02001114 SK_U32 *pMdReg = &MdReg;
wdenk7152b1d2003-09-05 23:19:14 +00001115
1116 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001117
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02001118 XM_IN32(IoC, Port, XM_MODE, pMdReg);
wdenk7152b1d2003-09-05 23:19:14 +00001119
1120 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
1121 }
1122 else {
1123 /* no way to flush the FIFO we have to issue a reset */
1124 /* TBD */
1125 }
1126} /* SkMacFlushTxFifo */
1127
1128
1129/******************************************************************************
1130 *
1131 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
1132 *
1133 * Description:
1134 * Flush the receive FIFO of the MAC specified by the index 'Port'
1135 *
1136 * Returns:
1137 * nothing
1138 */
1139void SkMacFlushRxFifo(
1140SK_AC *pAC, /* adapter context */
1141SK_IOC IoC, /* IO context */
1142int Port) /* Port Index (MAC_1 + n) */
1143{
1144 SK_U32 MdReg;
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02001145 SK_U32 *pMdReg = &MdReg;
wdenk7152b1d2003-09-05 23:19:14 +00001146
1147 if (pAC->GIni.GIGenesis) {
1148
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02001149 XM_IN32(IoC, Port, XM_MODE, pMdReg);
wdenk7152b1d2003-09-05 23:19:14 +00001150
1151 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
1152 }
1153 else {
1154 /* no way to flush the FIFO we have to issue a reset */
1155 /* TBD */
1156 }
1157} /* SkMacFlushRxFifo */
1158
1159
1160/******************************************************************************
1161 *
1162 * SkXmSoftRst() - Do a XMAC software reset
1163 *
1164 * Description:
1165 * The PHY registers should not be destroyed during this
1166 * kind of software reset. Therefore the XMAC Software Reset
1167 * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
1168 *
1169 * The software reset is done by
1170 * - disabling the Rx and Tx state machine,
1171 * - resetting the statistics module,
1172 * - clear all other significant XMAC Mode,
1173 * Command, and Control Registers
1174 * - clearing the Hash Register and the
1175 * Exact Match Address registers, and
1176 * - flushing the XMAC's Rx and Tx FIFOs.
1177 *
1178 * Note:
1179 * Another requirement when stopping the XMAC is to
1180 * avoid sending corrupted frames on the network.
1181 * Disabling the Tx state machine will NOT interrupt
1182 * the currently transmitted frame. But we must take care
1183 * that the Tx FIFO is cleared AFTER the current frame
1184 * is complete sent to the network.
1185 *
1186 * It takes about 12ns to send a frame with 1538 bytes.
1187 * One PCI clock goes at least 15ns (66MHz). Therefore
1188 * after reading XM_GP_PORT back, we are sure that the
1189 * transmitter is disabled AND idle. And this means
1190 * we may flush the transmit FIFO now.
1191 *
1192 * Returns:
1193 * nothing
1194 */
1195static void SkXmSoftRst(
1196SK_AC *pAC, /* adapter context */
1197SK_IOC IoC, /* IO context */
1198int Port) /* Port Index (MAC_1 + n) */
1199{
1200 SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
wdenk42d1f032003-10-15 23:53:47 +00001201
wdenk7152b1d2003-09-05 23:19:14 +00001202 /* reset the statistics module */
1203 XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
1204
1205 /* disable all XMAC IRQs */
1206 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
wdenk42d1f032003-10-15 23:53:47 +00001207
wdenk7152b1d2003-09-05 23:19:14 +00001208 XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
wdenk42d1f032003-10-15 23:53:47 +00001209
wdenk7152b1d2003-09-05 23:19:14 +00001210 XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
1211 XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
wdenk42d1f032003-10-15 23:53:47 +00001212
wdenk7152b1d2003-09-05 23:19:14 +00001213 /* disable all PHY IRQs */
1214 switch (pAC->GIni.GP[Port].PhyType) {
1215 case SK_PHY_BCOM:
1216 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
1217 break;
1218#ifdef OTHER_PHY
1219 case SK_PHY_LONE:
1220 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
1221 break;
1222 case SK_PHY_NAT:
1223 /* todo: National
1224 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
1225 break;
1226#endif /* OTHER_PHY */
1227 }
1228
1229 /* clear the Hash Register */
1230 XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
1231
1232 /* clear the Exact Match Address registers */
1233 SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
wdenk42d1f032003-10-15 23:53:47 +00001234
wdenk7152b1d2003-09-05 23:19:14 +00001235 /* clear the Source Check Address registers */
1236 XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
1237
1238} /* SkXmSoftRst */
1239
1240
1241/******************************************************************************
1242 *
1243 * SkXmHardRst() - Do a XMAC hardware reset
1244 *
1245 * Description:
1246 * The XMAC of the specified 'Port' and all connected devices
1247 * (PHY and SERDES) will receive a reset signal on its *Reset pins.
1248 * External PHYs must be reset be clearing a bit in the GPIO register
1249 * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
1250 *
1251 * ATTENTION:
Wolfgang Denk53677ef2008-05-20 16:00:29 +02001252 * It is absolutely necessary to reset the SW_RST Bit first
wdenk7152b1d2003-09-05 23:19:14 +00001253 * before calling this function.
1254 *
1255 * Returns:
1256 * nothing
1257 */
1258static void SkXmHardRst(
1259SK_AC *pAC, /* adapter context */
1260SK_IOC IoC, /* IO context */
1261int Port) /* Port Index (MAC_1 + n) */
1262{
1263 SK_U32 Reg;
1264 int i;
1265 int TOut;
1266 SK_U16 Word;
1267
1268 for (i = 0; i < 4; i++) {
1269 /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
1270 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1271
1272 TOut = 0;
1273 do {
1274 if (TOut++ > 10000) {
1275 /*
1276 * Adapter seems to be in RESET state.
1277 * Registers cannot be written.
1278 */
1279 return;
1280 }
1281
1282 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
wdenk42d1f032003-10-15 23:53:47 +00001283
wdenk7152b1d2003-09-05 23:19:14 +00001284 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
wdenk42d1f032003-10-15 23:53:47 +00001285
wdenk7152b1d2003-09-05 23:19:14 +00001286 } while ((Word & MFF_SET_MAC_RST) == 0);
1287 }
1288
1289 /* For external PHYs there must be special handling */
1290 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
1291 /* reset external PHY */
1292 SK_IN32(IoC, B2_GP_IO, &Reg);
1293 if (Port == 0) {
1294 Reg |= GP_DIR_0; /* set to output */
1295 Reg &= ~GP_IO_0;
1296 }
1297 else {
1298 Reg |= GP_DIR_2; /* set to output */
1299 Reg &= ~GP_IO_2;
1300 }
1301 SK_OUT32(IoC, B2_GP_IO, Reg);
1302
1303 /* short delay */
1304 SK_IN32(IoC, B2_GP_IO, &Reg);
1305 }
1306
1307} /* SkXmHardRst */
1308
1309
1310/******************************************************************************
1311 *
1312 * SkGmSoftRst() - Do a GMAC software reset
1313 *
1314 * Description:
1315 * The GPHY registers should not be destroyed during this
1316 * kind of software reset.
1317 *
1318 * Returns:
1319 * nothing
1320 */
1321static void SkGmSoftRst(
1322SK_AC *pAC, /* adapter context */
1323SK_IOC IoC, /* IO context */
1324int Port) /* Port Index (MAC_1 + n) */
1325{
1326 SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1327 SK_U16 RxCtrl;
1328
1329 /* reset the statistics module */
1330
1331 /* disable all GMAC IRQs */
1332 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
wdenk42d1f032003-10-15 23:53:47 +00001333
wdenk7152b1d2003-09-05 23:19:14 +00001334 /* disable all PHY IRQs */
1335 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
wdenk42d1f032003-10-15 23:53:47 +00001336
wdenk7152b1d2003-09-05 23:19:14 +00001337 /* clear the Hash Register */
1338 GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
1339
1340 /* Enable Unicast and Multicast filtering */
1341 GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
wdenk42d1f032003-10-15 23:53:47 +00001342
wdenk7152b1d2003-09-05 23:19:14 +00001343 GM_OUT16(IoC, Port, GM_RX_CTRL,
1344 RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
1345
1346} /* SkGmSoftRst */
1347
1348
1349/******************************************************************************
1350 *
1351 * SkGmHardRst() - Do a GMAC hardware reset
1352 *
1353 * Description:
1354 *
1355 * ATTENTION:
Wolfgang Denk53677ef2008-05-20 16:00:29 +02001356 * It is absolutely necessary to reset the SW_RST Bit first
wdenk7152b1d2003-09-05 23:19:14 +00001357 * before calling this function.
1358 *
1359 * Returns:
1360 * nothing
1361 */
1362static void SkGmHardRst(
1363SK_AC *pAC, /* adapter context */
1364SK_IOC IoC, /* IO context */
1365int Port) /* Port Index (MAC_1 + n) */
1366{
1367 /* set GPHY Control reset */
1368 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1369
1370 /* set GMAC Control reset */
1371 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1372
1373} /* SkGmHardRst */
1374
1375
1376/******************************************************************************
1377 *
1378 * SkMacSoftRst() - Do a MAC software reset
1379 *
1380 * Description: calls a MAC software reset routine dep. on board type
1381 *
1382 * Returns:
1383 * nothing
1384 */
1385void SkMacSoftRst(
1386SK_AC *pAC, /* adapter context */
1387SK_IOC IoC, /* IO context */
1388int Port) /* Port Index (MAC_1 + n) */
1389{
1390 SK_GEPORT *pPrt;
1391
1392 pPrt = &pAC->GIni.GP[Port];
1393
1394 /* disable receiver and transmitter */
1395 SkMacRxTxDisable(pAC, IoC, Port);
1396
1397 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001398
wdenk7152b1d2003-09-05 23:19:14 +00001399 SkXmSoftRst(pAC, IoC, Port);
1400 }
1401 else {
wdenk42d1f032003-10-15 23:53:47 +00001402
wdenk7152b1d2003-09-05 23:19:14 +00001403 SkGmSoftRst(pAC, IoC, Port);
1404 }
1405
1406 /* flush the MAC's Rx and Tx FIFOs */
1407 SkMacFlushTxFifo(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00001408
wdenk7152b1d2003-09-05 23:19:14 +00001409 SkMacFlushRxFifo(pAC, IoC, Port);
1410
1411 pPrt->PState = SK_PRT_STOP;
1412
1413} /* SkMacSoftRst */
1414
1415
1416/******************************************************************************
1417 *
1418 * SkMacHardRst() - Do a MAC hardware reset
1419 *
1420 * Description: calls a MAC hardware reset routine dep. on board type
1421 *
1422 * Returns:
1423 * nothing
1424 */
1425void SkMacHardRst(
1426SK_AC *pAC, /* adapter context */
1427SK_IOC IoC, /* IO context */
1428int Port) /* Port Index (MAC_1 + n) */
1429{
wdenk42d1f032003-10-15 23:53:47 +00001430
wdenk7152b1d2003-09-05 23:19:14 +00001431 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001432
wdenk7152b1d2003-09-05 23:19:14 +00001433 SkXmHardRst(pAC, IoC, Port);
1434 }
1435 else {
wdenk42d1f032003-10-15 23:53:47 +00001436
wdenk7152b1d2003-09-05 23:19:14 +00001437 SkGmHardRst(pAC, IoC, Port);
1438 }
1439
1440 pAC->GIni.GP[Port].PState = SK_PRT_RESET;
1441
1442} /* SkMacHardRst */
1443
1444
wdenk7152b1d2003-09-05 23:19:14 +00001445/******************************************************************************
1446 *
1447 * SkXmInitMac() - Initialize the XMAC II
1448 *
1449 * Description:
1450 * Initialize the XMAC of the specified port.
1451 * The XMAC must be reset or stopped before calling this function.
1452 *
1453 * Note:
1454 * The XMAC's Rx and Tx state machine is still disabled when returning.
1455 *
1456 * Returns:
1457 * nothing
1458 */
1459void SkXmInitMac(
1460SK_AC *pAC, /* adapter context */
1461SK_IOC IoC, /* IO context */
1462int Port) /* Port Index (MAC_1 + n) */
1463{
1464 SK_GEPORT *pPrt;
1465 SK_U32 Reg;
1466 int i;
1467 SK_U16 SWord;
1468
1469 pPrt = &pAC->GIni.GP[Port];
1470
1471 if (pPrt->PState == SK_PRT_STOP) {
1472 /* Port State: SK_PRT_STOP */
1473 /* Verify that the reset bit is cleared */
1474 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1475
1476 if ((SWord & MFF_SET_MAC_RST) != 0) {
1477 /* PState does not match HW state */
1478 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1479 /* Correct it */
1480 pPrt->PState = SK_PRT_RESET;
1481 }
1482 }
1483
1484 if (pPrt->PState == SK_PRT_RESET) {
1485 /*
1486 * clear HW reset
1487 * Note: The SW reset is self clearing, therefore there is
1488 * nothing to do here.
1489 */
1490 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1491
1492 /* Ensure that XMAC reset release is done (errata from LReinbold?) */
1493 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1494
1495 /* Clear PHY reset */
1496 if (pPrt->PhyType != SK_PHY_XMAC) {
1497
1498 SK_IN32(IoC, B2_GP_IO, &Reg);
wdenk42d1f032003-10-15 23:53:47 +00001499
wdenk7152b1d2003-09-05 23:19:14 +00001500 if (Port == 0) {
1501 Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */
1502 }
1503 else {
1504 Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */
1505 }
1506 SK_OUT32(IoC, B2_GP_IO, Reg);
1507
1508 /* Enable GMII interface */
1509 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
1510
1511 /* read Id from external PHY (all have the same address) */
1512 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1513
1514 /*
1515 * Optimize MDIO transfer by suppressing preamble.
1516 * Must be done AFTER first access to BCOM chip.
1517 */
1518 XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001519
wdenk7152b1d2003-09-05 23:19:14 +00001520 XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1521
1522 if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1523 /*
1524 * Workaround BCOM Errata for the C0 type.
1525 * Write magic patterns to reserved registers.
1526 */
1527 i = 0;
1528 while (BcomRegC0Hack[i].PhyReg != 0) {
1529 SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1530 BcomRegC0Hack[i].PhyVal);
1531 i++;
1532 }
1533 }
1534 else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1535 /*
1536 * Workaround BCOM Errata for the A1 type.
1537 * Write magic patterns to reserved registers.
1538 */
1539 i = 0;
1540 while (BcomRegA1Hack[i].PhyReg != 0) {
1541 SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1542 BcomRegA1Hack[i].PhyVal);
1543 i++;
1544 }
1545 }
1546
1547 /*
1548 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1549 * Disable Power Management after reset.
1550 */
1551 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001552
wdenk7152b1d2003-09-05 23:19:14 +00001553 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1554 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
1555
1556 /* PHY LED initialization is done in SkGeXmitLED() */
1557 }
1558
1559 /* Dummy read the Interrupt source register */
1560 XM_IN16(IoC, Port, XM_ISRC, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001561
wdenk7152b1d2003-09-05 23:19:14 +00001562 /*
1563 * The auto-negotiation process starts immediately after
1564 * clearing the reset. The auto-negotiation process should be
1565 * started by the SIRQ, therefore stop it here immediately.
1566 */
1567 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1568
1569#if 0
1570 /* temp. code: enable signal detect */
1571 /* WARNING: do not override GMII setting above */
1572 XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1573#endif
1574 }
1575
1576 /*
1577 * configure the XMACs Station Address
1578 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1579 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1580 */
1581 for (i = 0; i < 3; i++) {
1582 /*
1583 * The following 2 statements are together endianess
1584 * independent. Remember this when changing.
1585 */
1586 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001587
wdenk7152b1d2003-09-05 23:19:14 +00001588 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1589 }
1590
1591 /* Tx Inter Packet Gap (XM_TX_IPG): use default */
1592 /* Tx High Water Mark (XM_TX_HI_WM): use default */
1593 /* Tx Low Water Mark (XM_TX_LO_WM): use default */
1594 /* Host Request Threshold (XM_HT_THR): use default */
1595 /* Rx Request Threshold (XM_RX_THR): use default */
1596 /* Rx Low Water Mark (XM_RX_LO_WM): use default */
1597
1598 /* configure Rx High Water Mark (XM_RX_HI_WM) */
1599 XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1600
1601 /* Configure Tx Request Threshold */
1602 SWord = SK_XM_THR_SL; /* for single port */
1603
1604 if (pAC->GIni.GIMacsFound > 1) {
1605 switch (pAC->GIni.GIPortUsage) {
1606 case SK_RED_LINK:
1607 SWord = SK_XM_THR_REDL; /* redundant link */
1608 break;
1609 case SK_MUL_LINK:
1610 SWord = SK_XM_THR_MULL; /* load balancing */
1611 break;
1612 case SK_JUMBO_LINK:
1613 SWord = SK_XM_THR_JUMBO; /* jumbo frames */
1614 break;
1615 default:
1616 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1617 break;
1618 }
1619 }
1620 XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1621
1622 /* setup register defaults for the Tx Command Register */
1623 XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1624
1625 /* setup register defaults for the Rx Command Register */
1626 SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1627
1628 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1629 SWord |= XM_RX_BIG_PK_OK;
1630 }
1631
1632 if (pPrt->PLinkModeConf == SK_LMODE_HALF) {
1633 /*
1634 * If in manual half duplex mode the other side might be in
1635 * full duplex mode, so ignore if a carrier extension is not seen
1636 * on frames received
1637 */
1638 SWord |= XM_RX_DIS_CEXT;
1639 }
wdenk42d1f032003-10-15 23:53:47 +00001640
wdenk7152b1d2003-09-05 23:19:14 +00001641 XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1642
1643 /*
1644 * setup register defaults for the Mode Register
1645 * - Don't strip error frames to avoid Store & Forward
1646 * on the Rx side.
1647 * - Enable 'Check Station Address' bit
1648 * - Enable 'Check Address Array' bit
1649 */
1650 XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1651
1652 /*
1653 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1654 * - Enable all bits excepting 'Octets Rx OK Low CntOv'
1655 * and 'Octets Rx OK Hi Cnt Ov'.
1656 */
1657 XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1658
1659 /*
1660 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1661 * - Enable all bits excepting 'Octets Tx OK Low CntOv'
1662 * and 'Octets Tx OK Hi Cnt Ov'.
1663 */
1664 XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1665
1666 /*
1667 * Do NOT init XMAC interrupt mask here.
1668 * All interrupts remain disable until link comes up!
1669 */
1670
1671 /*
1672 * Any additional configuration changes may be done now.
1673 * The last action is to enable the Rx and Tx state machine.
1674 * This should be done after the auto-negotiation process
1675 * has been completed successfully.
1676 */
1677} /* SkXmInitMac */
1678
1679/******************************************************************************
1680 *
1681 * SkGmInitMac() - Initialize the GMAC
1682 *
1683 * Description:
1684 * Initialize the GMAC of the specified port.
1685 * The GMAC must be reset or stopped before calling this function.
1686 *
1687 * Note:
1688 * The GMAC's Rx and Tx state machine is still disabled when returning.
1689 *
1690 * Returns:
1691 * nothing
1692 */
1693void SkGmInitMac(
1694SK_AC *pAC, /* adapter context */
1695SK_IOC IoC, /* IO context */
1696int Port) /* Port Index (MAC_1 + n) */
1697{
1698 SK_GEPORT *pPrt;
1699 int i;
1700 SK_U16 SWord;
1701 SK_U32 DWord;
1702
1703 pPrt = &pAC->GIni.GP[Port];
1704
1705 if (pPrt->PState == SK_PRT_STOP) {
1706 /* Port State: SK_PRT_STOP */
1707 /* Verify that the reset bit is cleared */
1708 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
wdenk42d1f032003-10-15 23:53:47 +00001709
wdenk7152b1d2003-09-05 23:19:14 +00001710 if ((DWord & GMC_RST_SET) != 0) {
1711 /* PState does not match HW state */
1712 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1713 /* Correct it */
1714 pPrt->PState = SK_PRT_RESET;
1715 }
1716 }
1717
1718 if (pPrt->PState == SK_PRT_RESET) {
1719 /* set GPHY Control reset */
1720 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1721
1722 /* set GMAC Control reset */
1723 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1724
1725 /* clear GMAC Control reset */
1726 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
1727
1728 /* set GMAC Control reset */
1729 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1730
1731 /* set HWCFG_MODE */
1732 DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
1733 GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
1734 (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
1735 GPC_HWCFG_GMII_FIB);
1736
1737 /* set GPHY Control reset */
1738 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
1739
1740 /* release GPHY Control reset */
1741 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
1742
1743 /* clear GMAC Control reset */
1744 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
1745
1746 /* Dummy read the Interrupt source register */
1747 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001748
wdenk7152b1d2003-09-05 23:19:14 +00001749#ifndef VCPU
1750 /* read Id from PHY */
1751 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
wdenk42d1f032003-10-15 23:53:47 +00001752
wdenk7152b1d2003-09-05 23:19:14 +00001753 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1754#endif /* VCPU */
1755 }
1756
1757 (void)SkGmResetCounter(pAC, IoC, Port);
1758
1759 SWord = 0;
1760
1761 /* speed settings */
1762 switch (pPrt->PLinkSpeed) {
1763 case SK_LSPEED_AUTO:
1764 case SK_LSPEED_1000MBPS:
1765 SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1766 break;
1767 case SK_LSPEED_100MBPS:
1768 SWord |= GM_GPCR_SPEED_100;
1769 break;
1770 case SK_LSPEED_10MBPS:
1771 break;
1772 }
wdenk42d1f032003-10-15 23:53:47 +00001773
wdenk7152b1d2003-09-05 23:19:14 +00001774 /* duplex settings */
1775 if (pPrt->PLinkMode != SK_LMODE_HALF) {
1776 /* set full duplex */
1777 SWord |= GM_GPCR_DUP_FULL;
1778 }
1779
1780 /* flow control settings */
1781 switch (pPrt->PFlowCtrlMode) {
1782 case SK_FLOW_MODE_NONE:
1783 /* disable auto-negotiation for flow-control */
1784 SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS;
1785 break;
1786 case SK_FLOW_MODE_LOC_SEND:
1787 SWord |= GM_GPCR_FC_RX_DIS;
1788 break;
1789 case SK_FLOW_MODE_SYMMETRIC:
1790 /* TBD */
1791 case SK_FLOW_MODE_SYM_OR_REM:
1792 /* enable auto-negotiation for flow-control and */
1793 /* enable Rx and Tx of pause frames */
1794 break;
1795 }
1796
1797 /* Auto-negotiation ? */
1798 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1799 /* disable auto-update for speed, duplex and flow-control */
1800 SWord |= GM_GPCR_AU_ALL_DIS;
1801 }
wdenk42d1f032003-10-15 23:53:47 +00001802
wdenk7152b1d2003-09-05 23:19:14 +00001803 /* setup General Purpose Control Register */
1804 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1805
1806 /* setup Transmit Control Register */
1807 GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR);
1808
1809 /* setup Receive Control Register */
1810 GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1811 GM_RXCR_CRC_DIS);
1812
1813 /* setup Transmit Flow Control Register */
1814 GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1815
1816 /* setup Transmit Parameter Register */
1817#ifdef VCPU
1818 GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1819#endif /* VCPU */
1820
1821 SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26);
wdenk42d1f032003-10-15 23:53:47 +00001822
wdenk7152b1d2003-09-05 23:19:14 +00001823 GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1824
1825 /* configure the Serial Mode Register */
1826#ifdef VCPU
1827 GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1828#endif /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00001829
wdenk7152b1d2003-09-05 23:19:14 +00001830 SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH;
1831
1832 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1833 /* enable jumbo mode (Max. Frame Length = 9018) */
1834 SWord |= GM_SMOD_JUMBO_ENA;
1835 }
wdenk42d1f032003-10-15 23:53:47 +00001836
wdenk7152b1d2003-09-05 23:19:14 +00001837 GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
wdenk42d1f032003-10-15 23:53:47 +00001838
wdenk7152b1d2003-09-05 23:19:14 +00001839 /*
1840 * configure the GMACs Station Addresses
1841 * in PROM you can find our addresses at:
1842 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1843 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1844 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1845 */
1846
1847 for (i = 0; i < 3; i++) {
1848 /*
1849 * The following 2 statements are together endianess
1850 * independent. Remember this when changing.
1851 */
1852 /* physical address: will be used for pause frames */
1853 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1854
1855#ifdef WA_DEV_16
1856 /* WA for deviation #16 */
1857 if (pAC->GIni.GIChipRev == 0) {
1858 /* swap the address bytes */
1859 SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
1860
1861 /* write to register in reversed order */
1862 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
1863 }
1864 else {
1865 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1866 }
wdenk42d1f032003-10-15 23:53:47 +00001867#else
wdenk7152b1d2003-09-05 23:19:14 +00001868 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1869#endif /* WA_DEV_16 */
wdenk42d1f032003-10-15 23:53:47 +00001870
wdenk7152b1d2003-09-05 23:19:14 +00001871 /* virtual address: will be used for data */
1872 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
1873
1874 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
wdenk42d1f032003-10-15 23:53:47 +00001875
wdenk7152b1d2003-09-05 23:19:14 +00001876 /* reset Multicast filtering Hash registers 1-3 */
1877 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
1878 }
1879
1880 /* reset Multicast filtering Hash register 4 */
1881 GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
1882
1883 /* enable interrupt mask for counter overflows */
1884 GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
1885 GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
1886 GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
1887
1888 /* read General Purpose Status */
1889 GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001890
wdenk7152b1d2003-09-05 23:19:14 +00001891 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1892 ("MAC Stat Reg=0x%04X\n", SWord));
1893
1894#ifdef SK_DIAG
1895 c_print("MAC Stat Reg=0x%04X\n", SWord);
1896#endif /* SK_DIAG */
1897
1898} /* SkGmInitMac */
1899
1900
1901/******************************************************************************
1902 *
1903 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1904 *
1905 * Description:
1906 * This function initializes the XMACs Duplex Mode.
1907 * It should be called after successfully finishing
1908 * the Auto-negotiation Process
1909 *
1910 * Returns:
1911 * nothing
1912 */
1913void SkXmInitDupMd(
1914SK_AC *pAC, /* adapter context */
1915SK_IOC IoC, /* IO context */
1916int Port) /* Port Index (MAC_1 + n) */
1917{
1918 switch (pAC->GIni.GP[Port].PLinkModeStatus) {
1919 case SK_LMODE_STAT_AUTOHALF:
1920 case SK_LMODE_STAT_HALF:
1921 /* Configuration Actions for Half Duplex Mode */
1922 /*
1923 * XM_BURST = default value. We are probable not quick
Wolfgang Denk53677ef2008-05-20 16:00:29 +02001924 * enough at the 'XMAC' bus to burst 8kB.
wdenk7152b1d2003-09-05 23:19:14 +00001925 * The XMAC stops bursting if no transmit frames
1926 * are available or the burst limit is exceeded.
1927 */
1928 /* XM_TX_RT_LIM = default value (15) */
1929 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
1930 break;
1931 case SK_LMODE_STAT_AUTOFULL:
1932 case SK_LMODE_STAT_FULL:
1933 /* Configuration Actions for Full Duplex Mode */
1934 /*
1935 * The duplex mode is configured by the PHY,
1936 * therefore it seems to be that there is nothing
1937 * to do here.
1938 */
1939 break;
1940 case SK_LMODE_STAT_UNKNOWN:
1941 default:
1942 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
1943 break;
1944 }
1945} /* SkXmInitDupMd */
1946
1947
1948/******************************************************************************
1949 *
1950 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1951 *
1952 * Description:
1953 * This function initializes the Pause Mode which should
1954 * be used for this port.
1955 * It should be called after successfully finishing
1956 * the Auto-negotiation Process
1957 *
1958 * Returns:
1959 * nothing
1960 */
1961void SkXmInitPauseMd(
1962SK_AC *pAC, /* adapter context */
1963SK_IOC IoC, /* IO context */
1964int Port) /* Port Index (MAC_1 + n) */
1965{
1966 SK_GEPORT *pPrt;
1967 SK_U32 DWord;
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02001968 SK_U32 *pDWord = &DWord;
wdenk7152b1d2003-09-05 23:19:14 +00001969 SK_U16 Word;
1970
1971 pPrt = &pAC->GIni.GP[Port];
1972
1973 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
wdenk42d1f032003-10-15 23:53:47 +00001974
wdenk7152b1d2003-09-05 23:19:14 +00001975 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
1976 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1977
1978 /* Disable Pause Frame Reception */
1979 Word |= XM_MMU_IGN_PF;
1980 }
1981 else {
1982 /*
1983 * enabling pause frame reception is required for 1000BT
1984 * because the XMAC is not reset if the link is going down
1985 */
1986 /* Enable Pause Frame Reception */
1987 Word &= ~XM_MMU_IGN_PF;
wdenk42d1f032003-10-15 23:53:47 +00001988 }
1989
wdenk7152b1d2003-09-05 23:19:14 +00001990 XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
1991
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02001992 XM_IN32(IoC, Port, XM_MODE, pDWord);
wdenk7152b1d2003-09-05 23:19:14 +00001993
1994 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
1995 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1996
1997 /*
1998 * Configure Pause Frame Generation
1999 * Use internal and external Pause Frame Generation.
2000 * Sending pause frames is edge triggered.
2001 * Send a Pause frame with the maximum pause time if
2002 * internal oder external FIFO full condition occurs.
2003 * Send a zero pause time frame to re-start transmission.
2004 */
2005
2006 /* XM_PAUSE_DA = '010000C28001' (default) */
2007
2008 /* XM_MAC_PTIME = 0xffff (maximum) */
2009 /* remember this value is defined in big endian (!) */
2010 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
2011
2012 /* Set Pause Mode in Mode Register */
2013 DWord |= XM_PAUSE_MODE;
2014
2015 /* Set Pause Mode in MAC Rx FIFO */
2016 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
2017 }
2018 else {
2019 /*
2020 * disable pause frame generation is required for 1000BT
2021 * because the XMAC is not reset if the link is going down
2022 */
2023 /* Disable Pause Mode in Mode Register */
2024 DWord &= ~XM_PAUSE_MODE;
2025
2026 /* Disable Pause Mode in MAC Rx FIFO */
2027 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
2028 }
wdenk42d1f032003-10-15 23:53:47 +00002029
wdenk7152b1d2003-09-05 23:19:14 +00002030 XM_OUT32(IoC, Port, XM_MODE, DWord);
2031} /* SkXmInitPauseMd*/
2032
2033
2034/******************************************************************************
2035 *
2036 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
2037 *
2038 * Description: initializes all the XMACs Phy registers
2039 *
2040 * Note:
2041 *
2042 * Returns:
2043 * nothing
2044 */
2045static void SkXmInitPhyXmac(
2046SK_AC *pAC, /* adapter context */
2047SK_IOC IoC, /* IO context */
2048int Port, /* Port Index (MAC_1 + n) */
2049SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2050{
2051 SK_GEPORT *pPrt;
2052 SK_U16 Ctrl;
2053
2054 pPrt = &pAC->GIni.GP[Port];
2055 Ctrl = 0;
wdenk42d1f032003-10-15 23:53:47 +00002056
wdenk7152b1d2003-09-05 23:19:14 +00002057 /* Auto-negotiation ? */
2058 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2059 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2060 ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
2061 /* Set DuplexMode in Config register */
2062 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2063 Ctrl |= PHY_CT_DUP_MD;
2064 }
2065
2066 /*
2067 * Do NOT enable Auto-negotiation here. This would hold
2068 * the link down because no IDLEs are transmitted
2069 */
2070 }
2071 else {
2072 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2073 ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
2074 /* Set Auto-negotiation advertisement */
2075
2076 /* Set Full/half duplex capabilities */
2077 switch (pPrt->PLinkMode) {
2078 case SK_LMODE_AUTOHALF:
2079 Ctrl |= PHY_X_AN_HD;
2080 break;
2081 case SK_LMODE_AUTOFULL:
2082 Ctrl |= PHY_X_AN_FD;
2083 break;
2084 case SK_LMODE_AUTOBOTH:
2085 Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
2086 break;
2087 default:
2088 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2089 SKERR_HWI_E015MSG);
2090 }
2091
2092 switch (pPrt->PFlowCtrlMode) {
2093 case SK_FLOW_MODE_NONE:
2094 Ctrl |= PHY_X_P_NO_PAUSE;
2095 break;
2096 case SK_FLOW_MODE_LOC_SEND:
2097 Ctrl |= PHY_X_P_ASYM_MD;
2098 break;
2099 case SK_FLOW_MODE_SYMMETRIC:
2100 Ctrl |= PHY_X_P_SYM_MD;
2101 break;
2102 case SK_FLOW_MODE_SYM_OR_REM:
2103 Ctrl |= PHY_X_P_BOTH_MD;
2104 break;
2105 default:
2106 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2107 SKERR_HWI_E016MSG);
2108 }
2109
2110 /* Write AutoNeg Advertisement Register */
2111 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
2112
2113 /* Restart Auto-negotiation */
2114 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
2115 }
2116
2117 if (DoLoop) {
2118 /* Set the Phy Loopback bit, too */
2119 Ctrl |= PHY_CT_LOOP;
2120 }
2121
2122 /* Write to the Phy control register */
2123 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
2124} /* SkXmInitPhyXmac */
2125
2126
2127/******************************************************************************
2128 *
2129 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
2130 *
2131 * Description: initializes all the Broadcom Phy registers
2132 *
2133 * Note:
2134 *
2135 * Returns:
2136 * nothing
2137 */
2138static void SkXmInitPhyBcom(
2139SK_AC *pAC, /* adapter context */
2140SK_IOC IoC, /* IO context */
2141int Port, /* Port Index (MAC_1 + n) */
2142SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2143{
2144 SK_GEPORT *pPrt;
2145 SK_U16 Ctrl1;
2146 SK_U16 Ctrl2;
2147 SK_U16 Ctrl3;
2148 SK_U16 Ctrl4;
2149 SK_U16 Ctrl5;
2150
2151 Ctrl1 = PHY_CT_SP1000;
2152 Ctrl2 = 0;
2153 Ctrl3 = PHY_SEL_TYPE;
2154 Ctrl4 = PHY_B_PEC_EN_LTR;
2155 Ctrl5 = PHY_B_AC_TX_TST;
2156
2157 pPrt = &pAC->GIni.GP[Port];
2158
2159 /* manually Master/Slave ? */
2160 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2161 Ctrl2 |= PHY_B_1000C_MSE;
wdenk42d1f032003-10-15 23:53:47 +00002162
wdenk7152b1d2003-09-05 23:19:14 +00002163 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2164 Ctrl2 |= PHY_B_1000C_MSC;
2165 }
2166 }
2167 /* Auto-negotiation ? */
2168 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2169 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2170 ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
2171 /* Set DuplexMode in Config register */
2172 Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2173
2174 /* Determine Master/Slave manually if not already done */
2175 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2176 Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
2177 }
2178
2179 /*
2180 * Do NOT enable Auto-negotiation here. This would hold
2181 * the link down because no IDLES are transmitted
2182 */
2183 }
2184 else {
2185 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2186 ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
2187 /* Set Auto-negotiation advertisement */
2188
2189 /*
2190 * Workaround BCOM Errata #1 for the C5 type.
2191 * 1000Base-T Link Acquisition Failure in Slave Mode
2192 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
2193 */
2194 Ctrl2 |= PHY_B_1000C_RD;
wdenk42d1f032003-10-15 23:53:47 +00002195
wdenk7152b1d2003-09-05 23:19:14 +00002196 /* Set Full/half duplex capabilities */
2197 switch (pPrt->PLinkMode) {
2198 case SK_LMODE_AUTOHALF:
2199 Ctrl2 |= PHY_B_1000C_AHD;
2200 break;
2201 case SK_LMODE_AUTOFULL:
2202 Ctrl2 |= PHY_B_1000C_AFD;
2203 break;
2204 case SK_LMODE_AUTOBOTH:
2205 Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
2206 break;
2207 default:
2208 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2209 SKERR_HWI_E015MSG);
2210 }
2211
2212 switch (pPrt->PFlowCtrlMode) {
2213 case SK_FLOW_MODE_NONE:
2214 Ctrl3 |= PHY_B_P_NO_PAUSE;
2215 break;
2216 case SK_FLOW_MODE_LOC_SEND:
2217 Ctrl3 |= PHY_B_P_ASYM_MD;
2218 break;
2219 case SK_FLOW_MODE_SYMMETRIC:
2220 Ctrl3 |= PHY_B_P_SYM_MD;
2221 break;
2222 case SK_FLOW_MODE_SYM_OR_REM:
2223 Ctrl3 |= PHY_B_P_BOTH_MD;
2224 break;
2225 default:
2226 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2227 SKERR_HWI_E016MSG);
2228 }
2229
2230 /* Restart Auto-negotiation */
2231 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2232 }
wdenk42d1f032003-10-15 23:53:47 +00002233
wdenk7152b1d2003-09-05 23:19:14 +00002234 /* Initialize LED register here? */
2235 /* No. Please do it in SkDgXmitLed() (if required) and swap
2236 init order of LEDs and XMAC. (MAl) */
wdenk42d1f032003-10-15 23:53:47 +00002237
wdenk7152b1d2003-09-05 23:19:14 +00002238 /* Write 1000Base-T Control Register */
2239 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2240 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2241 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
wdenk42d1f032003-10-15 23:53:47 +00002242
wdenk7152b1d2003-09-05 23:19:14 +00002243 /* Write AutoNeg Advertisement Register */
2244 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2245 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2246 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
wdenk42d1f032003-10-15 23:53:47 +00002247
wdenk7152b1d2003-09-05 23:19:14 +00002248 if (DoLoop) {
2249 /* Set the Phy Loopback bit, too */
2250 Ctrl1 |= PHY_CT_LOOP;
2251 }
2252
2253 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2254 /* configure FIFO to high latency for transmission of ext. packets */
2255 Ctrl4 |= PHY_B_PEC_HIGH_LA;
2256
2257 /* configure reception of extended packets */
2258 Ctrl5 |= PHY_B_AC_LONG_PACK;
2259
2260 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2261 }
2262
2263 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2264 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
wdenk42d1f032003-10-15 23:53:47 +00002265
wdenk7152b1d2003-09-05 23:19:14 +00002266 /* Write to the Phy control register */
2267 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2268 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2269 ("PHY Control Reg=0x%04X\n", Ctrl1));
2270} /* SkXmInitPhyBcom */
2271
2272
2273/******************************************************************************
2274 *
2275 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2276 *
2277 * Description: initializes all the Marvell Phy registers
2278 *
2279 * Note:
2280 *
2281 * Returns:
2282 * nothing
2283 */
2284static void SkGmInitPhyMarv(
2285SK_AC *pAC, /* adapter context */
2286SK_IOC IoC, /* IO context */
2287int Port, /* Port Index (MAC_1 + n) */
2288SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2289{
2290 SK_GEPORT *pPrt;
2291 SK_U16 PhyCtrl;
2292 SK_U16 C1000BaseT;
2293 SK_U16 AutoNegAdv;
2294 SK_U16 ExtPhyCtrl;
2295 SK_U16 PhyStat;
2296 SK_U16 PhyStat1;
2297 SK_U16 PhySpecStat;
2298 SK_U16 LedCtrl;
2299 SK_BOOL AutoNeg;
2300
2301#ifdef VCPU
2302 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2303 Port, DoLoop);
2304#else /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00002305
wdenk7152b1d2003-09-05 23:19:14 +00002306 pPrt = &pAC->GIni.GP[Port];
2307
2308 /* Auto-negotiation ? */
2309 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2310 AutoNeg = SK_FALSE;
2311 }
2312 else {
2313 AutoNeg = SK_TRUE;
2314 }
wdenk42d1f032003-10-15 23:53:47 +00002315
wdenk7152b1d2003-09-05 23:19:14 +00002316 if (!DoLoop) {
2317 /* Read Ext. PHY Specific Control */
2318 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
wdenk42d1f032003-10-15 23:53:47 +00002319
wdenk7152b1d2003-09-05 23:19:14 +00002320 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2321 PHY_M_EC_MAC_S_MSK);
wdenk42d1f032003-10-15 23:53:47 +00002322
wdenk7152b1d2003-09-05 23:19:14 +00002323 ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) |
2324 PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
wdenk42d1f032003-10-15 23:53:47 +00002325
wdenk7152b1d2003-09-05 23:19:14 +00002326 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2327 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2328 ("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl));
wdenk42d1f032003-10-15 23:53:47 +00002329
wdenk7152b1d2003-09-05 23:19:14 +00002330 /* Read PHY Control */
2331 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
wdenk42d1f032003-10-15 23:53:47 +00002332
wdenk7152b1d2003-09-05 23:19:14 +00002333 /* Assert software reset */
2334 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL,
2335 (SK_U16)(PhyCtrl | PHY_CT_RESET));
2336 }
2337#endif /* VCPU */
2338
2339 PhyCtrl = 0 /* PHY_CT_COL_TST */;
2340 C1000BaseT = 0;
2341 AutoNegAdv = PHY_SEL_TYPE;
2342
2343 /* manually Master/Slave ? */
2344 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2345 /* enable Manual Master/Slave */
2346 C1000BaseT |= PHY_M_1000C_MSE;
wdenk42d1f032003-10-15 23:53:47 +00002347
wdenk7152b1d2003-09-05 23:19:14 +00002348 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2349 C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
2350 }
2351 }
wdenk42d1f032003-10-15 23:53:47 +00002352
wdenk7152b1d2003-09-05 23:19:14 +00002353 /* Auto-negotiation ? */
2354 if (!AutoNeg) {
2355 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2356 ("InitPhyMarv: no auto-negotiation Port %d\n", Port));
wdenk42d1f032003-10-15 23:53:47 +00002357
wdenk7152b1d2003-09-05 23:19:14 +00002358 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2359 /* Set Full Duplex Mode */
2360 PhyCtrl |= PHY_CT_DUP_MD;
2361 }
2362
2363 /* Set Master/Slave manually if not already done */
2364 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2365 C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
2366 }
2367
2368 /* Set Speed */
2369 switch (pPrt->PLinkSpeed) {
2370 case SK_LSPEED_AUTO:
2371 case SK_LSPEED_1000MBPS:
2372 PhyCtrl |= PHY_CT_SP1000;
2373 break;
2374 case SK_LSPEED_100MBPS:
2375 PhyCtrl |= PHY_CT_SP100;
2376 break;
2377 case SK_LSPEED_10MBPS:
2378 break;
2379 default:
2380 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2381 SKERR_HWI_E019MSG);
2382 }
2383
2384 if (!DoLoop) {
2385 PhyCtrl |= PHY_CT_RESET;
2386 }
2387 /*
2388 * Do NOT enable Auto-negotiation here. This would hold
2389 * the link down because no IDLES are transmitted
2390 */
2391 }
2392 else {
2393 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2394 ("InitPhyMarv: with auto-negotiation Port %d\n", Port));
wdenk42d1f032003-10-15 23:53:47 +00002395
wdenk7152b1d2003-09-05 23:19:14 +00002396 PhyCtrl |= PHY_CT_ANE;
wdenk42d1f032003-10-15 23:53:47 +00002397
wdenk7152b1d2003-09-05 23:19:14 +00002398 if (pAC->GIni.GICopperType) {
2399 /* Set Speed capabilities */
2400 switch (pPrt->PLinkSpeed) {
2401 case SK_LSPEED_AUTO:
2402 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2403 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2404 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2405 break;
2406 case SK_LSPEED_1000MBPS:
2407 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2408 break;
2409 case SK_LSPEED_100MBPS:
2410 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2411 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2412 break;
2413 case SK_LSPEED_10MBPS:
2414 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2415 break;
2416 default:
2417 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2418 SKERR_HWI_E019MSG);
2419 }
2420
2421 /* Set Full/half duplex capabilities */
2422 switch (pPrt->PLinkMode) {
2423 case SK_LMODE_AUTOHALF:
2424 C1000BaseT &= ~PHY_M_1000C_AFD;
2425 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2426 break;
2427 case SK_LMODE_AUTOFULL:
2428 C1000BaseT &= ~PHY_M_1000C_AHD;
2429 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2430 break;
2431 case SK_LMODE_AUTOBOTH:
2432 break;
2433 default:
2434 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2435 SKERR_HWI_E015MSG);
2436 }
wdenk42d1f032003-10-15 23:53:47 +00002437
wdenk7152b1d2003-09-05 23:19:14 +00002438 /* Set Auto-negotiation advertisement */
2439 switch (pPrt->PFlowCtrlMode) {
2440 case SK_FLOW_MODE_NONE:
2441 AutoNegAdv |= PHY_B_P_NO_PAUSE;
2442 break;
2443 case SK_FLOW_MODE_LOC_SEND:
2444 AutoNegAdv |= PHY_B_P_ASYM_MD;
2445 break;
2446 case SK_FLOW_MODE_SYMMETRIC:
2447 AutoNegAdv |= PHY_B_P_SYM_MD;
2448 break;
2449 case SK_FLOW_MODE_SYM_OR_REM:
2450 AutoNegAdv |= PHY_B_P_BOTH_MD;
2451 break;
2452 default:
2453 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2454 SKERR_HWI_E016MSG);
2455 }
2456 }
2457 else { /* special defines for FIBER (88E1011S only) */
wdenk42d1f032003-10-15 23:53:47 +00002458
wdenk7152b1d2003-09-05 23:19:14 +00002459 /* Set Full/half duplex capabilities */
2460 switch (pPrt->PLinkMode) {
2461 case SK_LMODE_AUTOHALF:
2462 AutoNegAdv |= PHY_M_AN_1000X_AHD;
2463 break;
2464 case SK_LMODE_AUTOFULL:
2465 AutoNegAdv |= PHY_M_AN_1000X_AFD;
2466 break;
2467 case SK_LMODE_AUTOBOTH:
2468 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2469 break;
2470 default:
2471 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2472 SKERR_HWI_E015MSG);
2473 }
wdenk42d1f032003-10-15 23:53:47 +00002474
wdenk7152b1d2003-09-05 23:19:14 +00002475 /* Set Auto-negotiation advertisement */
2476 switch (pPrt->PFlowCtrlMode) {
2477 case SK_FLOW_MODE_NONE:
2478 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2479 break;
2480 case SK_FLOW_MODE_LOC_SEND:
2481 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2482 break;
2483 case SK_FLOW_MODE_SYMMETRIC:
2484 AutoNegAdv |= PHY_M_P_SYM_MD_X;
2485 break;
2486 case SK_FLOW_MODE_SYM_OR_REM:
2487 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2488 break;
2489 default:
2490 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2491 SKERR_HWI_E016MSG);
2492 }
2493 }
2494
2495 if (!DoLoop) {
2496 /* Restart Auto-negotiation */
2497 PhyCtrl |= PHY_CT_RE_CFG;
2498 }
2499 }
wdenk42d1f032003-10-15 23:53:47 +00002500
wdenk7152b1d2003-09-05 23:19:14 +00002501#ifdef VCPU
2502 /*
2503 * E-mail from Gu Lin (08-03-2002):
2504 */
wdenk42d1f032003-10-15 23:53:47 +00002505
wdenk7152b1d2003-09-05 23:19:14 +00002506 /* Program PHY register 30 as 16'h0708 for simulation speed up */
2507 SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708);
wdenk42d1f032003-10-15 23:53:47 +00002508
wdenk7152b1d2003-09-05 23:19:14 +00002509 VCpuWait(2000);
2510
2511#else /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00002512
wdenk7152b1d2003-09-05 23:19:14 +00002513 /* Write 1000Base-T Control Register */
2514 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2515 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2516 ("1000B-T Ctrl=0x%04X\n", C1000BaseT));
wdenk42d1f032003-10-15 23:53:47 +00002517
wdenk7152b1d2003-09-05 23:19:14 +00002518 /* Write AutoNeg Advertisement Register */
2519 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2520 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2521 ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv));
2522#endif /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00002523
wdenk7152b1d2003-09-05 23:19:14 +00002524 if (DoLoop) {
2525 /* Set the PHY Loopback bit */
2526 PhyCtrl |= PHY_CT_LOOP;
2527
2528 /* Program PHY register 16 as 16'h0400 to force link good */
2529 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2530
2531#if 0
2532 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2533 /* Write Ext. PHY Specific Control */
2534 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2535 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2536 }
2537 }
2538 else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2539 /* Write PHY Specific Control */
2540 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK);
2541 }
2542#endif /* 0 */
2543 }
2544
2545 /* Write to the PHY Control register */
2546 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2547
2548#ifdef VCPU
2549 VCpuWait(2000);
2550#else
2551
2552 LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2553
2554#ifdef ACT_LED_BLINK
2555 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2556#endif /* ACT_LED_BLINK */
2557
2558#ifdef DUP_LED_NORMAL
2559 LedCtrl |= PHY_M_LEDC_DP_CTRL;
2560#endif /* DUP_LED_NORMAL */
2561
2562 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2563
2564#endif /* VCPU */
2565
2566#ifdef SK_DIAG
2567 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2568 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2569 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2570 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2571#endif /* SK_DIAG */
2572
2573#ifndef xDEBUG
2574 /* Read PHY Control */
2575 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2576 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2577 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
wdenk42d1f032003-10-15 23:53:47 +00002578
wdenk7152b1d2003-09-05 23:19:14 +00002579 /* Read 1000Base-T Control Register */
2580 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2581 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2582 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
wdenk42d1f032003-10-15 23:53:47 +00002583
wdenk7152b1d2003-09-05 23:19:14 +00002584 /* Read AutoNeg Advertisement Register */
2585 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2586 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2587 ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv));
wdenk42d1f032003-10-15 23:53:47 +00002588
wdenk7152b1d2003-09-05 23:19:14 +00002589 /* Read Ext. PHY Specific Control */
2590 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2591 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2592 ("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl));
wdenk42d1f032003-10-15 23:53:47 +00002593
wdenk7152b1d2003-09-05 23:19:14 +00002594 /* Read PHY Status */
2595 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2596 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2597 ("PHY Stat Reg.=0x%04X\n", PhyStat));
2598 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2599 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2600 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
wdenk42d1f032003-10-15 23:53:47 +00002601
wdenk7152b1d2003-09-05 23:19:14 +00002602 /* Read PHY Specific Status */
2603 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2604 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2605 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
2606#endif /* DEBUG */
2607
2608#ifdef SK_DIAG
2609 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2610 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2611 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2612 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2613 c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2614 c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2615 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2616#endif /* SK_DIAG */
2617
2618} /* SkGmInitPhyMarv */
2619
2620
2621#ifdef OTHER_PHY
2622/******************************************************************************
2623 *
2624 * SkXmInitPhyLone() - Initialize the Level One Phy registers
2625 *
2626 * Description: initializes all the Level One Phy registers
2627 *
2628 * Note:
2629 *
2630 * Returns:
2631 * nothing
2632 */
2633static void SkXmInitPhyLone(
2634SK_AC *pAC, /* adapter context */
2635SK_IOC IoC, /* IO context */
2636int Port, /* Port Index (MAC_1 + n) */
2637SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2638{
2639 SK_GEPORT *pPrt;
2640 SK_U16 Ctrl1;
2641 SK_U16 Ctrl2;
2642 SK_U16 Ctrl3;
2643
2644 Ctrl1 = PHY_CT_SP1000;
2645 Ctrl2 = 0;
2646 Ctrl3 = PHY_SEL_TYPE;
2647
2648 pPrt = &pAC->GIni.GP[Port];
2649
2650 /* manually Master/Slave ? */
2651 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2652 Ctrl2 |= PHY_L_1000C_MSE;
wdenk42d1f032003-10-15 23:53:47 +00002653
wdenk7152b1d2003-09-05 23:19:14 +00002654 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2655 Ctrl2 |= PHY_L_1000C_MSC;
2656 }
2657 }
2658 /* Auto-negotiation ? */
2659 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2660 /*
2661 * level one spec say: "1000Mbps: manual mode not allowed"
2662 * but lets see what happens...
2663 */
2664 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2665 ("InitPhyLone: no auto-negotiation Port %d\n", Port));
2666 /* Set DuplexMode in Config register */
2667 Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2668
2669 /* Determine Master/Slave manually if not already done */
2670 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2671 Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
2672 }
2673
2674 /*
2675 * Do NOT enable Auto-negotiation here. This would hold
2676 * the link down because no IDLES are transmitted
2677 */
2678 }
2679 else {
2680 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2681 ("InitPhyLone: with auto-negotiation Port %d\n", Port));
2682 /* Set Auto-negotiation advertisement */
2683
2684 /* Set Full/half duplex capabilities */
2685 switch (pPrt->PLinkMode) {
2686 case SK_LMODE_AUTOHALF:
2687 Ctrl2 |= PHY_L_1000C_AHD;
2688 break;
2689 case SK_LMODE_AUTOFULL:
2690 Ctrl2 |= PHY_L_1000C_AFD;
2691 break;
2692 case SK_LMODE_AUTOBOTH:
2693 Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2694 break;
2695 default:
2696 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2697 SKERR_HWI_E015MSG);
2698 }
2699
2700 switch (pPrt->PFlowCtrlMode) {
2701 case SK_FLOW_MODE_NONE:
2702 Ctrl3 |= PHY_L_P_NO_PAUSE;
2703 break;
2704 case SK_FLOW_MODE_LOC_SEND:
2705 Ctrl3 |= PHY_L_P_ASYM_MD;
2706 break;
2707 case SK_FLOW_MODE_SYMMETRIC:
2708 Ctrl3 |= PHY_L_P_SYM_MD;
2709 break;
2710 case SK_FLOW_MODE_SYM_OR_REM:
2711 Ctrl3 |= PHY_L_P_BOTH_MD;
2712 break;
2713 default:
2714 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2715 SKERR_HWI_E016MSG);
2716 }
2717
2718 /* Restart Auto-negotiation */
2719 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2720
2721 }
wdenk42d1f032003-10-15 23:53:47 +00002722
wdenk7152b1d2003-09-05 23:19:14 +00002723 /* Initialize LED register here ? */
2724 /* No. Please do it in SkDgXmitLed() (if required) and swap
2725 init order of LEDs and XMAC. (MAl) */
wdenk42d1f032003-10-15 23:53:47 +00002726
wdenk7152b1d2003-09-05 23:19:14 +00002727 /* Write 1000Base-T Control Register */
2728 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2729 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2730 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
wdenk42d1f032003-10-15 23:53:47 +00002731
wdenk7152b1d2003-09-05 23:19:14 +00002732 /* Write AutoNeg Advertisement Register */
2733 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2734 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2735 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
wdenk42d1f032003-10-15 23:53:47 +00002736
wdenk7152b1d2003-09-05 23:19:14 +00002737
2738 if (DoLoop) {
2739 /* Set the Phy Loopback bit, too */
2740 Ctrl1 |= PHY_CT_LOOP;
2741 }
2742
2743 /* Write to the Phy control register */
2744 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2745 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2746 ("PHY Control Reg=0x%04X\n", Ctrl1));
2747} /* SkXmInitPhyLone */
2748
2749
2750/******************************************************************************
2751 *
2752 * SkXmInitPhyNat() - Initialize the National Phy registers
2753 *
2754 * Description: initializes all the National Phy registers
2755 *
2756 * Note:
2757 *
2758 * Returns:
2759 * nothing
2760 */
2761static void SkXmInitPhyNat(
2762SK_AC *pAC, /* adapter context */
2763SK_IOC IoC, /* IO context */
2764int Port, /* Port Index (MAC_1 + n) */
2765SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2766{
2767/* todo: National */
2768} /* SkXmInitPhyNat */
2769#endif /* OTHER_PHY */
2770
2771
2772/******************************************************************************
2773 *
2774 * SkMacInitPhy() - Initialize the PHY registers
2775 *
2776 * Description: calls the Init PHY routines dep. on board type
2777 *
2778 * Note:
2779 *
2780 * Returns:
2781 * nothing
2782 */
2783void SkMacInitPhy(
2784SK_AC *pAC, /* adapter context */
2785SK_IOC IoC, /* IO context */
2786int Port, /* Port Index (MAC_1 + n) */
2787SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2788{
2789 SK_GEPORT *pPrt;
2790
2791 pPrt = &pAC->GIni.GP[Port];
2792
2793 switch (pPrt->PhyType) {
2794 case SK_PHY_XMAC:
2795 SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2796 break;
2797 case SK_PHY_BCOM:
2798 SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2799 break;
2800 case SK_PHY_MARV_COPPER:
2801 case SK_PHY_MARV_FIBER:
2802 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2803 break;
2804#ifdef OTHER_PHY
2805 case SK_PHY_LONE:
2806 SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2807 break;
2808 case SK_PHY_NAT:
2809 SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2810 break;
2811#endif /* OTHER_PHY */
2812 }
2813} /* SkMacInitPhy */
2814
2815
2816#ifndef SK_DIAG
2817/******************************************************************************
2818 *
2819 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
2820 *
2821 * This function analyses the Interrupt status word. If any of the
2822 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
2823 * is set true.
2824 */
2825void SkXmAutoNegLipaXmac(
2826SK_AC *pAC, /* adapter context */
2827SK_IOC IoC, /* IO context */
2828int Port, /* Port Index (MAC_1 + n) */
2829SK_U16 IStatus) /* Interrupt Status word to analyse */
2830{
2831 SK_GEPORT *pPrt;
2832
2833 pPrt = &pAC->GIni.GP[Port];
2834
2835 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2836 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
2837
2838 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2839 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n",
2840 Port, IStatus));
2841 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2842 }
2843} /* SkXmAutoNegLipaXmac */
2844
2845
2846/******************************************************************************
2847 *
2848 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
2849 *
2850 * This function analyses the PHY status word.
2851 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
2852 * is set true.
2853 */
2854void SkMacAutoNegLipaPhy(
2855SK_AC *pAC, /* adapter context */
2856SK_IOC IoC, /* IO context */
2857int Port, /* Port Index (MAC_1 + n) */
2858SK_U16 PhyStat) /* PHY Status word to analyse */
2859{
2860 SK_GEPORT *pPrt;
2861
2862 pPrt = &pAC->GIni.GP[Port];
2863
2864 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2865 (PhyStat & PHY_ST_AN_OVER) != 0) {
2866
2867 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2868 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\n",
2869 Port, PhyStat));
2870 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2871 }
2872} /* SkMacAutoNegLipaPhy */
2873#endif /* SK_DIAG */
2874
2875
2876/******************************************************************************
2877 *
2878 * SkXmAutoNegDoneXmac() - Auto-negotiation handling
2879 *
2880 * Description:
2881 * This function handles the auto-negotiation if the Done bit is set.
2882 *
2883 * Returns:
2884 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02002885 * SK_AND_DUP_CAP Duplex capability error happened
2886 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00002887 */
2888static int SkXmAutoNegDoneXmac(
2889SK_AC *pAC, /* adapter context */
2890SK_IOC IoC, /* IO context */
2891int Port) /* Port Index (MAC_1 + n) */
2892{
2893 SK_GEPORT *pPrt;
2894 SK_U16 ResAb; /* Resolved Ability */
2895 SK_U16 LPAb; /* Link Partner Ability */
2896
2897 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2898 ("AutoNegDoneXmac, Port %d\n",Port));
2899
2900 pPrt = &pAC->GIni.GP[Port];
2901
2902 /* Get PHY parameters */
2903 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
2904 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
2905
2906 if ((LPAb & PHY_X_AN_RFB) != 0) {
2907 /* At least one of the remote fault bit is set */
2908 /* Error */
2909 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2910 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2911 pPrt->PAutoNegFail = SK_TRUE;
2912 return(SK_AND_OTHER);
2913 }
2914
2915 /* Check Duplex mismatch */
2916 if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
2917 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
2918 }
2919 else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
2920 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
2921 }
2922 else {
2923 /* Error */
2924 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2925 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2926 pPrt->PAutoNegFail = SK_TRUE;
2927 return(SK_AND_DUP_CAP);
2928 }
2929
2930 /* Check PAUSE mismatch */
2931 /* We are NOT using chapter 4.23 of the Xaqti manual */
2932 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2933 if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
2934 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
2935 (LPAb & PHY_X_P_SYM_MD) != 0) {
2936 /* Symmetric PAUSE */
2937 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2938 }
2939 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
2940 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
2941 /* Enable PAUSE receive, disable PAUSE transmit */
2942 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2943 }
2944 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
2945 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
2946 /* Disable PAUSE receive, enable PAUSE transmit */
2947 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2948 }
2949 else {
2950 /* PAUSE mismatch -> no PAUSE */
2951 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2952 }
2953 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
2954
2955 return(SK_AND_OK);
2956} /* SkXmAutoNegDoneXmac */
2957
2958
2959/******************************************************************************
2960 *
2961 * SkXmAutoNegDoneBcom() - Auto-negotiation handling
2962 *
2963 * Description:
2964 * This function handles the auto-negotiation if the Done bit is set.
2965 *
2966 * Returns:
2967 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02002968 * SK_AND_DUP_CAP Duplex capability error happened
2969 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00002970 */
2971static int SkXmAutoNegDoneBcom(
2972SK_AC *pAC, /* adapter context */
2973SK_IOC IoC, /* IO context */
2974int Port) /* Port Index (MAC_1 + n) */
2975{
2976 SK_GEPORT *pPrt;
2977 SK_U16 LPAb; /* Link Partner Ability */
2978 SK_U16 AuxStat; /* Auxiliary Status */
2979
2980#if 0
298101-Sep-2000 RA;:;:
2982 SK_U16 ResAb; /* Resolved Ability */
2983#endif /* 0 */
2984
2985 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2986 ("AutoNegDoneBcom, Port %d\n", Port));
2987 pPrt = &pAC->GIni.GP[Port];
2988
2989 /* Get PHY parameters */
2990 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
2991#if 0
299201-Sep-2000 RA;:;:
2993 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
2994#endif /* 0 */
wdenk42d1f032003-10-15 23:53:47 +00002995
wdenk7152b1d2003-09-05 23:19:14 +00002996 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
2997
2998 if ((LPAb & PHY_B_AN_RF) != 0) {
2999 /* Remote fault bit is set: Error */
3000 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3001 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3002 pPrt->PAutoNegFail = SK_TRUE;
3003 return(SK_AND_OTHER);
3004 }
3005
3006 /* Check Duplex mismatch */
3007 if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
3008 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3009 }
3010 else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
3011 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3012 }
3013 else {
3014 /* Error */
3015 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3016 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3017 pPrt->PAutoNegFail = SK_TRUE;
3018 return(SK_AND_DUP_CAP);
3019 }
wdenk42d1f032003-10-15 23:53:47 +00003020
wdenk7152b1d2003-09-05 23:19:14 +00003021#if 0
302201-Sep-2000 RA;:;:
3023 /* Check Master/Slave resolution */
3024 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3025 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3026 ("Master/Slave Fault Port %d\n", Port));
3027 pPrt->PAutoNegFail = SK_TRUE;
3028 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3029 return(SK_AND_OTHER);
3030 }
wdenk42d1f032003-10-15 23:53:47 +00003031
wdenk7152b1d2003-09-05 23:19:14 +00003032 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3033 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
3034#endif /* 0 */
3035
3036 /* Check PAUSE mismatch */
3037 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3038 if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
3039 /* Symmetric PAUSE */
3040 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3041 }
3042 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
3043 /* Enable PAUSE receive, disable PAUSE transmit */
3044 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3045 }
3046 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
3047 /* Disable PAUSE receive, enable PAUSE transmit */
3048 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3049 }
3050 else {
3051 /* PAUSE mismatch -> no PAUSE */
3052 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3053 }
3054 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3055
3056 return(SK_AND_OK);
3057} /* SkXmAutoNegDoneBcom */
3058
3059
3060/******************************************************************************
3061 *
3062 * SkGmAutoNegDoneMarv() - Auto-negotiation handling
3063 *
3064 * Description:
3065 * This function handles the auto-negotiation if the Done bit is set.
3066 *
3067 * Returns:
3068 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003069 * SK_AND_DUP_CAP Duplex capability error happened
3070 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003071 */
3072static int SkGmAutoNegDoneMarv(
3073SK_AC *pAC, /* adapter context */
3074SK_IOC IoC, /* IO context */
3075int Port) /* Port Index (MAC_1 + n) */
3076{
3077 SK_GEPORT *pPrt;
3078 SK_U16 LPAb; /* Link Partner Ability */
3079 SK_U16 ResAb; /* Resolved Ability */
3080 SK_U16 AuxStat; /* Auxiliary Status */
3081
3082 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3083 ("AutoNegDoneMarv, Port %d\n", Port));
3084 pPrt = &pAC->GIni.GP[Port];
3085
3086 /* Get PHY parameters */
3087 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
wdenk42d1f032003-10-15 23:53:47 +00003088
wdenk7152b1d2003-09-05 23:19:14 +00003089 if ((LPAb & PHY_M_AN_RF) != 0) {
3090 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3091 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3092 pPrt->PAutoNegFail = SK_TRUE;
3093 return(SK_AND_OTHER);
3094 }
3095
3096 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
wdenk42d1f032003-10-15 23:53:47 +00003097
wdenk7152b1d2003-09-05 23:19:14 +00003098 /* Check Master/Slave resolution */
3099 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3100 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3101 ("Master/Slave Fault Port %d\n", Port));
3102 pPrt->PAutoNegFail = SK_TRUE;
3103 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3104 return(SK_AND_OTHER);
3105 }
wdenk42d1f032003-10-15 23:53:47 +00003106
wdenk7152b1d2003-09-05 23:19:14 +00003107 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3108 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
wdenk42d1f032003-10-15 23:53:47 +00003109
wdenk7152b1d2003-09-05 23:19:14 +00003110 /* Read PHY Specific Status */
3111 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
wdenk42d1f032003-10-15 23:53:47 +00003112
wdenk7152b1d2003-09-05 23:19:14 +00003113 /* Check Speed & Duplex resolved */
3114 if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
3115 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3116 ("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port));
3117 pPrt->PAutoNegFail = SK_TRUE;
3118 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
3119 return(SK_AND_DUP_CAP);
3120 }
wdenk42d1f032003-10-15 23:53:47 +00003121
wdenk7152b1d2003-09-05 23:19:14 +00003122 if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
3123 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3124 }
3125 else {
3126 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3127 }
wdenk42d1f032003-10-15 23:53:47 +00003128
wdenk7152b1d2003-09-05 23:19:14 +00003129 /* Check PAUSE mismatch */
3130 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3131 if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
3132 /* Symmetric PAUSE */
3133 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3134 }
3135 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
3136 /* Enable PAUSE receive, disable PAUSE transmit */
3137 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3138 }
3139 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
3140 /* Disable PAUSE receive, enable PAUSE transmit */
3141 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3142 }
3143 else {
3144 /* PAUSE mismatch -> no PAUSE */
3145 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3146 }
wdenk42d1f032003-10-15 23:53:47 +00003147
wdenk7152b1d2003-09-05 23:19:14 +00003148 /* set used link speed */
3149 switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
3150 case (unsigned)PHY_M_PS_SPEED_1000:
3151 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3152 break;
3153 case PHY_M_PS_SPEED_100:
3154 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
3155 break;
3156 default:
3157 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
3158 }
3159
3160 return(SK_AND_OK);
3161} /* SkGmAutoNegDoneMarv */
3162
3163
3164#ifdef OTHER_PHY
3165/******************************************************************************
3166 *
3167 * SkXmAutoNegDoneLone() - Auto-negotiation handling
3168 *
3169 * Description:
3170 * This function handles the auto-negotiation if the Done bit is set.
3171 *
3172 * Returns:
3173 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003174 * SK_AND_DUP_CAP Duplex capability error happened
3175 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003176 */
3177static int SkXmAutoNegDoneLone(
3178SK_AC *pAC, /* adapter context */
3179SK_IOC IoC, /* IO context */
3180int Port) /* Port Index (MAC_1 + n) */
3181{
3182 SK_GEPORT *pPrt;
3183 SK_U16 ResAb; /* Resolved Ability */
3184 SK_U16 LPAb; /* Link Partner Ability */
3185 SK_U16 QuickStat; /* Auxiliary Status */
3186
3187 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3188 ("AutoNegDoneLone, Port %d\n",Port));
3189 pPrt = &pAC->GIni.GP[Port];
3190
3191 /* Get PHY parameters */
3192 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
3193 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
3194 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
3195
3196 if ((LPAb & PHY_L_AN_RF) != 0) {
3197 /* Remote fault bit is set */
3198 /* Error */
3199 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3200 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3201 pPrt->PAutoNegFail = SK_TRUE;
3202 return(SK_AND_OTHER);
3203 }
3204
3205 /* Check Duplex mismatch */
3206 if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
3207 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3208 }
3209 else {
3210 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3211 }
wdenk42d1f032003-10-15 23:53:47 +00003212
wdenk7152b1d2003-09-05 23:19:14 +00003213 /* Check Master/Slave resolution */
3214 if ((ResAb & PHY_L_1000S_MSF) != 0) {
3215 /* Error */
3216 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3217 ("Master/Slave Fault Port %d\n", Port));
3218 pPrt->PAutoNegFail = SK_TRUE;
3219 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3220 return(SK_AND_OTHER);
3221 }
3222 else if (ResAb & PHY_L_1000S_MSR) {
3223 pPrt->PMSStatus = SK_MS_STAT_MASTER;
3224 }
3225 else {
3226 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
3227 }
3228
3229 /* Check PAUSE mismatch */
3230 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3231 /* we must manually resolve the abilities here */
3232 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3233 switch (pPrt->PFlowCtrlMode) {
3234 case SK_FLOW_MODE_NONE:
3235 /* default */
3236 break;
3237 case SK_FLOW_MODE_LOC_SEND:
3238 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3239 (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
3240 /* Disable PAUSE receive, enable PAUSE transmit */
3241 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3242 }
3243 break;
3244 case SK_FLOW_MODE_SYMMETRIC:
3245 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3246 /* Symmetric PAUSE */
3247 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3248 }
3249 break;
3250 case SK_FLOW_MODE_SYM_OR_REM:
3251 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3252 PHY_L_QS_AS_PAUSE) {
3253 /* Enable PAUSE receive, disable PAUSE transmit */
3254 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3255 }
3256 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3257 /* Symmetric PAUSE */
3258 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3259 }
3260 break;
3261 default:
3262 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3263 SKERR_HWI_E016MSG);
3264 }
wdenk42d1f032003-10-15 23:53:47 +00003265
wdenk7152b1d2003-09-05 23:19:14 +00003266 return(SK_AND_OK);
3267} /* SkXmAutoNegDoneLone */
3268
3269
3270/******************************************************************************
3271 *
3272 * SkXmAutoNegDoneNat() - Auto-negotiation handling
3273 *
3274 * Description:
3275 * This function handles the auto-negotiation if the Done bit is set.
3276 *
3277 * Returns:
3278 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003279 * SK_AND_DUP_CAP Duplex capability error happened
3280 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003281 */
3282static int SkXmAutoNegDoneNat(
3283SK_AC *pAC, /* adapter context */
3284SK_IOC IoC, /* IO context */
3285int Port) /* Port Index (MAC_1 + n) */
3286{
3287/* todo: National */
3288 return(SK_AND_OK);
3289} /* SkXmAutoNegDoneNat */
3290#endif /* OTHER_PHY */
3291
3292
3293/******************************************************************************
3294 *
3295 * SkMacAutoNegDone() - Auto-negotiation handling
3296 *
3297 * Description: calls the auto-negotiation done routines dep. on board type
3298 *
3299 * Returns:
3300 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003301 * SK_AND_DUP_CAP Duplex capability error happened
3302 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003303 */
3304int SkMacAutoNegDone(
3305SK_AC *pAC, /* adapter context */
3306SK_IOC IoC, /* IO context */
3307int Port) /* Port Index (MAC_1 + n) */
3308{
3309 SK_GEPORT *pPrt;
3310 int Rtv;
3311
3312 pPrt = &pAC->GIni.GP[Port];
3313
3314 switch (pPrt->PhyType) {
3315 case SK_PHY_XMAC:
3316 Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3317 break;
3318 case SK_PHY_BCOM:
3319 Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3320 break;
3321 case SK_PHY_MARV_COPPER:
3322 case SK_PHY_MARV_FIBER:
3323 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3324 break;
3325#ifdef OTHER_PHY
3326 case SK_PHY_LONE:
3327 Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3328 break;
3329 case SK_PHY_NAT:
3330 Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3331 break;
3332#endif /* OTHER_PHY */
3333 default:
3334 return(SK_AND_OTHER);
3335 }
wdenk42d1f032003-10-15 23:53:47 +00003336
wdenk7152b1d2003-09-05 23:19:14 +00003337 if (Rtv != SK_AND_OK) {
3338 return(Rtv);
3339 }
3340
3341 /* We checked everything and may now enable the link */
3342 pPrt->PAutoNegFail = SK_FALSE;
3343
3344 SkMacRxTxEnable(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00003345
wdenk7152b1d2003-09-05 23:19:14 +00003346 return(SK_AND_OK);
3347} /* SkMacAutoNegDone */
3348
3349
3350/******************************************************************************
3351 *
3352 * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3353 *
3354 * Description:
3355 * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3356 * enables Rx/Tx
3357 *
3358 * Returns: N/A
3359 */
3360static void SkXmSetRxTxEn(
3361SK_AC *pAC, /* Adapter Context */
3362SK_IOC IoC, /* IO context */
3363int Port, /* Port Index (MAC_1 + n) */
3364int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3365{
3366 SK_U16 Word;
3367
3368 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3369
3370 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3371 case SK_MAC_LOOPB_ON:
3372 Word |= XM_MMU_MAC_LB;
3373 break;
3374 case SK_MAC_LOOPB_OFF:
3375 Word &= ~XM_MMU_MAC_LB;
3376 break;
3377 }
3378
3379 switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
3380 case SK_PHY_LOOPB_ON:
3381 Word |= XM_MMU_GMII_LOOP;
3382 break;
3383 case SK_PHY_LOOPB_OFF:
3384 Word &= ~XM_MMU_GMII_LOOP;
3385 break;
3386 }
wdenk42d1f032003-10-15 23:53:47 +00003387
wdenk7152b1d2003-09-05 23:19:14 +00003388 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3389 case SK_PHY_FULLD_ON:
3390 Word |= XM_MMU_GMII_FD;
3391 break;
3392 case SK_PHY_FULLD_OFF:
3393 Word &= ~XM_MMU_GMII_FD;
3394 break;
3395 }
wdenk42d1f032003-10-15 23:53:47 +00003396
wdenk7152b1d2003-09-05 23:19:14 +00003397 XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3398
3399 /* dummy read to ensure writing */
3400 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3401
3402} /* SkXmSetRxTxEn */
3403
3404
3405/******************************************************************************
3406 *
3407 * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3408 *
3409 * Description:
3410 * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3411 * enables Rx/Tx
3412 *
3413 * Returns: N/A
3414 */
3415static void SkGmSetRxTxEn(
3416SK_AC *pAC, /* Adapter Context */
3417SK_IOC IoC, /* IO context */
3418int Port, /* Port Index (MAC_1 + n) */
3419int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */
3420{
3421 SK_U16 Ctrl;
wdenk42d1f032003-10-15 23:53:47 +00003422
wdenk7152b1d2003-09-05 23:19:14 +00003423 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3424
3425 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3426 case SK_MAC_LOOPB_ON:
3427 Ctrl |= GM_GPCR_LOOP_ENA;
3428 break;
3429 case SK_MAC_LOOPB_OFF:
3430 Ctrl &= ~GM_GPCR_LOOP_ENA;
3431 break;
3432 }
3433
3434 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3435 case SK_PHY_FULLD_ON:
3436 Ctrl |= GM_GPCR_DUP_FULL;
3437 break;
3438 case SK_PHY_FULLD_OFF:
3439 Ctrl &= ~GM_GPCR_DUP_FULL;
3440 break;
3441 }
wdenk42d1f032003-10-15 23:53:47 +00003442
wdenk7152b1d2003-09-05 23:19:14 +00003443 GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3444
3445 /* dummy read to ensure writing */
3446 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3447
3448} /* SkGmSetRxTxEn */
3449
3450
3451/******************************************************************************
3452 *
3453 * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3454 *
3455 * Description: calls the Special Set Rx/Tx Enable routines dep. on board type
3456 *
3457 * Returns: N/A
3458 */
3459void SkMacSetRxTxEn(
3460SK_AC *pAC, /* Adapter Context */
3461SK_IOC IoC, /* IO context */
3462int Port, /* Port Index (MAC_1 + n) */
3463int Para)
3464{
3465 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00003466
wdenk7152b1d2003-09-05 23:19:14 +00003467 SkXmSetRxTxEn(pAC, IoC, Port, Para);
3468 }
3469 else {
wdenk42d1f032003-10-15 23:53:47 +00003470
wdenk7152b1d2003-09-05 23:19:14 +00003471 SkGmSetRxTxEn(pAC, IoC, Port, Para);
3472 }
3473
3474} /* SkMacSetRxTxEn */
3475
3476
3477/******************************************************************************
3478 *
3479 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3480 *
3481 * Description: enables Rx/Tx dep. on board type
3482 *
3483 * Returns:
3484 * 0 o.k.
3485 * != 0 Error happened
3486 */
3487int SkMacRxTxEnable(
3488SK_AC *pAC, /* adapter context */
3489SK_IOC IoC, /* IO context */
3490int Port) /* Port Index (MAC_1 + n) */
3491{
3492 SK_GEPORT *pPrt;
3493 SK_U16 Reg; /* 16-bit register value */
3494 SK_U16 IntMask; /* MAC interrupt mask */
3495 SK_U16 SWord;
3496
3497 pPrt = &pAC->GIni.GP[Port];
3498
3499 if (!pPrt->PHWLinkUp) {
3500 /* The Hardware link is NOT up */
3501 return(0);
3502 }
3503
3504 if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3505 pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3506 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3507 pPrt->PAutoNegFail) {
3508 /* Auto-negotiation is not done or failed */
3509 return(0);
3510 }
3511
3512 if (pAC->GIni.GIGenesis) {
3513 /* set Duplex Mode and Pause Mode */
3514 SkXmInitDupMd(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00003515
wdenk7152b1d2003-09-05 23:19:14 +00003516 SkXmInitPauseMd(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00003517
wdenk7152b1d2003-09-05 23:19:14 +00003518 /*
3519 * Initialize the Interrupt Mask Register. Default IRQs are...
3520 * - Link Asynchronous Event
3521 * - Link Partner requests config
3522 * - Auto Negotiation Done
3523 * - Rx Counter Event Overflow
3524 * - Tx Counter Event Overflow
3525 * - Transmit FIFO Underrun
3526 */
3527 IntMask = XM_DEF_MSK;
3528
3529#ifdef DEBUG
3530 /* add IRQ for Receive FIFO Overflow */
3531 IntMask &= ~XM_IS_RXF_OV;
3532#endif /* DEBUG */
wdenk42d1f032003-10-15 23:53:47 +00003533
wdenk7152b1d2003-09-05 23:19:14 +00003534 if (pPrt->PhyType != SK_PHY_XMAC) {
3535 /* disable GP0 interrupt bit */
3536 IntMask |= XM_IS_INP_ASS;
3537 }
3538 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
wdenk42d1f032003-10-15 23:53:47 +00003539
wdenk7152b1d2003-09-05 23:19:14 +00003540 /* get MMU Command Reg. */
3541 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
wdenk42d1f032003-10-15 23:53:47 +00003542
wdenk7152b1d2003-09-05 23:19:14 +00003543 if (pPrt->PhyType != SK_PHY_XMAC &&
3544 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3545 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3546 /* set to Full Duplex */
3547 Reg |= XM_MMU_GMII_FD;
3548 }
wdenk42d1f032003-10-15 23:53:47 +00003549
wdenk7152b1d2003-09-05 23:19:14 +00003550 switch (pPrt->PhyType) {
3551 case SK_PHY_BCOM:
3552 /*
3553 * Workaround BCOM Errata (#10523) for all BCom Phys
3554 * Enable Power Management after link up
3555 */
3556 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3557 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3558 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3559 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
3560 break;
3561#ifdef OTHER_PHY
3562 case SK_PHY_LONE:
3563 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3564 break;
3565 case SK_PHY_NAT:
3566 /* todo National:
3567 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3568 /* no interrupts possible from National ??? */
3569 break;
3570#endif /* OTHER_PHY */
3571 }
wdenk42d1f032003-10-15 23:53:47 +00003572
wdenk7152b1d2003-09-05 23:19:14 +00003573 /* enable Rx/Tx */
3574 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3575 }
3576 else {
3577 /*
3578 * Initialize the Interrupt Mask Register. Default IRQs are...
3579 * - Rx Counter Event Overflow
3580 * - Tx Counter Event Overflow
3581 * - Transmit FIFO Underrun
3582 */
3583 IntMask = GMAC_DEF_MSK;
3584
3585#ifdef DEBUG
3586 /* add IRQ for Receive FIFO Overrun */
3587 IntMask |= GM_IS_RX_FF_OR;
3588#endif /* DEBUG */
wdenk42d1f032003-10-15 23:53:47 +00003589
wdenk7152b1d2003-09-05 23:19:14 +00003590 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
wdenk42d1f032003-10-15 23:53:47 +00003591
wdenk7152b1d2003-09-05 23:19:14 +00003592 /* get General Purpose Control */
3593 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
wdenk42d1f032003-10-15 23:53:47 +00003594
wdenk7152b1d2003-09-05 23:19:14 +00003595 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3596 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3597 /* set to Full Duplex */
3598 Reg |= GM_GPCR_DUP_FULL;
3599 }
wdenk42d1f032003-10-15 23:53:47 +00003600
wdenk7152b1d2003-09-05 23:19:14 +00003601 /* enable Rx/Tx */
3602 GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3603
3604#ifndef VCPU
3605 /* Enable all PHY interrupts */
3606 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
3607#endif /* VCPU */
3608 }
wdenk42d1f032003-10-15 23:53:47 +00003609
wdenk7152b1d2003-09-05 23:19:14 +00003610 return(0);
3611
3612} /* SkMacRxTxEnable */
3613
3614
3615/******************************************************************************
3616 *
3617 * SkMacRxTxDisable() - Disable Receiver and Transmitter
3618 *
3619 * Description: disables Rx/Tx dep. on board type
3620 *
3621 * Returns: N/A
3622 */
3623void SkMacRxTxDisable(
3624SK_AC *pAC, /* Adapter Context */
3625SK_IOC IoC, /* IO context */
3626int Port) /* Port Index (MAC_1 + n) */
3627{
3628 SK_U16 Word;
3629
3630 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00003631
wdenk7152b1d2003-09-05 23:19:14 +00003632 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
wdenk42d1f032003-10-15 23:53:47 +00003633
wdenk7152b1d2003-09-05 23:19:14 +00003634 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
wdenk42d1f032003-10-15 23:53:47 +00003635
wdenk7152b1d2003-09-05 23:19:14 +00003636 /* dummy read to ensure writing */
3637 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3638 }
3639 else {
wdenk42d1f032003-10-15 23:53:47 +00003640
wdenk7152b1d2003-09-05 23:19:14 +00003641 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3642
3643 GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
3644
3645 /* dummy read to ensure writing */
3646 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3647 }
3648} /* SkMacRxTxDisable */
3649
3650
3651/******************************************************************************
3652 *
3653 * SkMacIrqDisable() - Disable IRQ from MAC
3654 *
3655 * Description: sets the IRQ-mask to disable IRQ dep. on board type
3656 *
3657 * Returns: N/A
3658 */
3659void SkMacIrqDisable(
3660SK_AC *pAC, /* Adapter Context */
3661SK_IOC IoC, /* IO context */
3662int Port) /* Port Index (MAC_1 + n) */
3663{
3664 SK_GEPORT *pPrt;
3665 SK_U16 Word;
3666
3667 pPrt = &pAC->GIni.GP[Port];
3668
3669 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00003670
wdenk7152b1d2003-09-05 23:19:14 +00003671 /* disable all XMAC IRQs */
wdenk42d1f032003-10-15 23:53:47 +00003672 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
3673
wdenk7152b1d2003-09-05 23:19:14 +00003674 /* Disable all PHY interrupts */
3675 switch (pPrt->PhyType) {
3676 case SK_PHY_BCOM:
3677 /* Make sure that PHY is initialized */
3678 if (pPrt->PState != SK_PRT_RESET) {
3679 /* NOT allowed if BCOM is in RESET state */
3680 /* Workaround BCOM Errata (#10523) all BCom */
3681 /* Disable Power Management if link is down */
3682 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3683 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3684 (SK_U16)(Word | PHY_B_AC_DIS_PM));
3685 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3686 }
3687 break;
3688#ifdef OTHER_PHY
3689 case SK_PHY_LONE:
3690 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3691 break;
3692 case SK_PHY_NAT:
3693 /* todo: National
3694 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3695 break;
3696#endif /* OTHER_PHY */
3697 }
3698 }
3699 else {
3700 /* disable all GMAC IRQs */
3701 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
wdenk42d1f032003-10-15 23:53:47 +00003702
wdenk7152b1d2003-09-05 23:19:14 +00003703#ifndef VCPU
3704 /* Disable all PHY interrupts */
3705 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3706#endif /* VCPU */
3707 }
3708} /* SkMacIrqDisable */
3709
3710
3711#ifdef SK_DIAG
3712/******************************************************************************
3713 *
3714 * SkXmSendCont() - Enable / Disable Send Continuous Mode
3715 *
3716 * Description: enable / disable Send Continuous Mode on XMAC
3717 *
3718 * Returns:
3719 * nothing
3720 */
3721void SkXmSendCont(
3722SK_AC *pAC, /* adapter context */
3723SK_IOC IoC, /* IO context */
3724int Port, /* Port Index (MAC_1 + n) */
3725SK_BOOL Enable) /* Enable / Disable */
3726{
3727 SK_U32 MdReg;
3728
3729 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3730
3731 if (Enable) {
3732 MdReg |= XM_MD_TX_CONT;
3733 }
3734 else {
3735 MdReg &= ~XM_MD_TX_CONT;
3736 }
3737 /* setup Mode Register */
3738 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3739
3740} /* SkXmSendCont*/
3741
3742/******************************************************************************
3743 *
3744 * SkMacTimeStamp() - Enable / Disable Time Stamp
3745 *
3746 * Description: enable / disable Time Stamp generation for Rx packets
3747 *
3748 * Returns:
3749 * nothing
3750 */
3751void SkMacTimeStamp(
3752SK_AC *pAC, /* adapter context */
3753SK_IOC IoC, /* IO context */
3754int Port, /* Port Index (MAC_1 + n) */
3755SK_BOOL Enable) /* Enable / Disable */
3756{
3757 SK_U32 MdReg;
3758 SK_U8 TimeCtrl;
3759
3760 if (pAC->GIni.GIGenesis) {
3761
3762 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3763
3764 if (Enable) {
3765 MdReg |= XM_MD_ATS;
3766 }
3767 else {
3768 MdReg &= ~XM_MD_ATS;
3769 }
3770 /* setup Mode Register */
3771 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3772 }
3773 else {
3774 if (Enable) {
3775 TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3776 }
3777 else {
3778 TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3779 }
3780 /* Start/Stop Time Stamp Timer */
3781 SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl);
3782 }
3783} /* SkMacTimeStamp*/
3784
3785#else /* SK_DIAG */
3786
3787/******************************************************************************
3788 *
3789 * SkXmIrq() - Interrupt Service Routine
3790 *
3791 * Description: services an Interrupt Request of the XMAC
3792 *
3793 * Note:
3794 * With an external PHY, some interrupt bits are not meaningfull any more:
3795 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
3796 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
3797 * - Page Received (bit #9) XM_IS_RX_PAGE
3798 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
3799 * - AutoNegDone (bit #7) XM_IS_AND
3800 * Also probably not valid any more is the GP0 input bit:
3801 * - GPRegisterBit0set XM_IS_INP_ASS
3802 *
3803 * Returns:
3804 * nothing
3805 */
3806void SkXmIrq(
3807SK_AC *pAC, /* adapter context */
3808SK_IOC IoC, /* IO context */
3809int Port) /* Port Index (MAC_1 + n) */
3810{
3811 SK_GEPORT *pPrt;
3812 SK_EVPARA Para;
3813 SK_U16 IStatus; /* Interrupt status read from the XMAC */
3814 SK_U16 IStatus2;
3815
3816 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +00003817
wdenk7152b1d2003-09-05 23:19:14 +00003818 XM_IN16(IoC, Port, XM_ISRC, &IStatus);
wdenk42d1f032003-10-15 23:53:47 +00003819
wdenk7152b1d2003-09-05 23:19:14 +00003820 /* LinkPartner Auto-negable? */
3821 if (pPrt->PhyType == SK_PHY_XMAC) {
3822 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
3823 }
3824 else {
3825 /* mask bits that are not used with ext. PHY */
3826 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
3827 XM_IS_RX_PAGE | XM_IS_TX_PAGE |
3828 XM_IS_AND | XM_IS_INP_ASS);
3829 }
wdenk42d1f032003-10-15 23:53:47 +00003830
wdenk7152b1d2003-09-05 23:19:14 +00003831 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3832 ("XmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3833
3834 if (!pPrt->PHWLinkUp) {
3835 /* Spurious XMAC interrupt */
3836 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3837 ("SkXmIrq: spurious interrupt on Port %d\n", Port));
3838 return;
3839 }
3840
3841 if ((IStatus & XM_IS_INP_ASS) != 0) {
3842 /* Reread ISR Register if link is not in sync */
3843 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
3844
3845 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3846 ("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\n",
3847 Port, IStatus, IStatus2));
3848 IStatus &= ~XM_IS_INP_ASS;
3849 IStatus |= IStatus2;
3850 }
3851
3852 if ((IStatus & XM_IS_LNK_AE) != 0) {
3853 /* not used, GP0 is used instead */
3854 }
3855
3856 if ((IStatus & XM_IS_TX_ABORT) != 0) {
3857 /* not used */
3858 }
3859
3860 if ((IStatus & XM_IS_FRC_INT) != 0) {
3861 /* not used, use ASIC IRQ instead if needed */
3862 }
3863
3864 if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
3865 SkHWLinkDown(pAC, IoC, Port);
3866
3867 /* Signal to RLMT */
3868 Para.Para32[0] = (SK_U32)Port;
3869 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
3870
3871 /* Start workaround Errata #2 timer */
3872 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
3873 SKGE_HWAC, SK_HWEV_WATIM, Para);
3874 }
3875
3876 if ((IStatus & XM_IS_RX_PAGE) != 0) {
3877 /* not used */
3878 }
3879
3880 if ((IStatus & XM_IS_TX_PAGE) != 0) {
3881 /* not used */
3882 }
3883
3884 if ((IStatus & XM_IS_AND) != 0) {
3885 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3886 ("SkXmIrq: AND on link that is up Port %d\n", Port));
3887 }
3888
3889 if ((IStatus & XM_IS_TSC_OV) != 0) {
3890 /* not used */
3891 }
3892
3893 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3894 if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
3895 Para.Para32[0] = (SK_U32)Port;
3896 Para.Para32[1] = (SK_U32)IStatus;
3897 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3898 }
3899
3900 if ((IStatus & XM_IS_RXF_OV) != 0) {
3901 /* normal situation -> no effect */
3902#ifdef DEBUG
3903 pPrt->PRxOverCnt++;
3904#endif /* DEBUG */
3905 }
3906
3907 if ((IStatus & XM_IS_TXF_UR) != 0) {
3908 /* may NOT happen -> error log */
3909 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3910 }
3911
3912 if ((IStatus & XM_IS_TX_COMP) != 0) {
3913 /* not served here */
3914 }
3915
3916 if ((IStatus & XM_IS_RX_COMP) != 0) {
3917 /* not served here */
3918 }
3919} /* SkXmIrq */
3920
3921
3922/******************************************************************************
3923 *
3924 * SkGmIrq() - Interrupt Service Routine
3925 *
3926 * Description: services an Interrupt Request of the GMAC
3927 *
3928 * Note:
3929 *
3930 * Returns:
3931 * nothing
3932 */
3933void SkGmIrq(
3934SK_AC *pAC, /* adapter context */
3935SK_IOC IoC, /* IO context */
3936int Port) /* Port Index (MAC_1 + n) */
3937{
3938 SK_GEPORT *pPrt;
3939 SK_EVPARA Para;
3940 SK_U8 IStatus; /* Interrupt status */
3941
3942 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +00003943
wdenk7152b1d2003-09-05 23:19:14 +00003944 SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
wdenk42d1f032003-10-15 23:53:47 +00003945
wdenk7152b1d2003-09-05 23:19:14 +00003946 /* LinkPartner Auto-negable? */
3947 SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
wdenk42d1f032003-10-15 23:53:47 +00003948
wdenk7152b1d2003-09-05 23:19:14 +00003949 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3950 ("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3951
3952 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3953 if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
3954 /* these IRQs will be cleared by reading GMACs register */
3955 Para.Para32[0] = (SK_U32)Port;
3956 Para.Para32[1] = (SK_U32)IStatus;
3957 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3958 }
3959
3960 if (IStatus & GM_IS_RX_FF_OR) {
3961 /* clear GMAC Rx FIFO Overrun IRQ */
3962 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
3963#ifdef DEBUG
3964 pPrt->PRxOverCnt++;
3965#endif /* DEBUG */
3966 }
3967
3968 if (IStatus & GM_IS_TX_FF_UR) {
3969 /* clear GMAC Tx FIFO Underrun IRQ */
3970 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
3971 /* may NOT happen -> error log */
3972 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3973 }
3974
3975 if (IStatus & GM_IS_TX_COMPL) {
3976 /* not served here */
3977 }
3978
3979 if (IStatus & GM_IS_RX_COMPL) {
3980 /* not served here */
3981 }
3982} /* SkGmIrq */
3983
3984/******************************************************************************
3985 *
3986 * SkMacIrq() - Interrupt Service Routine for MAC
3987 *
3988 * Description: calls the Interrupt Service Routine dep. on board type
3989 *
3990 * Returns:
3991 * nothing
3992 */
3993void SkMacIrq(
3994SK_AC *pAC, /* adapter context */
3995SK_IOC IoC, /* IO context */
3996int Port) /* Port Index (MAC_1 + n) */
3997{
3998
3999 if (pAC->GIni.GIGenesis) {
4000 /* IRQ from XMAC */
4001 SkXmIrq(pAC, IoC, Port);
4002 }
4003 else {
4004 /* IRQ from GMAC */
4005 SkGmIrq(pAC, IoC, Port);
4006 }
4007} /* SkMacIrq */
4008
4009#endif /* !SK_DIAG */
4010
4011/******************************************************************************
4012 *
4013 * SkXmUpdateStats() - Force the XMAC to output the current statistic
4014 *
4015 * Description:
4016 * The XMAC holds its statistic internally. To obtain the current
4017 * values a command must be sent so that the statistic data will
4018 * be written to a predefined memory area on the adapter.
4019 *
4020 * Returns:
4021 * 0: success
4022 * 1: something went wrong
4023 */
4024int SkXmUpdateStats(
4025SK_AC *pAC, /* adapter context */
4026SK_IOC IoC, /* IO context */
4027unsigned int Port) /* Port Index (MAC_1 + n) */
4028{
4029 SK_GEPORT *pPrt;
4030 SK_U16 StatReg;
4031 int WaitIndex;
4032
4033 pPrt = &pAC->GIni.GP[Port];
4034 WaitIndex = 0;
4035
4036 /* Send an update command to XMAC specified */
4037 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
4038
4039 /*
4040 * It is an auto-clearing register. If the command bits
4041 * went to zero again, the statistics are transferred.
4042 * Normally the command should be executed immediately.
4043 * But just to be sure we execute a loop.
4044 */
4045 do {
4046
4047 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
wdenk42d1f032003-10-15 23:53:47 +00004048
wdenk7152b1d2003-09-05 23:19:14 +00004049 if (++WaitIndex > 10) {
4050
4051 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
4052
4053 return(1);
4054 }
4055 } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
wdenk42d1f032003-10-15 23:53:47 +00004056
wdenk7152b1d2003-09-05 23:19:14 +00004057 return(0);
4058} /* SkXmUpdateStats */
4059
4060/******************************************************************************
4061 *
4062 * SkGmUpdateStats() - Force the GMAC to output the current statistic
4063 *
4064 * Description:
4065 * Empty function for GMAC. Statistic data is accessible in direct way.
4066 *
4067 * Returns:
4068 * 0: success
4069 * 1: something went wrong
4070 */
4071int SkGmUpdateStats(
4072SK_AC *pAC, /* adapter context */
4073SK_IOC IoC, /* IO context */
4074unsigned int Port) /* Port Index (MAC_1 + n) */
4075{
4076 return(0);
4077}
4078
4079/******************************************************************************
4080 *
4081 * SkXmMacStatistic() - Get XMAC counter value
4082 *
4083 * Description:
4084 * Gets the 32bit counter value. Except for the octet counters
4085 * the lower 32bit are counted in hardware and the upper 32bit
4086 * must be counted in software by monitoring counter overflow interrupts.
4087 *
4088 * Returns:
4089 * 0: success
4090 * 1: something went wrong
4091 */
4092int SkXmMacStatistic(
4093SK_AC *pAC, /* adapter context */
4094SK_IOC IoC, /* IO context */
4095unsigned int Port, /* Port Index (MAC_1 + n) */
4096SK_U16 StatAddr, /* MIB counter base address */
4097SK_U32 *pVal) /* ptr to return statistic value */
4098{
4099 if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
wdenk42d1f032003-10-15 23:53:47 +00004100
wdenk7152b1d2003-09-05 23:19:14 +00004101 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
wdenk42d1f032003-10-15 23:53:47 +00004102
wdenk7152b1d2003-09-05 23:19:14 +00004103 return(1);
4104 }
wdenk42d1f032003-10-15 23:53:47 +00004105
wdenk7152b1d2003-09-05 23:19:14 +00004106 XM_IN32(IoC, Port, StatAddr, pVal);
4107
4108 return(0);
4109} /* SkXmMacStatistic */
4110
4111/******************************************************************************
4112 *
4113 * SkGmMacStatistic() - Get GMAC counter value
4114 *
4115 * Description:
4116 * Gets the 32bit counter value. Except for the octet counters
4117 * the lower 32bit are counted in hardware and the upper 32bit
4118 * must be counted in software by monitoring counter overflow interrupts.
4119 *
4120 * Returns:
4121 * 0: success
4122 * 1: something went wrong
4123 */
4124int SkGmMacStatistic(
4125SK_AC *pAC, /* adapter context */
4126SK_IOC IoC, /* IO context */
4127unsigned int Port, /* Port Index (MAC_1 + n) */
4128SK_U16 StatAddr, /* MIB counter base address */
4129SK_U32 *pVal) /* ptr to return statistic value */
4130{
4131
4132 if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
wdenk42d1f032003-10-15 23:53:47 +00004133
wdenk7152b1d2003-09-05 23:19:14 +00004134 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
wdenk42d1f032003-10-15 23:53:47 +00004135
wdenk7152b1d2003-09-05 23:19:14 +00004136 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4137 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
4138 return(1);
4139 }
wdenk42d1f032003-10-15 23:53:47 +00004140
wdenk7152b1d2003-09-05 23:19:14 +00004141 GM_IN32(IoC, Port, StatAddr, pVal);
4142
4143 return(0);
4144} /* SkGmMacStatistic */
4145
4146/******************************************************************************
4147 *
4148 * SkXmResetCounter() - Clear MAC statistic counter
4149 *
4150 * Description:
4151 * Force the XMAC to clear its statistic counter.
4152 *
4153 * Returns:
4154 * 0: success
4155 * 1: something went wrong
4156 */
4157int SkXmResetCounter(
4158SK_AC *pAC, /* adapter context */
4159SK_IOC IoC, /* IO context */
4160unsigned int Port) /* Port Index (MAC_1 + n) */
4161{
4162 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4163 /* Clear two times according to Errata #3 */
4164 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4165
4166 return(0);
4167} /* SkXmResetCounter */
4168
4169/******************************************************************************
4170 *
4171 * SkGmResetCounter() - Clear MAC statistic counter
4172 *
4173 * Description:
4174 * Force GMAC to clear its statistic counter.
4175 *
4176 * Returns:
4177 * 0: success
4178 * 1: something went wrong
4179 */
4180int SkGmResetCounter(
4181SK_AC *pAC, /* adapter context */
4182SK_IOC IoC, /* IO context */
4183unsigned int Port) /* Port Index (MAC_1 + n) */
4184{
4185 SK_U16 Reg; /* Phy Address Register */
4186 SK_U16 Word;
4187 int i;
4188
4189 GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4190
4191#ifndef VCPU
4192 /* set MIB Clear Counter Mode */
4193 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
wdenk42d1f032003-10-15 23:53:47 +00004194
wdenk7152b1d2003-09-05 23:19:14 +00004195 /* read all MIB Counters with Clear Mode set */
4196 for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4197 /* the reset is performed only when the lower 16 bits are read */
4198 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4199 }
wdenk42d1f032003-10-15 23:53:47 +00004200
wdenk7152b1d2003-09-05 23:19:14 +00004201 /* clear MIB Clear Counter Mode */
4202 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4203#endif /* !VCPU */
wdenk42d1f032003-10-15 23:53:47 +00004204
wdenk7152b1d2003-09-05 23:19:14 +00004205 return(0);
4206} /* SkGmResetCounter */
4207
4208/******************************************************************************
4209 *
4210 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4211 *
4212 * Description:
4213 * Checks the source causing an counter overflow interrupt. On success the
4214 * resulting counter overflow status is written to <pStatus>, whereas the
4215 * upper dword stores the XMAC ReceiveCounterEvent register and the lower
4216 * dword the XMAC TransmitCounterEvent register.
4217 *
4218 * Note:
4219 * For XMAC the interrupt source is a self-clearing register, so the source
4220 * must be checked only once. SIRQ module does another check to be sure
4221 * that no interrupt get lost during process time.
4222 *
4223 * Returns:
4224 * 0: success
4225 * 1: something went wrong
4226 */
4227int SkXmOverflowStatus(
4228SK_AC *pAC, /* adapter context */
4229SK_IOC IoC, /* IO context */
4230unsigned int Port, /* Port Index (MAC_1 + n) */
4231SK_U16 IStatus, /* Interupt Status from MAC */
4232SK_U64 *pStatus) /* ptr for return overflow status value */
4233{
4234 SK_U64 Status; /* Overflow status */
4235 SK_U32 RegVal;
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02004236 SK_U32 *pRegVal = &RegVal;
wdenk7152b1d2003-09-05 23:19:14 +00004237
4238 Status = 0;
4239
4240 if ((IStatus & XM_IS_RXC_OV) != 0) {
4241
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02004242 XM_IN32(IoC, Port, XM_RX_CNT_EV, pRegVal);
wdenk7152b1d2003-09-05 23:19:14 +00004243 Status |= (SK_U64)RegVal << 32;
4244 }
wdenk42d1f032003-10-15 23:53:47 +00004245
wdenk7152b1d2003-09-05 23:19:14 +00004246 if ((IStatus & XM_IS_TXC_OV) != 0) {
4247
Wolfgang Denk2d6d9f02009-09-11 09:36:31 +02004248 XM_IN32(IoC, Port, XM_TX_CNT_EV, pRegVal);
wdenk7152b1d2003-09-05 23:19:14 +00004249 Status |= (SK_U64)RegVal;
4250 }
4251
4252 *pStatus = Status;
4253
4254 return(0);
4255} /* SkXmOverflowStatus */
4256
4257
4258/******************************************************************************
4259 *
4260 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4261 *
4262 * Description:
4263 * Checks the source causing an counter overflow interrupt. On success the
4264 * resulting counter overflow status is written to <pStatus>, whereas the
4265 * the following bit coding is used:
4266 * 63:56 - unused
4267 * 55:48 - TxRx interrupt register bit7:0
4268 * 32:47 - Rx interrupt register
4269 * 31:24 - unused
4270 * 23:16 - TxRx interrupt register bit15:8
4271 * 15:0 - Tx interrupt register
4272 *
4273 * Returns:
4274 * 0: success
4275 * 1: something went wrong
4276 */
4277int SkGmOverflowStatus(
4278SK_AC *pAC, /* adapter context */
4279SK_IOC IoC, /* IO context */
4280unsigned int Port, /* Port Index (MAC_1 + n) */
4281SK_U16 IStatus, /* Interupt Status from MAC */
4282SK_U64 *pStatus) /* ptr for return overflow status value */
4283{
4284 SK_U64 Status; /* Overflow status */
4285 SK_U16 RegVal;
4286
4287 Status = 0;
4288
4289 if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4290 /* this register is self-clearing after read */
4291 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4292 Status |= (SK_U64)RegVal << 32;
4293 }
wdenk42d1f032003-10-15 23:53:47 +00004294
wdenk7152b1d2003-09-05 23:19:14 +00004295 if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4296 /* this register is self-clearing after read */
4297 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4298 Status |= (SK_U64)RegVal;
4299 }
wdenk42d1f032003-10-15 23:53:47 +00004300
wdenk7152b1d2003-09-05 23:19:14 +00004301 /* this register is self-clearing after read */
4302 GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4303 /* Rx overflow interrupt register bits (LoByte)*/
4304 Status |= (SK_U64)((SK_U8)RegVal) << 48;
4305 /* Tx overflow interrupt register bits (HiByte)*/
4306 Status |= (SK_U64)(RegVal >> 8) << 16;
4307
4308 *pStatus = Status;
4309
4310 return(0);
4311} /* SkGmOverflowStatus */
4312
4313/******************************************************************************
4314 *
4315 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4316 *
4317 * Description:
4318 * starts the cable diagnostic test if 'StartTest' is true
4319 * gets the results if 'StartTest' is true
4320 *
4321 * NOTE: this test is meaningful only when link is down
wdenk42d1f032003-10-15 23:53:47 +00004322 *
wdenk7152b1d2003-09-05 23:19:14 +00004323 * Returns:
4324 * 0: success
4325 * 1: no YUKON copper
4326 * 2: test in progress
4327 */
4328int SkGmCableDiagStatus(
4329SK_AC *pAC, /* adapter context */
Wolfgang Denk53677ef2008-05-20 16:00:29 +02004330SK_IOC IoC, /* IO context */
wdenk7152b1d2003-09-05 23:19:14 +00004331int Port, /* Port Index (MAC_1 + n) */
4332SK_BOOL StartTest) /* flag for start / get result */
4333{
4334 int i;
4335 SK_U16 RegVal;
4336 SK_GEPORT *pPrt;
4337
4338 pPrt = &pAC->GIni.GP[Port];
4339
4340 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
wdenk42d1f032003-10-15 23:53:47 +00004341
wdenk7152b1d2003-09-05 23:19:14 +00004342 return(1);
4343 }
4344
4345 if (StartTest) {
4346 /* only start the cable test */
4347 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4348 /* apply TDR workaround from Marvell */
4349 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
wdenk42d1f032003-10-15 23:53:47 +00004350
wdenk7152b1d2003-09-05 23:19:14 +00004351 SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4352 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4353 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4354 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4355 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4356 }
4357
4358 /* set address to 0 for MDI[0] */
4359 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4360
4361 /* Read Cable Diagnostic Reg */
4362 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4363
4364 /* start Cable Diagnostic Test */
4365 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4366 (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
wdenk42d1f032003-10-15 23:53:47 +00004367
wdenk7152b1d2003-09-05 23:19:14 +00004368 return(0);
4369 }
wdenk42d1f032003-10-15 23:53:47 +00004370
wdenk7152b1d2003-09-05 23:19:14 +00004371 /* Read Cable Diagnostic Reg */
4372 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4373
4374 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4375 ("PHY Cable Diag.=0x%04X\n", RegVal));
4376
4377 if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4378 /* test is running */
4379 return(2);
4380 }
4381
4382 /* get the test results */
4383 for (i = 0; i < 4; i++) {
4384 /* set address to i for MDI[i] */
4385 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4386
4387 /* get Cable Diagnostic values */
4388 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4389
4390 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4391
4392 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4393 }
4394
4395 return(0);
4396} /* SkGmCableDiagStatus */
4397
wdenk7152b1d2003-09-05 23:19:14 +00004398/* End of file */