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