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