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