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