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