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