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