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