blob: e0ded42bae5d4c84cba809603d5d1adbd23cf733 [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;
750
751 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +0000752
wdenk7152b1d2003-09-05 23:19:14 +0000753 XM_IN32(IoC, Port, XM_MODE, &MdReg);
754 /* enable or disable promiscuous mode */
755 if (Enable) {
756 MdReg |= XM_MD_ENA_PROM;
757 }
758 else {
759 MdReg &= ~XM_MD_ENA_PROM;
760 }
761 /* setup Mode Register */
762 XM_OUT32(IoC, Port, XM_MODE, MdReg);
763 }
764 else {
wdenk42d1f032003-10-15 23:53:47 +0000765
wdenk7152b1d2003-09-05 23:19:14 +0000766 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
wdenk42d1f032003-10-15 23:53:47 +0000767
wdenk7152b1d2003-09-05 23:19:14 +0000768 /* enable or disable unicast and multicast filtering */
769 if (Enable) {
770 RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
771 }
772 else {
773 RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
774 }
775 /* setup Receive Control Register */
776 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
777 }
778} /* SkMacPromiscMode*/
779
780
781/******************************************************************************
782 *
783 * SkMacHashing() - Enable / Disable Hashing
784 *
785 * Description:
786 * enables / disables hashing by setting Mode Register (XMAC) or
wdenk42d1f032003-10-15 23:53:47 +0000787 * Receive Control Register (GMAC) dep. on board type
wdenk7152b1d2003-09-05 23:19:14 +0000788 *
789 * Returns:
790 * nothing
791 */
792void SkMacHashing(
793SK_AC *pAC, /* adapter context */
794SK_IOC IoC, /* IO context */
795int Port, /* Port Index (MAC_1 + n) */
796SK_BOOL Enable) /* Enable / Disable */
797{
798 SK_U16 RcReg;
799 SK_U32 MdReg;
800
801 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +0000802
wdenk7152b1d2003-09-05 23:19:14 +0000803 XM_IN32(IoC, Port, XM_MODE, &MdReg);
804 /* enable or disable hashing */
805 if (Enable) {
806 MdReg |= XM_MD_ENA_HASH;
807 }
808 else {
809 MdReg &= ~XM_MD_ENA_HASH;
810 }
811 /* setup Mode Register */
812 XM_OUT32(IoC, Port, XM_MODE, MdReg);
813 }
814 else {
wdenk42d1f032003-10-15 23:53:47 +0000815
wdenk7152b1d2003-09-05 23:19:14 +0000816 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
wdenk42d1f032003-10-15 23:53:47 +0000817
wdenk7152b1d2003-09-05 23:19:14 +0000818 /* enable or disable multicast filtering */
819 if (Enable) {
820 RcReg |= GM_RXCR_MCF_ENA;
821 }
822 else {
823 RcReg &= ~GM_RXCR_MCF_ENA;
824 }
825 /* setup Receive Control Register */
826 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
827 }
828} /* SkMacHashing*/
829
830
831#ifdef SK_DIAG
832/******************************************************************************
833 *
834 * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
835 *
836 * Description:
837 * The features
838 * - FCS stripping, SK_STRIP_FCS_ON/OFF
839 * - pad byte stripping, SK_STRIP_PAD_ON/OFF
840 * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
841 * for inrange length error frames
842 * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
843 * for frames > 1514 bytes
844 * - enable Rx of own packets SK_SELF_RX_ON/OFF
845 *
846 * for incoming packets may be enabled/disabled by this function.
847 * Additional modes may be added later.
848 * Multiple modes can be enabled/disabled at the same time.
849 * The new configuration is written to the Rx Command register immediately.
850 *
851 * Returns:
852 * nothing
853 */
854static void SkXmSetRxCmd(
855SK_AC *pAC, /* adapter context */
856SK_IOC IoC, /* IO context */
857int Port, /* Port Index (MAC_1 + n) */
858int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
859 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
860{
861 SK_U16 OldRxCmd;
862 SK_U16 RxCmd;
863
864 XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
865
866 RxCmd = OldRxCmd;
wdenk42d1f032003-10-15 23:53:47 +0000867
wdenk7152b1d2003-09-05 23:19:14 +0000868 switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
869 case SK_STRIP_FCS_ON:
870 RxCmd |= XM_RX_STRIP_FCS;
871 break;
872 case SK_STRIP_FCS_OFF:
873 RxCmd &= ~XM_RX_STRIP_FCS;
874 break;
875 }
876
877 switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
878 case SK_STRIP_PAD_ON:
879 RxCmd |= XM_RX_STRIP_PAD;
880 break;
881 case SK_STRIP_PAD_OFF:
882 RxCmd &= ~XM_RX_STRIP_PAD;
883 break;
884 }
885
886 switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
887 case SK_LENERR_OK_ON:
888 RxCmd |= XM_RX_LENERR_OK;
889 break;
890 case SK_LENERR_OK_OFF:
891 RxCmd &= ~XM_RX_LENERR_OK;
892 break;
893 }
894
895 switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
896 case SK_BIG_PK_OK_ON:
897 RxCmd |= XM_RX_BIG_PK_OK;
898 break;
899 case SK_BIG_PK_OK_OFF:
900 RxCmd &= ~XM_RX_BIG_PK_OK;
901 break;
902 }
903
904 switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
905 case SK_SELF_RX_ON:
906 RxCmd |= XM_RX_SELF_RX;
907 break;
908 case SK_SELF_RX_OFF:
909 RxCmd &= ~XM_RX_SELF_RX;
910 break;
911 }
912
913 /* Write the new mode to the Rx command register if required */
914 if (OldRxCmd != RxCmd) {
915 XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
916 }
917} /* SkXmSetRxCmd */
918
919
920/******************************************************************************
921 *
922 * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
923 *
924 * Description:
925 * The features
926 * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
927 * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
928 * for frames > 1514 bytes
929 * - enable Rx of own packets SK_SELF_RX_ON/OFF
930 *
931 * for incoming packets may be enabled/disabled by this function.
932 * Additional modes may be added later.
933 * Multiple modes can be enabled/disabled at the same time.
934 * The new configuration is written to the Rx Command register immediately.
935 *
936 * Returns:
937 * nothing
938 */
939static void SkGmSetRxCmd(
940SK_AC *pAC, /* adapter context */
941SK_IOC IoC, /* IO context */
942int Port, /* Port Index (MAC_1 + n) */
943int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
944 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
945{
946 SK_U16 OldRxCmd;
947 SK_U16 RxCmd;
948
949 if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
wdenk42d1f032003-10-15 23:53:47 +0000950
wdenk7152b1d2003-09-05 23:19:14 +0000951 GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
952
953 RxCmd = OldRxCmd;
954
955 if ((Mode & SK_STRIP_FCS_ON) != 0) {
956 RxCmd |= GM_RXCR_CRC_DIS;
957 }
958 else {
959 RxCmd &= ~GM_RXCR_CRC_DIS;
960 }
961 /* Write the new mode to the Rx control register if required */
962 if (OldRxCmd != RxCmd) {
963 GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
964 }
965 }
966
967 if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
wdenk42d1f032003-10-15 23:53:47 +0000968
wdenk7152b1d2003-09-05 23:19:14 +0000969 GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
970
971 RxCmd = OldRxCmd;
972
973 if ((Mode & SK_BIG_PK_OK_ON) != 0) {
974 RxCmd |= GM_SMOD_JUMBO_ENA;
975 }
976 else {
977 RxCmd &= ~GM_SMOD_JUMBO_ENA;
978 }
979 /* Write the new mode to the Rx control register if required */
980 if (OldRxCmd != RxCmd) {
981 GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
982 }
983 }
984} /* SkGmSetRxCmd */
985
986
987/******************************************************************************
988 *
989 * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
990 *
991 * Description: modifies the MAC's Rx Control reg. dep. on board type
992 *
993 * Returns:
994 * nothing
995 */
996void SkMacSetRxCmd(
997SK_AC *pAC, /* adapter context */
998SK_IOC IoC, /* IO context */
999int Port, /* Port Index (MAC_1 + n) */
1000int Mode) /* Rx Mode */
1001{
1002 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001003
wdenk7152b1d2003-09-05 23:19:14 +00001004 SkXmSetRxCmd(pAC, IoC, Port, Mode);
1005 }
1006 else {
wdenk42d1f032003-10-15 23:53:47 +00001007
wdenk7152b1d2003-09-05 23:19:14 +00001008 SkGmSetRxCmd(pAC, IoC, Port, Mode);
1009 }
1010} /* SkMacSetRxCmd */
1011
1012
1013/******************************************************************************
1014 *
1015 * SkMacCrcGener() - Enable / Disable CRC Generation
1016 *
1017 * Description: enables / disables CRC generation dep. on board type
1018 *
1019 * Returns:
1020 * nothing
1021 */
1022void SkMacCrcGener(
1023SK_AC *pAC, /* adapter context */
1024SK_IOC IoC, /* IO context */
1025int Port, /* Port Index (MAC_1 + n) */
1026SK_BOOL Enable) /* Enable / Disable */
1027{
1028 SK_U16 Word;
1029
1030 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001031
wdenk7152b1d2003-09-05 23:19:14 +00001032 XM_IN16(IoC, Port, XM_TX_CMD, &Word);
1033
1034 if (Enable) {
1035 Word &= ~XM_TX_NO_CRC;
1036 }
1037 else {
1038 Word |= XM_TX_NO_CRC;
1039 }
1040 /* setup Tx Command Register */
1041 XM_OUT16(pAC, Port, XM_TX_CMD, Word);
1042 }
1043 else {
wdenk42d1f032003-10-15 23:53:47 +00001044
wdenk7152b1d2003-09-05 23:19:14 +00001045 GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
wdenk42d1f032003-10-15 23:53:47 +00001046
wdenk7152b1d2003-09-05 23:19:14 +00001047 if (Enable) {
1048 Word &= ~GM_TXCR_CRC_DIS;
1049 }
1050 else {
1051 Word |= GM_TXCR_CRC_DIS;
1052 }
1053 /* setup Tx Control Register */
1054 GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
1055 }
1056} /* SkMacCrcGener*/
1057
1058#endif /* SK_DIAG */
1059
1060
1061/******************************************************************************
1062 *
1063 * SkXmClrExactAddr() - Clear Exact Match Address Registers
1064 *
1065 * Description:
1066 * All Exact Match Address registers of the XMAC 'Port' will be
1067 * cleared starting with 'StartNum' up to (and including) the
1068 * Exact Match address number of 'StopNum'.
1069 *
1070 * Returns:
1071 * nothing
1072 */
1073void SkXmClrExactAddr(
1074SK_AC *pAC, /* adapter context */
1075SK_IOC IoC, /* IO context */
1076int Port, /* Port Index (MAC_1 + n) */
1077int StartNum, /* Begin with this Address Register Index (0..15) */
1078int StopNum) /* Stop after finished with this Register Idx (0..15) */
1079{
1080 int i;
1081 SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
1082
1083 if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
1084 StartNum > StopNum) {
1085
1086 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
1087 return;
1088 }
1089
1090 for (i = StartNum; i <= StopNum; i++) {
1091 XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
1092 }
1093} /* SkXmClrExactAddr */
1094
1095
1096/******************************************************************************
1097 *
1098 * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
1099 *
1100 * Description:
1101 * Flush the transmit FIFO of the MAC specified by the index 'Port'
1102 *
1103 * Returns:
1104 * nothing
1105 */
1106void SkMacFlushTxFifo(
1107SK_AC *pAC, /* adapter context */
1108SK_IOC IoC, /* IO context */
1109int Port) /* Port Index (MAC_1 + n) */
1110{
1111 SK_U32 MdReg;
1112
1113 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001114
wdenk7152b1d2003-09-05 23:19:14 +00001115 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1116
1117 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
1118 }
1119 else {
1120 /* no way to flush the FIFO we have to issue a reset */
1121 /* TBD */
1122 }
1123} /* SkMacFlushTxFifo */
1124
1125
1126/******************************************************************************
1127 *
1128 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
1129 *
1130 * Description:
1131 * Flush the receive FIFO of the MAC specified by the index 'Port'
1132 *
1133 * Returns:
1134 * nothing
1135 */
1136void SkMacFlushRxFifo(
1137SK_AC *pAC, /* adapter context */
1138SK_IOC IoC, /* IO context */
1139int Port) /* Port Index (MAC_1 + n) */
1140{
1141 SK_U32 MdReg;
1142
1143 if (pAC->GIni.GIGenesis) {
1144
1145 XM_IN32(IoC, Port, XM_MODE, &MdReg);
1146
1147 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
1148 }
1149 else {
1150 /* no way to flush the FIFO we have to issue a reset */
1151 /* TBD */
1152 }
1153} /* SkMacFlushRxFifo */
1154
1155
1156/******************************************************************************
1157 *
1158 * SkXmSoftRst() - Do a XMAC software reset
1159 *
1160 * Description:
1161 * The PHY registers should not be destroyed during this
1162 * kind of software reset. Therefore the XMAC Software Reset
1163 * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
1164 *
1165 * The software reset is done by
1166 * - disabling the Rx and Tx state machine,
1167 * - resetting the statistics module,
1168 * - clear all other significant XMAC Mode,
1169 * Command, and Control Registers
1170 * - clearing the Hash Register and the
1171 * Exact Match Address registers, and
1172 * - flushing the XMAC's Rx and Tx FIFOs.
1173 *
1174 * Note:
1175 * Another requirement when stopping the XMAC is to
1176 * avoid sending corrupted frames on the network.
1177 * Disabling the Tx state machine will NOT interrupt
1178 * the currently transmitted frame. But we must take care
1179 * that the Tx FIFO is cleared AFTER the current frame
1180 * is complete sent to the network.
1181 *
1182 * It takes about 12ns to send a frame with 1538 bytes.
1183 * One PCI clock goes at least 15ns (66MHz). Therefore
1184 * after reading XM_GP_PORT back, we are sure that the
1185 * transmitter is disabled AND idle. And this means
1186 * we may flush the transmit FIFO now.
1187 *
1188 * Returns:
1189 * nothing
1190 */
1191static void SkXmSoftRst(
1192SK_AC *pAC, /* adapter context */
1193SK_IOC IoC, /* IO context */
1194int Port) /* Port Index (MAC_1 + n) */
1195{
1196 SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
wdenk42d1f032003-10-15 23:53:47 +00001197
wdenk7152b1d2003-09-05 23:19:14 +00001198 /* reset the statistics module */
1199 XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
1200
1201 /* disable all XMAC IRQs */
1202 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
wdenk42d1f032003-10-15 23:53:47 +00001203
wdenk7152b1d2003-09-05 23:19:14 +00001204 XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
wdenk42d1f032003-10-15 23:53:47 +00001205
wdenk7152b1d2003-09-05 23:19:14 +00001206 XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
1207 XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
wdenk42d1f032003-10-15 23:53:47 +00001208
wdenk7152b1d2003-09-05 23:19:14 +00001209 /* disable all PHY IRQs */
1210 switch (pAC->GIni.GP[Port].PhyType) {
1211 case SK_PHY_BCOM:
1212 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
1213 break;
1214#ifdef OTHER_PHY
1215 case SK_PHY_LONE:
1216 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
1217 break;
1218 case SK_PHY_NAT:
1219 /* todo: National
1220 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
1221 break;
1222#endif /* OTHER_PHY */
1223 }
1224
1225 /* clear the Hash Register */
1226 XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
1227
1228 /* clear the Exact Match Address registers */
1229 SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
wdenk42d1f032003-10-15 23:53:47 +00001230
wdenk7152b1d2003-09-05 23:19:14 +00001231 /* clear the Source Check Address registers */
1232 XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
1233
1234} /* SkXmSoftRst */
1235
1236
1237/******************************************************************************
1238 *
1239 * SkXmHardRst() - Do a XMAC hardware reset
1240 *
1241 * Description:
1242 * The XMAC of the specified 'Port' and all connected devices
1243 * (PHY and SERDES) will receive a reset signal on its *Reset pins.
1244 * External PHYs must be reset be clearing a bit in the GPIO register
1245 * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
1246 *
1247 * ATTENTION:
Wolfgang Denk53677ef2008-05-20 16:00:29 +02001248 * It is absolutely necessary to reset the SW_RST Bit first
wdenk7152b1d2003-09-05 23:19:14 +00001249 * before calling this function.
1250 *
1251 * Returns:
1252 * nothing
1253 */
1254static void SkXmHardRst(
1255SK_AC *pAC, /* adapter context */
1256SK_IOC IoC, /* IO context */
1257int Port) /* Port Index (MAC_1 + n) */
1258{
1259 SK_U32 Reg;
1260 int i;
1261 int TOut;
1262 SK_U16 Word;
1263
1264 for (i = 0; i < 4; i++) {
1265 /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
1266 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1267
1268 TOut = 0;
1269 do {
1270 if (TOut++ > 10000) {
1271 /*
1272 * Adapter seems to be in RESET state.
1273 * Registers cannot be written.
1274 */
1275 return;
1276 }
1277
1278 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
wdenk42d1f032003-10-15 23:53:47 +00001279
wdenk7152b1d2003-09-05 23:19:14 +00001280 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
wdenk42d1f032003-10-15 23:53:47 +00001281
wdenk7152b1d2003-09-05 23:19:14 +00001282 } while ((Word & MFF_SET_MAC_RST) == 0);
1283 }
1284
1285 /* For external PHYs there must be special handling */
1286 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
1287 /* reset external PHY */
1288 SK_IN32(IoC, B2_GP_IO, &Reg);
1289 if (Port == 0) {
1290 Reg |= GP_DIR_0; /* set to output */
1291 Reg &= ~GP_IO_0;
1292 }
1293 else {
1294 Reg |= GP_DIR_2; /* set to output */
1295 Reg &= ~GP_IO_2;
1296 }
1297 SK_OUT32(IoC, B2_GP_IO, Reg);
1298
1299 /* short delay */
1300 SK_IN32(IoC, B2_GP_IO, &Reg);
1301 }
1302
1303} /* SkXmHardRst */
1304
1305
1306/******************************************************************************
1307 *
1308 * SkGmSoftRst() - Do a GMAC software reset
1309 *
1310 * Description:
1311 * The GPHY registers should not be destroyed during this
1312 * kind of software reset.
1313 *
1314 * Returns:
1315 * nothing
1316 */
1317static void SkGmSoftRst(
1318SK_AC *pAC, /* adapter context */
1319SK_IOC IoC, /* IO context */
1320int Port) /* Port Index (MAC_1 + n) */
1321{
1322 SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
1323 SK_U16 RxCtrl;
1324
1325 /* reset the statistics module */
1326
1327 /* disable all GMAC IRQs */
1328 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
wdenk42d1f032003-10-15 23:53:47 +00001329
wdenk7152b1d2003-09-05 23:19:14 +00001330 /* disable all PHY IRQs */
1331 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
wdenk42d1f032003-10-15 23:53:47 +00001332
wdenk7152b1d2003-09-05 23:19:14 +00001333 /* clear the Hash Register */
1334 GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
1335
1336 /* Enable Unicast and Multicast filtering */
1337 GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
wdenk42d1f032003-10-15 23:53:47 +00001338
wdenk7152b1d2003-09-05 23:19:14 +00001339 GM_OUT16(IoC, Port, GM_RX_CTRL,
1340 RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
1341
1342} /* SkGmSoftRst */
1343
1344
1345/******************************************************************************
1346 *
1347 * SkGmHardRst() - Do a GMAC hardware reset
1348 *
1349 * Description:
1350 *
1351 * ATTENTION:
Wolfgang Denk53677ef2008-05-20 16:00:29 +02001352 * It is absolutely necessary to reset the SW_RST Bit first
wdenk7152b1d2003-09-05 23:19:14 +00001353 * before calling this function.
1354 *
1355 * Returns:
1356 * nothing
1357 */
1358static void SkGmHardRst(
1359SK_AC *pAC, /* adapter context */
1360SK_IOC IoC, /* IO context */
1361int Port) /* Port Index (MAC_1 + n) */
1362{
1363 /* set GPHY Control reset */
1364 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1365
1366 /* set GMAC Control reset */
1367 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1368
1369} /* SkGmHardRst */
1370
1371
1372/******************************************************************************
1373 *
1374 * SkMacSoftRst() - Do a MAC software reset
1375 *
1376 * Description: calls a MAC software reset routine dep. on board type
1377 *
1378 * Returns:
1379 * nothing
1380 */
1381void SkMacSoftRst(
1382SK_AC *pAC, /* adapter context */
1383SK_IOC IoC, /* IO context */
1384int Port) /* Port Index (MAC_1 + n) */
1385{
1386 SK_GEPORT *pPrt;
1387
1388 pPrt = &pAC->GIni.GP[Port];
1389
1390 /* disable receiver and transmitter */
1391 SkMacRxTxDisable(pAC, IoC, Port);
1392
1393 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001394
wdenk7152b1d2003-09-05 23:19:14 +00001395 SkXmSoftRst(pAC, IoC, Port);
1396 }
1397 else {
wdenk42d1f032003-10-15 23:53:47 +00001398
wdenk7152b1d2003-09-05 23:19:14 +00001399 SkGmSoftRst(pAC, IoC, Port);
1400 }
1401
1402 /* flush the MAC's Rx and Tx FIFOs */
1403 SkMacFlushTxFifo(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00001404
wdenk7152b1d2003-09-05 23:19:14 +00001405 SkMacFlushRxFifo(pAC, IoC, Port);
1406
1407 pPrt->PState = SK_PRT_STOP;
1408
1409} /* SkMacSoftRst */
1410
1411
1412/******************************************************************************
1413 *
1414 * SkMacHardRst() - Do a MAC hardware reset
1415 *
1416 * Description: calls a MAC hardware reset routine dep. on board type
1417 *
1418 * Returns:
1419 * nothing
1420 */
1421void SkMacHardRst(
1422SK_AC *pAC, /* adapter context */
1423SK_IOC IoC, /* IO context */
1424int Port) /* Port Index (MAC_1 + n) */
1425{
wdenk42d1f032003-10-15 23:53:47 +00001426
wdenk7152b1d2003-09-05 23:19:14 +00001427 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00001428
wdenk7152b1d2003-09-05 23:19:14 +00001429 SkXmHardRst(pAC, IoC, Port);
1430 }
1431 else {
wdenk42d1f032003-10-15 23:53:47 +00001432
wdenk7152b1d2003-09-05 23:19:14 +00001433 SkGmHardRst(pAC, IoC, Port);
1434 }
1435
1436 pAC->GIni.GP[Port].PState = SK_PRT_RESET;
1437
1438} /* SkMacHardRst */
1439
1440
wdenk7152b1d2003-09-05 23:19:14 +00001441/******************************************************************************
1442 *
1443 * SkXmInitMac() - Initialize the XMAC II
1444 *
1445 * Description:
1446 * Initialize the XMAC of the specified port.
1447 * The XMAC must be reset or stopped before calling this function.
1448 *
1449 * Note:
1450 * The XMAC's Rx and Tx state machine is still disabled when returning.
1451 *
1452 * Returns:
1453 * nothing
1454 */
1455void SkXmInitMac(
1456SK_AC *pAC, /* adapter context */
1457SK_IOC IoC, /* IO context */
1458int Port) /* Port Index (MAC_1 + n) */
1459{
1460 SK_GEPORT *pPrt;
1461 SK_U32 Reg;
1462 int i;
1463 SK_U16 SWord;
1464
1465 pPrt = &pAC->GIni.GP[Port];
1466
1467 if (pPrt->PState == SK_PRT_STOP) {
1468 /* Port State: SK_PRT_STOP */
1469 /* Verify that the reset bit is cleared */
1470 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1471
1472 if ((SWord & MFF_SET_MAC_RST) != 0) {
1473 /* PState does not match HW state */
1474 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1475 /* Correct it */
1476 pPrt->PState = SK_PRT_RESET;
1477 }
1478 }
1479
1480 if (pPrt->PState == SK_PRT_RESET) {
1481 /*
1482 * clear HW reset
1483 * Note: The SW reset is self clearing, therefore there is
1484 * nothing to do here.
1485 */
1486 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
1487
1488 /* Ensure that XMAC reset release is done (errata from LReinbold?) */
1489 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1490
1491 /* Clear PHY reset */
1492 if (pPrt->PhyType != SK_PHY_XMAC) {
1493
1494 SK_IN32(IoC, B2_GP_IO, &Reg);
wdenk42d1f032003-10-15 23:53:47 +00001495
wdenk7152b1d2003-09-05 23:19:14 +00001496 if (Port == 0) {
1497 Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */
1498 }
1499 else {
1500 Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */
1501 }
1502 SK_OUT32(IoC, B2_GP_IO, Reg);
1503
1504 /* Enable GMII interface */
1505 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
1506
1507 /* read Id from external PHY (all have the same address) */
1508 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1509
1510 /*
1511 * Optimize MDIO transfer by suppressing preamble.
1512 * Must be done AFTER first access to BCOM chip.
1513 */
1514 XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001515
wdenk7152b1d2003-09-05 23:19:14 +00001516 XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1517
1518 if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1519 /*
1520 * Workaround BCOM Errata for the C0 type.
1521 * Write magic patterns to reserved registers.
1522 */
1523 i = 0;
1524 while (BcomRegC0Hack[i].PhyReg != 0) {
1525 SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1526 BcomRegC0Hack[i].PhyVal);
1527 i++;
1528 }
1529 }
1530 else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1531 /*
1532 * Workaround BCOM Errata for the A1 type.
1533 * Write magic patterns to reserved registers.
1534 */
1535 i = 0;
1536 while (BcomRegA1Hack[i].PhyReg != 0) {
1537 SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1538 BcomRegA1Hack[i].PhyVal);
1539 i++;
1540 }
1541 }
1542
1543 /*
1544 * Workaround BCOM Errata (#10523) for all BCom PHYs.
1545 * Disable Power Management after reset.
1546 */
1547 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001548
wdenk7152b1d2003-09-05 23:19:14 +00001549 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1550 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
1551
1552 /* PHY LED initialization is done in SkGeXmitLED() */
1553 }
1554
1555 /* Dummy read the Interrupt source register */
1556 XM_IN16(IoC, Port, XM_ISRC, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001557
wdenk7152b1d2003-09-05 23:19:14 +00001558 /*
1559 * The auto-negotiation process starts immediately after
1560 * clearing the reset. The auto-negotiation process should be
1561 * started by the SIRQ, therefore stop it here immediately.
1562 */
1563 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1564
1565#if 0
1566 /* temp. code: enable signal detect */
1567 /* WARNING: do not override GMII setting above */
1568 XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1569#endif
1570 }
1571
1572 /*
1573 * configure the XMACs Station Address
1574 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1575 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1576 */
1577 for (i = 0; i < 3; i++) {
1578 /*
1579 * The following 2 statements are together endianess
1580 * independent. Remember this when changing.
1581 */
1582 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001583
wdenk7152b1d2003-09-05 23:19:14 +00001584 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1585 }
1586
1587 /* Tx Inter Packet Gap (XM_TX_IPG): use default */
1588 /* Tx High Water Mark (XM_TX_HI_WM): use default */
1589 /* Tx Low Water Mark (XM_TX_LO_WM): use default */
1590 /* Host Request Threshold (XM_HT_THR): use default */
1591 /* Rx Request Threshold (XM_RX_THR): use default */
1592 /* Rx Low Water Mark (XM_RX_LO_WM): use default */
1593
1594 /* configure Rx High Water Mark (XM_RX_HI_WM) */
1595 XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1596
1597 /* Configure Tx Request Threshold */
1598 SWord = SK_XM_THR_SL; /* for single port */
1599
1600 if (pAC->GIni.GIMacsFound > 1) {
1601 switch (pAC->GIni.GIPortUsage) {
1602 case SK_RED_LINK:
1603 SWord = SK_XM_THR_REDL; /* redundant link */
1604 break;
1605 case SK_MUL_LINK:
1606 SWord = SK_XM_THR_MULL; /* load balancing */
1607 break;
1608 case SK_JUMBO_LINK:
1609 SWord = SK_XM_THR_JUMBO; /* jumbo frames */
1610 break;
1611 default:
1612 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1613 break;
1614 }
1615 }
1616 XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1617
1618 /* setup register defaults for the Tx Command Register */
1619 XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1620
1621 /* setup register defaults for the Rx Command Register */
1622 SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1623
1624 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1625 SWord |= XM_RX_BIG_PK_OK;
1626 }
1627
1628 if (pPrt->PLinkModeConf == SK_LMODE_HALF) {
1629 /*
1630 * If in manual half duplex mode the other side might be in
1631 * full duplex mode, so ignore if a carrier extension is not seen
1632 * on frames received
1633 */
1634 SWord |= XM_RX_DIS_CEXT;
1635 }
wdenk42d1f032003-10-15 23:53:47 +00001636
wdenk7152b1d2003-09-05 23:19:14 +00001637 XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1638
1639 /*
1640 * setup register defaults for the Mode Register
1641 * - Don't strip error frames to avoid Store & Forward
1642 * on the Rx side.
1643 * - Enable 'Check Station Address' bit
1644 * - Enable 'Check Address Array' bit
1645 */
1646 XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1647
1648 /*
1649 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1650 * - Enable all bits excepting 'Octets Rx OK Low CntOv'
1651 * and 'Octets Rx OK Hi Cnt Ov'.
1652 */
1653 XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1654
1655 /*
1656 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1657 * - Enable all bits excepting 'Octets Tx OK Low CntOv'
1658 * and 'Octets Tx OK Hi Cnt Ov'.
1659 */
1660 XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1661
1662 /*
1663 * Do NOT init XMAC interrupt mask here.
1664 * All interrupts remain disable until link comes up!
1665 */
1666
1667 /*
1668 * Any additional configuration changes may be done now.
1669 * The last action is to enable the Rx and Tx state machine.
1670 * This should be done after the auto-negotiation process
1671 * has been completed successfully.
1672 */
1673} /* SkXmInitMac */
1674
1675/******************************************************************************
1676 *
1677 * SkGmInitMac() - Initialize the GMAC
1678 *
1679 * Description:
1680 * Initialize the GMAC of the specified port.
1681 * The GMAC must be reset or stopped before calling this function.
1682 *
1683 * Note:
1684 * The GMAC's Rx and Tx state machine is still disabled when returning.
1685 *
1686 * Returns:
1687 * nothing
1688 */
1689void SkGmInitMac(
1690SK_AC *pAC, /* adapter context */
1691SK_IOC IoC, /* IO context */
1692int Port) /* Port Index (MAC_1 + n) */
1693{
1694 SK_GEPORT *pPrt;
1695 int i;
1696 SK_U16 SWord;
1697 SK_U32 DWord;
1698
1699 pPrt = &pAC->GIni.GP[Port];
1700
1701 if (pPrt->PState == SK_PRT_STOP) {
1702 /* Port State: SK_PRT_STOP */
1703 /* Verify that the reset bit is cleared */
1704 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
wdenk42d1f032003-10-15 23:53:47 +00001705
wdenk7152b1d2003-09-05 23:19:14 +00001706 if ((DWord & GMC_RST_SET) != 0) {
1707 /* PState does not match HW state */
1708 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1709 /* Correct it */
1710 pPrt->PState = SK_PRT_RESET;
1711 }
1712 }
1713
1714 if (pPrt->PState == SK_PRT_RESET) {
1715 /* set GPHY Control reset */
1716 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
1717
1718 /* set GMAC Control reset */
1719 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1720
1721 /* clear GMAC Control reset */
1722 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
1723
1724 /* set GMAC Control reset */
1725 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
1726
1727 /* set HWCFG_MODE */
1728 DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
1729 GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
1730 (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
1731 GPC_HWCFG_GMII_FIB);
1732
1733 /* set GPHY Control reset */
1734 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
1735
1736 /* release GPHY Control reset */
1737 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
1738
1739 /* clear GMAC Control reset */
1740 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
1741
1742 /* Dummy read the Interrupt source register */
1743 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001744
wdenk7152b1d2003-09-05 23:19:14 +00001745#ifndef VCPU
1746 /* read Id from PHY */
1747 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
wdenk42d1f032003-10-15 23:53:47 +00001748
wdenk7152b1d2003-09-05 23:19:14 +00001749 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1750#endif /* VCPU */
1751 }
1752
1753 (void)SkGmResetCounter(pAC, IoC, Port);
1754
1755 SWord = 0;
1756
1757 /* speed settings */
1758 switch (pPrt->PLinkSpeed) {
1759 case SK_LSPEED_AUTO:
1760 case SK_LSPEED_1000MBPS:
1761 SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1762 break;
1763 case SK_LSPEED_100MBPS:
1764 SWord |= GM_GPCR_SPEED_100;
1765 break;
1766 case SK_LSPEED_10MBPS:
1767 break;
1768 }
wdenk42d1f032003-10-15 23:53:47 +00001769
wdenk7152b1d2003-09-05 23:19:14 +00001770 /* duplex settings */
1771 if (pPrt->PLinkMode != SK_LMODE_HALF) {
1772 /* set full duplex */
1773 SWord |= GM_GPCR_DUP_FULL;
1774 }
1775
1776 /* flow control settings */
1777 switch (pPrt->PFlowCtrlMode) {
1778 case SK_FLOW_MODE_NONE:
1779 /* disable auto-negotiation for flow-control */
1780 SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS;
1781 break;
1782 case SK_FLOW_MODE_LOC_SEND:
1783 SWord |= GM_GPCR_FC_RX_DIS;
1784 break;
1785 case SK_FLOW_MODE_SYMMETRIC:
1786 /* TBD */
1787 case SK_FLOW_MODE_SYM_OR_REM:
1788 /* enable auto-negotiation for flow-control and */
1789 /* enable Rx and Tx of pause frames */
1790 break;
1791 }
1792
1793 /* Auto-negotiation ? */
1794 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1795 /* disable auto-update for speed, duplex and flow-control */
1796 SWord |= GM_GPCR_AU_ALL_DIS;
1797 }
wdenk42d1f032003-10-15 23:53:47 +00001798
wdenk7152b1d2003-09-05 23:19:14 +00001799 /* setup General Purpose Control Register */
1800 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1801
1802 /* setup Transmit Control Register */
1803 GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR);
1804
1805 /* setup Receive Control Register */
1806 GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1807 GM_RXCR_CRC_DIS);
1808
1809 /* setup Transmit Flow Control Register */
1810 GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1811
1812 /* setup Transmit Parameter Register */
1813#ifdef VCPU
1814 GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1815#endif /* VCPU */
1816
1817 SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26);
wdenk42d1f032003-10-15 23:53:47 +00001818
wdenk7152b1d2003-09-05 23:19:14 +00001819 GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1820
1821 /* configure the Serial Mode Register */
1822#ifdef VCPU
1823 GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1824#endif /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00001825
wdenk7152b1d2003-09-05 23:19:14 +00001826 SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH;
1827
1828 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1829 /* enable jumbo mode (Max. Frame Length = 9018) */
1830 SWord |= GM_SMOD_JUMBO_ENA;
1831 }
wdenk42d1f032003-10-15 23:53:47 +00001832
wdenk7152b1d2003-09-05 23:19:14 +00001833 GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
wdenk42d1f032003-10-15 23:53:47 +00001834
wdenk7152b1d2003-09-05 23:19:14 +00001835 /*
1836 * configure the GMACs Station Addresses
1837 * in PROM you can find our addresses at:
1838 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1839 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1840 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1841 */
1842
1843 for (i = 0; i < 3; i++) {
1844 /*
1845 * The following 2 statements are together endianess
1846 * independent. Remember this when changing.
1847 */
1848 /* physical address: will be used for pause frames */
1849 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1850
1851#ifdef WA_DEV_16
1852 /* WA for deviation #16 */
1853 if (pAC->GIni.GIChipRev == 0) {
1854 /* swap the address bytes */
1855 SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
1856
1857 /* write to register in reversed order */
1858 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
1859 }
1860 else {
1861 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1862 }
wdenk42d1f032003-10-15 23:53:47 +00001863#else
wdenk7152b1d2003-09-05 23:19:14 +00001864 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1865#endif /* WA_DEV_16 */
wdenk42d1f032003-10-15 23:53:47 +00001866
wdenk7152b1d2003-09-05 23:19:14 +00001867 /* virtual address: will be used for data */
1868 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
1869
1870 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
wdenk42d1f032003-10-15 23:53:47 +00001871
wdenk7152b1d2003-09-05 23:19:14 +00001872 /* reset Multicast filtering Hash registers 1-3 */
1873 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
1874 }
1875
1876 /* reset Multicast filtering Hash register 4 */
1877 GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
1878
1879 /* enable interrupt mask for counter overflows */
1880 GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
1881 GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
1882 GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
1883
1884 /* read General Purpose Status */
1885 GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
wdenk42d1f032003-10-15 23:53:47 +00001886
wdenk7152b1d2003-09-05 23:19:14 +00001887 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1888 ("MAC Stat Reg=0x%04X\n", SWord));
1889
1890#ifdef SK_DIAG
1891 c_print("MAC Stat Reg=0x%04X\n", SWord);
1892#endif /* SK_DIAG */
1893
1894} /* SkGmInitMac */
1895
1896
1897/******************************************************************************
1898 *
1899 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1900 *
1901 * Description:
1902 * This function initializes the XMACs Duplex Mode.
1903 * It should be called after successfully finishing
1904 * the Auto-negotiation Process
1905 *
1906 * Returns:
1907 * nothing
1908 */
1909void SkXmInitDupMd(
1910SK_AC *pAC, /* adapter context */
1911SK_IOC IoC, /* IO context */
1912int Port) /* Port Index (MAC_1 + n) */
1913{
1914 switch (pAC->GIni.GP[Port].PLinkModeStatus) {
1915 case SK_LMODE_STAT_AUTOHALF:
1916 case SK_LMODE_STAT_HALF:
1917 /* Configuration Actions for Half Duplex Mode */
1918 /*
1919 * XM_BURST = default value. We are probable not quick
Wolfgang Denk53677ef2008-05-20 16:00:29 +02001920 * enough at the 'XMAC' bus to burst 8kB.
wdenk7152b1d2003-09-05 23:19:14 +00001921 * The XMAC stops bursting if no transmit frames
1922 * are available or the burst limit is exceeded.
1923 */
1924 /* XM_TX_RT_LIM = default value (15) */
1925 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
1926 break;
1927 case SK_LMODE_STAT_AUTOFULL:
1928 case SK_LMODE_STAT_FULL:
1929 /* Configuration Actions for Full Duplex Mode */
1930 /*
1931 * The duplex mode is configured by the PHY,
1932 * therefore it seems to be that there is nothing
1933 * to do here.
1934 */
1935 break;
1936 case SK_LMODE_STAT_UNKNOWN:
1937 default:
1938 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
1939 break;
1940 }
1941} /* SkXmInitDupMd */
1942
1943
1944/******************************************************************************
1945 *
1946 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1947 *
1948 * Description:
1949 * This function initializes the Pause Mode which should
1950 * be used for this port.
1951 * It should be called after successfully finishing
1952 * the Auto-negotiation Process
1953 *
1954 * Returns:
1955 * nothing
1956 */
1957void SkXmInitPauseMd(
1958SK_AC *pAC, /* adapter context */
1959SK_IOC IoC, /* IO context */
1960int Port) /* Port Index (MAC_1 + n) */
1961{
1962 SK_GEPORT *pPrt;
1963 SK_U32 DWord;
1964 SK_U16 Word;
1965
1966 pPrt = &pAC->GIni.GP[Port];
1967
1968 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
wdenk42d1f032003-10-15 23:53:47 +00001969
wdenk7152b1d2003-09-05 23:19:14 +00001970 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
1971 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1972
1973 /* Disable Pause Frame Reception */
1974 Word |= XM_MMU_IGN_PF;
1975 }
1976 else {
1977 /*
1978 * enabling pause frame reception is required for 1000BT
1979 * because the XMAC is not reset if the link is going down
1980 */
1981 /* Enable Pause Frame Reception */
1982 Word &= ~XM_MMU_IGN_PF;
wdenk42d1f032003-10-15 23:53:47 +00001983 }
1984
wdenk7152b1d2003-09-05 23:19:14 +00001985 XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
1986
1987 XM_IN32(IoC, Port, XM_MODE, &DWord);
1988
1989 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
1990 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1991
1992 /*
1993 * Configure Pause Frame Generation
1994 * Use internal and external Pause Frame Generation.
1995 * Sending pause frames is edge triggered.
1996 * Send a Pause frame with the maximum pause time if
1997 * internal oder external FIFO full condition occurs.
1998 * Send a zero pause time frame to re-start transmission.
1999 */
2000
2001 /* XM_PAUSE_DA = '010000C28001' (default) */
2002
2003 /* XM_MAC_PTIME = 0xffff (maximum) */
2004 /* remember this value is defined in big endian (!) */
2005 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
2006
2007 /* Set Pause Mode in Mode Register */
2008 DWord |= XM_PAUSE_MODE;
2009
2010 /* Set Pause Mode in MAC Rx FIFO */
2011 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
2012 }
2013 else {
2014 /*
2015 * disable pause frame generation is required for 1000BT
2016 * because the XMAC is not reset if the link is going down
2017 */
2018 /* Disable Pause Mode in Mode Register */
2019 DWord &= ~XM_PAUSE_MODE;
2020
2021 /* Disable Pause Mode in MAC Rx FIFO */
2022 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
2023 }
wdenk42d1f032003-10-15 23:53:47 +00002024
wdenk7152b1d2003-09-05 23:19:14 +00002025 XM_OUT32(IoC, Port, XM_MODE, DWord);
2026} /* SkXmInitPauseMd*/
2027
2028
2029/******************************************************************************
2030 *
2031 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
2032 *
2033 * Description: initializes all the XMACs Phy registers
2034 *
2035 * Note:
2036 *
2037 * Returns:
2038 * nothing
2039 */
2040static void SkXmInitPhyXmac(
2041SK_AC *pAC, /* adapter context */
2042SK_IOC IoC, /* IO context */
2043int Port, /* Port Index (MAC_1 + n) */
2044SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2045{
2046 SK_GEPORT *pPrt;
2047 SK_U16 Ctrl;
2048
2049 pPrt = &pAC->GIni.GP[Port];
2050 Ctrl = 0;
wdenk42d1f032003-10-15 23:53:47 +00002051
wdenk7152b1d2003-09-05 23:19:14 +00002052 /* Auto-negotiation ? */
2053 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2054 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2055 ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
2056 /* Set DuplexMode in Config register */
2057 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2058 Ctrl |= PHY_CT_DUP_MD;
2059 }
2060
2061 /*
2062 * Do NOT enable Auto-negotiation here. This would hold
2063 * the link down because no IDLEs are transmitted
2064 */
2065 }
2066 else {
2067 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2068 ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
2069 /* Set Auto-negotiation advertisement */
2070
2071 /* Set Full/half duplex capabilities */
2072 switch (pPrt->PLinkMode) {
2073 case SK_LMODE_AUTOHALF:
2074 Ctrl |= PHY_X_AN_HD;
2075 break;
2076 case SK_LMODE_AUTOFULL:
2077 Ctrl |= PHY_X_AN_FD;
2078 break;
2079 case SK_LMODE_AUTOBOTH:
2080 Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
2081 break;
2082 default:
2083 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2084 SKERR_HWI_E015MSG);
2085 }
2086
2087 switch (pPrt->PFlowCtrlMode) {
2088 case SK_FLOW_MODE_NONE:
2089 Ctrl |= PHY_X_P_NO_PAUSE;
2090 break;
2091 case SK_FLOW_MODE_LOC_SEND:
2092 Ctrl |= PHY_X_P_ASYM_MD;
2093 break;
2094 case SK_FLOW_MODE_SYMMETRIC:
2095 Ctrl |= PHY_X_P_SYM_MD;
2096 break;
2097 case SK_FLOW_MODE_SYM_OR_REM:
2098 Ctrl |= PHY_X_P_BOTH_MD;
2099 break;
2100 default:
2101 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2102 SKERR_HWI_E016MSG);
2103 }
2104
2105 /* Write AutoNeg Advertisement Register */
2106 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
2107
2108 /* Restart Auto-negotiation */
2109 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
2110 }
2111
2112 if (DoLoop) {
2113 /* Set the Phy Loopback bit, too */
2114 Ctrl |= PHY_CT_LOOP;
2115 }
2116
2117 /* Write to the Phy control register */
2118 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
2119} /* SkXmInitPhyXmac */
2120
2121
2122/******************************************************************************
2123 *
2124 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
2125 *
2126 * Description: initializes all the Broadcom Phy registers
2127 *
2128 * Note:
2129 *
2130 * Returns:
2131 * nothing
2132 */
2133static void SkXmInitPhyBcom(
2134SK_AC *pAC, /* adapter context */
2135SK_IOC IoC, /* IO context */
2136int Port, /* Port Index (MAC_1 + n) */
2137SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2138{
2139 SK_GEPORT *pPrt;
2140 SK_U16 Ctrl1;
2141 SK_U16 Ctrl2;
2142 SK_U16 Ctrl3;
2143 SK_U16 Ctrl4;
2144 SK_U16 Ctrl5;
2145
2146 Ctrl1 = PHY_CT_SP1000;
2147 Ctrl2 = 0;
2148 Ctrl3 = PHY_SEL_TYPE;
2149 Ctrl4 = PHY_B_PEC_EN_LTR;
2150 Ctrl5 = PHY_B_AC_TX_TST;
2151
2152 pPrt = &pAC->GIni.GP[Port];
2153
2154 /* manually Master/Slave ? */
2155 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2156 Ctrl2 |= PHY_B_1000C_MSE;
wdenk42d1f032003-10-15 23:53:47 +00002157
wdenk7152b1d2003-09-05 23:19:14 +00002158 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2159 Ctrl2 |= PHY_B_1000C_MSC;
2160 }
2161 }
2162 /* Auto-negotiation ? */
2163 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2164 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2165 ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
2166 /* Set DuplexMode in Config register */
2167 Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2168
2169 /* Determine Master/Slave manually if not already done */
2170 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2171 Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
2172 }
2173
2174 /*
2175 * Do NOT enable Auto-negotiation here. This would hold
2176 * the link down because no IDLES are transmitted
2177 */
2178 }
2179 else {
2180 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2181 ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
2182 /* Set Auto-negotiation advertisement */
2183
2184 /*
2185 * Workaround BCOM Errata #1 for the C5 type.
2186 * 1000Base-T Link Acquisition Failure in Slave Mode
2187 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
2188 */
2189 Ctrl2 |= PHY_B_1000C_RD;
wdenk42d1f032003-10-15 23:53:47 +00002190
wdenk7152b1d2003-09-05 23:19:14 +00002191 /* Set Full/half duplex capabilities */
2192 switch (pPrt->PLinkMode) {
2193 case SK_LMODE_AUTOHALF:
2194 Ctrl2 |= PHY_B_1000C_AHD;
2195 break;
2196 case SK_LMODE_AUTOFULL:
2197 Ctrl2 |= PHY_B_1000C_AFD;
2198 break;
2199 case SK_LMODE_AUTOBOTH:
2200 Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
2201 break;
2202 default:
2203 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2204 SKERR_HWI_E015MSG);
2205 }
2206
2207 switch (pPrt->PFlowCtrlMode) {
2208 case SK_FLOW_MODE_NONE:
2209 Ctrl3 |= PHY_B_P_NO_PAUSE;
2210 break;
2211 case SK_FLOW_MODE_LOC_SEND:
2212 Ctrl3 |= PHY_B_P_ASYM_MD;
2213 break;
2214 case SK_FLOW_MODE_SYMMETRIC:
2215 Ctrl3 |= PHY_B_P_SYM_MD;
2216 break;
2217 case SK_FLOW_MODE_SYM_OR_REM:
2218 Ctrl3 |= PHY_B_P_BOTH_MD;
2219 break;
2220 default:
2221 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2222 SKERR_HWI_E016MSG);
2223 }
2224
2225 /* Restart Auto-negotiation */
2226 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2227 }
wdenk42d1f032003-10-15 23:53:47 +00002228
wdenk7152b1d2003-09-05 23:19:14 +00002229 /* Initialize LED register here? */
2230 /* No. Please do it in SkDgXmitLed() (if required) and swap
2231 init order of LEDs and XMAC. (MAl) */
wdenk42d1f032003-10-15 23:53:47 +00002232
wdenk7152b1d2003-09-05 23:19:14 +00002233 /* Write 1000Base-T Control Register */
2234 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2235 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2236 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
wdenk42d1f032003-10-15 23:53:47 +00002237
wdenk7152b1d2003-09-05 23:19:14 +00002238 /* Write AutoNeg Advertisement Register */
2239 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2240 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2241 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
wdenk42d1f032003-10-15 23:53:47 +00002242
wdenk7152b1d2003-09-05 23:19:14 +00002243 if (DoLoop) {
2244 /* Set the Phy Loopback bit, too */
2245 Ctrl1 |= PHY_CT_LOOP;
2246 }
2247
2248 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2249 /* configure FIFO to high latency for transmission of ext. packets */
2250 Ctrl4 |= PHY_B_PEC_HIGH_LA;
2251
2252 /* configure reception of extended packets */
2253 Ctrl5 |= PHY_B_AC_LONG_PACK;
2254
2255 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2256 }
2257
2258 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2259 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
wdenk42d1f032003-10-15 23:53:47 +00002260
wdenk7152b1d2003-09-05 23:19:14 +00002261 /* Write to the Phy control register */
2262 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2263 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2264 ("PHY Control Reg=0x%04X\n", Ctrl1));
2265} /* SkXmInitPhyBcom */
2266
2267
2268/******************************************************************************
2269 *
2270 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2271 *
2272 * Description: initializes all the Marvell Phy registers
2273 *
2274 * Note:
2275 *
2276 * Returns:
2277 * nothing
2278 */
2279static void SkGmInitPhyMarv(
2280SK_AC *pAC, /* adapter context */
2281SK_IOC IoC, /* IO context */
2282int Port, /* Port Index (MAC_1 + n) */
2283SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2284{
2285 SK_GEPORT *pPrt;
2286 SK_U16 PhyCtrl;
2287 SK_U16 C1000BaseT;
2288 SK_U16 AutoNegAdv;
2289 SK_U16 ExtPhyCtrl;
2290 SK_U16 PhyStat;
2291 SK_U16 PhyStat1;
2292 SK_U16 PhySpecStat;
2293 SK_U16 LedCtrl;
2294 SK_BOOL AutoNeg;
2295
2296#ifdef VCPU
2297 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2298 Port, DoLoop);
2299#else /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00002300
wdenk7152b1d2003-09-05 23:19:14 +00002301 pPrt = &pAC->GIni.GP[Port];
2302
2303 /* Auto-negotiation ? */
2304 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2305 AutoNeg = SK_FALSE;
2306 }
2307 else {
2308 AutoNeg = SK_TRUE;
2309 }
wdenk42d1f032003-10-15 23:53:47 +00002310
wdenk7152b1d2003-09-05 23:19:14 +00002311 if (!DoLoop) {
2312 /* Read Ext. PHY Specific Control */
2313 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
wdenk42d1f032003-10-15 23:53:47 +00002314
wdenk7152b1d2003-09-05 23:19:14 +00002315 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2316 PHY_M_EC_MAC_S_MSK);
wdenk42d1f032003-10-15 23:53:47 +00002317
wdenk7152b1d2003-09-05 23:19:14 +00002318 ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) |
2319 PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
wdenk42d1f032003-10-15 23:53:47 +00002320
wdenk7152b1d2003-09-05 23:19:14 +00002321 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2322 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2323 ("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl));
wdenk42d1f032003-10-15 23:53:47 +00002324
wdenk7152b1d2003-09-05 23:19:14 +00002325 /* Read PHY Control */
2326 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
wdenk42d1f032003-10-15 23:53:47 +00002327
wdenk7152b1d2003-09-05 23:19:14 +00002328 /* Assert software reset */
2329 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL,
2330 (SK_U16)(PhyCtrl | PHY_CT_RESET));
2331 }
2332#endif /* VCPU */
2333
2334 PhyCtrl = 0 /* PHY_CT_COL_TST */;
2335 C1000BaseT = 0;
2336 AutoNegAdv = PHY_SEL_TYPE;
2337
2338 /* manually Master/Slave ? */
2339 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2340 /* enable Manual Master/Slave */
2341 C1000BaseT |= PHY_M_1000C_MSE;
wdenk42d1f032003-10-15 23:53:47 +00002342
wdenk7152b1d2003-09-05 23:19:14 +00002343 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2344 C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
2345 }
2346 }
wdenk42d1f032003-10-15 23:53:47 +00002347
wdenk7152b1d2003-09-05 23:19:14 +00002348 /* Auto-negotiation ? */
2349 if (!AutoNeg) {
2350 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2351 ("InitPhyMarv: no auto-negotiation Port %d\n", Port));
wdenk42d1f032003-10-15 23:53:47 +00002352
wdenk7152b1d2003-09-05 23:19:14 +00002353 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2354 /* Set Full Duplex Mode */
2355 PhyCtrl |= PHY_CT_DUP_MD;
2356 }
2357
2358 /* Set Master/Slave manually if not already done */
2359 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2360 C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
2361 }
2362
2363 /* Set Speed */
2364 switch (pPrt->PLinkSpeed) {
2365 case SK_LSPEED_AUTO:
2366 case SK_LSPEED_1000MBPS:
2367 PhyCtrl |= PHY_CT_SP1000;
2368 break;
2369 case SK_LSPEED_100MBPS:
2370 PhyCtrl |= PHY_CT_SP100;
2371 break;
2372 case SK_LSPEED_10MBPS:
2373 break;
2374 default:
2375 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2376 SKERR_HWI_E019MSG);
2377 }
2378
2379 if (!DoLoop) {
2380 PhyCtrl |= PHY_CT_RESET;
2381 }
2382 /*
2383 * Do NOT enable Auto-negotiation here. This would hold
2384 * the link down because no IDLES are transmitted
2385 */
2386 }
2387 else {
2388 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2389 ("InitPhyMarv: with auto-negotiation Port %d\n", Port));
wdenk42d1f032003-10-15 23:53:47 +00002390
wdenk7152b1d2003-09-05 23:19:14 +00002391 PhyCtrl |= PHY_CT_ANE;
wdenk42d1f032003-10-15 23:53:47 +00002392
wdenk7152b1d2003-09-05 23:19:14 +00002393 if (pAC->GIni.GICopperType) {
2394 /* Set Speed capabilities */
2395 switch (pPrt->PLinkSpeed) {
2396 case SK_LSPEED_AUTO:
2397 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2398 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2399 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2400 break;
2401 case SK_LSPEED_1000MBPS:
2402 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2403 break;
2404 case SK_LSPEED_100MBPS:
2405 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2406 PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2407 break;
2408 case SK_LSPEED_10MBPS:
2409 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2410 break;
2411 default:
2412 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2413 SKERR_HWI_E019MSG);
2414 }
2415
2416 /* Set Full/half duplex capabilities */
2417 switch (pPrt->PLinkMode) {
2418 case SK_LMODE_AUTOHALF:
2419 C1000BaseT &= ~PHY_M_1000C_AFD;
2420 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2421 break;
2422 case SK_LMODE_AUTOFULL:
2423 C1000BaseT &= ~PHY_M_1000C_AHD;
2424 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2425 break;
2426 case SK_LMODE_AUTOBOTH:
2427 break;
2428 default:
2429 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2430 SKERR_HWI_E015MSG);
2431 }
wdenk42d1f032003-10-15 23:53:47 +00002432
wdenk7152b1d2003-09-05 23:19:14 +00002433 /* Set Auto-negotiation advertisement */
2434 switch (pPrt->PFlowCtrlMode) {
2435 case SK_FLOW_MODE_NONE:
2436 AutoNegAdv |= PHY_B_P_NO_PAUSE;
2437 break;
2438 case SK_FLOW_MODE_LOC_SEND:
2439 AutoNegAdv |= PHY_B_P_ASYM_MD;
2440 break;
2441 case SK_FLOW_MODE_SYMMETRIC:
2442 AutoNegAdv |= PHY_B_P_SYM_MD;
2443 break;
2444 case SK_FLOW_MODE_SYM_OR_REM:
2445 AutoNegAdv |= PHY_B_P_BOTH_MD;
2446 break;
2447 default:
2448 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2449 SKERR_HWI_E016MSG);
2450 }
2451 }
2452 else { /* special defines for FIBER (88E1011S only) */
wdenk42d1f032003-10-15 23:53:47 +00002453
wdenk7152b1d2003-09-05 23:19:14 +00002454 /* Set Full/half duplex capabilities */
2455 switch (pPrt->PLinkMode) {
2456 case SK_LMODE_AUTOHALF:
2457 AutoNegAdv |= PHY_M_AN_1000X_AHD;
2458 break;
2459 case SK_LMODE_AUTOFULL:
2460 AutoNegAdv |= PHY_M_AN_1000X_AFD;
2461 break;
2462 case SK_LMODE_AUTOBOTH:
2463 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2464 break;
2465 default:
2466 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2467 SKERR_HWI_E015MSG);
2468 }
wdenk42d1f032003-10-15 23:53:47 +00002469
wdenk7152b1d2003-09-05 23:19:14 +00002470 /* Set Auto-negotiation advertisement */
2471 switch (pPrt->PFlowCtrlMode) {
2472 case SK_FLOW_MODE_NONE:
2473 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2474 break;
2475 case SK_FLOW_MODE_LOC_SEND:
2476 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2477 break;
2478 case SK_FLOW_MODE_SYMMETRIC:
2479 AutoNegAdv |= PHY_M_P_SYM_MD_X;
2480 break;
2481 case SK_FLOW_MODE_SYM_OR_REM:
2482 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2483 break;
2484 default:
2485 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2486 SKERR_HWI_E016MSG);
2487 }
2488 }
2489
2490 if (!DoLoop) {
2491 /* Restart Auto-negotiation */
2492 PhyCtrl |= PHY_CT_RE_CFG;
2493 }
2494 }
wdenk42d1f032003-10-15 23:53:47 +00002495
wdenk7152b1d2003-09-05 23:19:14 +00002496#ifdef VCPU
2497 /*
2498 * E-mail from Gu Lin (08-03-2002):
2499 */
wdenk42d1f032003-10-15 23:53:47 +00002500
wdenk7152b1d2003-09-05 23:19:14 +00002501 /* Program PHY register 30 as 16'h0708 for simulation speed up */
2502 SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708);
wdenk42d1f032003-10-15 23:53:47 +00002503
wdenk7152b1d2003-09-05 23:19:14 +00002504 VCpuWait(2000);
2505
2506#else /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00002507
wdenk7152b1d2003-09-05 23:19:14 +00002508 /* Write 1000Base-T Control Register */
2509 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2510 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2511 ("1000B-T Ctrl=0x%04X\n", C1000BaseT));
wdenk42d1f032003-10-15 23:53:47 +00002512
wdenk7152b1d2003-09-05 23:19:14 +00002513 /* Write AutoNeg Advertisement Register */
2514 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2515 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2516 ("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv));
2517#endif /* VCPU */
wdenk42d1f032003-10-15 23:53:47 +00002518
wdenk7152b1d2003-09-05 23:19:14 +00002519 if (DoLoop) {
2520 /* Set the PHY Loopback bit */
2521 PhyCtrl |= PHY_CT_LOOP;
2522
2523 /* Program PHY register 16 as 16'h0400 to force link good */
2524 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2525
2526#if 0
2527 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2528 /* Write Ext. PHY Specific Control */
2529 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2530 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2531 }
2532 }
2533 else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2534 /* Write PHY Specific Control */
2535 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK);
2536 }
2537#endif /* 0 */
2538 }
2539
2540 /* Write to the PHY Control register */
2541 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2542
2543#ifdef VCPU
2544 VCpuWait(2000);
2545#else
2546
2547 LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2548
2549#ifdef ACT_LED_BLINK
2550 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2551#endif /* ACT_LED_BLINK */
2552
2553#ifdef DUP_LED_NORMAL
2554 LedCtrl |= PHY_M_LEDC_DP_CTRL;
2555#endif /* DUP_LED_NORMAL */
2556
2557 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2558
2559#endif /* VCPU */
2560
2561#ifdef SK_DIAG
2562 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2563 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2564 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2565 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2566#endif /* SK_DIAG */
2567
2568#ifndef xDEBUG
2569 /* Read PHY Control */
2570 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2571 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2572 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
wdenk42d1f032003-10-15 23:53:47 +00002573
wdenk7152b1d2003-09-05 23:19:14 +00002574 /* Read 1000Base-T Control Register */
2575 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2576 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2577 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
wdenk42d1f032003-10-15 23:53:47 +00002578
wdenk7152b1d2003-09-05 23:19:14 +00002579 /* Read AutoNeg Advertisement Register */
2580 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2581 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2582 ("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv));
wdenk42d1f032003-10-15 23:53:47 +00002583
wdenk7152b1d2003-09-05 23:19:14 +00002584 /* Read Ext. PHY Specific Control */
2585 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2586 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2587 ("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl));
wdenk42d1f032003-10-15 23:53:47 +00002588
wdenk7152b1d2003-09-05 23:19:14 +00002589 /* Read PHY Status */
2590 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2591 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2592 ("PHY Stat Reg.=0x%04X\n", PhyStat));
2593 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2594 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2595 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
wdenk42d1f032003-10-15 23:53:47 +00002596
wdenk7152b1d2003-09-05 23:19:14 +00002597 /* Read PHY Specific Status */
2598 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2599 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2600 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
2601#endif /* DEBUG */
2602
2603#ifdef SK_DIAG
2604 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2605 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2606 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2607 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2608 c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2609 c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2610 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2611#endif /* SK_DIAG */
2612
2613} /* SkGmInitPhyMarv */
2614
2615
2616#ifdef OTHER_PHY
2617/******************************************************************************
2618 *
2619 * SkXmInitPhyLone() - Initialize the Level One Phy registers
2620 *
2621 * Description: initializes all the Level One Phy registers
2622 *
2623 * Note:
2624 *
2625 * Returns:
2626 * nothing
2627 */
2628static void SkXmInitPhyLone(
2629SK_AC *pAC, /* adapter context */
2630SK_IOC IoC, /* IO context */
2631int Port, /* Port Index (MAC_1 + n) */
2632SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2633{
2634 SK_GEPORT *pPrt;
2635 SK_U16 Ctrl1;
2636 SK_U16 Ctrl2;
2637 SK_U16 Ctrl3;
2638
2639 Ctrl1 = PHY_CT_SP1000;
2640 Ctrl2 = 0;
2641 Ctrl3 = PHY_SEL_TYPE;
2642
2643 pPrt = &pAC->GIni.GP[Port];
2644
2645 /* manually Master/Slave ? */
2646 if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2647 Ctrl2 |= PHY_L_1000C_MSE;
wdenk42d1f032003-10-15 23:53:47 +00002648
wdenk7152b1d2003-09-05 23:19:14 +00002649 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2650 Ctrl2 |= PHY_L_1000C_MSC;
2651 }
2652 }
2653 /* Auto-negotiation ? */
2654 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2655 /*
2656 * level one spec say: "1000Mbps: manual mode not allowed"
2657 * but lets see what happens...
2658 */
2659 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2660 ("InitPhyLone: no auto-negotiation Port %d\n", Port));
2661 /* Set DuplexMode in Config register */
2662 Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
2663
2664 /* Determine Master/Slave manually if not already done */
2665 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2666 Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
2667 }
2668
2669 /*
2670 * Do NOT enable Auto-negotiation here. This would hold
2671 * the link down because no IDLES are transmitted
2672 */
2673 }
2674 else {
2675 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2676 ("InitPhyLone: with auto-negotiation Port %d\n", Port));
2677 /* Set Auto-negotiation advertisement */
2678
2679 /* Set Full/half duplex capabilities */
2680 switch (pPrt->PLinkMode) {
2681 case SK_LMODE_AUTOHALF:
2682 Ctrl2 |= PHY_L_1000C_AHD;
2683 break;
2684 case SK_LMODE_AUTOFULL:
2685 Ctrl2 |= PHY_L_1000C_AFD;
2686 break;
2687 case SK_LMODE_AUTOBOTH:
2688 Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2689 break;
2690 default:
2691 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2692 SKERR_HWI_E015MSG);
2693 }
2694
2695 switch (pPrt->PFlowCtrlMode) {
2696 case SK_FLOW_MODE_NONE:
2697 Ctrl3 |= PHY_L_P_NO_PAUSE;
2698 break;
2699 case SK_FLOW_MODE_LOC_SEND:
2700 Ctrl3 |= PHY_L_P_ASYM_MD;
2701 break;
2702 case SK_FLOW_MODE_SYMMETRIC:
2703 Ctrl3 |= PHY_L_P_SYM_MD;
2704 break;
2705 case SK_FLOW_MODE_SYM_OR_REM:
2706 Ctrl3 |= PHY_L_P_BOTH_MD;
2707 break;
2708 default:
2709 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2710 SKERR_HWI_E016MSG);
2711 }
2712
2713 /* Restart Auto-negotiation */
2714 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2715
2716 }
wdenk42d1f032003-10-15 23:53:47 +00002717
wdenk7152b1d2003-09-05 23:19:14 +00002718 /* Initialize LED register here ? */
2719 /* No. Please do it in SkDgXmitLed() (if required) and swap
2720 init order of LEDs and XMAC. (MAl) */
wdenk42d1f032003-10-15 23:53:47 +00002721
wdenk7152b1d2003-09-05 23:19:14 +00002722 /* Write 1000Base-T Control Register */
2723 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2724 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2725 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
wdenk42d1f032003-10-15 23:53:47 +00002726
wdenk7152b1d2003-09-05 23:19:14 +00002727 /* Write AutoNeg Advertisement Register */
2728 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2729 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2730 ("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
wdenk42d1f032003-10-15 23:53:47 +00002731
wdenk7152b1d2003-09-05 23:19:14 +00002732
2733 if (DoLoop) {
2734 /* Set the Phy Loopback bit, too */
2735 Ctrl1 |= PHY_CT_LOOP;
2736 }
2737
2738 /* Write to the Phy control register */
2739 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2740 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2741 ("PHY Control Reg=0x%04X\n", Ctrl1));
2742} /* SkXmInitPhyLone */
2743
2744
2745/******************************************************************************
2746 *
2747 * SkXmInitPhyNat() - Initialize the National Phy registers
2748 *
2749 * Description: initializes all the National Phy registers
2750 *
2751 * Note:
2752 *
2753 * Returns:
2754 * nothing
2755 */
2756static void SkXmInitPhyNat(
2757SK_AC *pAC, /* adapter context */
2758SK_IOC IoC, /* IO context */
2759int Port, /* Port Index (MAC_1 + n) */
2760SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2761{
2762/* todo: National */
2763} /* SkXmInitPhyNat */
2764#endif /* OTHER_PHY */
2765
2766
2767/******************************************************************************
2768 *
2769 * SkMacInitPhy() - Initialize the PHY registers
2770 *
2771 * Description: calls the Init PHY routines dep. on board type
2772 *
2773 * Note:
2774 *
2775 * Returns:
2776 * nothing
2777 */
2778void SkMacInitPhy(
2779SK_AC *pAC, /* adapter context */
2780SK_IOC IoC, /* IO context */
2781int Port, /* Port Index (MAC_1 + n) */
2782SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
2783{
2784 SK_GEPORT *pPrt;
2785
2786 pPrt = &pAC->GIni.GP[Port];
2787
2788 switch (pPrt->PhyType) {
2789 case SK_PHY_XMAC:
2790 SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2791 break;
2792 case SK_PHY_BCOM:
2793 SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2794 break;
2795 case SK_PHY_MARV_COPPER:
2796 case SK_PHY_MARV_FIBER:
2797 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2798 break;
2799#ifdef OTHER_PHY
2800 case SK_PHY_LONE:
2801 SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2802 break;
2803 case SK_PHY_NAT:
2804 SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2805 break;
2806#endif /* OTHER_PHY */
2807 }
2808} /* SkMacInitPhy */
2809
2810
2811#ifndef SK_DIAG
2812/******************************************************************************
2813 *
2814 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
2815 *
2816 * This function analyses the Interrupt status word. If any of the
2817 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
2818 * is set true.
2819 */
2820void SkXmAutoNegLipaXmac(
2821SK_AC *pAC, /* adapter context */
2822SK_IOC IoC, /* IO context */
2823int Port, /* Port Index (MAC_1 + n) */
2824SK_U16 IStatus) /* Interrupt Status word to analyse */
2825{
2826 SK_GEPORT *pPrt;
2827
2828 pPrt = &pAC->GIni.GP[Port];
2829
2830 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2831 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
2832
2833 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2834 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n",
2835 Port, IStatus));
2836 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2837 }
2838} /* SkXmAutoNegLipaXmac */
2839
2840
2841/******************************************************************************
2842 *
2843 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
2844 *
2845 * This function analyses the PHY status word.
2846 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
2847 * is set true.
2848 */
2849void SkMacAutoNegLipaPhy(
2850SK_AC *pAC, /* adapter context */
2851SK_IOC IoC, /* IO context */
2852int Port, /* Port Index (MAC_1 + n) */
2853SK_U16 PhyStat) /* PHY Status word to analyse */
2854{
2855 SK_GEPORT *pPrt;
2856
2857 pPrt = &pAC->GIni.GP[Port];
2858
2859 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
2860 (PhyStat & PHY_ST_AN_OVER) != 0) {
2861
2862 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2863 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\n",
2864 Port, PhyStat));
2865 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
2866 }
2867} /* SkMacAutoNegLipaPhy */
2868#endif /* SK_DIAG */
2869
2870
2871/******************************************************************************
2872 *
2873 * SkXmAutoNegDoneXmac() - Auto-negotiation handling
2874 *
2875 * Description:
2876 * This function handles the auto-negotiation if the Done bit is set.
2877 *
2878 * Returns:
2879 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02002880 * SK_AND_DUP_CAP Duplex capability error happened
2881 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00002882 */
2883static int SkXmAutoNegDoneXmac(
2884SK_AC *pAC, /* adapter context */
2885SK_IOC IoC, /* IO context */
2886int Port) /* Port Index (MAC_1 + n) */
2887{
2888 SK_GEPORT *pPrt;
2889 SK_U16 ResAb; /* Resolved Ability */
2890 SK_U16 LPAb; /* Link Partner Ability */
2891
2892 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2893 ("AutoNegDoneXmac, Port %d\n",Port));
2894
2895 pPrt = &pAC->GIni.GP[Port];
2896
2897 /* Get PHY parameters */
2898 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
2899 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
2900
2901 if ((LPAb & PHY_X_AN_RFB) != 0) {
2902 /* At least one of the remote fault bit is set */
2903 /* Error */
2904 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2905 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2906 pPrt->PAutoNegFail = SK_TRUE;
2907 return(SK_AND_OTHER);
2908 }
2909
2910 /* Check Duplex mismatch */
2911 if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
2912 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
2913 }
2914 else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
2915 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
2916 }
2917 else {
2918 /* Error */
2919 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2920 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2921 pPrt->PAutoNegFail = SK_TRUE;
2922 return(SK_AND_DUP_CAP);
2923 }
2924
2925 /* Check PAUSE mismatch */
2926 /* We are NOT using chapter 4.23 of the Xaqti manual */
2927 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2928 if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
2929 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
2930 (LPAb & PHY_X_P_SYM_MD) != 0) {
2931 /* Symmetric PAUSE */
2932 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2933 }
2934 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
2935 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
2936 /* Enable PAUSE receive, disable PAUSE transmit */
2937 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2938 }
2939 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
2940 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
2941 /* Disable PAUSE receive, enable PAUSE transmit */
2942 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
2943 }
2944 else {
2945 /* PAUSE mismatch -> no PAUSE */
2946 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
2947 }
2948 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
2949
2950 return(SK_AND_OK);
2951} /* SkXmAutoNegDoneXmac */
2952
2953
2954/******************************************************************************
2955 *
2956 * SkXmAutoNegDoneBcom() - Auto-negotiation handling
2957 *
2958 * Description:
2959 * This function handles the auto-negotiation if the Done bit is set.
2960 *
2961 * Returns:
2962 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02002963 * SK_AND_DUP_CAP Duplex capability error happened
2964 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00002965 */
2966static int SkXmAutoNegDoneBcom(
2967SK_AC *pAC, /* adapter context */
2968SK_IOC IoC, /* IO context */
2969int Port) /* Port Index (MAC_1 + n) */
2970{
2971 SK_GEPORT *pPrt;
2972 SK_U16 LPAb; /* Link Partner Ability */
2973 SK_U16 AuxStat; /* Auxiliary Status */
2974
2975#if 0
297601-Sep-2000 RA;:;:
2977 SK_U16 ResAb; /* Resolved Ability */
2978#endif /* 0 */
2979
2980 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2981 ("AutoNegDoneBcom, Port %d\n", Port));
2982 pPrt = &pAC->GIni.GP[Port];
2983
2984 /* Get PHY parameters */
2985 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
2986#if 0
298701-Sep-2000 RA;:;:
2988 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
2989#endif /* 0 */
wdenk42d1f032003-10-15 23:53:47 +00002990
wdenk7152b1d2003-09-05 23:19:14 +00002991 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
2992
2993 if ((LPAb & PHY_B_AN_RF) != 0) {
2994 /* Remote fault bit is set: Error */
2995 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2996 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2997 pPrt->PAutoNegFail = SK_TRUE;
2998 return(SK_AND_OTHER);
2999 }
3000
3001 /* Check Duplex mismatch */
3002 if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
3003 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3004 }
3005 else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
3006 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3007 }
3008 else {
3009 /* Error */
3010 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3011 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3012 pPrt->PAutoNegFail = SK_TRUE;
3013 return(SK_AND_DUP_CAP);
3014 }
wdenk42d1f032003-10-15 23:53:47 +00003015
wdenk7152b1d2003-09-05 23:19:14 +00003016#if 0
301701-Sep-2000 RA;:;:
3018 /* Check Master/Slave resolution */
3019 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3020 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3021 ("Master/Slave Fault Port %d\n", Port));
3022 pPrt->PAutoNegFail = SK_TRUE;
3023 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3024 return(SK_AND_OTHER);
3025 }
wdenk42d1f032003-10-15 23:53:47 +00003026
wdenk7152b1d2003-09-05 23:19:14 +00003027 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3028 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
3029#endif /* 0 */
3030
3031 /* Check PAUSE mismatch */
3032 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3033 if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
3034 /* Symmetric PAUSE */
3035 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3036 }
3037 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
3038 /* Enable PAUSE receive, disable PAUSE transmit */
3039 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3040 }
3041 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
3042 /* Disable PAUSE receive, enable PAUSE transmit */
3043 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3044 }
3045 else {
3046 /* PAUSE mismatch -> no PAUSE */
3047 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3048 }
3049 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3050
3051 return(SK_AND_OK);
3052} /* SkXmAutoNegDoneBcom */
3053
3054
3055/******************************************************************************
3056 *
3057 * SkGmAutoNegDoneMarv() - Auto-negotiation handling
3058 *
3059 * Description:
3060 * This function handles the auto-negotiation if the Done bit is set.
3061 *
3062 * Returns:
3063 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003064 * SK_AND_DUP_CAP Duplex capability error happened
3065 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003066 */
3067static int SkGmAutoNegDoneMarv(
3068SK_AC *pAC, /* adapter context */
3069SK_IOC IoC, /* IO context */
3070int Port) /* Port Index (MAC_1 + n) */
3071{
3072 SK_GEPORT *pPrt;
3073 SK_U16 LPAb; /* Link Partner Ability */
3074 SK_U16 ResAb; /* Resolved Ability */
3075 SK_U16 AuxStat; /* Auxiliary Status */
3076
3077 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3078 ("AutoNegDoneMarv, Port %d\n", Port));
3079 pPrt = &pAC->GIni.GP[Port];
3080
3081 /* Get PHY parameters */
3082 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
wdenk42d1f032003-10-15 23:53:47 +00003083
wdenk7152b1d2003-09-05 23:19:14 +00003084 if ((LPAb & PHY_M_AN_RF) != 0) {
3085 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3086 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3087 pPrt->PAutoNegFail = SK_TRUE;
3088 return(SK_AND_OTHER);
3089 }
3090
3091 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
wdenk42d1f032003-10-15 23:53:47 +00003092
wdenk7152b1d2003-09-05 23:19:14 +00003093 /* Check Master/Slave resolution */
3094 if ((ResAb & PHY_B_1000S_MSF) != 0) {
3095 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3096 ("Master/Slave Fault Port %d\n", Port));
3097 pPrt->PAutoNegFail = SK_TRUE;
3098 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3099 return(SK_AND_OTHER);
3100 }
wdenk42d1f032003-10-15 23:53:47 +00003101
wdenk7152b1d2003-09-05 23:19:14 +00003102 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3103 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
wdenk42d1f032003-10-15 23:53:47 +00003104
wdenk7152b1d2003-09-05 23:19:14 +00003105 /* Read PHY Specific Status */
3106 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
wdenk42d1f032003-10-15 23:53:47 +00003107
wdenk7152b1d2003-09-05 23:19:14 +00003108 /* Check Speed & Duplex resolved */
3109 if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
3110 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3111 ("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port));
3112 pPrt->PAutoNegFail = SK_TRUE;
3113 pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
3114 return(SK_AND_DUP_CAP);
3115 }
wdenk42d1f032003-10-15 23:53:47 +00003116
wdenk7152b1d2003-09-05 23:19:14 +00003117 if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
3118 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3119 }
3120 else {
3121 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3122 }
wdenk42d1f032003-10-15 23:53:47 +00003123
wdenk7152b1d2003-09-05 23:19:14 +00003124 /* Check PAUSE mismatch */
3125 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3126 if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
3127 /* Symmetric PAUSE */
3128 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3129 }
3130 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
3131 /* Enable PAUSE receive, disable PAUSE transmit */
3132 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3133 }
3134 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
3135 /* Disable PAUSE receive, enable PAUSE transmit */
3136 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3137 }
3138 else {
3139 /* PAUSE mismatch -> no PAUSE */
3140 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3141 }
wdenk42d1f032003-10-15 23:53:47 +00003142
wdenk7152b1d2003-09-05 23:19:14 +00003143 /* set used link speed */
3144 switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
3145 case (unsigned)PHY_M_PS_SPEED_1000:
3146 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
3147 break;
3148 case PHY_M_PS_SPEED_100:
3149 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
3150 break;
3151 default:
3152 pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
3153 }
3154
3155 return(SK_AND_OK);
3156} /* SkGmAutoNegDoneMarv */
3157
3158
3159#ifdef OTHER_PHY
3160/******************************************************************************
3161 *
3162 * SkXmAutoNegDoneLone() - Auto-negotiation handling
3163 *
3164 * Description:
3165 * This function handles the auto-negotiation if the Done bit is set.
3166 *
3167 * Returns:
3168 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003169 * SK_AND_DUP_CAP Duplex capability error happened
3170 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003171 */
3172static int SkXmAutoNegDoneLone(
3173SK_AC *pAC, /* adapter context */
3174SK_IOC IoC, /* IO context */
3175int Port) /* Port Index (MAC_1 + n) */
3176{
3177 SK_GEPORT *pPrt;
3178 SK_U16 ResAb; /* Resolved Ability */
3179 SK_U16 LPAb; /* Link Partner Ability */
3180 SK_U16 QuickStat; /* Auxiliary Status */
3181
3182 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3183 ("AutoNegDoneLone, Port %d\n",Port));
3184 pPrt = &pAC->GIni.GP[Port];
3185
3186 /* Get PHY parameters */
3187 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
3188 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
3189 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
3190
3191 if ((LPAb & PHY_L_AN_RF) != 0) {
3192 /* Remote fault bit is set */
3193 /* Error */
3194 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3195 ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3196 pPrt->PAutoNegFail = SK_TRUE;
3197 return(SK_AND_OTHER);
3198 }
3199
3200 /* Check Duplex mismatch */
3201 if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
3202 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
3203 }
3204 else {
3205 pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
3206 }
wdenk42d1f032003-10-15 23:53:47 +00003207
wdenk7152b1d2003-09-05 23:19:14 +00003208 /* Check Master/Slave resolution */
3209 if ((ResAb & PHY_L_1000S_MSF) != 0) {
3210 /* Error */
3211 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3212 ("Master/Slave Fault Port %d\n", Port));
3213 pPrt->PAutoNegFail = SK_TRUE;
3214 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3215 return(SK_AND_OTHER);
3216 }
3217 else if (ResAb & PHY_L_1000S_MSR) {
3218 pPrt->PMSStatus = SK_MS_STAT_MASTER;
3219 }
3220 else {
3221 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
3222 }
3223
3224 /* Check PAUSE mismatch */
3225 /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3226 /* we must manually resolve the abilities here */
3227 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3228 switch (pPrt->PFlowCtrlMode) {
3229 case SK_FLOW_MODE_NONE:
3230 /* default */
3231 break;
3232 case SK_FLOW_MODE_LOC_SEND:
3233 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3234 (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
3235 /* Disable PAUSE receive, enable PAUSE transmit */
3236 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3237 }
3238 break;
3239 case SK_FLOW_MODE_SYMMETRIC:
3240 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3241 /* Symmetric PAUSE */
3242 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3243 }
3244 break;
3245 case SK_FLOW_MODE_SYM_OR_REM:
3246 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3247 PHY_L_QS_AS_PAUSE) {
3248 /* Enable PAUSE receive, disable PAUSE transmit */
3249 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3250 }
3251 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3252 /* Symmetric PAUSE */
3253 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3254 }
3255 break;
3256 default:
3257 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3258 SKERR_HWI_E016MSG);
3259 }
wdenk42d1f032003-10-15 23:53:47 +00003260
wdenk7152b1d2003-09-05 23:19:14 +00003261 return(SK_AND_OK);
3262} /* SkXmAutoNegDoneLone */
3263
3264
3265/******************************************************************************
3266 *
3267 * SkXmAutoNegDoneNat() - Auto-negotiation handling
3268 *
3269 * Description:
3270 * This function handles the auto-negotiation if the Done bit is set.
3271 *
3272 * Returns:
3273 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003274 * SK_AND_DUP_CAP Duplex capability error happened
3275 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003276 */
3277static int SkXmAutoNegDoneNat(
3278SK_AC *pAC, /* adapter context */
3279SK_IOC IoC, /* IO context */
3280int Port) /* Port Index (MAC_1 + n) */
3281{
3282/* todo: National */
3283 return(SK_AND_OK);
3284} /* SkXmAutoNegDoneNat */
3285#endif /* OTHER_PHY */
3286
3287
3288/******************************************************************************
3289 *
3290 * SkMacAutoNegDone() - Auto-negotiation handling
3291 *
3292 * Description: calls the auto-negotiation done routines dep. on board type
3293 *
3294 * Returns:
3295 * SK_AND_OK o.k.
Wolfgang Denk53677ef2008-05-20 16:00:29 +02003296 * SK_AND_DUP_CAP Duplex capability error happened
3297 * SK_AND_OTHER Other error happened
wdenk7152b1d2003-09-05 23:19:14 +00003298 */
3299int SkMacAutoNegDone(
3300SK_AC *pAC, /* adapter context */
3301SK_IOC IoC, /* IO context */
3302int Port) /* Port Index (MAC_1 + n) */
3303{
3304 SK_GEPORT *pPrt;
3305 int Rtv;
3306
3307 pPrt = &pAC->GIni.GP[Port];
3308
3309 switch (pPrt->PhyType) {
3310 case SK_PHY_XMAC:
3311 Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3312 break;
3313 case SK_PHY_BCOM:
3314 Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3315 break;
3316 case SK_PHY_MARV_COPPER:
3317 case SK_PHY_MARV_FIBER:
3318 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3319 break;
3320#ifdef OTHER_PHY
3321 case SK_PHY_LONE:
3322 Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3323 break;
3324 case SK_PHY_NAT:
3325 Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3326 break;
3327#endif /* OTHER_PHY */
3328 default:
3329 return(SK_AND_OTHER);
3330 }
wdenk42d1f032003-10-15 23:53:47 +00003331
wdenk7152b1d2003-09-05 23:19:14 +00003332 if (Rtv != SK_AND_OK) {
3333 return(Rtv);
3334 }
3335
3336 /* We checked everything and may now enable the link */
3337 pPrt->PAutoNegFail = SK_FALSE;
3338
3339 SkMacRxTxEnable(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00003340
wdenk7152b1d2003-09-05 23:19:14 +00003341 return(SK_AND_OK);
3342} /* SkMacAutoNegDone */
3343
3344
3345/******************************************************************************
3346 *
3347 * SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3348 *
3349 * Description:
3350 * sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3351 * enables Rx/Tx
3352 *
3353 * Returns: N/A
3354 */
3355static void SkXmSetRxTxEn(
3356SK_AC *pAC, /* Adapter Context */
3357SK_IOC IoC, /* IO context */
3358int Port, /* Port Index (MAC_1 + n) */
3359int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3360{
3361 SK_U16 Word;
3362
3363 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3364
3365 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3366 case SK_MAC_LOOPB_ON:
3367 Word |= XM_MMU_MAC_LB;
3368 break;
3369 case SK_MAC_LOOPB_OFF:
3370 Word &= ~XM_MMU_MAC_LB;
3371 break;
3372 }
3373
3374 switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
3375 case SK_PHY_LOOPB_ON:
3376 Word |= XM_MMU_GMII_LOOP;
3377 break;
3378 case SK_PHY_LOOPB_OFF:
3379 Word &= ~XM_MMU_GMII_LOOP;
3380 break;
3381 }
wdenk42d1f032003-10-15 23:53:47 +00003382
wdenk7152b1d2003-09-05 23:19:14 +00003383 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3384 case SK_PHY_FULLD_ON:
3385 Word |= XM_MMU_GMII_FD;
3386 break;
3387 case SK_PHY_FULLD_OFF:
3388 Word &= ~XM_MMU_GMII_FD;
3389 break;
3390 }
wdenk42d1f032003-10-15 23:53:47 +00003391
wdenk7152b1d2003-09-05 23:19:14 +00003392 XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3393
3394 /* dummy read to ensure writing */
3395 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3396
3397} /* SkXmSetRxTxEn */
3398
3399
3400/******************************************************************************
3401 *
3402 * SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3403 *
3404 * Description:
3405 * sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3406 * enables Rx/Tx
3407 *
3408 * Returns: N/A
3409 */
3410static void SkGmSetRxTxEn(
3411SK_AC *pAC, /* Adapter Context */
3412SK_IOC IoC, /* IO context */
3413int Port, /* Port Index (MAC_1 + n) */
3414int Para) /* Parameter to set: MAC LoopBack, Duplex Mode */
3415{
3416 SK_U16 Ctrl;
wdenk42d1f032003-10-15 23:53:47 +00003417
wdenk7152b1d2003-09-05 23:19:14 +00003418 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3419
3420 switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3421 case SK_MAC_LOOPB_ON:
3422 Ctrl |= GM_GPCR_LOOP_ENA;
3423 break;
3424 case SK_MAC_LOOPB_OFF:
3425 Ctrl &= ~GM_GPCR_LOOP_ENA;
3426 break;
3427 }
3428
3429 switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3430 case SK_PHY_FULLD_ON:
3431 Ctrl |= GM_GPCR_DUP_FULL;
3432 break;
3433 case SK_PHY_FULLD_OFF:
3434 Ctrl &= ~GM_GPCR_DUP_FULL;
3435 break;
3436 }
wdenk42d1f032003-10-15 23:53:47 +00003437
wdenk7152b1d2003-09-05 23:19:14 +00003438 GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3439
3440 /* dummy read to ensure writing */
3441 GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3442
3443} /* SkGmSetRxTxEn */
3444
3445
3446/******************************************************************************
3447 *
3448 * SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3449 *
3450 * Description: calls the Special Set Rx/Tx Enable routines dep. on board type
3451 *
3452 * Returns: N/A
3453 */
3454void SkMacSetRxTxEn(
3455SK_AC *pAC, /* Adapter Context */
3456SK_IOC IoC, /* IO context */
3457int Port, /* Port Index (MAC_1 + n) */
3458int Para)
3459{
3460 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00003461
wdenk7152b1d2003-09-05 23:19:14 +00003462 SkXmSetRxTxEn(pAC, IoC, Port, Para);
3463 }
3464 else {
wdenk42d1f032003-10-15 23:53:47 +00003465
wdenk7152b1d2003-09-05 23:19:14 +00003466 SkGmSetRxTxEn(pAC, IoC, Port, Para);
3467 }
3468
3469} /* SkMacSetRxTxEn */
3470
3471
3472/******************************************************************************
3473 *
3474 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3475 *
3476 * Description: enables Rx/Tx dep. on board type
3477 *
3478 * Returns:
3479 * 0 o.k.
3480 * != 0 Error happened
3481 */
3482int SkMacRxTxEnable(
3483SK_AC *pAC, /* adapter context */
3484SK_IOC IoC, /* IO context */
3485int Port) /* Port Index (MAC_1 + n) */
3486{
3487 SK_GEPORT *pPrt;
3488 SK_U16 Reg; /* 16-bit register value */
3489 SK_U16 IntMask; /* MAC interrupt mask */
3490 SK_U16 SWord;
3491
3492 pPrt = &pAC->GIni.GP[Port];
3493
3494 if (!pPrt->PHWLinkUp) {
3495 /* The Hardware link is NOT up */
3496 return(0);
3497 }
3498
3499 if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3500 pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3501 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3502 pPrt->PAutoNegFail) {
3503 /* Auto-negotiation is not done or failed */
3504 return(0);
3505 }
3506
3507 if (pAC->GIni.GIGenesis) {
3508 /* set Duplex Mode and Pause Mode */
3509 SkXmInitDupMd(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00003510
wdenk7152b1d2003-09-05 23:19:14 +00003511 SkXmInitPauseMd(pAC, IoC, Port);
wdenk42d1f032003-10-15 23:53:47 +00003512
wdenk7152b1d2003-09-05 23:19:14 +00003513 /*
3514 * Initialize the Interrupt Mask Register. Default IRQs are...
3515 * - Link Asynchronous Event
3516 * - Link Partner requests config
3517 * - Auto Negotiation Done
3518 * - Rx Counter Event Overflow
3519 * - Tx Counter Event Overflow
3520 * - Transmit FIFO Underrun
3521 */
3522 IntMask = XM_DEF_MSK;
3523
3524#ifdef DEBUG
3525 /* add IRQ for Receive FIFO Overflow */
3526 IntMask &= ~XM_IS_RXF_OV;
3527#endif /* DEBUG */
wdenk42d1f032003-10-15 23:53:47 +00003528
wdenk7152b1d2003-09-05 23:19:14 +00003529 if (pPrt->PhyType != SK_PHY_XMAC) {
3530 /* disable GP0 interrupt bit */
3531 IntMask |= XM_IS_INP_ASS;
3532 }
3533 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
wdenk42d1f032003-10-15 23:53:47 +00003534
wdenk7152b1d2003-09-05 23:19:14 +00003535 /* get MMU Command Reg. */
3536 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
wdenk42d1f032003-10-15 23:53:47 +00003537
wdenk7152b1d2003-09-05 23:19:14 +00003538 if (pPrt->PhyType != SK_PHY_XMAC &&
3539 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3540 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3541 /* set to Full Duplex */
3542 Reg |= XM_MMU_GMII_FD;
3543 }
wdenk42d1f032003-10-15 23:53:47 +00003544
wdenk7152b1d2003-09-05 23:19:14 +00003545 switch (pPrt->PhyType) {
3546 case SK_PHY_BCOM:
3547 /*
3548 * Workaround BCOM Errata (#10523) for all BCom Phys
3549 * Enable Power Management after link up
3550 */
3551 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3552 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3553 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3554 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
3555 break;
3556#ifdef OTHER_PHY
3557 case SK_PHY_LONE:
3558 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3559 break;
3560 case SK_PHY_NAT:
3561 /* todo National:
3562 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3563 /* no interrupts possible from National ??? */
3564 break;
3565#endif /* OTHER_PHY */
3566 }
wdenk42d1f032003-10-15 23:53:47 +00003567
wdenk7152b1d2003-09-05 23:19:14 +00003568 /* enable Rx/Tx */
3569 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3570 }
3571 else {
3572 /*
3573 * Initialize the Interrupt Mask Register. Default IRQs are...
3574 * - Rx Counter Event Overflow
3575 * - Tx Counter Event Overflow
3576 * - Transmit FIFO Underrun
3577 */
3578 IntMask = GMAC_DEF_MSK;
3579
3580#ifdef DEBUG
3581 /* add IRQ for Receive FIFO Overrun */
3582 IntMask |= GM_IS_RX_FF_OR;
3583#endif /* DEBUG */
wdenk42d1f032003-10-15 23:53:47 +00003584
wdenk7152b1d2003-09-05 23:19:14 +00003585 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
wdenk42d1f032003-10-15 23:53:47 +00003586
wdenk7152b1d2003-09-05 23:19:14 +00003587 /* get General Purpose Control */
3588 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
wdenk42d1f032003-10-15 23:53:47 +00003589
wdenk7152b1d2003-09-05 23:19:14 +00003590 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3591 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3592 /* set to Full Duplex */
3593 Reg |= GM_GPCR_DUP_FULL;
3594 }
wdenk42d1f032003-10-15 23:53:47 +00003595
wdenk7152b1d2003-09-05 23:19:14 +00003596 /* enable Rx/Tx */
3597 GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
3598
3599#ifndef VCPU
3600 /* Enable all PHY interrupts */
3601 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
3602#endif /* VCPU */
3603 }
wdenk42d1f032003-10-15 23:53:47 +00003604
wdenk7152b1d2003-09-05 23:19:14 +00003605 return(0);
3606
3607} /* SkMacRxTxEnable */
3608
3609
3610/******************************************************************************
3611 *
3612 * SkMacRxTxDisable() - Disable Receiver and Transmitter
3613 *
3614 * Description: disables Rx/Tx dep. on board type
3615 *
3616 * Returns: N/A
3617 */
3618void SkMacRxTxDisable(
3619SK_AC *pAC, /* Adapter Context */
3620SK_IOC IoC, /* IO context */
3621int Port) /* Port Index (MAC_1 + n) */
3622{
3623 SK_U16 Word;
3624
3625 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00003626
wdenk7152b1d2003-09-05 23:19:14 +00003627 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
wdenk42d1f032003-10-15 23:53:47 +00003628
wdenk7152b1d2003-09-05 23:19:14 +00003629 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
wdenk42d1f032003-10-15 23:53:47 +00003630
wdenk7152b1d2003-09-05 23:19:14 +00003631 /* dummy read to ensure writing */
3632 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3633 }
3634 else {
wdenk42d1f032003-10-15 23:53:47 +00003635
wdenk7152b1d2003-09-05 23:19:14 +00003636 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3637
3638 GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
3639
3640 /* dummy read to ensure writing */
3641 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3642 }
3643} /* SkMacRxTxDisable */
3644
3645
3646/******************************************************************************
3647 *
3648 * SkMacIrqDisable() - Disable IRQ from MAC
3649 *
3650 * Description: sets the IRQ-mask to disable IRQ dep. on board type
3651 *
3652 * Returns: N/A
3653 */
3654void SkMacIrqDisable(
3655SK_AC *pAC, /* Adapter Context */
3656SK_IOC IoC, /* IO context */
3657int Port) /* Port Index (MAC_1 + n) */
3658{
3659 SK_GEPORT *pPrt;
3660 SK_U16 Word;
3661
3662 pPrt = &pAC->GIni.GP[Port];
3663
3664 if (pAC->GIni.GIGenesis) {
wdenk42d1f032003-10-15 23:53:47 +00003665
wdenk7152b1d2003-09-05 23:19:14 +00003666 /* disable all XMAC IRQs */
wdenk42d1f032003-10-15 23:53:47 +00003667 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
3668
wdenk7152b1d2003-09-05 23:19:14 +00003669 /* Disable all PHY interrupts */
3670 switch (pPrt->PhyType) {
3671 case SK_PHY_BCOM:
3672 /* Make sure that PHY is initialized */
3673 if (pPrt->PState != SK_PRT_RESET) {
3674 /* NOT allowed if BCOM is in RESET state */
3675 /* Workaround BCOM Errata (#10523) all BCom */
3676 /* Disable Power Management if link is down */
3677 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3678 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3679 (SK_U16)(Word | PHY_B_AC_DIS_PM));
3680 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3681 }
3682 break;
3683#ifdef OTHER_PHY
3684 case SK_PHY_LONE:
3685 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3686 break;
3687 case SK_PHY_NAT:
3688 /* todo: National
3689 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3690 break;
3691#endif /* OTHER_PHY */
3692 }
3693 }
3694 else {
3695 /* disable all GMAC IRQs */
3696 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
wdenk42d1f032003-10-15 23:53:47 +00003697
wdenk7152b1d2003-09-05 23:19:14 +00003698#ifndef VCPU
3699 /* Disable all PHY interrupts */
3700 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3701#endif /* VCPU */
3702 }
3703} /* SkMacIrqDisable */
3704
3705
3706#ifdef SK_DIAG
3707/******************************************************************************
3708 *
3709 * SkXmSendCont() - Enable / Disable Send Continuous Mode
3710 *
3711 * Description: enable / disable Send Continuous Mode on XMAC
3712 *
3713 * Returns:
3714 * nothing
3715 */
3716void SkXmSendCont(
3717SK_AC *pAC, /* adapter context */
3718SK_IOC IoC, /* IO context */
3719int Port, /* Port Index (MAC_1 + n) */
3720SK_BOOL Enable) /* Enable / Disable */
3721{
3722 SK_U32 MdReg;
3723
3724 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3725
3726 if (Enable) {
3727 MdReg |= XM_MD_TX_CONT;
3728 }
3729 else {
3730 MdReg &= ~XM_MD_TX_CONT;
3731 }
3732 /* setup Mode Register */
3733 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3734
3735} /* SkXmSendCont*/
3736
3737/******************************************************************************
3738 *
3739 * SkMacTimeStamp() - Enable / Disable Time Stamp
3740 *
3741 * Description: enable / disable Time Stamp generation for Rx packets
3742 *
3743 * Returns:
3744 * nothing
3745 */
3746void SkMacTimeStamp(
3747SK_AC *pAC, /* adapter context */
3748SK_IOC IoC, /* IO context */
3749int Port, /* Port Index (MAC_1 + n) */
3750SK_BOOL Enable) /* Enable / Disable */
3751{
3752 SK_U32 MdReg;
3753 SK_U8 TimeCtrl;
3754
3755 if (pAC->GIni.GIGenesis) {
3756
3757 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3758
3759 if (Enable) {
3760 MdReg |= XM_MD_ATS;
3761 }
3762 else {
3763 MdReg &= ~XM_MD_ATS;
3764 }
3765 /* setup Mode Register */
3766 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3767 }
3768 else {
3769 if (Enable) {
3770 TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3771 }
3772 else {
3773 TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3774 }
3775 /* Start/Stop Time Stamp Timer */
3776 SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl);
3777 }
3778} /* SkMacTimeStamp*/
3779
3780#else /* SK_DIAG */
3781
3782/******************************************************************************
3783 *
3784 * SkXmIrq() - Interrupt Service Routine
3785 *
3786 * Description: services an Interrupt Request of the XMAC
3787 *
3788 * Note:
3789 * With an external PHY, some interrupt bits are not meaningfull any more:
3790 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
3791 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
3792 * - Page Received (bit #9) XM_IS_RX_PAGE
3793 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
3794 * - AutoNegDone (bit #7) XM_IS_AND
3795 * Also probably not valid any more is the GP0 input bit:
3796 * - GPRegisterBit0set XM_IS_INP_ASS
3797 *
3798 * Returns:
3799 * nothing
3800 */
3801void SkXmIrq(
3802SK_AC *pAC, /* adapter context */
3803SK_IOC IoC, /* IO context */
3804int Port) /* Port Index (MAC_1 + n) */
3805{
3806 SK_GEPORT *pPrt;
3807 SK_EVPARA Para;
3808 SK_U16 IStatus; /* Interrupt status read from the XMAC */
3809 SK_U16 IStatus2;
3810
3811 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +00003812
wdenk7152b1d2003-09-05 23:19:14 +00003813 XM_IN16(IoC, Port, XM_ISRC, &IStatus);
wdenk42d1f032003-10-15 23:53:47 +00003814
wdenk7152b1d2003-09-05 23:19:14 +00003815 /* LinkPartner Auto-negable? */
3816 if (pPrt->PhyType == SK_PHY_XMAC) {
3817 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
3818 }
3819 else {
3820 /* mask bits that are not used with ext. PHY */
3821 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
3822 XM_IS_RX_PAGE | XM_IS_TX_PAGE |
3823 XM_IS_AND | XM_IS_INP_ASS);
3824 }
wdenk42d1f032003-10-15 23:53:47 +00003825
wdenk7152b1d2003-09-05 23:19:14 +00003826 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3827 ("XmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3828
3829 if (!pPrt->PHWLinkUp) {
3830 /* Spurious XMAC interrupt */
3831 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3832 ("SkXmIrq: spurious interrupt on Port %d\n", Port));
3833 return;
3834 }
3835
3836 if ((IStatus & XM_IS_INP_ASS) != 0) {
3837 /* Reread ISR Register if link is not in sync */
3838 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
3839
3840 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3841 ("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\n",
3842 Port, IStatus, IStatus2));
3843 IStatus &= ~XM_IS_INP_ASS;
3844 IStatus |= IStatus2;
3845 }
3846
3847 if ((IStatus & XM_IS_LNK_AE) != 0) {
3848 /* not used, GP0 is used instead */
3849 }
3850
3851 if ((IStatus & XM_IS_TX_ABORT) != 0) {
3852 /* not used */
3853 }
3854
3855 if ((IStatus & XM_IS_FRC_INT) != 0) {
3856 /* not used, use ASIC IRQ instead if needed */
3857 }
3858
3859 if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
3860 SkHWLinkDown(pAC, IoC, Port);
3861
3862 /* Signal to RLMT */
3863 Para.Para32[0] = (SK_U32)Port;
3864 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
3865
3866 /* Start workaround Errata #2 timer */
3867 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
3868 SKGE_HWAC, SK_HWEV_WATIM, Para);
3869 }
3870
3871 if ((IStatus & XM_IS_RX_PAGE) != 0) {
3872 /* not used */
3873 }
3874
3875 if ((IStatus & XM_IS_TX_PAGE) != 0) {
3876 /* not used */
3877 }
3878
3879 if ((IStatus & XM_IS_AND) != 0) {
3880 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3881 ("SkXmIrq: AND on link that is up Port %d\n", Port));
3882 }
3883
3884 if ((IStatus & XM_IS_TSC_OV) != 0) {
3885 /* not used */
3886 }
3887
3888 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3889 if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
3890 Para.Para32[0] = (SK_U32)Port;
3891 Para.Para32[1] = (SK_U32)IStatus;
3892 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3893 }
3894
3895 if ((IStatus & XM_IS_RXF_OV) != 0) {
3896 /* normal situation -> no effect */
3897#ifdef DEBUG
3898 pPrt->PRxOverCnt++;
3899#endif /* DEBUG */
3900 }
3901
3902 if ((IStatus & XM_IS_TXF_UR) != 0) {
3903 /* may NOT happen -> error log */
3904 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3905 }
3906
3907 if ((IStatus & XM_IS_TX_COMP) != 0) {
3908 /* not served here */
3909 }
3910
3911 if ((IStatus & XM_IS_RX_COMP) != 0) {
3912 /* not served here */
3913 }
3914} /* SkXmIrq */
3915
3916
3917/******************************************************************************
3918 *
3919 * SkGmIrq() - Interrupt Service Routine
3920 *
3921 * Description: services an Interrupt Request of the GMAC
3922 *
3923 * Note:
3924 *
3925 * Returns:
3926 * nothing
3927 */
3928void SkGmIrq(
3929SK_AC *pAC, /* adapter context */
3930SK_IOC IoC, /* IO context */
3931int Port) /* Port Index (MAC_1 + n) */
3932{
3933 SK_GEPORT *pPrt;
3934 SK_EVPARA Para;
3935 SK_U8 IStatus; /* Interrupt status */
3936
3937 pPrt = &pAC->GIni.GP[Port];
wdenk42d1f032003-10-15 23:53:47 +00003938
wdenk7152b1d2003-09-05 23:19:14 +00003939 SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
wdenk42d1f032003-10-15 23:53:47 +00003940
wdenk7152b1d2003-09-05 23:19:14 +00003941 /* LinkPartner Auto-negable? */
3942 SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
wdenk42d1f032003-10-15 23:53:47 +00003943
wdenk7152b1d2003-09-05 23:19:14 +00003944 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
3945 ("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
3946
3947 /* Combined Tx & Rx Counter Overflow SIRQ Event */
3948 if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
3949 /* these IRQs will be cleared by reading GMACs register */
3950 Para.Para32[0] = (SK_U32)Port;
3951 Para.Para32[1] = (SK_U32)IStatus;
3952 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
3953 }
3954
3955 if (IStatus & GM_IS_RX_FF_OR) {
3956 /* clear GMAC Rx FIFO Overrun IRQ */
3957 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
3958#ifdef DEBUG
3959 pPrt->PRxOverCnt++;
3960#endif /* DEBUG */
3961 }
3962
3963 if (IStatus & GM_IS_TX_FF_UR) {
3964 /* clear GMAC Tx FIFO Underrun IRQ */
3965 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
3966 /* may NOT happen -> error log */
3967 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
3968 }
3969
3970 if (IStatus & GM_IS_TX_COMPL) {
3971 /* not served here */
3972 }
3973
3974 if (IStatus & GM_IS_RX_COMPL) {
3975 /* not served here */
3976 }
3977} /* SkGmIrq */
3978
3979/******************************************************************************
3980 *
3981 * SkMacIrq() - Interrupt Service Routine for MAC
3982 *
3983 * Description: calls the Interrupt Service Routine dep. on board type
3984 *
3985 * Returns:
3986 * nothing
3987 */
3988void SkMacIrq(
3989SK_AC *pAC, /* adapter context */
3990SK_IOC IoC, /* IO context */
3991int Port) /* Port Index (MAC_1 + n) */
3992{
3993
3994 if (pAC->GIni.GIGenesis) {
3995 /* IRQ from XMAC */
3996 SkXmIrq(pAC, IoC, Port);
3997 }
3998 else {
3999 /* IRQ from GMAC */
4000 SkGmIrq(pAC, IoC, Port);
4001 }
4002} /* SkMacIrq */
4003
4004#endif /* !SK_DIAG */
4005
4006/******************************************************************************
4007 *
4008 * SkXmUpdateStats() - Force the XMAC to output the current statistic
4009 *
4010 * Description:
4011 * The XMAC holds its statistic internally. To obtain the current
4012 * values a command must be sent so that the statistic data will
4013 * be written to a predefined memory area on the adapter.
4014 *
4015 * Returns:
4016 * 0: success
4017 * 1: something went wrong
4018 */
4019int SkXmUpdateStats(
4020SK_AC *pAC, /* adapter context */
4021SK_IOC IoC, /* IO context */
4022unsigned int Port) /* Port Index (MAC_1 + n) */
4023{
4024 SK_GEPORT *pPrt;
4025 SK_U16 StatReg;
4026 int WaitIndex;
4027
4028 pPrt = &pAC->GIni.GP[Port];
4029 WaitIndex = 0;
4030
4031 /* Send an update command to XMAC specified */
4032 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
4033
4034 /*
4035 * It is an auto-clearing register. If the command bits
4036 * went to zero again, the statistics are transferred.
4037 * Normally the command should be executed immediately.
4038 * But just to be sure we execute a loop.
4039 */
4040 do {
4041
4042 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
wdenk42d1f032003-10-15 23:53:47 +00004043
wdenk7152b1d2003-09-05 23:19:14 +00004044 if (++WaitIndex > 10) {
4045
4046 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
4047
4048 return(1);
4049 }
4050 } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
wdenk42d1f032003-10-15 23:53:47 +00004051
wdenk7152b1d2003-09-05 23:19:14 +00004052 return(0);
4053} /* SkXmUpdateStats */
4054
4055/******************************************************************************
4056 *
4057 * SkGmUpdateStats() - Force the GMAC to output the current statistic
4058 *
4059 * Description:
4060 * Empty function for GMAC. Statistic data is accessible in direct way.
4061 *
4062 * Returns:
4063 * 0: success
4064 * 1: something went wrong
4065 */
4066int SkGmUpdateStats(
4067SK_AC *pAC, /* adapter context */
4068SK_IOC IoC, /* IO context */
4069unsigned int Port) /* Port Index (MAC_1 + n) */
4070{
4071 return(0);
4072}
4073
4074/******************************************************************************
4075 *
4076 * SkXmMacStatistic() - Get XMAC counter value
4077 *
4078 * Description:
4079 * Gets the 32bit counter value. Except for the octet counters
4080 * the lower 32bit are counted in hardware and the upper 32bit
4081 * must be counted in software by monitoring counter overflow interrupts.
4082 *
4083 * Returns:
4084 * 0: success
4085 * 1: something went wrong
4086 */
4087int SkXmMacStatistic(
4088SK_AC *pAC, /* adapter context */
4089SK_IOC IoC, /* IO context */
4090unsigned int Port, /* Port Index (MAC_1 + n) */
4091SK_U16 StatAddr, /* MIB counter base address */
4092SK_U32 *pVal) /* ptr to return statistic value */
4093{
4094 if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
wdenk42d1f032003-10-15 23:53:47 +00004095
wdenk7152b1d2003-09-05 23:19:14 +00004096 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
wdenk42d1f032003-10-15 23:53:47 +00004097
wdenk7152b1d2003-09-05 23:19:14 +00004098 return(1);
4099 }
wdenk42d1f032003-10-15 23:53:47 +00004100
wdenk7152b1d2003-09-05 23:19:14 +00004101 XM_IN32(IoC, Port, StatAddr, pVal);
4102
4103 return(0);
4104} /* SkXmMacStatistic */
4105
4106/******************************************************************************
4107 *
4108 * SkGmMacStatistic() - Get GMAC counter value
4109 *
4110 * Description:
4111 * Gets the 32bit counter value. Except for the octet counters
4112 * the lower 32bit are counted in hardware and the upper 32bit
4113 * must be counted in software by monitoring counter overflow interrupts.
4114 *
4115 * Returns:
4116 * 0: success
4117 * 1: something went wrong
4118 */
4119int SkGmMacStatistic(
4120SK_AC *pAC, /* adapter context */
4121SK_IOC IoC, /* IO context */
4122unsigned int Port, /* Port Index (MAC_1 + n) */
4123SK_U16 StatAddr, /* MIB counter base address */
4124SK_U32 *pVal) /* ptr to return statistic value */
4125{
4126
4127 if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
wdenk42d1f032003-10-15 23:53:47 +00004128
wdenk7152b1d2003-09-05 23:19:14 +00004129 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
wdenk42d1f032003-10-15 23:53:47 +00004130
wdenk7152b1d2003-09-05 23:19:14 +00004131 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4132 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
4133 return(1);
4134 }
wdenk42d1f032003-10-15 23:53:47 +00004135
wdenk7152b1d2003-09-05 23:19:14 +00004136 GM_IN32(IoC, Port, StatAddr, pVal);
4137
4138 return(0);
4139} /* SkGmMacStatistic */
4140
4141/******************************************************************************
4142 *
4143 * SkXmResetCounter() - Clear MAC statistic counter
4144 *
4145 * Description:
4146 * Force the XMAC to clear its statistic counter.
4147 *
4148 * Returns:
4149 * 0: success
4150 * 1: something went wrong
4151 */
4152int SkXmResetCounter(
4153SK_AC *pAC, /* adapter context */
4154SK_IOC IoC, /* IO context */
4155unsigned int Port) /* Port Index (MAC_1 + n) */
4156{
4157 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4158 /* Clear two times according to Errata #3 */
4159 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4160
4161 return(0);
4162} /* SkXmResetCounter */
4163
4164/******************************************************************************
4165 *
4166 * SkGmResetCounter() - Clear MAC statistic counter
4167 *
4168 * Description:
4169 * Force GMAC to clear its statistic counter.
4170 *
4171 * Returns:
4172 * 0: success
4173 * 1: something went wrong
4174 */
4175int SkGmResetCounter(
4176SK_AC *pAC, /* adapter context */
4177SK_IOC IoC, /* IO context */
4178unsigned int Port) /* Port Index (MAC_1 + n) */
4179{
4180 SK_U16 Reg; /* Phy Address Register */
4181 SK_U16 Word;
4182 int i;
4183
4184 GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4185
4186#ifndef VCPU
4187 /* set MIB Clear Counter Mode */
4188 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
wdenk42d1f032003-10-15 23:53:47 +00004189
wdenk7152b1d2003-09-05 23:19:14 +00004190 /* read all MIB Counters with Clear Mode set */
4191 for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4192 /* the reset is performed only when the lower 16 bits are read */
4193 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4194 }
wdenk42d1f032003-10-15 23:53:47 +00004195
wdenk7152b1d2003-09-05 23:19:14 +00004196 /* clear MIB Clear Counter Mode */
4197 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4198#endif /* !VCPU */
wdenk42d1f032003-10-15 23:53:47 +00004199
wdenk7152b1d2003-09-05 23:19:14 +00004200 return(0);
4201} /* SkGmResetCounter */
4202
4203/******************************************************************************
4204 *
4205 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4206 *
4207 * Description:
4208 * Checks the source causing an counter overflow interrupt. On success the
4209 * resulting counter overflow status is written to <pStatus>, whereas the
4210 * upper dword stores the XMAC ReceiveCounterEvent register and the lower
4211 * dword the XMAC TransmitCounterEvent register.
4212 *
4213 * Note:
4214 * For XMAC the interrupt source is a self-clearing register, so the source
4215 * must be checked only once. SIRQ module does another check to be sure
4216 * that no interrupt get lost during process time.
4217 *
4218 * Returns:
4219 * 0: success
4220 * 1: something went wrong
4221 */
4222int SkXmOverflowStatus(
4223SK_AC *pAC, /* adapter context */
4224SK_IOC IoC, /* IO context */
4225unsigned int Port, /* Port Index (MAC_1 + n) */
4226SK_U16 IStatus, /* Interupt Status from MAC */
4227SK_U64 *pStatus) /* ptr for return overflow status value */
4228{
4229 SK_U64 Status; /* Overflow status */
4230 SK_U32 RegVal;
4231
4232 Status = 0;
4233
4234 if ((IStatus & XM_IS_RXC_OV) != 0) {
4235
4236 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
4237 Status |= (SK_U64)RegVal << 32;
4238 }
wdenk42d1f032003-10-15 23:53:47 +00004239
wdenk7152b1d2003-09-05 23:19:14 +00004240 if ((IStatus & XM_IS_TXC_OV) != 0) {
4241
4242 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
4243 Status |= (SK_U64)RegVal;
4244 }
4245
4246 *pStatus = Status;
4247
4248 return(0);
4249} /* SkXmOverflowStatus */
4250
4251
4252/******************************************************************************
4253 *
4254 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4255 *
4256 * Description:
4257 * Checks the source causing an counter overflow interrupt. On success the
4258 * resulting counter overflow status is written to <pStatus>, whereas the
4259 * the following bit coding is used:
4260 * 63:56 - unused
4261 * 55:48 - TxRx interrupt register bit7:0
4262 * 32:47 - Rx interrupt register
4263 * 31:24 - unused
4264 * 23:16 - TxRx interrupt register bit15:8
4265 * 15:0 - Tx interrupt register
4266 *
4267 * Returns:
4268 * 0: success
4269 * 1: something went wrong
4270 */
4271int SkGmOverflowStatus(
4272SK_AC *pAC, /* adapter context */
4273SK_IOC IoC, /* IO context */
4274unsigned int Port, /* Port Index (MAC_1 + n) */
4275SK_U16 IStatus, /* Interupt Status from MAC */
4276SK_U64 *pStatus) /* ptr for return overflow status value */
4277{
4278 SK_U64 Status; /* Overflow status */
4279 SK_U16 RegVal;
4280
4281 Status = 0;
4282
4283 if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4284 /* this register is self-clearing after read */
4285 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4286 Status |= (SK_U64)RegVal << 32;
4287 }
wdenk42d1f032003-10-15 23:53:47 +00004288
wdenk7152b1d2003-09-05 23:19:14 +00004289 if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4290 /* this register is self-clearing after read */
4291 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4292 Status |= (SK_U64)RegVal;
4293 }
wdenk42d1f032003-10-15 23:53:47 +00004294
wdenk7152b1d2003-09-05 23:19:14 +00004295 /* this register is self-clearing after read */
4296 GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4297 /* Rx overflow interrupt register bits (LoByte)*/
4298 Status |= (SK_U64)((SK_U8)RegVal) << 48;
4299 /* Tx overflow interrupt register bits (HiByte)*/
4300 Status |= (SK_U64)(RegVal >> 8) << 16;
4301
4302 *pStatus = Status;
4303
4304 return(0);
4305} /* SkGmOverflowStatus */
4306
4307/******************************************************************************
4308 *
4309 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4310 *
4311 * Description:
4312 * starts the cable diagnostic test if 'StartTest' is true
4313 * gets the results if 'StartTest' is true
4314 *
4315 * NOTE: this test is meaningful only when link is down
wdenk42d1f032003-10-15 23:53:47 +00004316 *
wdenk7152b1d2003-09-05 23:19:14 +00004317 * Returns:
4318 * 0: success
4319 * 1: no YUKON copper
4320 * 2: test in progress
4321 */
4322int SkGmCableDiagStatus(
4323SK_AC *pAC, /* adapter context */
Wolfgang Denk53677ef2008-05-20 16:00:29 +02004324SK_IOC IoC, /* IO context */
wdenk7152b1d2003-09-05 23:19:14 +00004325int Port, /* Port Index (MAC_1 + n) */
4326SK_BOOL StartTest) /* flag for start / get result */
4327{
4328 int i;
4329 SK_U16 RegVal;
4330 SK_GEPORT *pPrt;
4331
4332 pPrt = &pAC->GIni.GP[Port];
4333
4334 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
wdenk42d1f032003-10-15 23:53:47 +00004335
wdenk7152b1d2003-09-05 23:19:14 +00004336 return(1);
4337 }
4338
4339 if (StartTest) {
4340 /* only start the cable test */
4341 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4342 /* apply TDR workaround from Marvell */
4343 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
wdenk42d1f032003-10-15 23:53:47 +00004344
wdenk7152b1d2003-09-05 23:19:14 +00004345 SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4346 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4347 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4348 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4349 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4350 }
4351
4352 /* set address to 0 for MDI[0] */
4353 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4354
4355 /* Read Cable Diagnostic Reg */
4356 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4357
4358 /* start Cable Diagnostic Test */
4359 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4360 (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
wdenk42d1f032003-10-15 23:53:47 +00004361
wdenk7152b1d2003-09-05 23:19:14 +00004362 return(0);
4363 }
wdenk42d1f032003-10-15 23:53:47 +00004364
wdenk7152b1d2003-09-05 23:19:14 +00004365 /* Read Cable Diagnostic Reg */
4366 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4367
4368 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4369 ("PHY Cable Diag.=0x%04X\n", RegVal));
4370
4371 if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4372 /* test is running */
4373 return(2);
4374 }
4375
4376 /* get the test results */
4377 for (i = 0; i < 4; i++) {
4378 /* set address to i for MDI[i] */
4379 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4380
4381 /* get Cable Diagnostic values */
4382 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4383
4384 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4385
4386 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4387 }
4388
4389 return(0);
4390} /* SkGmCableDiagStatus */
4391
wdenk7152b1d2003-09-05 23:19:14 +00004392/* End of file */