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