Merge /spare/repo/linux-2.6/
[pandora-kernel.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 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 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 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 /******************************************************************************
1235  *
1236  *      SkMacClearRst() - Clear the MAC reset
1237  *
1238  * Description: calls a clear MAC reset routine dep. on board type
1239  *
1240  * Returns:
1241  *      nothing
1242  */
1243 void SkMacClearRst(
1244 SK_AC   *pAC,   /* adapter context */
1245 SK_IOC  IoC,    /* IO context */
1246 int             Port)   /* Port Index (MAC_1 + n) */
1247 {
1248         
1249 #ifdef GENESIS
1250         if (pAC->GIni.GIGenesis) {
1251                 
1252                 SkXmClearRst(pAC, IoC, Port);
1253         }
1254 #endif /* GENESIS */
1255         
1256 #ifdef YUKON
1257         if (pAC->GIni.GIYukon) {
1258                 
1259                 SkGmClearRst(pAC, IoC, Port);
1260         }
1261 #endif /* YUKON */
1262
1263 }       /* SkMacClearRst */
1264
1265
1266 #ifdef GENESIS
1267 /******************************************************************************
1268  *
1269  *      SkXmInitMac() - Initialize the XMAC II
1270  *
1271  * Description:
1272  *      Initialize the XMAC of the specified port.
1273  *      The XMAC must be reset or stopped before calling this function.
1274  *
1275  * Note:
1276  *      The XMAC's Rx and Tx state machine is still disabled when returning.
1277  *
1278  * Returns:
1279  *      nothing
1280  */
1281 void SkXmInitMac(
1282 SK_AC   *pAC,           /* adapter context */
1283 SK_IOC  IoC,            /* IO context */
1284 int             Port)           /* Port Index (MAC_1 + n) */
1285 {
1286         SK_GEPORT       *pPrt;
1287         int                     i;
1288         SK_U16          SWord;
1289
1290         pPrt = &pAC->GIni.GP[Port];
1291
1292         if (pPrt->PState == SK_PRT_STOP) {
1293                 /* Port State: SK_PRT_STOP */
1294                 /* Verify that the reset bit is cleared */
1295                 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
1296
1297                 if ((SWord & MFF_SET_MAC_RST) != 0) {
1298                         /* PState does not match HW state */
1299                         SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1300                         /* Correct it */
1301                         pPrt->PState = SK_PRT_RESET;
1302                 }
1303         }
1304
1305         if (pPrt->PState == SK_PRT_RESET) {
1306
1307                 SkXmClearRst(pAC, IoC, Port);
1308
1309                 if (pPrt->PhyType != SK_PHY_XMAC) {
1310                         /* read Id from external PHY (all have the same address) */
1311                         SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
1312
1313                         /*
1314                          * Optimize MDIO transfer by suppressing preamble.
1315                          * Must be done AFTER first access to BCOM chip.
1316                          */
1317                         XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
1318                         
1319                         XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
1320
1321                         if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
1322                                 /*
1323                                  * Workaround BCOM Errata for the C0 type.
1324                                  * Write magic patterns to reserved registers.
1325                                  */
1326                                 i = 0;
1327                                 while (BcomRegC0Hack[i].PhyReg != 0) {
1328                                         SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
1329                                                 BcomRegC0Hack[i].PhyVal);
1330                                         i++;
1331                                 }
1332                         }
1333                         else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
1334                                 /*
1335                                  * Workaround BCOM Errata for the A1 type.
1336                                  * Write magic patterns to reserved registers.
1337                                  */
1338                                 i = 0;
1339                                 while (BcomRegA1Hack[i].PhyReg != 0) {
1340                                         SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
1341                                                 BcomRegA1Hack[i].PhyVal);
1342                                         i++;
1343                                 }
1344                         }
1345
1346                         /*
1347                          * Workaround BCOM Errata (#10523) for all BCom PHYs.
1348                          * Disable Power Management after reset.
1349                          */
1350                         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
1351                         
1352                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
1353                                 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
1354
1355                         /* PHY LED initialization is done in SkGeXmitLED() */
1356                 }
1357
1358                 /* Dummy read the Interrupt source register */
1359                 XM_IN16(IoC, Port, XM_ISRC, &SWord);
1360                 
1361                 /*
1362                  * The auto-negotiation process starts immediately after
1363                  * clearing the reset. The auto-negotiation process should be
1364                  * started by the SIRQ, therefore stop it here immediately.
1365                  */
1366                 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
1367
1368 #ifdef TEST_ONLY
1369                 /* temp. code: enable signal detect */
1370                 /* WARNING: do not override GMII setting above */
1371                 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
1372 #endif
1373         }
1374
1375         /*
1376          * configure the XMACs Station Address
1377          * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
1378          * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
1379          */
1380         for (i = 0; i < 3; i++) {
1381                 /*
1382                  * The following 2 statements are together endianess
1383                  * independent. Remember this when changing.
1384                  */
1385                 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1386                 
1387                 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
1388         }
1389
1390         /* Tx Inter Packet Gap (XM_TX_IPG):     use default */
1391         /* Tx High Water Mark (XM_TX_HI_WM):    use default */
1392         /* Tx Low Water Mark (XM_TX_LO_WM):     use default */
1393         /* Host Request Threshold (XM_HT_THR):  use default */
1394         /* Rx Request Threshold (XM_RX_THR):    use default */
1395         /* Rx Low Water Mark (XM_RX_LO_WM):     use default */
1396
1397         /* configure Rx High Water Mark (XM_RX_HI_WM) */
1398         XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
1399
1400         /* Configure Tx Request Threshold */
1401         SWord = SK_XM_THR_SL;                           /* for single port */
1402
1403         if (pAC->GIni.GIMacsFound > 1) {
1404                 switch (pAC->GIni.GIPortUsage) {
1405                 case SK_RED_LINK:
1406                         SWord = SK_XM_THR_REDL;         /* redundant link */
1407                         break;
1408                 case SK_MUL_LINK:
1409                         SWord = SK_XM_THR_MULL;         /* load balancing */
1410                         break;
1411                 case SK_JUMBO_LINK:
1412                         SWord = SK_XM_THR_JUMBO;        /* jumbo frames */
1413                         break;
1414                 default:
1415                         SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
1416                         break;
1417                 }
1418         }
1419         XM_OUT16(IoC, Port, XM_TX_THR, SWord);
1420
1421         /* setup register defaults for the Tx Command Register */
1422         XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
1423
1424         /* setup register defaults for the Rx Command Register */
1425         SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
1426
1427         if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1428                 SWord |= XM_RX_BIG_PK_OK;
1429         }
1430
1431         if (pPrt->PLinkMode == SK_LMODE_HALF) {
1432                 /*
1433                  * If in manual half duplex mode the other side might be in
1434                  * full duplex mode, so ignore if a carrier extension is not seen
1435                  * on frames received
1436                  */
1437                 SWord |= XM_RX_DIS_CEXT;
1438         }
1439         
1440         XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
1441
1442         /*
1443          * setup register defaults for the Mode Register
1444          *      - Don't strip error frames to avoid Store & Forward
1445          *        on the Rx side.
1446          *      - Enable 'Check Station Address' bit
1447          *      - Enable 'Check Address Array' bit
1448          */
1449         XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
1450
1451         /*
1452          * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
1453          *      - Enable all bits excepting 'Octets Rx OK Low CntOv'
1454          *        and 'Octets Rx OK Hi Cnt Ov'.
1455          */
1456         XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
1457
1458         /*
1459          * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
1460          *      - Enable all bits excepting 'Octets Tx OK Low CntOv'
1461          *        and 'Octets Tx OK Hi Cnt Ov'.
1462          */
1463         XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
1464
1465         /*
1466          * Do NOT init XMAC interrupt mask here.
1467          * All interrupts remain disable until link comes up!
1468          */
1469
1470         /*
1471          * Any additional configuration changes may be done now.
1472          * The last action is to enable the Rx and Tx state machine.
1473          * This should be done after the auto-negotiation process
1474          * has been completed successfully.
1475          */
1476 }       /* SkXmInitMac */
1477 #endif /* GENESIS */
1478
1479
1480 #ifdef YUKON
1481 /******************************************************************************
1482  *
1483  *      SkGmInitMac() - Initialize the GMAC
1484  *
1485  * Description:
1486  *      Initialize the GMAC of the specified port.
1487  *      The GMAC must be reset or stopped before calling this function.
1488  *
1489  * Note:
1490  *      The GMAC's Rx and Tx state machine is still disabled when returning.
1491  *
1492  * Returns:
1493  *      nothing
1494  */
1495 void SkGmInitMac(
1496 SK_AC   *pAC,           /* adapter context */
1497 SK_IOC  IoC,            /* IO context */
1498 int             Port)           /* Port Index (MAC_1 + n) */
1499 {
1500         SK_GEPORT       *pPrt;
1501         int                     i;
1502         SK_U16          SWord;
1503         SK_U32          DWord;
1504
1505         pPrt = &pAC->GIni.GP[Port];
1506
1507         if (pPrt->PState == SK_PRT_STOP) {
1508                 /* Port State: SK_PRT_STOP */
1509                 /* Verify that the reset bit is cleared */
1510                 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
1511                 
1512                 if ((DWord & GMC_RST_SET) != 0) {
1513                         /* PState does not match HW state */
1514                         SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
1515                         /* Correct it */
1516                         pPrt->PState = SK_PRT_RESET;
1517                 }
1518         }
1519
1520         if (pPrt->PState == SK_PRT_RESET) {
1521                 
1522                 SkGmHardRst(pAC, IoC, Port);
1523
1524                 SkGmClearRst(pAC, IoC, Port);
1525                 
1526                 /* Auto-negotiation ? */
1527                 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1528                         /* Auto-negotiation disabled */
1529
1530                         /* get General Purpose Control */
1531                         GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
1532
1533                         /* disable auto-update for speed, duplex and flow-control */
1534                         SWord |= GM_GPCR_AU_ALL_DIS;
1535                         
1536                         /* setup General Purpose Control Register */
1537                         GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1538                         
1539                         SWord = GM_GPCR_AU_ALL_DIS;
1540                 }
1541                 else {
1542                         SWord = 0;
1543                 }
1544
1545                 /* speed settings */
1546                 switch (pPrt->PLinkSpeed) {
1547                 case SK_LSPEED_AUTO:
1548                 case SK_LSPEED_1000MBPS:
1549                         SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
1550                         break;
1551                 case SK_LSPEED_100MBPS:
1552                         SWord |= GM_GPCR_SPEED_100;
1553                         break;
1554                 case SK_LSPEED_10MBPS:
1555                         break;
1556                 }
1557
1558                 /* duplex settings */
1559                 if (pPrt->PLinkMode != SK_LMODE_HALF) {
1560                         /* set full duplex */
1561                         SWord |= GM_GPCR_DUP_FULL;
1562                 }
1563
1564                 /* flow-control settings */
1565                 switch (pPrt->PFlowCtrlMode) {
1566                 case SK_FLOW_MODE_NONE:
1567                         /* set Pause Off */
1568                         SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
1569                         /* disable Tx & Rx flow-control */
1570                         SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1571                         break;
1572                 case SK_FLOW_MODE_LOC_SEND:
1573                         /* disable Rx flow-control */
1574                         SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
1575                         break;
1576                 case SK_FLOW_MODE_SYMMETRIC:
1577                 case SK_FLOW_MODE_SYM_OR_REM:
1578                         /* enable Tx & Rx flow-control */
1579                         break;
1580                 }
1581
1582                 /* setup General Purpose Control Register */
1583                 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
1584
1585                 /* dummy read the Interrupt Source Register */
1586                 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
1587                 
1588 #ifndef VCPU
1589                 /* read Id from PHY */
1590                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
1591                 
1592                 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
1593 #endif /* VCPU */
1594         }
1595
1596         (void)SkGmResetCounter(pAC, IoC, Port);
1597
1598         /* setup Transmit Control Register */
1599         GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
1600
1601         /* setup Receive Control Register */
1602         GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
1603                 GM_RXCR_CRC_DIS);
1604
1605         /* setup Transmit Flow Control Register */
1606         GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
1607
1608         /* setup Transmit Parameter Register */
1609 #ifdef VCPU
1610         GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
1611 #endif /* VCPU */
1612
1613     SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
1614                         TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
1615                         TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
1616         
1617         GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
1618
1619         /* configure the Serial Mode Register */
1620 #ifdef VCPU
1621         GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
1622 #endif /* VCPU */
1623         
1624         SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
1625
1626         if (pPrt->PMacLimit4) {
1627                 /* reset of collision counter after 4 consecutive collisions */
1628                 SWord |= GM_SMOD_LIMIT_4;
1629         }
1630
1631         if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
1632                 /* enable jumbo mode (Max. Frame Length = 9018) */
1633                 SWord |= GM_SMOD_JUMBO_ENA;
1634         }
1635         
1636         GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
1637         
1638         /*
1639          * configure the GMACs Station Addresses
1640          * in PROM you can find our addresses at:
1641          * B2_MAC_1 = xx xx xx xx xx x0 virtual address
1642          * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
1643          * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
1644          */
1645
1646         for (i = 0; i < 3; i++) {
1647                 /*
1648                  * The following 2 statements are together endianess
1649                  * independent. Remember this when changing.
1650                  */
1651                 /* physical address: will be used for pause frames */
1652                 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
1653
1654 #ifdef WA_DEV_16
1655                 /* WA for deviation #16 */
1656                 if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
1657                         /* swap the address bytes */
1658                         SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
1659
1660                         /* write to register in reversed order */
1661                         GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
1662                 }
1663                 else {
1664                         GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1665                 }
1666 #else           
1667                 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
1668 #endif /* WA_DEV_16 */
1669                 
1670                 /* virtual address: will be used for data */
1671                 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
1672
1673                 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
1674                 
1675                 /* reset Multicast filtering Hash registers 1-3 */
1676                 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
1677         }
1678
1679         /* reset Multicast filtering Hash register 4 */
1680         GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
1681
1682         /* enable interrupt mask for counter overflows */
1683         GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
1684         GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
1685         GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
1686
1687 #if defined(SK_DIAG) || defined(DEBUG)
1688         /* read General Purpose Status */
1689         GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
1690         
1691         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1692                 ("MAC Stat Reg.=0x%04X\n", SWord));
1693 #endif /* SK_DIAG || DEBUG */
1694
1695 #ifdef SK_DIAG
1696         c_print("MAC Stat Reg=0x%04X\n", SWord);
1697 #endif /* SK_DIAG */
1698
1699 }       /* SkGmInitMac */
1700 #endif /* YUKON */
1701
1702
1703 #ifdef GENESIS
1704 /******************************************************************************
1705  *
1706  *      SkXmInitDupMd() - Initialize the XMACs Duplex Mode
1707  *
1708  * Description:
1709  *      This function initializes the XMACs Duplex Mode.
1710  *      It should be called after successfully finishing
1711  *      the Auto-negotiation Process
1712  *
1713  * Returns:
1714  *      nothing
1715  */
1716 void SkXmInitDupMd(
1717 SK_AC   *pAC,           /* adapter context */
1718 SK_IOC  IoC,            /* IO context */
1719 int             Port)           /* Port Index (MAC_1 + n) */
1720 {
1721         switch (pAC->GIni.GP[Port].PLinkModeStatus) {
1722         case SK_LMODE_STAT_AUTOHALF:
1723         case SK_LMODE_STAT_HALF:
1724                 /* Configuration Actions for Half Duplex Mode */
1725                 /*
1726                  * XM_BURST = default value. We are probable not quick
1727                  *      enough at the 'XMAC' bus to burst 8kB.
1728                  *      The XMAC stops bursting if no transmit frames
1729                  *      are available or the burst limit is exceeded.
1730                  */
1731                 /* XM_TX_RT_LIM = default value (15) */
1732                 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
1733                 break;
1734         case SK_LMODE_STAT_AUTOFULL:
1735         case SK_LMODE_STAT_FULL:
1736                 /* Configuration Actions for Full Duplex Mode */
1737                 /*
1738                  * The duplex mode is configured by the PHY,
1739                  * therefore it seems to be that there is nothing
1740                  * to do here.
1741                  */
1742                 break;
1743         case SK_LMODE_STAT_UNKNOWN:
1744         default:
1745                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
1746                 break;
1747         }
1748 }       /* SkXmInitDupMd */
1749
1750
1751 /******************************************************************************
1752  *
1753  *      SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
1754  *
1755  * Description:
1756  *      This function initializes the Pause Mode which should
1757  *      be used for this port.
1758  *      It should be called after successfully finishing
1759  *      the Auto-negotiation Process
1760  *
1761  * Returns:
1762  *      nothing
1763  */
1764 void SkXmInitPauseMd(
1765 SK_AC   *pAC,           /* adapter context */
1766 SK_IOC  IoC,            /* IO context */
1767 int             Port)           /* Port Index (MAC_1 + n) */
1768 {
1769         SK_GEPORT       *pPrt;
1770         SK_U32          DWord;
1771         SK_U16          Word;
1772
1773         pPrt = &pAC->GIni.GP[Port];
1774
1775         XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
1776         
1777         if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
1778                 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1779
1780                 /* Disable Pause Frame Reception */
1781                 Word |= XM_MMU_IGN_PF;
1782         }
1783         else {
1784                 /*
1785                  * enabling pause frame reception is required for 1000BT
1786                  * because the XMAC is not reset if the link is going down
1787                  */
1788                 /* Enable Pause Frame Reception */
1789                 Word &= ~XM_MMU_IGN_PF;
1790         }       
1791         
1792         XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
1793
1794         XM_IN32(IoC, Port, XM_MODE, &DWord);
1795
1796         if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
1797                 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
1798
1799                 /*
1800                  * Configure Pause Frame Generation
1801                  * Use internal and external Pause Frame Generation.
1802                  * Sending pause frames is edge triggered.
1803                  * Send a Pause frame with the maximum pause time if
1804                  * internal oder external FIFO full condition occurs.
1805                  * Send a zero pause time frame to re-start transmission.
1806                  */
1807
1808                 /* XM_PAUSE_DA = '010000C28001' (default) */
1809
1810                 /* XM_MAC_PTIME = 0xffff (maximum) */
1811                 /* remember this value is defined in big endian (!) */
1812                 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
1813
1814                 /* Set Pause Mode in Mode Register */
1815                 DWord |= XM_PAUSE_MODE;
1816
1817                 /* Set Pause Mode in MAC Rx FIFO */
1818                 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
1819         }
1820         else {
1821                 /*
1822                  * disable pause frame generation is required for 1000BT
1823                  * because the XMAC is not reset if the link is going down
1824                  */
1825                 /* Disable Pause Mode in Mode Register */
1826                 DWord &= ~XM_PAUSE_MODE;
1827
1828                 /* Disable Pause Mode in MAC Rx FIFO */
1829                 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
1830         }
1831         
1832         XM_OUT32(IoC, Port, XM_MODE, DWord);
1833 }       /* SkXmInitPauseMd*/
1834
1835
1836 /******************************************************************************
1837  *
1838  *      SkXmInitPhyXmac() - Initialize the XMAC Phy registers
1839  *
1840  * Description: initializes all the XMACs Phy registers
1841  *
1842  * Note:
1843  *
1844  * Returns:
1845  *      nothing
1846  */
1847 static void SkXmInitPhyXmac(
1848 SK_AC   *pAC,           /* adapter context */
1849 SK_IOC  IoC,            /* IO context */
1850 int             Port,           /* Port Index (MAC_1 + n) */
1851 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
1852 {
1853         SK_GEPORT       *pPrt;
1854         SK_U16          Ctrl;
1855
1856         pPrt = &pAC->GIni.GP[Port];
1857         Ctrl = 0;
1858         
1859         /* Auto-negotiation ? */
1860         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1861                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1862                         ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
1863                 /* Set DuplexMode in Config register */
1864                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
1865                         Ctrl |= PHY_CT_DUP_MD;
1866                 }
1867
1868                 /*
1869                  * Do NOT enable Auto-negotiation here. This would hold
1870                  * the link down because no IDLEs are transmitted
1871                  */
1872         }
1873         else {
1874                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1875                         ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
1876                 /* Set Auto-negotiation advertisement */
1877
1878                 /* Set Full/half duplex capabilities */
1879                 switch (pPrt->PLinkMode) {
1880                 case SK_LMODE_AUTOHALF:
1881                         Ctrl |= PHY_X_AN_HD;
1882                         break;
1883                 case SK_LMODE_AUTOFULL:
1884                         Ctrl |= PHY_X_AN_FD;
1885                         break;
1886                 case SK_LMODE_AUTOBOTH:
1887                         Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
1888                         break;
1889                 default:
1890                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
1891                                 SKERR_HWI_E015MSG);
1892                 }
1893
1894                 /* Set Flow-control capabilities */
1895                 switch (pPrt->PFlowCtrlMode) {
1896                 case SK_FLOW_MODE_NONE:
1897                         Ctrl |= PHY_X_P_NO_PAUSE;
1898                         break;
1899                 case SK_FLOW_MODE_LOC_SEND:
1900                         Ctrl |= PHY_X_P_ASYM_MD;
1901                         break;
1902                 case SK_FLOW_MODE_SYMMETRIC:
1903                         Ctrl |= PHY_X_P_SYM_MD;
1904                         break;
1905                 case SK_FLOW_MODE_SYM_OR_REM:
1906                         Ctrl |= PHY_X_P_BOTH_MD;
1907                         break;
1908                 default:
1909                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
1910                                 SKERR_HWI_E016MSG);
1911                 }
1912
1913                 /* Write AutoNeg Advertisement Register */
1914                 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
1915
1916                 /* Restart Auto-negotiation */
1917                 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
1918         }
1919
1920         if (DoLoop) {
1921                 /* Set the Phy Loopback bit, too */
1922                 Ctrl |= PHY_CT_LOOP;
1923         }
1924
1925         /* Write to the Phy control register */
1926         SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
1927 }       /* SkXmInitPhyXmac */
1928
1929
1930 /******************************************************************************
1931  *
1932  *      SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
1933  *
1934  * Description: initializes all the Broadcom Phy registers
1935  *
1936  * Note:
1937  *
1938  * Returns:
1939  *      nothing
1940  */
1941 static void SkXmInitPhyBcom(
1942 SK_AC   *pAC,           /* adapter context */
1943 SK_IOC  IoC,            /* IO context */
1944 int             Port,           /* Port Index (MAC_1 + n) */
1945 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
1946 {
1947         SK_GEPORT       *pPrt;
1948         SK_U16          Ctrl1;
1949         SK_U16          Ctrl2;
1950         SK_U16          Ctrl3;
1951         SK_U16          Ctrl4;
1952         SK_U16          Ctrl5;
1953
1954         Ctrl1 = PHY_CT_SP1000;
1955         Ctrl2 = 0;
1956         Ctrl3 = PHY_SEL_TYPE;
1957         Ctrl4 = PHY_B_PEC_EN_LTR;
1958         Ctrl5 = PHY_B_AC_TX_TST;
1959
1960         pPrt = &pAC->GIni.GP[Port];
1961
1962         /* manually Master/Slave ? */
1963         if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
1964                 Ctrl2 |= PHY_B_1000C_MSE;
1965                 
1966                 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
1967                         Ctrl2 |= PHY_B_1000C_MSC;
1968                 }
1969         }
1970         /* Auto-negotiation ? */
1971         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1972                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1973                         ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
1974                 /* Set DuplexMode in Config register */
1975                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
1976                         Ctrl1 |= PHY_CT_DUP_MD;
1977                 }
1978
1979                 /* Determine Master/Slave manually if not already done */
1980                 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
1981                         Ctrl2 |= PHY_B_1000C_MSE;       /* set it to Slave */
1982                 }
1983
1984                 /*
1985                  * Do NOT enable Auto-negotiation here. This would hold
1986                  * the link down because no IDLES are transmitted
1987                  */
1988         }
1989         else {
1990                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1991                         ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
1992                 /* Set Auto-negotiation advertisement */
1993
1994                 /*
1995                  * Workaround BCOM Errata #1 for the C5 type.
1996                  * 1000Base-T Link Acquisition Failure in Slave Mode
1997                  * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
1998                  */
1999                 Ctrl2 |= PHY_B_1000C_RD;
2000                 
2001                  /* Set Full/half duplex capabilities */
2002                 switch (pPrt->PLinkMode) {
2003                 case SK_LMODE_AUTOHALF:
2004                         Ctrl2 |= PHY_B_1000C_AHD;
2005                         break;
2006                 case SK_LMODE_AUTOFULL:
2007                         Ctrl2 |= PHY_B_1000C_AFD;
2008                         break;
2009                 case SK_LMODE_AUTOBOTH:
2010                         Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
2011                         break;
2012                 default:
2013                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2014                                 SKERR_HWI_E015MSG);
2015                 }
2016
2017                 /* Set Flow-control capabilities */
2018                 switch (pPrt->PFlowCtrlMode) {
2019                 case SK_FLOW_MODE_NONE:
2020                         Ctrl3 |= PHY_B_P_NO_PAUSE;
2021                         break;
2022                 case SK_FLOW_MODE_LOC_SEND:
2023                         Ctrl3 |= PHY_B_P_ASYM_MD;
2024                         break;
2025                 case SK_FLOW_MODE_SYMMETRIC:
2026                         Ctrl3 |= PHY_B_P_SYM_MD;
2027                         break;
2028                 case SK_FLOW_MODE_SYM_OR_REM:
2029                         Ctrl3 |= PHY_B_P_BOTH_MD;
2030                         break;
2031                 default:
2032                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2033                                 SKERR_HWI_E016MSG);
2034                 }
2035
2036                 /* Restart Auto-negotiation */
2037                 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
2038         }
2039         
2040         /* Initialize LED register here? */
2041         /* No. Please do it in SkDgXmitLed() (if required) and swap
2042            init order of LEDs and XMAC. (MAl) */
2043         
2044         /* Write 1000Base-T Control Register */
2045         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
2046         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2047                 ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2048         
2049         /* Write AutoNeg Advertisement Register */
2050         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
2051         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2052                 ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2053         
2054         if (DoLoop) {
2055                 /* Set the Phy Loopback bit, too */
2056                 Ctrl1 |= PHY_CT_LOOP;
2057         }
2058
2059         if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
2060                 /* configure FIFO to high latency for transmission of ext. packets */
2061                 Ctrl4 |= PHY_B_PEC_HIGH_LA;
2062
2063                 /* configure reception of extended packets */
2064                 Ctrl5 |= PHY_B_AC_LONG_PACK;
2065
2066                 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
2067         }
2068
2069         /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
2070         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
2071         
2072         /* Write to the Phy control register */
2073         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
2074         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2075                 ("PHY Control Reg=0x%04X\n", Ctrl1));
2076 }       /* SkXmInitPhyBcom */
2077 #endif /* GENESIS */
2078
2079
2080 #ifdef YUKON
2081 #ifndef SK_SLIM
2082 /******************************************************************************
2083  *
2084  *      SkGmEnterLowPowerMode()
2085  *
2086  * Description: 
2087  *      This function sets the Marvell Alaska PHY to the low power mode
2088  *      given by parameter mode.
2089  *      The following low power modes are available:
2090  *              
2091  *              - Coma Mode (Deep Sleep):
2092  *                      Power consumption: ~15 - 30 mW
2093  *                      The PHY cannot wake up on its own.
2094  *
2095  *              - IEEE 22.2.4.1.5 compatible power down mode
2096  *                      Power consumption: ~240 mW
2097  *                      The PHY cannot wake up on its own.
2098  *
2099  *              - energy detect mode
2100  *                      Power consumption: ~160 mW
2101  *                      The PHY can wake up on its own by detecting activity
2102  *                      on the CAT 5 cable.
2103  *
2104  *              - energy detect plus mode
2105  *                      Power consumption: ~150 mW
2106  *                      The PHY can wake up on its own by detecting activity
2107  *                      on the CAT 5 cable.
2108  *                      Connected devices can be woken up by sending normal link
2109  *                      pulses every one second.
2110  *
2111  * Note:
2112  *
2113  * Returns:
2114  *              0: ok
2115  *              1: error
2116  */
2117 int SkGmEnterLowPowerMode(
2118 SK_AC   *pAC,           /* adapter context */
2119 SK_IOC  IoC,            /* IO context */
2120 int             Port,           /* Port Index (e.g. MAC_1) */
2121 SK_U8   Mode)           /* low power mode */
2122 {
2123         SK_U16  Word;
2124         SK_U32  DWord;
2125         SK_U8   LastMode;
2126         int             Ret = 0;
2127
2128         if (pAC->GIni.GIYukonLite &&
2129             pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
2130
2131                 /* save current power mode */
2132                 LastMode = pAC->GIni.GP[Port].PPhyPowerState;
2133                 pAC->GIni.GP[Port].PPhyPowerState = Mode;
2134
2135                 switch (Mode) {
2136                         /* coma mode (deep sleep) */
2137                         case PHY_PM_DEEP_SLEEP:
2138                                 /* setup General Purpose Control Register */
2139                                 GM_OUT16(IoC, 0, GM_GP_CTRL, GM_GPCR_FL_PASS |
2140                                         GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
2141
2142                                 /* apply COMA mode workaround */
2143                                 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001f);
2144                                 SkGmPhyWrite(pAC, IoC, Port, 30, 0xfff3);
2145
2146                                 SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
2147
2148                                 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
2149                                 
2150                                 /* Set PHY to Coma Mode */
2151                                 SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord | PCI_PHY_COMA);
2152                                 
2153                                 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
2154
2155                         break;
2156                         
2157                         /* IEEE 22.2.4.1.5 compatible power down mode */
2158                         case PHY_PM_IEEE_POWER_DOWN:
2159                                 /*
2160                                  * - disable MAC 125 MHz clock
2161                                  * - allow MAC power down
2162                                  */
2163                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2164                                 Word |= PHY_M_PC_DIS_125CLK;
2165                                 Word &= ~PHY_M_PC_MAC_POW_UP;
2166                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2167
2168                                 /*
2169                                  * register changes must be followed by a software
2170                                  * reset to take effect
2171                                  */
2172                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2173                                 Word |= PHY_CT_RESET;
2174                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2175
2176                                 /* switch IEEE compatible power down mode on */
2177                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2178                                 Word |= PHY_CT_PDOWN;
2179                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2180                         break;
2181
2182                         /* energy detect and energy detect plus mode */
2183                         case PHY_PM_ENERGY_DETECT:
2184                         case PHY_PM_ENERGY_DETECT_PLUS:
2185                                 /*
2186                                  * - disable MAC 125 MHz clock
2187                                  */
2188                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2189                                 Word |= PHY_M_PC_DIS_125CLK;
2190                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2191                                 
2192                                 /* activate energy detect mode 1 */
2193                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2194
2195                                 /* energy detect mode */
2196                                 if (Mode == PHY_PM_ENERGY_DETECT) {
2197                                         Word |= PHY_M_PC_EN_DET;
2198                                 }
2199                                 /* energy detect plus mode */
2200                                 else {
2201                                         Word |= PHY_M_PC_EN_DET_PLUS;
2202                                 }
2203
2204                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2205
2206                                 /*
2207                                  * reinitialize the PHY to force a software reset
2208                                  * which is necessary after the register settings
2209                                  * for the energy detect modes.
2210                                  * Furthermore reinitialisation prevents that the
2211                                  * PHY is running out of a stable state.
2212                                  */
2213                                 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
2214                         break;
2215
2216                         /* don't change current power mode */
2217                         default:
2218                                 pAC->GIni.GP[Port].PPhyPowerState = LastMode;
2219                                 Ret = 1;
2220                         break;
2221                 }
2222         }
2223         /* low power modes are not supported by this chip */
2224         else {
2225                 Ret = 1;
2226         }
2227
2228         return(Ret);
2229
2230 }       /* SkGmEnterLowPowerMode */
2231
2232 /******************************************************************************
2233  *
2234  *      SkGmLeaveLowPowerMode()
2235  *
2236  * Description: 
2237  *      Leave the current low power mode and switch to normal mode
2238  *
2239  * Note:
2240  *
2241  * Returns:
2242  *              0:      ok
2243  *              1:      error
2244  */
2245 int SkGmLeaveLowPowerMode(
2246 SK_AC   *pAC,           /* adapter context */
2247 SK_IOC  IoC,            /* IO context */
2248 int             Port)           /* Port Index (e.g. MAC_1) */
2249 {
2250         SK_U32  DWord;
2251         SK_U16  Word;
2252         SK_U8   LastMode;
2253         int             Ret = 0;
2254
2255         if (pAC->GIni.GIYukonLite &&
2256                 pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
2257
2258                 /* save current power mode */
2259                 LastMode = pAC->GIni.GP[Port].PPhyPowerState;
2260                 pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
2261
2262                 switch (LastMode) {
2263                         /* coma mode (deep sleep) */
2264                         case PHY_PM_DEEP_SLEEP:
2265                                 SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
2266
2267                                 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
2268                                 
2269                                 /* Release PHY from Coma Mode */
2270                                 SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord & ~PCI_PHY_COMA);
2271                                 
2272                                 SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
2273                                 
2274                                 SK_IN32(IoC, B2_GP_IO, &DWord);
2275
2276                                 /* set to output */
2277                                 DWord |= (GP_DIR_9 | GP_IO_9);
2278
2279                                 /* set PHY reset */
2280                                 SK_OUT32(IoC, B2_GP_IO, DWord);
2281
2282                                 DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
2283
2284                                 /* clear PHY reset */
2285                                 SK_OUT32(IoC, B2_GP_IO, DWord);
2286                         break;
2287                         
2288                         /* IEEE 22.2.4.1.5 compatible power down mode */
2289                         case PHY_PM_IEEE_POWER_DOWN:
2290                                 /*
2291                                  * - enable MAC 125 MHz clock
2292                                  * - set MAC power up
2293                                  */
2294                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2295                                 Word &= ~PHY_M_PC_DIS_125CLK;
2296                                 Word |= PHY_M_PC_MAC_POW_UP;
2297                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2298
2299                                 /*
2300                                  * register changes must be followed by a software
2301                                  * reset to take effect
2302                                  */
2303                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2304                                 Word |= PHY_CT_RESET;
2305                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2306
2307                                 /* switch IEEE compatible power down mode off */
2308                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
2309                                 Word &= ~PHY_CT_PDOWN;
2310                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
2311                         break;
2312
2313                         /* energy detect and energy detect plus mode */
2314                         case PHY_PM_ENERGY_DETECT:
2315                         case PHY_PM_ENERGY_DETECT_PLUS:
2316                                 /*
2317                                  * - enable MAC 125 MHz clock
2318                                  */
2319                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2320                                 Word &= ~PHY_M_PC_DIS_125CLK;
2321                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2322                                 
2323                                 /* disable energy detect mode */
2324                                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
2325                                 Word &= ~PHY_M_PC_EN_DET_MSK;
2326                                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
2327
2328                                 /*
2329                                  * reinitialize the PHY to force a software reset
2330                                  * which is necessary after the register settings
2331                                  * for the energy detect modes.
2332                                  * Furthermore reinitialisation prevents that the
2333                                  * PHY is running out of a stable state.
2334                                  */
2335                                 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
2336                         break;
2337
2338                         /* don't change current power mode */
2339                         default:
2340                                 pAC->GIni.GP[Port].PPhyPowerState = LastMode;
2341                                 Ret = 1;
2342                         break;
2343                 }
2344         }
2345         /* low power modes are not supported by this chip */
2346         else {
2347                 Ret = 1;
2348         }
2349
2350         return(Ret);
2351
2352 }       /* SkGmLeaveLowPowerMode */
2353 #endif /* !SK_SLIM */
2354
2355
2356 /******************************************************************************
2357  *
2358  *      SkGmInitPhyMarv() - Initialize the Marvell Phy registers
2359  *
2360  * Description: initializes all the Marvell Phy registers
2361  *
2362  * Note:
2363  *
2364  * Returns:
2365  *      nothing
2366  */
2367 static void SkGmInitPhyMarv(
2368 SK_AC   *pAC,           /* adapter context */
2369 SK_IOC  IoC,            /* IO context */
2370 int             Port,           /* Port Index (MAC_1 + n) */
2371 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
2372 {
2373         SK_GEPORT       *pPrt;
2374         SK_U16          PhyCtrl;
2375         SK_U16          C1000BaseT;
2376         SK_U16          AutoNegAdv;
2377         SK_U16          ExtPhyCtrl;
2378         SK_U16          LedCtrl;
2379         SK_BOOL         AutoNeg;
2380 #if defined(SK_DIAG) || defined(DEBUG)
2381         SK_U16          PhyStat;
2382         SK_U16          PhyStat1;
2383         SK_U16          PhySpecStat;
2384 #endif /* SK_DIAG || DEBUG */
2385
2386         pPrt = &pAC->GIni.GP[Port];
2387
2388         /* Auto-negotiation ? */
2389         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2390                 AutoNeg = SK_FALSE;
2391         }
2392         else {
2393                 AutoNeg = SK_TRUE;
2394         }
2395         
2396         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2397                 ("InitPhyMarv: Port %d, auto-negotiation %s\n",
2398                  Port, AutoNeg ? "ON" : "OFF"));
2399
2400 #ifdef VCPU
2401         VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
2402                 Port, DoLoop);
2403 #else /* VCPU */
2404         if (DoLoop) {
2405                 /* Set 'MAC Power up'-bit, set Manual MDI configuration */
2406                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2407                         PHY_M_PC_MAC_POW_UP);
2408         }
2409         else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
2410                 /* Read Ext. PHY Specific Control */
2411                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2412                 
2413                 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
2414                         PHY_M_EC_MAC_S_MSK);
2415                 
2416                 ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
2417                         PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
2418         
2419                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
2420                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2421                         ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2422         }
2423
2424         /* Read PHY Control */
2425         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2426
2427         if (!AutoNeg) {
2428                 /* Disable Auto-negotiation */
2429                 PhyCtrl &= ~PHY_CT_ANE;
2430         }
2431
2432         PhyCtrl |= PHY_CT_RESET;
2433         /* Assert software reset */
2434         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2435 #endif /* VCPU */
2436
2437         PhyCtrl = 0 /* PHY_CT_COL_TST */;
2438         C1000BaseT = 0;
2439         AutoNegAdv = PHY_SEL_TYPE;
2440
2441         /* manually Master/Slave ? */
2442         if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2443                 /* enable Manual Master/Slave */
2444                 C1000BaseT |= PHY_M_1000C_MSE;
2445                 
2446                 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2447                         C1000BaseT |= PHY_M_1000C_MSC;  /* set it to Master */
2448                 }
2449         }
2450         
2451         /* Auto-negotiation ? */
2452         if (!AutoNeg) {
2453                 
2454                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2455                         /* Set Full Duplex Mode */
2456                         PhyCtrl |= PHY_CT_DUP_MD;
2457                 }
2458
2459                 /* Set Master/Slave manually if not already done */
2460                 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2461                         C1000BaseT |= PHY_M_1000C_MSE;  /* set it to Slave */
2462                 }
2463
2464                 /* Set Speed */
2465                 switch (pPrt->PLinkSpeed) {
2466                 case SK_LSPEED_AUTO:
2467                 case SK_LSPEED_1000MBPS:
2468                         PhyCtrl |= PHY_CT_SP1000;
2469                         break;
2470                 case SK_LSPEED_100MBPS:
2471                         PhyCtrl |= PHY_CT_SP100;
2472                         break;
2473                 case SK_LSPEED_10MBPS:
2474                         break;
2475                 default:
2476                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2477                                 SKERR_HWI_E019MSG);
2478                 }
2479
2480                 if (!DoLoop) {
2481                         PhyCtrl |= PHY_CT_RESET;
2482                 }
2483         }
2484         else {
2485                 /* Set Auto-negotiation advertisement */
2486                 
2487                 if (pAC->GIni.GICopperType) {
2488                         /* Set Speed capabilities */
2489                         switch (pPrt->PLinkSpeed) {
2490                         case SK_LSPEED_AUTO:
2491                                 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2492                                 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2493                                         PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2494                                 break;
2495                         case SK_LSPEED_1000MBPS:
2496                                 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
2497                                 break;
2498                         case SK_LSPEED_100MBPS:
2499                                 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
2500                                         /* advertise 10Base-T also */
2501                                         PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2502                                 break;
2503                         case SK_LSPEED_10MBPS:
2504                                 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
2505                                 break;
2506                         default:
2507                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
2508                                         SKERR_HWI_E019MSG);
2509                         }
2510
2511                         /* Set Full/half duplex capabilities */
2512                         switch (pPrt->PLinkMode) {
2513                         case SK_LMODE_AUTOHALF:
2514                                 C1000BaseT &= ~PHY_M_1000C_AFD;
2515                                 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
2516                                 break;
2517                         case SK_LMODE_AUTOFULL:
2518                                 C1000BaseT &= ~PHY_M_1000C_AHD;
2519                                 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
2520                                 break;
2521                         case SK_LMODE_AUTOBOTH:
2522                                 break;
2523                         default:
2524                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2525                                         SKERR_HWI_E015MSG);
2526                         }
2527                         
2528                         /* Set Flow-control capabilities */
2529                         switch (pPrt->PFlowCtrlMode) {
2530                         case SK_FLOW_MODE_NONE:
2531                                 AutoNegAdv |= PHY_B_P_NO_PAUSE;
2532                                 break;
2533                         case SK_FLOW_MODE_LOC_SEND:
2534                                 AutoNegAdv |= PHY_B_P_ASYM_MD;
2535                                 break;
2536                         case SK_FLOW_MODE_SYMMETRIC:
2537                                 AutoNegAdv |= PHY_B_P_SYM_MD;
2538                                 break;
2539                         case SK_FLOW_MODE_SYM_OR_REM:
2540                                 AutoNegAdv |= PHY_B_P_BOTH_MD;
2541                                 break;
2542                         default:
2543                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2544                                         SKERR_HWI_E016MSG);
2545                         }
2546                 }
2547                 else {  /* special defines for FIBER (88E1011S only) */
2548                         
2549                         /* Set Full/half duplex capabilities */
2550                         switch (pPrt->PLinkMode) {
2551                         case SK_LMODE_AUTOHALF:
2552                                 AutoNegAdv |= PHY_M_AN_1000X_AHD;
2553                                 break;
2554                         case SK_LMODE_AUTOFULL:
2555                                 AutoNegAdv |= PHY_M_AN_1000X_AFD;
2556                                 break;
2557                         case SK_LMODE_AUTOBOTH:
2558                                 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
2559                                 break;
2560                         default:
2561                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2562                                         SKERR_HWI_E015MSG);
2563                         }
2564                         
2565                         /* Set Flow-control capabilities */
2566                         switch (pPrt->PFlowCtrlMode) {
2567                         case SK_FLOW_MODE_NONE:
2568                                 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
2569                                 break;
2570                         case SK_FLOW_MODE_LOC_SEND:
2571                                 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
2572                                 break;
2573                         case SK_FLOW_MODE_SYMMETRIC:
2574                                 AutoNegAdv |= PHY_M_P_SYM_MD_X;
2575                                 break;
2576                         case SK_FLOW_MODE_SYM_OR_REM:
2577                                 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
2578                                 break;
2579                         default:
2580                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2581                                         SKERR_HWI_E016MSG);
2582                         }
2583                 }
2584
2585                 if (!DoLoop) {
2586                         /* Restart Auto-negotiation */
2587                         PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
2588                 }
2589         }
2590         
2591 #ifdef VCPU
2592         /*
2593          * E-mail from Gu Lin (08-03-2002):
2594          */
2595         
2596         /* Program PHY register 30 as 16'h0708 for simulation speed up */
2597         SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
2598         
2599         VCpuWait(2000);
2600
2601 #else /* VCPU */
2602         
2603         /* Write 1000Base-T Control Register */
2604         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
2605         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2606                 ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
2607         
2608         /* Write AutoNeg Advertisement Register */
2609         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
2610         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2611                 ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
2612 #endif /* VCPU */
2613         
2614         if (DoLoop) {
2615                 /* Set the PHY Loopback bit */
2616                 PhyCtrl |= PHY_CT_LOOP;
2617
2618 #ifdef XXX
2619                 /* Program PHY register 16 as 16'h0400 to force link good */
2620                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
2621 #endif /* XXX */
2622
2623 #ifndef VCPU
2624                 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
2625                         /* Write Ext. PHY Specific Control */
2626                         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
2627                                 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
2628                 }
2629 #endif /* VCPU */
2630         }
2631 #ifdef TEST_ONLY
2632         else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
2633                         /* Write PHY Specific Control */
2634                         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
2635                                 PHY_M_PC_EN_DET_MSK);
2636         }
2637 #endif
2638
2639         /* Write to the PHY Control register */
2640         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
2641         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2642                 ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2643
2644 #ifdef VCPU
2645         VCpuWait(2000);
2646 #else
2647
2648         LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
2649
2650         if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
2651                 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
2652         }
2653
2654         if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
2655                 LedCtrl |= PHY_M_LEDC_DP_CTRL;
2656         }
2657         
2658         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
2659
2660         if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
2661                 /* only in forced 100 Mbps mode */
2662                 if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
2663
2664                         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
2665                                 PHY_M_LED_MO_100(MO_LED_ON));
2666                 }
2667         }
2668
2669 #ifdef SK_DIAG
2670         c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
2671         c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
2672         c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
2673         c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
2674 #endif /* SK_DIAG */
2675
2676 #if defined(SK_DIAG) || defined(DEBUG)
2677         /* Read PHY Control */
2678         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
2679         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2680                 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
2681         
2682         /* Read 1000Base-T Control Register */
2683         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
2684         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2685                 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
2686         
2687         /* Read AutoNeg Advertisement Register */
2688         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
2689         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2690                 ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
2691         
2692         /* Read Ext. PHY Specific Control */
2693         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
2694         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2695                 ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
2696         
2697         /* Read PHY Status */
2698         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
2699         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2700                 ("PHY Stat Reg.=0x%04X\n", PhyStat));
2701         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
2702         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2703                 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
2704         
2705         /* Read PHY Specific Status */
2706         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
2707         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2708                 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
2709 #endif /* SK_DIAG || DEBUG */
2710
2711 #ifdef SK_DIAG
2712         c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
2713         c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
2714         c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
2715         c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
2716         c_print("PHY Stat Reg=0x%04X\n", PhyStat);
2717         c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
2718         c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
2719 #endif /* SK_DIAG */
2720
2721 #endif /* VCPU */
2722
2723 }       /* SkGmInitPhyMarv */
2724 #endif /* YUKON */
2725
2726
2727 #ifdef OTHER_PHY
2728 /******************************************************************************
2729  *
2730  *      SkXmInitPhyLone() - Initialize the Level One Phy registers
2731  *
2732  * Description: initializes all the Level One Phy registers
2733  *
2734  * Note:
2735  *
2736  * Returns:
2737  *      nothing
2738  */
2739 static void SkXmInitPhyLone(
2740 SK_AC   *pAC,           /* adapter context */
2741 SK_IOC  IoC,            /* IO context */
2742 int             Port,           /* Port Index (MAC_1 + n) */
2743 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
2744 {
2745         SK_GEPORT       *pPrt;
2746         SK_U16          Ctrl1;
2747         SK_U16          Ctrl2;
2748         SK_U16          Ctrl3;
2749
2750         Ctrl1 = PHY_CT_SP1000;
2751         Ctrl2 = 0;
2752         Ctrl3 = PHY_SEL_TYPE;
2753
2754         pPrt = &pAC->GIni.GP[Port];
2755
2756         /* manually Master/Slave ? */
2757         if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
2758                 Ctrl2 |= PHY_L_1000C_MSE;
2759                 
2760                 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
2761                         Ctrl2 |= PHY_L_1000C_MSC;
2762                 }
2763         }
2764         /* Auto-negotiation ? */
2765         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
2766                 /*
2767                  * level one spec say: "1000 Mbps: manual mode not allowed"
2768                  * but lets see what happens...
2769                  */
2770                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2771                         ("InitPhyLone: no auto-negotiation Port %d\n", Port));
2772                 /* Set DuplexMode in Config register */
2773                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
2774                         Ctrl1 |= PHY_CT_DUP_MD;
2775                 }
2776
2777                 /* Determine Master/Slave manually if not already done */
2778                 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
2779                         Ctrl2 |= PHY_L_1000C_MSE;       /* set it to Slave */
2780                 }
2781
2782                 /*
2783                  * Do NOT enable Auto-negotiation here. This would hold
2784                  * the link down because no IDLES are transmitted
2785                  */
2786         }
2787         else {
2788                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2789                         ("InitPhyLone: with auto-negotiation Port %d\n", Port));
2790                 /* Set Auto-negotiation advertisement */
2791
2792                 /* Set Full/half duplex capabilities */
2793                 switch (pPrt->PLinkMode) {
2794                 case SK_LMODE_AUTOHALF:
2795                         Ctrl2 |= PHY_L_1000C_AHD;
2796                         break;
2797                 case SK_LMODE_AUTOFULL:
2798                         Ctrl2 |= PHY_L_1000C_AFD;
2799                         break;
2800                 case SK_LMODE_AUTOBOTH:
2801                         Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
2802                         break;
2803                 default:
2804                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
2805                                 SKERR_HWI_E015MSG);
2806                 }
2807
2808                 /* Set Flow-control capabilities */
2809                 switch (pPrt->PFlowCtrlMode) {
2810                 case SK_FLOW_MODE_NONE:
2811                         Ctrl3 |= PHY_L_P_NO_PAUSE;
2812                         break;
2813                 case SK_FLOW_MODE_LOC_SEND:
2814                         Ctrl3 |= PHY_L_P_ASYM_MD;
2815                         break;
2816                 case SK_FLOW_MODE_SYMMETRIC:
2817                         Ctrl3 |= PHY_L_P_SYM_MD;
2818                         break;
2819                 case SK_FLOW_MODE_SYM_OR_REM:
2820                         Ctrl3 |= PHY_L_P_BOTH_MD;
2821                         break;
2822                 default:
2823                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
2824                                 SKERR_HWI_E016MSG);
2825                 }
2826
2827                 /* Restart Auto-negotiation */
2828                 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
2829         }
2830         
2831         /* Write 1000Base-T Control Register */
2832         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
2833         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2834                 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
2835         
2836         /* Write AutoNeg Advertisement Register */
2837         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
2838         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2839                 ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
2840
2841         if (DoLoop) {
2842                 /* Set the Phy Loopback bit, too */
2843                 Ctrl1 |= PHY_CT_LOOP;
2844         }
2845
2846         /* Write to the Phy control register */
2847         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
2848         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2849                 ("PHY Control Reg=0x%04X\n", Ctrl1));
2850 }       /* SkXmInitPhyLone */
2851
2852
2853 /******************************************************************************
2854  *
2855  *      SkXmInitPhyNat() - Initialize the National Phy registers
2856  *
2857  * Description: initializes all the National Phy registers
2858  *
2859  * Note:
2860  *
2861  * Returns:
2862  *      nothing
2863  */
2864 static void SkXmInitPhyNat(
2865 SK_AC   *pAC,           /* adapter context */
2866 SK_IOC  IoC,            /* IO context */
2867 int             Port,           /* Port Index (MAC_1 + n) */
2868 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
2869 {
2870 /* todo: National */
2871 }       /* SkXmInitPhyNat */
2872 #endif /* OTHER_PHY */
2873
2874
2875 /******************************************************************************
2876  *
2877  *      SkMacInitPhy() - Initialize the PHY registers
2878  *
2879  * Description: calls the Init PHY routines dep. on board type
2880  *
2881  * Note:
2882  *
2883  * Returns:
2884  *      nothing
2885  */
2886 void SkMacInitPhy(
2887 SK_AC   *pAC,           /* adapter context */
2888 SK_IOC  IoC,            /* IO context */
2889 int             Port,           /* Port Index (MAC_1 + n) */
2890 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
2891 {
2892         SK_GEPORT       *pPrt;
2893
2894         pPrt = &pAC->GIni.GP[Port];
2895
2896 #ifdef GENESIS
2897         if (pAC->GIni.GIGenesis) {
2898                 
2899                 switch (pPrt->PhyType) {
2900                 case SK_PHY_XMAC:
2901                         SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
2902                         break;
2903                 case SK_PHY_BCOM:
2904                         SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
2905                         break;
2906 #ifdef OTHER_PHY
2907                 case SK_PHY_LONE:
2908                         SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
2909                         break;
2910                 case SK_PHY_NAT:
2911                         SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
2912                         break;
2913 #endif /* OTHER_PHY */
2914                 }
2915         }
2916 #endif /* GENESIS */
2917         
2918 #ifdef YUKON
2919         if (pAC->GIni.GIYukon) {
2920                 
2921                 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
2922         }
2923 #endif /* YUKON */
2924
2925 }       /* SkMacInitPhy */
2926
2927
2928 #ifdef GENESIS
2929 /******************************************************************************
2930  *
2931  *      SkXmAutoNegDoneXmac() - Auto-negotiation handling
2932  *
2933  * Description:
2934  *      This function handles the auto-negotiation if the Done bit is set.
2935  *
2936  * Returns:
2937  *      SK_AND_OK       o.k.
2938  *      SK_AND_DUP_CAP  Duplex capability error happened
2939  *      SK_AND_OTHER    Other error happened
2940  */
2941 static int SkXmAutoNegDoneXmac(
2942 SK_AC   *pAC,           /* adapter context */
2943 SK_IOC  IoC,            /* IO context */
2944 int             Port)           /* Port Index (MAC_1 + n) */
2945 {
2946         SK_GEPORT       *pPrt;
2947         SK_U16          ResAb;          /* Resolved Ability */
2948         SK_U16          LPAb;           /* Link Partner Ability */
2949
2950         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2951                 ("AutoNegDoneXmac, Port %d\n", Port));
2952
2953         pPrt = &pAC->GIni.GP[Port];
2954
2955         /* Get PHY parameters */
2956         SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
2957         SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
2958
2959         if ((LPAb & PHY_X_AN_RFB) != 0) {
2960                 /* At least one of the remote fault bit is set */
2961                 /* Error */
2962                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2963                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
2964                 pPrt->PAutoNegFail = SK_TRUE;
2965                 return(SK_AND_OTHER);
2966         }
2967
2968         /* Check Duplex mismatch */
2969         if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
2970                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
2971         }
2972         else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
2973                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
2974         }
2975         else {
2976                 /* Error */
2977                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2978                         ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
2979                 pPrt->PAutoNegFail = SK_TRUE;
2980                 return(SK_AND_DUP_CAP);
2981         }
2982
2983         /* Check PAUSE mismatch */
2984         /* We are NOT using chapter 4.23 of the Xaqti manual */
2985         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
2986         if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
2987              pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
2988             (LPAb & PHY_X_P_SYM_MD) != 0) {
2989                 /* Symmetric PAUSE */
2990                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
2991         }
2992         else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
2993                    (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
2994                 /* Enable PAUSE receive, disable PAUSE transmit */
2995                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
2996         }
2997         else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
2998                    (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
2999                 /* Disable PAUSE receive, enable PAUSE transmit */
3000                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3001         }
3002         else {
3003                 /* PAUSE mismatch -> no PAUSE */
3004                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3005         }
3006         pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
3007
3008         return(SK_AND_OK);
3009 }       /* SkXmAutoNegDoneXmac */
3010
3011
3012 /******************************************************************************
3013  *
3014  *      SkXmAutoNegDoneBcom() - Auto-negotiation handling
3015  *
3016  * Description:
3017  *      This function handles the auto-negotiation if the Done bit is set.
3018  *
3019  * Returns:
3020  *      SK_AND_OK       o.k.
3021  *      SK_AND_DUP_CAP  Duplex capability error happened
3022  *      SK_AND_OTHER    Other error happened
3023  */
3024 static int SkXmAutoNegDoneBcom(
3025 SK_AC   *pAC,           /* adapter context */
3026 SK_IOC  IoC,            /* IO context */
3027 int             Port)           /* Port Index (MAC_1 + n) */
3028 {
3029         SK_GEPORT       *pPrt;
3030         SK_U16          LPAb;           /* Link Partner Ability */
3031         SK_U16          AuxStat;        /* Auxiliary Status */
3032
3033 #ifdef TEST_ONLY
3034 01-Sep-2000 RA;:;:
3035         SK_U16          ResAb;          /* Resolved Ability */
3036 #endif  /* 0 */
3037
3038         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3039                 ("AutoNegDoneBcom, Port %d\n", Port));
3040         pPrt = &pAC->GIni.GP[Port];
3041
3042         /* Get PHY parameters */
3043         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
3044 #ifdef TEST_ONLY
3045 01-Sep-2000 RA;:;:
3046         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
3047 #endif  /* 0 */
3048         
3049         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
3050
3051         if ((LPAb & PHY_B_AN_RF) != 0) {
3052                 /* Remote fault bit is set: Error */
3053                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3054                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3055                 pPrt->PAutoNegFail = SK_TRUE;
3056                 return(SK_AND_OTHER);
3057         }
3058
3059         /* Check Duplex mismatch */
3060         if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
3061                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
3062         }
3063         else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
3064                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
3065         }
3066         else {
3067                 /* Error */
3068                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3069                         ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
3070                 pPrt->PAutoNegFail = SK_TRUE;
3071                 return(SK_AND_DUP_CAP);
3072         }
3073         
3074 #ifdef TEST_ONLY
3075 01-Sep-2000 RA;:;:
3076         /* Check Master/Slave resolution */
3077         if ((ResAb & PHY_B_1000S_MSF) != 0) {
3078                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3079                         ("Master/Slave Fault Port %d\n", Port));
3080                 pPrt->PAutoNegFail = SK_TRUE;
3081                 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3082                 return(SK_AND_OTHER);
3083         }
3084         
3085         pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3086                 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
3087 #endif  /* 0 */
3088
3089         /* Check PAUSE mismatch ??? */
3090         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3091         if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
3092                 /* Symmetric PAUSE */
3093                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3094         }
3095         else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
3096                 /* Enable PAUSE receive, disable PAUSE transmit */
3097                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3098         }
3099         else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
3100                 /* Disable PAUSE receive, enable PAUSE transmit */
3101                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3102         }
3103         else {
3104                 /* PAUSE mismatch -> no PAUSE */
3105                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3106         }
3107         pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
3108
3109         return(SK_AND_OK);
3110 }       /* SkXmAutoNegDoneBcom */
3111 #endif /* GENESIS */
3112
3113
3114 #ifdef YUKON
3115 /******************************************************************************
3116  *
3117  *      SkGmAutoNegDoneMarv() - Auto-negotiation handling
3118  *
3119  * Description:
3120  *      This function handles the auto-negotiation if the Done bit is set.
3121  *
3122  * Returns:
3123  *      SK_AND_OK       o.k.
3124  *      SK_AND_DUP_CAP  Duplex capability error happened
3125  *      SK_AND_OTHER    Other error happened
3126  */
3127 static int SkGmAutoNegDoneMarv(
3128 SK_AC   *pAC,           /* adapter context */
3129 SK_IOC  IoC,            /* IO context */
3130 int             Port)           /* Port Index (MAC_1 + n) */
3131 {
3132         SK_GEPORT       *pPrt;
3133         SK_U16          LPAb;           /* Link Partner Ability */
3134         SK_U16          ResAb;          /* Resolved Ability */
3135         SK_U16          AuxStat;        /* Auxiliary Status */
3136
3137         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3138                 ("AutoNegDoneMarv, Port %d\n", Port));
3139         pPrt = &pAC->GIni.GP[Port];
3140
3141         /* Get PHY parameters */
3142         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
3143         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3144                 ("Link P.Abil.=0x%04X\n", LPAb));
3145         
3146         if ((LPAb & PHY_M_AN_RF) != 0) {
3147                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3148                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3149                 pPrt->PAutoNegFail = SK_TRUE;
3150                 return(SK_AND_OTHER);
3151         }
3152
3153         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
3154         
3155         /* Check Master/Slave resolution */
3156         if ((ResAb & PHY_B_1000S_MSF) != 0) {
3157                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3158                         ("Master/Slave Fault Port %d\n", Port));
3159                 pPrt->PAutoNegFail = SK_TRUE;
3160                 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3161                 return(SK_AND_OTHER);
3162         }
3163         
3164         pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
3165                 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
3166         
3167         /* Read PHY Specific Status */
3168         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
3169         
3170         /* Check Speed & Duplex resolved */
3171         if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
3172                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3173                         ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
3174                 pPrt->PAutoNegFail = SK_TRUE;
3175                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
3176                 return(SK_AND_DUP_CAP);
3177         }
3178         
3179         if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
3180                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
3181         }
3182         else {
3183                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
3184         }
3185         
3186         /* Check PAUSE mismatch ??? */
3187         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3188         if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
3189                 /* Symmetric PAUSE */
3190                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3191         }
3192         else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
3193                 /* Enable PAUSE receive, disable PAUSE transmit */
3194                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3195         }
3196         else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
3197                 /* Disable PAUSE receive, enable PAUSE transmit */
3198                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3199         }
3200         else {
3201                 /* PAUSE mismatch -> no PAUSE */
3202                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3203         }
3204         
3205         /* set used link speed */
3206         switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
3207         case (unsigned)PHY_M_PS_SPEED_1000:
3208                 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
3209                 break;
3210         case PHY_M_PS_SPEED_100:
3211                 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
3212                 break;
3213         default:
3214                 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
3215         }
3216
3217         return(SK_AND_OK);
3218 }       /* SkGmAutoNegDoneMarv */
3219 #endif /* YUKON */
3220
3221
3222 #ifdef OTHER_PHY
3223 /******************************************************************************
3224  *
3225  *      SkXmAutoNegDoneLone() - Auto-negotiation handling
3226  *
3227  * Description:
3228  *      This function handles the auto-negotiation if the Done bit is set.
3229  *
3230  * Returns:
3231  *      SK_AND_OK       o.k.
3232  *      SK_AND_DUP_CAP  Duplex capability error happened
3233  *      SK_AND_OTHER    Other error happened
3234  */
3235 static int SkXmAutoNegDoneLone(
3236 SK_AC   *pAC,           /* adapter context */
3237 SK_IOC  IoC,            /* IO context */
3238 int             Port)           /* Port Index (MAC_1 + n) */
3239 {
3240         SK_GEPORT       *pPrt;
3241         SK_U16          ResAb;          /* Resolved Ability */
3242         SK_U16          LPAb;           /* Link Partner Ability */
3243         SK_U16          QuickStat;      /* Auxiliary Status */
3244
3245         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3246                 ("AutoNegDoneLone, Port %d\n", Port));
3247         pPrt = &pAC->GIni.GP[Port];
3248
3249         /* Get PHY parameters */
3250         SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
3251         SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
3252         SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
3253
3254         if ((LPAb & PHY_L_AN_RF) != 0) {
3255                 /* Remote fault bit is set */
3256                 /* Error */
3257                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3258                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
3259                 pPrt->PAutoNegFail = SK_TRUE;
3260                 return(SK_AND_OTHER);
3261         }
3262
3263         /* Check Duplex mismatch */
3264         if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
3265                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
3266         }
3267         else {
3268                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
3269         }
3270         
3271         /* Check Master/Slave resolution */
3272         if ((ResAb & PHY_L_1000S_MSF) != 0) {
3273                 /* Error */
3274                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3275                         ("Master/Slave Fault Port %d\n", Port));
3276                 pPrt->PAutoNegFail = SK_TRUE;
3277                 pPrt->PMSStatus = SK_MS_STAT_FAULT;
3278                 return(SK_AND_OTHER);
3279         }
3280         else if (ResAb & PHY_L_1000S_MSR) {
3281                 pPrt->PMSStatus = SK_MS_STAT_MASTER;
3282         }
3283         else {
3284                 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
3285         }
3286
3287         /* Check PAUSE mismatch */
3288         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
3289         /* we must manually resolve the abilities here */
3290         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
3291         
3292         switch (pPrt->PFlowCtrlMode) {
3293         case SK_FLOW_MODE_NONE:
3294                 /* default */
3295                 break;
3296         case SK_FLOW_MODE_LOC_SEND:
3297                 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3298                         (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
3299                         /* Disable PAUSE receive, enable PAUSE transmit */
3300                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
3301                 }
3302                 break;
3303         case SK_FLOW_MODE_SYMMETRIC:
3304                 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3305                         /* Symmetric PAUSE */
3306                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3307                 }
3308                 break;
3309         case SK_FLOW_MODE_SYM_OR_REM:
3310                 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
3311                         PHY_L_QS_AS_PAUSE) {
3312                         /* Enable PAUSE receive, disable PAUSE transmit */
3313                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
3314                 }
3315                 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
3316                         /* Symmetric PAUSE */
3317                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
3318                 }
3319                 break;
3320         default:
3321                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
3322                         SKERR_HWI_E016MSG);
3323         }
3324         
3325         return(SK_AND_OK);
3326 }       /* SkXmAutoNegDoneLone */
3327
3328
3329 /******************************************************************************
3330  *
3331  *      SkXmAutoNegDoneNat() - Auto-negotiation handling
3332  *
3333  * Description:
3334  *      This function handles the auto-negotiation if the Done bit is set.
3335  *
3336  * Returns:
3337  *      SK_AND_OK       o.k.
3338  *      SK_AND_DUP_CAP  Duplex capability error happened
3339  *      SK_AND_OTHER    Other error happened
3340  */
3341 static int SkXmAutoNegDoneNat(
3342 SK_AC   *pAC,           /* adapter context */
3343 SK_IOC  IoC,            /* IO context */
3344 int             Port)           /* Port Index (MAC_1 + n) */
3345 {
3346 /* todo: National */
3347         return(SK_AND_OK);
3348 }       /* SkXmAutoNegDoneNat */
3349 #endif /* OTHER_PHY */
3350
3351
3352 /******************************************************************************
3353  *
3354  *      SkMacAutoNegDone() - Auto-negotiation handling
3355  *
3356  * Description: calls the auto-negotiation done routines dep. on board type
3357  *
3358  * Returns:
3359  *      SK_AND_OK       o.k.
3360  *      SK_AND_DUP_CAP  Duplex capability error happened
3361  *      SK_AND_OTHER    Other error happened
3362  */
3363 int     SkMacAutoNegDone(
3364 SK_AC   *pAC,           /* adapter context */
3365 SK_IOC  IoC,            /* IO context */
3366 int             Port)           /* Port Index (MAC_1 + n) */
3367 {
3368         SK_GEPORT       *pPrt;
3369         int     Rtv;
3370
3371         Rtv = SK_AND_OK;
3372
3373         pPrt = &pAC->GIni.GP[Port];
3374
3375 #ifdef GENESIS
3376         if (pAC->GIni.GIGenesis) {
3377                 
3378                 switch (pPrt->PhyType) {
3379                 
3380                 case SK_PHY_XMAC:
3381                         Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
3382                         break;
3383                 case SK_PHY_BCOM:
3384                         Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
3385                         break;
3386 #ifdef OTHER_PHY
3387                 case SK_PHY_LONE:
3388                         Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
3389                         break;
3390                 case SK_PHY_NAT:
3391                         Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
3392                         break;
3393 #endif /* OTHER_PHY */
3394                 default:
3395                         return(SK_AND_OTHER);
3396                 }
3397         }
3398 #endif /* GENESIS */
3399         
3400 #ifdef YUKON
3401         if (pAC->GIni.GIYukon) {
3402                 
3403                 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
3404         }
3405 #endif /* YUKON */
3406         
3407         if (Rtv != SK_AND_OK) {
3408                 return(Rtv);
3409         }
3410
3411         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3412                 ("AutoNeg done Port %d\n", Port));
3413         
3414         /* We checked everything and may now enable the link */
3415         pPrt->PAutoNegFail = SK_FALSE;
3416
3417         SkMacRxTxEnable(pAC, IoC, Port);
3418         
3419         return(SK_AND_OK);
3420 }       /* SkMacAutoNegDone */
3421
3422
3423 #ifdef GENESIS
3424 /******************************************************************************
3425  *
3426  *      SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
3427  *
3428  * Description:
3429  *  sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
3430  *  enables Rx/Tx
3431  *
3432  * Returns: N/A
3433  */
3434 static void SkXmSetRxTxEn(
3435 SK_AC   *pAC,           /* Adapter Context */
3436 SK_IOC  IoC,            /* IO context */
3437 int             Port,           /* Port Index (MAC_1 + n) */
3438 int             Para)           /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
3439 {
3440         SK_U16  Word;
3441
3442         XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3443
3444         switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3445         case SK_MAC_LOOPB_ON:
3446                 Word |= XM_MMU_MAC_LB;
3447                 break;
3448         case SK_MAC_LOOPB_OFF:
3449                 Word &= ~XM_MMU_MAC_LB;
3450                 break;
3451         }
3452
3453         switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
3454         case SK_PHY_LOOPB_ON:
3455                 Word |= XM_MMU_GMII_LOOP;
3456                 break;
3457         case SK_PHY_LOOPB_OFF:
3458                 Word &= ~XM_MMU_GMII_LOOP;
3459                 break;
3460         }
3461         
3462         switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3463         case SK_PHY_FULLD_ON:
3464                 Word |= XM_MMU_GMII_FD;
3465                 break;
3466         case SK_PHY_FULLD_OFF:
3467                 Word &= ~XM_MMU_GMII_FD;
3468                 break;
3469         }
3470         
3471         XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3472
3473         /* dummy read to ensure writing */
3474         XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3475
3476 }       /* SkXmSetRxTxEn */
3477 #endif /* GENESIS */
3478
3479
3480 #ifdef YUKON
3481 /******************************************************************************
3482  *
3483  *      SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
3484  *
3485  * Description:
3486  *  sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
3487  *  enables Rx/Tx
3488  *
3489  * Returns: N/A
3490  */
3491 static void SkGmSetRxTxEn(
3492 SK_AC   *pAC,           /* Adapter Context */
3493 SK_IOC  IoC,            /* IO context */
3494 int             Port,           /* Port Index (MAC_1 + n) */
3495 int             Para)           /* Parameter to set: MAC LoopBack, Duplex Mode */
3496 {
3497         SK_U16  Ctrl;
3498         
3499         GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3500
3501         switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
3502         case SK_MAC_LOOPB_ON:
3503                 Ctrl |= GM_GPCR_LOOP_ENA;
3504                 break;
3505         case SK_MAC_LOOPB_OFF:
3506                 Ctrl &= ~GM_GPCR_LOOP_ENA;
3507                 break;
3508         }
3509
3510         switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
3511         case SK_PHY_FULLD_ON:
3512                 Ctrl |= GM_GPCR_DUP_FULL;
3513                 break;
3514         case SK_PHY_FULLD_OFF:
3515                 Ctrl &= ~GM_GPCR_DUP_FULL;
3516                 break;
3517         }
3518         
3519     GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Ctrl | GM_GPCR_RX_ENA |
3520                 GM_GPCR_TX_ENA));
3521
3522         /* dummy read to ensure writing */
3523         GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
3524
3525 }       /* SkGmSetRxTxEn */
3526 #endif /* YUKON */
3527
3528
3529 #ifndef SK_SLIM
3530 /******************************************************************************
3531  *
3532  *      SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
3533  *
3534  * Description: calls the Special Set Rx/Tx Enable routines dep. on board type
3535  *
3536  * Returns: N/A
3537  */
3538 void SkMacSetRxTxEn(
3539 SK_AC   *pAC,           /* Adapter Context */
3540 SK_IOC  IoC,            /* IO context */
3541 int             Port,           /* Port Index (MAC_1 + n) */
3542 int             Para)
3543 {
3544 #ifdef GENESIS
3545         if (pAC->GIni.GIGenesis) {
3546                 
3547                 SkXmSetRxTxEn(pAC, IoC, Port, Para);
3548         }
3549 #endif /* GENESIS */
3550         
3551 #ifdef YUKON
3552         if (pAC->GIni.GIYukon) {
3553                 
3554                 SkGmSetRxTxEn(pAC, IoC, Port, Para);
3555         }
3556 #endif /* YUKON */
3557
3558 }       /* SkMacSetRxTxEn */
3559 #endif /* !SK_SLIM */
3560
3561
3562 /******************************************************************************
3563  *
3564  *      SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
3565  *
3566  * Description: enables Rx/Tx dep. on board type
3567  *
3568  * Returns:
3569  *      0       o.k.
3570  *      != 0    Error happened
3571  */
3572 int SkMacRxTxEnable(
3573 SK_AC   *pAC,           /* adapter context */
3574 SK_IOC  IoC,            /* IO context */
3575 int             Port)           /* Port Index (MAC_1 + n) */
3576 {
3577         SK_GEPORT       *pPrt;
3578         SK_U16          Reg;            /* 16-bit register value */
3579         SK_U16          IntMask;        /* MAC interrupt mask */
3580 #ifdef GENESIS
3581         SK_U16          SWord;
3582 #endif
3583
3584         pPrt = &pAC->GIni.GP[Port];
3585
3586         if (!pPrt->PHWLinkUp) {
3587                 /* The Hardware link is NOT up */
3588                 return(0);
3589         }
3590
3591         if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
3592              pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
3593              pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
3594              pPrt->PAutoNegFail) {
3595                 /* Auto-negotiation is not done or failed */
3596                 return(0);
3597         }
3598
3599 #ifdef GENESIS
3600         if (pAC->GIni.GIGenesis) {
3601                 /* set Duplex Mode and Pause Mode */
3602                 SkXmInitDupMd(pAC, IoC, Port);
3603                 
3604                 SkXmInitPauseMd(pAC, IoC, Port);
3605         
3606                 /*
3607                  * Initialize the Interrupt Mask Register. Default IRQs are...
3608                  *      - Link Asynchronous Event
3609                  *      - Link Partner requests config
3610                  *      - Auto Negotiation Done
3611                  *      - Rx Counter Event Overflow
3612                  *      - Tx Counter Event Overflow
3613                  *      - Transmit FIFO Underrun
3614                  */
3615                 IntMask = XM_DEF_MSK;
3616
3617 #ifdef DEBUG
3618                 /* add IRQ for Receive FIFO Overflow */
3619                 IntMask &= ~XM_IS_RXF_OV;
3620 #endif /* DEBUG */
3621                 
3622                 if (pPrt->PhyType != SK_PHY_XMAC) {
3623                         /* disable GP0 interrupt bit */
3624                         IntMask |= XM_IS_INP_ASS;
3625                 }
3626                 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
3627         
3628                 /* get MMU Command Reg. */
3629                 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
3630                 
3631                 if (pPrt->PhyType != SK_PHY_XMAC &&
3632                         (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3633                          pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
3634                         /* set to Full Duplex */
3635                         Reg |= XM_MMU_GMII_FD;
3636                 }
3637                 
3638                 switch (pPrt->PhyType) {
3639                 case SK_PHY_BCOM:
3640                         /*
3641                          * Workaround BCOM Errata (#10523) for all BCom Phys
3642                          * Enable Power Management after link up
3643                          */
3644                         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
3645                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3646                                 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
3647             SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
3648                                 (SK_U16)PHY_B_DEF_MSK);
3649                         break;
3650 #ifdef OTHER_PHY
3651                 case SK_PHY_LONE:
3652                         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
3653                         break;
3654                 case SK_PHY_NAT:
3655                         /* todo National:
3656                         SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
3657                         /* no interrupts possible from National ??? */
3658                         break;
3659 #endif /* OTHER_PHY */
3660                 }
3661                 
3662                 /* enable Rx/Tx */
3663                 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
3664         }
3665 #endif /* GENESIS */
3666         
3667 #ifdef YUKON
3668         if (pAC->GIni.GIYukon) {
3669                 /*
3670                  * Initialize the Interrupt Mask Register. Default IRQs are...
3671                  *      - Rx Counter Event Overflow
3672                  *      - Tx Counter Event Overflow
3673                  *      - Transmit FIFO Underrun
3674                  */
3675                 IntMask = GMAC_DEF_MSK;
3676
3677 #ifdef DEBUG
3678                 /* add IRQ for Receive FIFO Overrun */
3679                 IntMask |= GM_IS_RX_FF_OR;
3680 #endif /* DEBUG */
3681                 
3682                 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
3683                 
3684                 /* get General Purpose Control */
3685                 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
3686                 
3687                 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
3688                         pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
3689                         /* set to Full Duplex */
3690                         Reg |= GM_GPCR_DUP_FULL;
3691                 }
3692                 
3693                 /* enable Rx/Tx */
3694         GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
3695                         GM_GPCR_TX_ENA));
3696
3697 #ifndef VCPU
3698                 /* Enable all PHY interrupts */
3699         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
3700                         (SK_U16)PHY_M_DEF_MSK);
3701 #endif /* VCPU */
3702         }
3703 #endif /* YUKON */
3704                                         
3705         return(0);
3706
3707 }       /* SkMacRxTxEnable */
3708
3709
3710 /******************************************************************************
3711  *
3712  *      SkMacRxTxDisable() - Disable Receiver and Transmitter
3713  *
3714  * Description: disables Rx/Tx dep. on board type
3715  *
3716  * Returns: N/A
3717  */
3718 void SkMacRxTxDisable(
3719 SK_AC   *pAC,           /* Adapter Context */
3720 SK_IOC  IoC,            /* IO context */
3721 int             Port)           /* Port Index (MAC_1 + n) */
3722 {
3723         SK_U16  Word;
3724
3725 #ifdef GENESIS
3726         if (pAC->GIni.GIGenesis) {
3727                 
3728                 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3729                 
3730                 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
3731         
3732                 /* dummy read to ensure writing */
3733                 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
3734         }
3735 #endif /* GENESIS */
3736         
3737 #ifdef YUKON
3738         if (pAC->GIni.GIYukon) {
3739                 
3740                 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3741
3742         GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
3743                         GM_GPCR_TX_ENA)));
3744
3745                 /* dummy read to ensure writing */
3746                 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
3747         }
3748 #endif /* YUKON */
3749
3750 }       /* SkMacRxTxDisable */
3751
3752
3753 /******************************************************************************
3754  *
3755  *      SkMacIrqDisable() - Disable IRQ from MAC
3756  *
3757  * Description: sets the IRQ-mask to disable IRQ dep. on board type
3758  *
3759  * Returns: N/A
3760  */
3761 void SkMacIrqDisable(
3762 SK_AC   *pAC,           /* Adapter Context */
3763 SK_IOC  IoC,            /* IO context */
3764 int             Port)           /* Port Index (MAC_1 + n) */
3765 {
3766         SK_GEPORT       *pPrt;
3767 #ifdef GENESIS
3768         SK_U16          Word;
3769 #endif
3770
3771         pPrt = &pAC->GIni.GP[Port];
3772
3773 #ifdef GENESIS
3774         if (pAC->GIni.GIGenesis) {
3775                 
3776                 /* disable all XMAC IRQs */
3777                 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);   
3778                 
3779                 /* Disable all PHY interrupts */
3780                 switch (pPrt->PhyType) {
3781                         case SK_PHY_BCOM:
3782                                 /* Make sure that PHY is initialized */
3783                                 if (pPrt->PState != SK_PRT_RESET) {
3784                                         /* NOT allowed if BCOM is in RESET state */
3785                                         /* Workaround BCOM Errata (#10523) all BCom */
3786                                         /* Disable Power Management if link is down */
3787                                         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
3788                                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
3789                                                 (SK_U16)(Word | PHY_B_AC_DIS_PM));
3790                                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
3791                                 }
3792                                 break;
3793 #ifdef OTHER_PHY
3794                         case SK_PHY_LONE:
3795                                 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
3796                                 break;
3797                         case SK_PHY_NAT:
3798                                 /* todo: National
3799                                 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
3800                                 break;
3801 #endif /* OTHER_PHY */
3802                 }
3803         }
3804 #endif /* GENESIS */
3805         
3806 #ifdef YUKON
3807         if (pAC->GIni.GIYukon) {
3808                 /* disable all GMAC IRQs */
3809                 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
3810                 
3811 #ifndef VCPU
3812                 /* Disable all PHY interrupts */
3813                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
3814 #endif /* VCPU */
3815         }
3816 #endif /* YUKON */
3817
3818 }       /* SkMacIrqDisable */
3819
3820
3821 #ifdef SK_DIAG
3822 /******************************************************************************
3823  *
3824  *      SkXmSendCont() - Enable / Disable Send Continuous Mode
3825  *
3826  * Description: enable / disable Send Continuous Mode on XMAC
3827  *
3828  * Returns:
3829  *      nothing
3830  */
3831 void SkXmSendCont(
3832 SK_AC   *pAC,   /* adapter context */
3833 SK_IOC  IoC,    /* IO context */
3834 int             Port,   /* Port Index (MAC_1 + n) */
3835 SK_BOOL Enable) /* Enable / Disable */
3836 {
3837         SK_U32  MdReg;
3838
3839         XM_IN32(IoC, Port, XM_MODE, &MdReg);
3840
3841         if (Enable) {
3842                 MdReg |= XM_MD_TX_CONT;
3843         }
3844         else {
3845                 MdReg &= ~XM_MD_TX_CONT;
3846         }
3847         /* setup Mode Register */
3848         XM_OUT32(IoC, Port, XM_MODE, MdReg);
3849
3850 }       /* SkXmSendCont */
3851
3852
3853 /******************************************************************************
3854  *
3855  *      SkMacTimeStamp() - Enable / Disable Time Stamp
3856  *
3857  * Description: enable / disable Time Stamp generation for Rx packets
3858  *
3859  * Returns:
3860  *      nothing
3861  */
3862 void SkMacTimeStamp(
3863 SK_AC   *pAC,   /* adapter context */
3864 SK_IOC  IoC,    /* IO context */
3865 int             Port,   /* Port Index (MAC_1 + n) */
3866 SK_BOOL Enable) /* Enable / Disable */
3867 {
3868         SK_U32  MdReg;
3869         SK_U8   TimeCtrl;
3870
3871         if (pAC->GIni.GIGenesis) {
3872
3873                 XM_IN32(IoC, Port, XM_MODE, &MdReg);
3874
3875                 if (Enable) {
3876                         MdReg |= XM_MD_ATS;
3877                 }
3878                 else {
3879                         MdReg &= ~XM_MD_ATS;
3880                 }
3881                 /* setup Mode Register */
3882                 XM_OUT32(IoC, Port, XM_MODE, MdReg);
3883         }
3884         else {
3885                 if (Enable) {
3886                         TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
3887                 }
3888                 else {
3889                         TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
3890                 }
3891                 /* Start/Stop Time Stamp Timer */
3892                 SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
3893         }
3894
3895 }       /* SkMacTimeStamp*/
3896
3897 #else /* !SK_DIAG */
3898
3899 #ifdef GENESIS
3900 /******************************************************************************
3901  *
3902  *      SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
3903  *
3904  *      This function analyses the Interrupt status word. If any of the
3905  *      Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
3906  *      is set true.
3907  */
3908 void SkXmAutoNegLipaXmac(
3909 SK_AC   *pAC,           /* adapter context */
3910 SK_IOC  IoC,            /* IO context */
3911 int             Port,           /* Port Index (MAC_1 + n) */
3912 SK_U16  IStatus)        /* Interrupt Status word to analyse */
3913 {
3914         SK_GEPORT       *pPrt;
3915
3916         pPrt = &pAC->GIni.GP[Port];
3917
3918         if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3919                 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
3920
3921                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3922                         ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
3923                         Port, IStatus));
3924                 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
3925         }
3926 }       /* SkXmAutoNegLipaXmac */
3927 #endif /* GENESIS */
3928
3929
3930 /******************************************************************************
3931  *
3932  *      SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
3933  *
3934  *      This function analyses the PHY status word.
3935  *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
3936  *      is set true.
3937  */
3938 void SkMacAutoNegLipaPhy(
3939 SK_AC   *pAC,           /* adapter context */
3940 SK_IOC  IoC,            /* IO context */
3941 int             Port,           /* Port Index (MAC_1 + n) */
3942 SK_U16  PhyStat)        /* PHY Status word to analyse */
3943 {
3944         SK_GEPORT       *pPrt;
3945
3946         pPrt = &pAC->GIni.GP[Port];
3947
3948         if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
3949                 (PhyStat & PHY_ST_AN_OVER) != 0) {
3950
3951                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
3952                         ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
3953                         Port, PhyStat));
3954                 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
3955         }
3956 }       /* SkMacAutoNegLipaPhy */
3957
3958
3959 #ifdef GENESIS
3960 /******************************************************************************
3961  *
3962  *      SkXmIrq() - Interrupt Service Routine
3963  *
3964  * Description: services an Interrupt Request of the XMAC
3965  *
3966  * Note:
3967  *      With an external PHY, some interrupt bits are not meaningfull any more:
3968  *      - LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
3969  *      - LinkPartnerReqConfig (bit #10)        XM_IS_LIPA_RC
3970  *      - Page Received (bit #9)                XM_IS_RX_PAGE
3971  *      - NextPageLoadedForXmt (bit #8)         XM_IS_TX_PAGE
3972  *      - AutoNegDone (bit #7)                  XM_IS_AND
3973  *      Also probably not valid any more is the GP0 input bit:
3974  *      - GPRegisterBit0set                     XM_IS_INP_ASS
3975  *
3976  * Returns:
3977  *      nothing
3978  */
3979 void SkXmIrq(
3980 SK_AC   *pAC,           /* adapter context */
3981 SK_IOC  IoC,            /* IO context */
3982 int             Port)           /* Port Index (MAC_1 + n) */
3983 {
3984         SK_GEPORT       *pPrt;
3985         SK_EVPARA       Para;
3986         SK_U16          IStatus;        /* Interrupt status read from the XMAC */
3987         SK_U16          IStatus2;
3988 #ifdef SK_SLIM
3989     SK_U64      OverflowStatus;
3990 #endif  
3991
3992         pPrt = &pAC->GIni.GP[Port];
3993         
3994         XM_IN16(IoC, Port, XM_ISRC, &IStatus);
3995         
3996         /* LinkPartner Auto-negable? */
3997         if (pPrt->PhyType == SK_PHY_XMAC) {
3998                 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
3999         }
4000         else {
4001                 /* mask bits that are not used with ext. PHY */
4002                 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
4003                         XM_IS_RX_PAGE | XM_IS_TX_PAGE |
4004                         XM_IS_AND | XM_IS_INP_ASS);
4005         }
4006         
4007         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4008                 ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
4009
4010         if (!pPrt->PHWLinkUp) {
4011                 /* Spurious XMAC interrupt */
4012                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4013                         ("SkXmIrq: spurious interrupt on Port %d\n", Port));
4014                 return;
4015         }
4016
4017         if ((IStatus & XM_IS_INP_ASS) != 0) {
4018                 /* Reread ISR Register if link is not in sync */
4019                 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
4020
4021                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4022                         ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
4023                          Port, IStatus, IStatus2));
4024                 IStatus &= ~XM_IS_INP_ASS;
4025                 IStatus |= IStatus2;
4026         }
4027
4028         if ((IStatus & XM_IS_LNK_AE) != 0) {
4029                 /* not used, GP0 is used instead */
4030         }
4031
4032         if ((IStatus & XM_IS_TX_ABORT) != 0) {
4033                 /* not used */
4034         }
4035
4036         if ((IStatus & XM_IS_FRC_INT) != 0) {
4037                 /* not used, use ASIC IRQ instead if needed */
4038         }
4039
4040         if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
4041                 SkHWLinkDown(pAC, IoC, Port);
4042
4043                 /* Signal to RLMT */
4044                 Para.Para32[0] = (SK_U32)Port;
4045                 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
4046
4047                 /* Start workaround Errata #2 timer */
4048                 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
4049                         SKGE_HWAC, SK_HWEV_WATIM, Para);
4050         }
4051
4052         if ((IStatus & XM_IS_RX_PAGE) != 0) {
4053                 /* not used */
4054         }
4055
4056         if ((IStatus & XM_IS_TX_PAGE) != 0) {
4057                 /* not used */
4058         }
4059
4060         if ((IStatus & XM_IS_AND) != 0) {
4061                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4062                         ("SkXmIrq: AND on link that is up Port %d\n", Port));
4063         }
4064
4065         if ((IStatus & XM_IS_TSC_OV) != 0) {
4066                 /* not used */
4067         }
4068
4069         /* Combined Tx & Rx Counter Overflow SIRQ Event */
4070         if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
4071 #ifdef SK_SLIM
4072                 SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
4073 #else
4074                 Para.Para32[0] = (SK_U32)Port;
4075                 Para.Para32[1] = (SK_U32)IStatus;
4076                 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
4077 #endif /* SK_SLIM */
4078         }
4079
4080         if ((IStatus & XM_IS_RXF_OV) != 0) {
4081                 /* normal situation -> no effect */
4082 #ifdef DEBUG
4083                 pPrt->PRxOverCnt++;
4084 #endif /* DEBUG */
4085         }
4086
4087         if ((IStatus & XM_IS_TXF_UR) != 0) {
4088                 /* may NOT happen -> error log */
4089                 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
4090         }
4091
4092         if ((IStatus & XM_IS_TX_COMP) != 0) {
4093                 /* not served here */
4094         }
4095
4096         if ((IStatus & XM_IS_RX_COMP) != 0) {
4097                 /* not served here */
4098         }
4099 }       /* SkXmIrq */
4100 #endif /* GENESIS */
4101
4102
4103 #ifdef YUKON
4104 /******************************************************************************
4105  *
4106  *      SkGmIrq() - Interrupt Service Routine
4107  *
4108  * Description: services an Interrupt Request of the GMAC
4109  *
4110  * Note:
4111  *
4112  * Returns:
4113  *      nothing
4114  */
4115 void SkGmIrq(
4116 SK_AC   *pAC,           /* adapter context */
4117 SK_IOC  IoC,            /* IO context */
4118 int             Port)           /* Port Index (MAC_1 + n) */
4119 {
4120         SK_GEPORT       *pPrt;
4121         SK_U8           IStatus;        /* Interrupt status */
4122 #ifdef SK_SLIM
4123     SK_U64      OverflowStatus;
4124 #else
4125         SK_EVPARA       Para;
4126 #endif  
4127
4128         pPrt = &pAC->GIni.GP[Port];
4129         
4130         SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
4131         
4132 #ifdef XXX
4133         /* LinkPartner Auto-negable? */
4134         SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
4135 #endif /* XXX */
4136         
4137         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
4138                 ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
4139
4140         /* Combined Tx & Rx Counter Overflow SIRQ Event */
4141         if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
4142                 /* these IRQs will be cleared by reading GMACs register */
4143 #ifdef SK_SLIM
4144         SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
4145 #else
4146                 Para.Para32[0] = (SK_U32)Port;
4147                 Para.Para32[1] = (SK_U32)IStatus;
4148                 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
4149 #endif          
4150         }
4151
4152         if (IStatus & GM_IS_RX_FF_OR) {
4153                 /* clear GMAC Rx FIFO Overrun IRQ */
4154                 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
4155 #ifdef DEBUG
4156                 pPrt->PRxOverCnt++;
4157 #endif /* DEBUG */
4158         }
4159
4160         if (IStatus & GM_IS_TX_FF_UR) {
4161                 /* clear GMAC Tx FIFO Underrun IRQ */
4162                 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
4163                 /* may NOT happen -> error log */
4164                 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
4165         }
4166
4167         if (IStatus & GM_IS_TX_COMPL) {
4168                 /* not served here */
4169         }
4170
4171         if (IStatus & GM_IS_RX_COMPL) {
4172                 /* not served here */
4173         }
4174 }       /* SkGmIrq */
4175 #endif /* YUKON */
4176
4177
4178 /******************************************************************************
4179  *
4180  *      SkMacIrq() - Interrupt Service Routine for MAC
4181  *
4182  * Description: calls the Interrupt Service Routine dep. on board type
4183  *
4184  * Returns:
4185  *      nothing
4186  */
4187 void SkMacIrq(
4188 SK_AC   *pAC,           /* adapter context */
4189 SK_IOC  IoC,            /* IO context */
4190 int             Port)           /* Port Index (MAC_1 + n) */
4191 {
4192 #ifdef GENESIS
4193         if (pAC->GIni.GIGenesis) {
4194                 /* IRQ from XMAC */
4195                 SkXmIrq(pAC, IoC, Port);
4196         }
4197 #endif /* GENESIS */
4198         
4199 #ifdef YUKON
4200         if (pAC->GIni.GIYukon) {
4201                 /* IRQ from GMAC */
4202                 SkGmIrq(pAC, IoC, Port);
4203         }
4204 #endif /* YUKON */
4205
4206 }       /* SkMacIrq */
4207
4208 #endif /* !SK_DIAG */
4209
4210 #ifdef GENESIS
4211 /******************************************************************************
4212  *
4213  *      SkXmUpdateStats() - Force the XMAC to output the current statistic
4214  *
4215  * Description:
4216  *      The XMAC holds its statistic internally. To obtain the current
4217  *      values a command must be sent so that the statistic data will
4218  *      be written to a predefined memory area on the adapter.
4219  *
4220  * Returns:
4221  *      0:  success
4222  *      1:  something went wrong
4223  */
4224 int SkXmUpdateStats(
4225 SK_AC   *pAC,           /* adapter context */
4226 SK_IOC  IoC,            /* IO context */
4227 unsigned int Port)      /* Port Index (MAC_1 + n) */
4228 {
4229         SK_GEPORT       *pPrt;
4230         SK_U16          StatReg;
4231         int                     WaitIndex;
4232
4233         pPrt = &pAC->GIni.GP[Port];
4234         WaitIndex = 0;
4235
4236         /* Send an update command to XMAC specified */
4237         XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
4238
4239         /*
4240          * It is an auto-clearing register. If the command bits
4241          * went to zero again, the statistics are transferred.
4242          * Normally the command should be executed immediately.
4243          * But just to be sure we execute a loop.
4244          */
4245         do {
4246
4247                 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
4248                 
4249                 if (++WaitIndex > 10) {
4250
4251                         SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
4252
4253                         return(1);
4254                 }
4255         } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
4256         
4257         return(0);
4258 }       /* SkXmUpdateStats */
4259
4260
4261 /******************************************************************************
4262  *
4263  *      SkXmMacStatistic() - Get XMAC counter value
4264  *
4265  * Description:
4266  *      Gets the 32bit counter value. Except for the octet counters
4267  *      the lower 32bit are counted in hardware and the upper 32bit
4268  *      must be counted in software by monitoring counter overflow interrupts.
4269  *
4270  * Returns:
4271  *      0:  success
4272  *      1:  something went wrong
4273  */
4274 int SkXmMacStatistic(
4275 SK_AC   *pAC,                   /* adapter context */
4276 SK_IOC  IoC,                    /* IO context */
4277 unsigned int Port,              /* Port Index (MAC_1 + n) */
4278 SK_U16  StatAddr,               /* MIB counter base address */
4279 SK_U32  SK_FAR *pVal)   /* ptr to return statistic value */
4280 {
4281         if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
4282                 
4283                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4284                 
4285                 return(1);
4286         }
4287         
4288         XM_IN32(IoC, Port, StatAddr, pVal);
4289
4290         return(0);
4291 }       /* SkXmMacStatistic */
4292
4293
4294 /******************************************************************************
4295  *
4296  *      SkXmResetCounter() - Clear MAC statistic counter
4297  *
4298  * Description:
4299  *      Force the XMAC to clear its statistic counter.
4300  *
4301  * Returns:
4302  *      0:  success
4303  *      1:  something went wrong
4304  */
4305 int SkXmResetCounter(
4306 SK_AC   *pAC,           /* adapter context */
4307 SK_IOC  IoC,            /* IO context */
4308 unsigned int Port)      /* Port Index (MAC_1 + n) */
4309 {
4310         XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4311         /* Clear two times according to Errata #3 */
4312         XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
4313
4314         return(0);
4315 }       /* SkXmResetCounter */
4316
4317
4318 /******************************************************************************
4319  *
4320  *      SkXmOverflowStatus() - Gets the status of counter overflow interrupt
4321  *
4322  * Description:
4323  *      Checks the source causing an counter overflow interrupt. On success the
4324  *      resulting counter overflow status is written to <pStatus>, whereas the
4325  *      upper dword stores the XMAC ReceiveCounterEvent register and the lower
4326  *      dword the XMAC TransmitCounterEvent register.
4327  *
4328  * Note:
4329  *      For XMAC the interrupt source is a self-clearing register, so the source
4330  *      must be checked only once. SIRQ module does another check to be sure
4331  *      that no interrupt get lost during process time.
4332  *
4333  * Returns:
4334  *      0:  success
4335  *      1:  something went wrong
4336  */
4337 int SkXmOverflowStatus(
4338 SK_AC   *pAC,                           /* adapter context */
4339 SK_IOC  IoC,                            /* IO context */
4340 unsigned int Port,                      /* Port Index (MAC_1 + n) */
4341 SK_U16  IStatus,                        /* Interupt Status from MAC */
4342 SK_U64  SK_FAR *pStatus)        /* ptr for return overflow status value */
4343 {
4344         SK_U64  Status; /* Overflow status */
4345         SK_U32  RegVal;
4346
4347         Status = 0;
4348
4349         if ((IStatus & XM_IS_RXC_OV) != 0) {
4350
4351                 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
4352                 Status |= (SK_U64)RegVal << 32;
4353         }
4354         
4355         if ((IStatus & XM_IS_TXC_OV) != 0) {
4356
4357                 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
4358                 Status |= (SK_U64)RegVal;
4359         }
4360
4361         *pStatus = Status;
4362
4363         return(0);
4364 }       /* SkXmOverflowStatus */
4365 #endif /* GENESIS */
4366
4367
4368 #ifdef YUKON
4369 /******************************************************************************
4370  *
4371  *      SkGmUpdateStats() - Force the GMAC to output the current statistic
4372  *
4373  * Description:
4374  *      Empty function for GMAC. Statistic data is accessible in direct way.
4375  *
4376  * Returns:
4377  *      0:  success
4378  *      1:  something went wrong
4379  */
4380 int SkGmUpdateStats(
4381 SK_AC   *pAC,           /* adapter context */
4382 SK_IOC  IoC,            /* IO context */
4383 unsigned int Port)      /* Port Index (MAC_1 + n) */
4384 {
4385         return(0);
4386 }
4387
4388
4389 /******************************************************************************
4390  *
4391  *      SkGmMacStatistic() - Get GMAC counter value
4392  *
4393  * Description:
4394  *      Gets the 32bit counter value. Except for the octet counters
4395  *      the lower 32bit are counted in hardware and the upper 32bit
4396  *      must be counted in software by monitoring counter overflow interrupts.
4397  *
4398  * Returns:
4399  *      0:  success
4400  *      1:  something went wrong
4401  */
4402 int SkGmMacStatistic(
4403 SK_AC   *pAC,                   /* adapter context */
4404 SK_IOC  IoC,                    /* IO context */
4405 unsigned int Port,              /* Port Index (MAC_1 + n) */
4406 SK_U16  StatAddr,               /* MIB counter base address */
4407 SK_U32  SK_FAR *pVal)   /* ptr to return statistic value */
4408 {
4409
4410         if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
4411                 
4412                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
4413                 
4414                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4415                         ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
4416                 return(1);
4417         }
4418                 
4419         GM_IN32(IoC, Port, StatAddr, pVal);
4420
4421         return(0);
4422 }       /* SkGmMacStatistic */
4423
4424
4425 /******************************************************************************
4426  *
4427  *      SkGmResetCounter() - Clear MAC statistic counter
4428  *
4429  * Description:
4430  *      Force GMAC to clear its statistic counter.
4431  *
4432  * Returns:
4433  *      0:  success
4434  *      1:  something went wrong
4435  */
4436 int SkGmResetCounter(
4437 SK_AC   *pAC,           /* adapter context */
4438 SK_IOC  IoC,            /* IO context */
4439 unsigned int Port)      /* Port Index (MAC_1 + n) */
4440 {
4441         SK_U16  Reg;    /* Phy Address Register */
4442         SK_U16  Word;
4443         int             i;
4444
4445         GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
4446
4447         /* set MIB Clear Counter Mode */
4448         GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
4449         
4450         /* read all MIB Counters with Clear Mode set */
4451         for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
4452                 /* the reset is performed only when the lower 16 bits are read */
4453                 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
4454         }
4455         
4456         /* clear MIB Clear Counter Mode */
4457         GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
4458         
4459         return(0);
4460 }       /* SkGmResetCounter */
4461
4462
4463 /******************************************************************************
4464  *
4465  *      SkGmOverflowStatus() - Gets the status of counter overflow interrupt
4466  *
4467  * Description:
4468  *      Checks the source causing an counter overflow interrupt. On success the
4469  *      resulting counter overflow status is written to <pStatus>, whereas the
4470  *      the following bit coding is used:
4471  *      63:56 - unused
4472  *      55:48 - TxRx interrupt register bit7:0
4473  *      32:47 - Rx interrupt register
4474  *      31:24 - unused
4475  *      23:16 - TxRx interrupt register bit15:8
4476  *      15:0  - Tx interrupt register
4477  *
4478  * Returns:
4479  *      0:  success
4480  *      1:  something went wrong
4481  */
4482 int SkGmOverflowStatus(
4483 SK_AC   *pAC,                           /* adapter context */
4484 SK_IOC  IoC,                            /* IO context */
4485 unsigned int Port,                      /* Port Index (MAC_1 + n) */
4486 SK_U16  IStatus,                        /* Interupt Status from MAC */
4487 SK_U64  SK_FAR *pStatus)        /* ptr for return overflow status value */
4488 {
4489         SK_U64  Status;         /* Overflow status */
4490         SK_U16  RegVal;
4491
4492         Status = 0;
4493
4494         if ((IStatus & GM_IS_RX_CO_OV) != 0) {
4495                 /* this register is self-clearing after read */
4496                 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
4497                 Status |= (SK_U64)RegVal << 32;
4498         }
4499         
4500         if ((IStatus & GM_IS_TX_CO_OV) != 0) {
4501                 /* this register is self-clearing after read */
4502                 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
4503                 Status |= (SK_U64)RegVal;
4504         }
4505         
4506         /* this register is self-clearing after read */
4507         GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
4508         /* Rx overflow interrupt register bits (LoByte)*/
4509         Status |= (SK_U64)((SK_U8)RegVal) << 48;
4510         /* Tx overflow interrupt register bits (HiByte)*/
4511         Status |= (SK_U64)(RegVal >> 8) << 16;
4512
4513         *pStatus = Status;
4514
4515         return(0);
4516 }       /* SkGmOverflowStatus */
4517
4518
4519 #ifndef SK_SLIM
4520 /******************************************************************************
4521  *
4522  *      SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
4523  *
4524  * Description:
4525  *  starts the cable diagnostic test if 'StartTest' is true
4526  *  gets the results if 'StartTest' is true
4527  *
4528  * NOTE:        this test is meaningful only when link is down
4529  *      
4530  * Returns:
4531  *      0:  success
4532  *      1:      no YUKON copper
4533  *      2:      test in progress
4534  */
4535 int SkGmCableDiagStatus(
4536 SK_AC   *pAC,           /* adapter context */
4537 SK_IOC  IoC,            /* IO context */
4538 int             Port,           /* Port Index (MAC_1 + n) */
4539 SK_BOOL StartTest)      /* flag for start / get result */
4540 {
4541         int             i;
4542         SK_U16  RegVal;
4543         SK_GEPORT       *pPrt;
4544
4545         pPrt = &pAC->GIni.GP[Port];
4546
4547         if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
4548                 
4549                 return(1);
4550         }
4551
4552         if (StartTest) {
4553                 /* only start the cable test */
4554                 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
4555                         /* apply TDR workaround from Marvell */
4556                         SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
4557                         
4558                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
4559                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
4560                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
4561                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
4562                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
4563                 }
4564
4565                 /* set address to 0 for MDI[0] */
4566                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
4567
4568                 /* Read Cable Diagnostic Reg */
4569                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4570
4571                 /* start Cable Diagnostic Test */
4572                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
4573                         (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
4574         
4575                 return(0);
4576         }
4577         
4578         /* Read Cable Diagnostic Reg */
4579         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4580
4581         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
4582                 ("PHY Cable Diag.=0x%04X\n", RegVal));
4583
4584         if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
4585                 /* test is running */
4586                 return(2);
4587         }
4588
4589         /* get the test results */
4590         for (i = 0; i < 4; i++)  {
4591                 /* set address to i for MDI[i] */
4592                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
4593
4594                 /* get Cable Diagnostic values */
4595                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
4596
4597                 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
4598
4599                 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
4600         }
4601
4602         return(0);
4603 }       /* SkGmCableDiagStatus */
4604 #endif /* !SK_SLIM */
4605 #endif /* YUKON */
4606
4607 /* End of file */