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