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