2 Copyright (c) 2002-2003, Micrel Semiconductor
4 Written 2002 by LIQUN RUAN
6 This software may be used and distributed according to the terms of
7 the GNU General Public License (GPL), incorporated herein by reference.
8 Drivers based on or derived from this code fall under the GPL and must
9 retain the authorship, copyright and license notice. This file is not
10 a complete program and may only be used when the entire operating
11 system is licensed under the GPL.
13 The author may be reached as liqun.ruan@micrel.com
18 This driver is for Micrel's KS8695/KS8695P SOHO Router Chipset as ethernet driver.
20 Support and updates available at
21 www.micrel.com/ks8695/ not ready yet!!!
24 #include "ks8695_drv.h"
25 #include "ks8695_chipdef.h"
26 #include "ks8695_ioctrl.h"
27 #include "ks8695_cache.h"
29 static int macReset(PADAPTER_STRUCT Adapter
);
30 static void macConfigure(PADAPTER_STRUCT Adapter
);
31 static void macConfigureFlow(PADAPTER_STRUCT Adapter
, uint8_t bFlowCtrl
);
32 static void macConfigureInterrupt(PADAPTER_STRUCT Adapter
);
34 static void swConfigure(PADAPTER_STRUCT Adapter
);
35 static void swCreateLookUpTable(PADAPTER_STRUCT Adapter
);
37 static void gpioConfigure(PADAPTER_STRUCT Adapter
);
39 #ifdef CONFIG_ARCH_KS8695P
40 void forceFlowControl(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bOn
);
41 void backPressureEnable(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bOn
);
46 * This function is used to do chip initialization.
49 * Adapter pointer to ADAPTER_STRUCT structure.
50 * bResetPhy flag indicates whether to reset PHY as well
56 BOOLEAN
ks8695_ChipInit(PADAPTER_STRUCT Adapter
, BOOLEAN bResetPhy
)
59 struct net_device
*netdev
= Adapter
->netdev
;
63 DRV_INFO("%s", __FUNCTION__
);
67 /* phy related initialization */
69 swPhyReset(Adapter
, i
);
70 if (DMA_LAN
== DI
.usDMAId
) {
71 for (i
= 1; i
< SW_MAX_LAN_PORTS
; i
++) {
72 swPhyReset(Adapter
, i
);
73 /* turn off GPIO, to make sure that if there is no cable connection, no light */
74 gpioSet(Adapter
, i
, FALSE
);
77 swAutoNegoAdvertisement(Adapter
, 0);
78 if (DMA_LAN
== DI
.usDMAId
) {
79 for (i
= 1; i
< SW_MAX_LAN_PORTS
; i
++) {
80 swAutoNegoAdvertisement(Adapter
, i
);
85 /* setup mac related stuff */
86 bStatus
= macReset(Adapter
);
88 DRV_ERR("%s: macReset failed", __FUNCTION__
);
91 macConfigure(Adapter
);
92 macConfigureInterrupt(Adapter
);
94 /* turn off GPIO, to make sure that if there is no cable connection, no light */
95 gpioSet(Adapter
, 0, FALSE
);
96 /* configuration switch related to LAN only */
97 if (DMA_LAN
== DI
.usDMAId
) {
99 swCreateLookUpTable(Adapter
);
100 for (i
= 1; i
< SW_MAX_LAN_PORTS
; i
++) {
101 /* turn off GPIO, to make sure that if there is no cable connection, no light */
102 gpioSet(Adapter
, i
, FALSE
);
106 /* copy the MAC address out of Station registers */
107 macSetStationAddress(Adapter
, DI
.stMacStation
);
108 if (netdev
->addr_len
< MAC_ADDRESS_LEN
)
109 netdev
->addr_len
= MAC_ADDRESS_LEN
;
110 memcpy(netdev
->dev_addr
, DI
.stMacStation
, netdev
->addr_len
);
111 memcpy(DI
.stMacCurrent
, netdev
->dev_addr
, netdev
->addr_len
);
114 DRV_INFO("MAC address %02X:%02X:%02X:%02X:%02X:%02X",
123 gpioConfigure(Adapter
);
125 /*RLQ, 11/20/2002, fix based on AN112. Changing transmitter gain in KS8695 to improve
126 the calbe length at which the Ethernet can operate */
127 if (0 == Adapter
->rev
) {
129 KS8695_WRITE_REG(KS8695_WAN_PHY_CONTROL
, 0x0000b000);
132 /* for KS8695P, rev A */
133 KS8695_WRITE_REG(KS8695_WAN_PHY_CONTROL
, 0x0200b000);
136 return bStatus
? FALSE
: TRUE
;
139 #define IRQ_WAN_LEVEL 12
140 #define IRQ_LAN_LEVEL 10
141 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
142 #define IRQ_HPNA_LEVEL 8
145 /* move to source file later */
146 static INTCFG stDMAIntCfg
[32] = {
147 { 0, -1 }, /* -1 don't touch, it's not ours */
158 { 0, -1 }, /* bit 11 */
160 { 0, 0x0b }, /* bit 12, LAN */
167 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
168 { 0, IRQ_HPNA_LEVEL
}, /* bit 18, HPNA */
169 { 0, IRQ_HPNA_LEVEL
},
170 { 0, IRQ_HPNA_LEVEL
},
171 { 0, IRQ_HPNA_LEVEL
},
172 { 0, IRQ_HPNA_LEVEL
},
173 { 0, IRQ_HPNA_LEVEL
},
175 { 0, -1 }, /* bit 18, KS8695P doesn't have HPNA port */
182 { 0, -1 }, /* bit 24 */
184 { 0, 0x0b }, /* bit 25, WAN */
190 { 0, IRQ_WAN_LEVEL
} /* WAN link */
195 * This function will execute a soft reset the chipset.
198 * Adapter pointer to ADAPTER_STRUCT structure.
202 * none zero otherwise
204 int macReset(PADAPTER_STRUCT Adapter
)
211 DRV_INFO("%s", __FUNCTION__
);
214 spin_lock_irqsave(&DI
.lock
, flags
);
215 /*spin_lock(&DI.lock);*/
216 /* disable IER if any */
217 uReg
= KS8695_READ_REG(KS8695_INT_ENABLE
);
218 switch (DI
.usDMAId
) {
219 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
221 uReg
&= ~INT_HPNA_MASK
;
226 uReg
&= ~INT_LAN_MASK
;
231 uReg
&= ~INT_WAN_MASK
;
234 KS8695_WRITE_REG(KS8695_INT_ENABLE
, uReg
);
235 /*spin_unlock(&DI.lock);*/
236 spin_unlock_irqrestore(&DI
.lock
, flags
);
238 /* reset corresponding register and wait for completion */
239 KS8695_WRITE_REG(REG_TXCTRL
+ DI
.nOffset
, DMA_SOFTRESET
);
242 DelayInMilliseconds(1);
243 uReg
= KS8695_READ_REG(REG_TXCTRL
+ DI
.nOffset
);
244 if (!(uReg
& DMA_SOFTRESET
))
246 } while (--nTimeOut
);
249 DRV_ERR("%s> timeout error", __FUNCTION__
);
253 /* clear statistic counters */
254 swResetSNMPInfo(Adapter
);
256 DRV_INFO("%s> succeeded (timeout count=%d)", __FUNCTION__
, nTimeOut
);
264 * This function is used to set MAC control register based on configurable
268 * Adapter pointer to ADAPTER_STRUCT structure.
273 void macConfigure(PADAPTER_STRUCT Adapter
)
278 DRV_INFO("%s", __FUNCTION__
);
281 /* read TX mode register */
282 uTxReg
= KS8695_READ_REG(REG_TXCTRL
+ DI
.nOffset
);
283 /* clear PBL bits first */
284 uTxReg
&= ~DMA_PBLTMASK
; /* 29:24 */
286 uTxReg
|= ((uint32_t)DI
.byTxPBL
<< DMA_PBLTSHIFT
);
288 if (DI
.bTxChecksum
) {
289 uTxReg
|= (DMA_IPCHECKSUM
| DMA_TCPCHECKSUM
| DMA_UDPCHECKSUM
);
292 uTxReg
&= ~(DMA_IPCHECKSUM
| DMA_TCPCHECKSUM
| DMA_UDPCHECKSUM
);
297 uTxReg
|= DMA_FLOWCTRL
;
300 uTxReg
&= ~DMA_FLOWCTRL
;
302 uTxReg
|= (DMA_PADDING
| DMA_CRC
);
303 /* write TX mode register */
304 KS8695_WRITE_REG(REG_TXCTRL
+ DI
.nOffset
, uTxReg
);
306 /* read RX mode register */
307 uRxReg
= KS8695_READ_REG(REG_RXCTRL
+ DI
.nOffset
);
308 /* clear PBL bits first */
309 uRxReg
&= ~DMA_PBLTMASK
; /* 29:24 */
311 uRxReg
|= ((uint32_t)DI
.byRxPBL
<< DMA_PBLTSHIFT
);
313 if (DI
.bRxChecksum
) {
314 uRxReg
|= (DMA_IPCHECKSUM
| DMA_TCPCHECKSUM
| DMA_UDPCHECKSUM
);
317 uRxReg
&= ~(DMA_IPCHECKSUM
| DMA_TCPCHECKSUM
| DMA_UDPCHECKSUM
);
322 uRxReg
|= DMA_FLOWCTRL
;
325 uRxReg
&= ~DMA_FLOWCTRL
;
327 /* set unicast only, and let ks8695_set_multi function to set the rest */
328 uRxReg
|= DMA_UNICAST
;
330 /* write RX mode register */
331 KS8695_WRITE_REG(REG_RXCTRL
+ DI
.nOffset
, uRxReg
);
336 * This function is used to set mac flow control as a workaround for WAN port.
340 * Adapter pointer to ADAPTER_STRUCT structure.
341 * bFlowCtrl flow control to set
346 void macConfigureFlow(PADAPTER_STRUCT Adapter
, uint8_t bFlowCtrl
)
349 BOOLEAN bTxStarted
, bRxStarted
;
352 DRV_INFO("%s: flowctrl = %d", __FUNCTION__
, bFlowCtrl
);
355 /* need to stop mac engines if started */
356 bTxStarted
= DI
.bTxStarted
;
357 bRxStarted
= DI
.bRxStarted
;
359 macStartRx(Adapter
, FALSE
);
361 macStartTx(Adapter
, FALSE
);
363 /* read TX mode register */
364 uTxReg
= KS8695_READ_REG(REG_TXCTRL
+ DI
.nOffset
);
367 uTxReg
|= DMA_FLOWCTRL
;
370 uTxReg
&= ~DMA_FLOWCTRL
;
372 /* write TX mode register */
373 KS8695_WRITE_REG(REG_TXCTRL
+ DI
.nOffset
, uTxReg
);
375 /* read RX mode register */
376 uRxReg
= KS8695_READ_REG(REG_RXCTRL
+ DI
.nOffset
);
379 uRxReg
|= DMA_FLOWCTRL
;
382 uRxReg
&= ~DMA_FLOWCTRL
;
384 /* write RX mode register */
385 KS8695_WRITE_REG(REG_RXCTRL
+ DI
.nOffset
, uRxReg
);
388 macStartRx(Adapter
, TRUE
);
390 macStartTx(Adapter
, TRUE
);
395 * This function is used to set MAC lookback mode (for debugging purpose)
398 * Adapter pointer to ADAPTER_STRUCT structure.
403 void macSetLoopback(PADAPTER_STRUCT Adapter
, BOOLEAN bLoopback
)
406 BOOLEAN bTxStarted
, bRxStarted
;
408 bTxStarted
= DI
.bTxStarted
;
409 bRxStarted
= DI
.bRxStarted
;
411 macStartRx(Adapter
, FALSE
);
413 macStartTx(Adapter
, FALSE
);
415 /* read TX mode register */
416 uTxReg
= KS8695_READ_REG(REG_TXCTRL
+ DI
.nOffset
);
420 uTxReg
|= DMA_LOOPBACK
;
423 uTxReg
&= ~DMA_LOOPBACK
;
426 /* write TX mode register */
427 KS8695_WRITE_REG(REG_TXCTRL
+ DI
.nOffset
, uTxReg
);
430 macStartRx(Adapter
, TRUE
);
432 macStartTx(Adapter
, TRUE
);
437 * This routine will start/stop RX machine.
440 * Adapter pointer to ADAPTER_STRUCT data structure.
441 * bStart TRUE if start Rx machine, FALSE if stop it
446 void macStartRx(PADAPTER_STRUCT Adapter
, BOOLEAN bStart
)
450 uReg
= KS8695_READ_REG(REG_RXCTRL
+ DI
.nOffset
);
452 /* start RX machine */
454 DI
.bRxStarted
= FALSE
;
456 /* Stop RX machine */
458 DI
.bRxStarted
= FALSE
;
460 KS8695_WRITE_REG(REG_RXCTRL
+ DI
.nOffset
, uReg
);
462 /* if there descriptors available for rx, tick off Rx engine */
464 if (atomic_read(&DI
.RxDescEmpty
) < DI
.nRxDescTotal
) {
465 KS8695_WRITE_REG(REG_RXSTART
+ DI
.nOffset
, 1);
469 /* clear corresponding ISR bits after stopped */
470 KS8695_WRITE_REG(KS8695_INT_STATUS
, DI
.uIntMask
);
476 * This routine will start/stop TX machine.
479 * Adapter pionter to ADAPTER_STRUCT data structure.
480 * bStart TRUE if start Tx machine, FALSE if stop it
485 void macStartTx(PADAPTER_STRUCT Adapter
, BOOLEAN bStart
)
489 uReg
= KS8695_READ_REG(REG_TXCTRL
+ DI
.nOffset
);
491 /* start TX machine */
493 KS8695_WRITE_REG(REG_TXCTRL
+ DI
.nOffset
, uReg
);
494 DI
.bTxStarted
= FALSE
;
495 /* clear corresponding ISR bits after stopped */
496 KS8695_WRITE_REG(KS8695_INT_STATUS
, DI
.uIntMask
);
498 /* Stop TX machine */
500 KS8695_WRITE_REG(REG_TXCTRL
+ DI
.nOffset
, uReg
);
501 DelayInMilliseconds(2);
502 DI
.bTxStarted
= FALSE
;
508 * This function is use to stop both Tx/Rx.
511 * Adapter pionter to ADAPTER_STRUCT data structure.
516 void macStopAll(PADAPTER_STRUCT Adapter
)
519 macStartRx(Adapter
, FALSE
);
520 macStartTx(Adapter
, FALSE
);
522 /* disable interrupt!!! */
523 macEnableInterrupt(Adapter
, FALSE
);
528 * This function is use to set extra MAC station address
531 * Adapter pionter to ADAPTER_STRUCT data structure.
532 * pMac pointer to mac address buffer (should be 6)
533 * uIndex index of extra mac address to set
537 * negative value if failed
539 int macSetStationEx(PADAPTER_STRUCT Adapter
, UCHAR
*pMac
, UINT uIndex
)
542 DRV_INFO("%s", __FUNCTION__
);
545 /* do we need to set multicast addr to extra station registers? */
546 if (uIndex
< MAC_MAX_EXTRA
) {
547 uint32_t uLowAddress
, uHighAddress
;
549 uLowAddress
= (*(pMac
+ 5) |
554 uHighAddress
= (*(pMac
+ 1) |
557 /* make sure mac address is not all zero */
558 if (uLowAddress
| uHighAddress
) {
559 /* enable additional MAC */
560 uHighAddress
|= DMA_MACENABLE
;
561 KS8695_WRITE_REG(REG_MAC0_LOW
+ DI
.nOffset
+ uIndex
* 8, uLowAddress
);
562 KS8695_WRITE_REG(REG_MAC0_HIGH
+ DI
.nOffset
+ uIndex
* 8, uHighAddress
);
572 * This function is use to clear extra MAC station address if set before
575 * Adapter pionter to ADAPTER_STRUCT data structure.
576 * nIndex index of extra mac address to set
577 * pMac pointer to mac address buffer (should be 6)
581 * negative value if failed
583 int macResetStationEx(PADAPTER_STRUCT Adapter
, UCHAR
*pMac
)
586 uint32_t uLowAddress
, uHighAddress
;
589 DRV_INFO("%s", __FUNCTION__
);
592 uLowAddress
= (*(pMac
+ 5) |
597 uHighAddress
= (*(pMac
+ 1) |
600 /* set mac enable bit for comparison purpose only! */
601 uHighAddress
|= DMA_MACENABLE
;
603 /* if match is found, remove it (set to 0) */
604 for (i
= 0; i
< MAC_MAX_EXTRA
; i
++) {
606 if (uLowAddress
== KS8695_READ_REG(REG_MAC0_LOW
+ DI
.nOffset
+ j
) &&
607 uHighAddress
== KS8695_READ_REG(REG_MAC0_HIGH
+ DI
.nOffset
+ j
)) {
608 KS8695_WRITE_REG(REG_MAC0_LOW
+ DI
.nOffset
+ j
, 0);
609 KS8695_WRITE_REG(REG_MAC0_HIGH
+ DI
.nOffset
+ j
, 0);
617 * macGetIndexStationEx
618 * This function is use to get the index of empty station
621 * Adapter pionter to ADAPTER_STRUCT data structure.
624 * nIndex index of empty to use
625 * negative value if it is full
627 int macGetIndexStationEx(PADAPTER_STRUCT Adapter
)
632 DRV_INFO("%s", __FUNCTION__
);
635 for (i
= 0; i
< MAC_MAX_EXTRA
; i
++) {
636 if (!(KS8695_READ_REG(REG_MAC0_HIGH
+ DI
.nOffset
+ i
* 8) & DMA_MACENABLE
)) {
641 DRV_WARN("%s: no empty slot for Additional Station Address", __FUNCTION__
);
645 /* Interrupt Bit definitions */
646 #define IB_WAN_LINK 31
647 #define IB_WAN_RX_STOPPED 25
648 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
649 #define IB_HPNA_TX 23
650 #define IB_HPNA_RX_STOPPED 18
653 #define IB_LAN_RX_STOPPED 12
656 * macConfigureInterrupt
657 * This routine is used to configure interrupt priority
660 * Adapter pionter to ADAPTER_STRUCT data structure.
665 void macConfigureInterrupt(PADAPTER_STRUCT Adapter
)
672 DRV_INFO("%s", __FUNCTION__
);
675 spin_lock_irqsave(&DI
.lock
, flags
);
676 /*spin_lock(&DI.lock);*/
677 uIMR
= KS8695_READ_REG(KS8695_INT_CONTL
);
678 switch (DI
.usDMAId
) {
680 for (i
= IB_LAN_RX_STOPPED
; i
<= IB_LAN_TX
; i
++) {
681 if (stDMAIntCfg
[i
].bFIQ
) {
687 uIPR
|= ((UINT
)(stDMAIntCfg
[i
].byPriority
) & 0xf) << (i
- IB_LAN_RX_STOPPED
+ 1) * 4;
690 KS8695_WRITE_REG(KS8695_INT_LAN_PRIORITY
, uIPR
);
693 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
695 for (i
= IB_HPNA_RX_STOPPED
; i
<= IB_HPNA_TX
; i
++) {
696 if (stDMAIntCfg
[i
].bFIQ
) {
702 uIPR
|= ((UINT
)(stDMAIntCfg
[i
].byPriority
) & 0xf) << (i
- IB_HPNA_RX_STOPPED
+ 1) * 4;
705 KS8695_WRITE_REG(KS8695_INT_HPNA_PRIORITY
, uIPR
);
711 for (i
= IB_WAN_RX_STOPPED
; i
<= IB_WAN_LINK
; i
++) {
712 if (stDMAIntCfg
[i
].bFIQ
) {
718 uIPR
|= ((UINT
)(stDMAIntCfg
[i
].byPriority
) & 0xf) << (i
- IB_WAN_RX_STOPPED
+ 1) * 4;
721 KS8695_WRITE_REG(KS8695_INT_WAN_PRIORITY
, uIPR
);
724 KS8695_WRITE_REG(KS8695_INT_CONTL
, uIMR
);
725 /*spin_unlock(&DI.lock);*/
726 spin_unlock_irqrestore(&DI
.lock
, flags
);
731 * This routine is used to enable/disable interrupt related to MAC only
734 * Adapter pionter to ADAPTER_STRUCT data structure.
735 * bEnable enable/disable interrupt
740 void macEnableInterrupt(PADAPTER_STRUCT Adapter
, BOOLEAN bEnable
)
745 uIER
= KS8695_READ_REG(KS8695_INT_ENABLE
);
746 switch (DI
.usDMAId
) {
748 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
754 uIER
&= ~DI
.uIntMask
;
759 uIER
|= (DI
.uIntMask
| DI
.uLinkIntMask
);
761 uIER
&= ~(DI
.uIntMask
| DI
.uLinkIntMask
);
765 DRV_INFO("unsupported option");
768 KS8695_WRITE_REG(KS8695_INT_ENABLE
, uIER
);
769 spin_unlock(&DI
.lock
);
770 ks8695_power_saving(bEnable
);
774 * macGetStationAddress
775 * This function reads MAC address from station address registers.
778 * Adapter pointer to ADAPTER_STRUCT struct
779 * pMacAddress pointer to a byte array to hold MAC address (at least 6 bytes long)
784 void macGetStationAddress(PADAPTER_STRUCT Adapter
, uint8_t *pMacAddress
)
790 DRV_INFO("%s", __FUNCTION__
);
793 /* read low 4 buytes, byte order (e.g. in our NIC card, 00101a00000d) */
794 uTmp
= KS8695_READ_REG(REG_STATION_LOW
+ DI
.nOffset
);
795 for (i
= (MAC_ADDRESS_LEN
- 1); i
> 1; i
--)
797 pMacAddress
[i
] = (UCHAR
)(uTmp
& 0x0ff);
800 /* read high 2 bytes */
801 uTmp
= KS8695_READ_REG(REG_STATION_HIGH
+ DI
.nOffset
);
802 pMacAddress
[1] = (UCHAR
)(uTmp
& 0x0ff);
804 pMacAddress
[0] = (UCHAR
)(uTmp
& 0x0ff);
808 * macSetStationAddress
809 * This function sets MAC address to given type (WAN, LAN or HPHA)
812 * Adapter pointer to ADAPTER_STRUCT struct
813 * pMacAddress pointer to a byte array to hold MAC address (at least 6 bytes long)
818 void macSetStationAddress(PADAPTER_STRUCT Adapter
, uint8_t *pMacAddress
)
823 DRV_INFO("%s", __FUNCTION__
);
826 uLow
= ((UINT32
)pMacAddress
[2] << 24);
827 uLow
+= ((UINT32
)pMacAddress
[3] << 16);
828 uLow
+= ((UINT32
)pMacAddress
[4] << 8);
829 uLow
+= pMacAddress
[5];
830 uHigh
= ((UINT32
)pMacAddress
[0] << 8) + pMacAddress
[1];
831 KS8695_WRITE_REG(REG_STATION_LOW
+ DI
.nOffset
, uLow
);
832 KS8695_WRITE_REG(REG_STATION_HIGH
+ DI
.nOffset
, uHigh
);
837 * This function is used to configure a give port for LAN.
840 * Adapter pointer to ADAPTER_STRUCT struct
841 * uPort port to start
846 void swConfigurePort(PADAPTER_STRUCT Adapter
, UINT uPort
)
849 BOOLEAN bPort5
= FALSE
;
851 if (uPort
>= SW_MAX_LAN_PORTS
) {
852 if (SW_MAX_LAN_PORTS
== uPort
) {
858 DRV_INFO("%s: port %d to configure out of range", __FUNCTION__
, uPort
);
862 #ifndef CONFIG_ARCH_KS8695P
863 uOff
= KS8695_SWITCH_PORT1
+ uPort
* 4;
866 uOff
= KS8695_SEP5C1
;
868 uOff
= KS8695_SEP1C1
+ uPort
* 0x0c;
872 uReg
|= (UINT
)DPI
[uPort
].usTag
<< 16;
875 /* connection media type */
876 /*uReg &= ~(SW_PORT_DISABLE_AUTONEG | SW_PORT_100BASE | SW_PORT_FULLDUPLEX);*/
877 if (SW_PHY_AUTO
!= DI
.usCType
[uPort
]) {
878 uReg
|= SW_PORT_DISABLE_AUTONEG
;
879 if (SW_PHY_100BASE_TX
== DI
.usCType
[uPort
] ||
880 SW_PHY_100BASE_TX_FD
== DI
.usCType
[uPort
]) {
881 uReg
|= SW_PORT_100BASE
;
883 if (SW_PHY_10BASE_T_FD
== DI
.usCType
[uPort
] ||
884 SW_PHY_100BASE_TX_FD
== DI
.usCType
[uPort
]) {
885 uReg
|= SW_PORT_FULLDUPLEX
;
891 if (DI
.bRxDirectMode
) {
892 uReg
|= SW_PORT_RX_DIRECT_MODE
;
894 /* Tx Pre-tag mode */
895 if (DI
.bTxRreTagMode
) {
896 uReg
|= SW_PORT_TX_PRETAG_MODE
;
900 /* cross talk bit mask */
901 uReg
|= ((UINT
)(DPI
[uPort
].byCrossTalkMask
& 0x1f)) << 8;
904 if (SW_SPANNINGTREE_ALL
== DPI
[uPort
].bySpanningTree
) {
905 uReg
|= SW_PORT_TX_SPANNINGTREE
| SW_PORT_RX_SPANNINGTREE
;
908 if (SW_SPANNINGTREE_TX
== DPI
[uPort
].bySpanningTree
) {
909 uReg
|= SW_PORT_TX_SPANNINGTREE
;
911 if (SW_SPANNINGTREE_RX
== DPI
[uPort
].bySpanningTree
) {
912 uReg
|= SW_PORT_RX_SPANNINGTREE
;
915 if (DPI
[uPort
].byDisableSpanningTreeLearn
) {
916 uReg
|= SW_PORT_NO_SPANNINGTREE
;
918 /* ingress broadcast storm protection */
919 if (DPI
[uPort
].byStormProtection
) {
920 uReg
|= SW_PORT_STORM_PROCTION
;
922 /* ingress priority */
923 if (DPI
[uPort
].byIngressPriority
) {
924 uReg
|= SW_PORT_HI_PRIORITY
;
926 if (DPI
[uPort
].byIngressPriorityTOS
) {
927 uReg
|= SW_PORT_TOS_ENABLE
;
929 if (DPI
[uPort
].byIngressPriority802_1P
) {
930 uReg
|= SW_PORT_8021Q_ENABLE
;
932 /* egress priority */
933 if (DPI
[uPort
].byEgressPriority
) {
934 uReg
|= SW_PORT_PRIOTIRY_ENABLE
;
936 KS8695_WRITE_REG(uOff
, uReg
);
937 /* need 20 cpu clock delay for switch related registers */
938 DelayInMicroseconds(10);
941 DRV_INFO("%s: uOff=0x%08x, reg=0x%08x", __FUNCTION__
, uOff
, uReg
);
947 * This function is used to enable/disable switch
950 * Adapter pointer to ADAPTER_STRUCT struct
951 * enable enable/disable switch
956 void swEnableSwitch(PADAPTER_STRUCT Adapter
, UINT enable
)
960 uReg
= KS8695_READ_REG(KS8695_SWITCH_CTRL0
);
962 uReg
|= SW_CTRL0_SWITCH_ENABLE
;
963 /* for debug purpose */
964 /*uReg |= 0x00080000;*/
966 uReg
&= ~SW_CTRL0_SWITCH_ENABLE
;
967 /* for debug purpose */
968 /*uReg &= ~0x00080000;*/
971 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0
, uReg
);
972 /* need 20 cpu clock delay for switch related registers */
973 DelayInMicroseconds(10);
978 * This function is used to read SNMP registers
981 * Adapter pointer to ADAPTER_STRUCT structure.
982 * uIndex index of SNMP register to read
987 UINT
swReadSNMPReg(PADAPTER_STRUCT Adapter
, UINT uIndex
)
989 #ifndef CONFIG_ARCH_KS8695P
990 UINT uValue
, uTimeout
= 0;
995 KS8695_WRITE_REG(KS8695_MANAGE_COUNTER
, uIndex
);
996 DelayInMicroseconds(10);
998 uValue
= KS8695_READ_REG(KS8695_MANAGE_DATA
);
999 if (uValue
& SW_SNMP_DATA_VALID
) {
1000 if (uValue
& SW_SNMP_DATA_OVERFLOW
) {
1001 KS8695_WRITE_REG(KS8695_MANAGE_DATA
, SW_SNMP_DATA_OVERFLOW
);
1003 /* clear status bits */
1004 uValue
&= 0x3fffffff;
1007 DelayInMilliseconds(1);
1009 while (uTimeout
++ < 2000);
1011 if (uValue
& SW_SNMP_DATA_OVERFLOW
) {
1012 KS8695_WRITE_REG(KS8695_MANAGE_DATA
, SW_SNMP_DATA_OVERFLOW
);
1015 u32 reg
, value
, timeout
= 0;
1017 reg
= KS8695_SEIAC_READ
| KS8695_SEIAC_TAB_MIB
| (KS8695_SEIAC_INDEX_MASK
& uIndex
);
1019 KS8695_WRITE_REG(KS8695_SEIAC
, reg
);
1020 DelayInMicroseconds(10);
1022 value
= KS8695_READ_REG(KS8695_SEIADL
);
1023 if (value
& SW_SNMP_DATA_VALID
) {
1024 if (value
& SW_SNMP_DATA_OVERFLOW
) {
1025 reg
= KS8695_SEIAC_WRITE
| KS8695_SEIAC_TAB_MIB
| (KS8695_SEIAC_INDEX_MASK
& uIndex
);
1026 KS8695_WRITE_REG(KS8695_SEIAC
, reg
);
1028 /* clear status bits */
1029 value
&= 0x3fffffff;
1033 while (timeout
++ < 2000);
1035 printk("%s: timeout\n", __FUNCTION__
);
1042 * This function is used to config switch engine. It is assume that
1043 * the BIST is performed already (by boot loader).
1046 * Adapter pointer to ADAPTER_STRUCT structure.
1051 void swConfigure(PADAPTER_STRUCT Adapter
)
1056 DRV_INFO("%s", __FUNCTION__
);
1059 if (DMA_LAN
== DI
.usDMAId
) {
1060 /* read switch control 0 register */
1061 uReg
= KS8695_READ_REG(KS8695_SWITCH_CTRL0
);
1062 /* flow control for LAN ports */
1063 if (DI
.bPort5FlowCtrl
)
1065 /* flow control for port 5 */
1066 uReg
|= SW_CTRL0_ENABLE_PORT5
;
1069 uReg
&= ~SW_CTRL0_ENABLE_PORT5
;
1071 #ifndef CONFIG_ARCH_KS8695P
1072 if (DI
.bPortsFlowCtrl
)
1074 /* four flow control for each LAN port */
1075 uReg
|= SW_CTRL0_ENABLE_PORTS
;
1078 uReg
&= ~SW_CTRL0_ENABLE_PORTS
;
1082 /* RLQ, need to verify */
1083 for (i
= 0; i
< SW_MAX_LAN_PORTS
; i
++) {
1084 forceFlowControl(Adapter
, i
, DI
.bPortsFlowCtrl
);
1085 //if (!DI.bPortsFlowCtrl)
1086 // backPressureEnable(Adapter, i, DI.bPortsFlowCtrl);
1087 backPressureEnable(Adapter
, i
, TRUE
);
1092 /*RLQ, 11/20/2002, requested by Hock, backpressure will fix packet
1093 * drop problem in half duplex mode
1095 uReg
|= 0x00000020; /* bit 5 */
1097 /* set flow control fairness mode based on LAN flow control settings, should use */
1099 /* read switch control 0 register */
1100 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0
, uReg
);
1101 /* need 20 cpu clock delay for switch related registers */
1102 DelayInMicroseconds(10);
1104 /* configure LAN port 1-4 and Port 5 */
1105 for (i
= 0; i
<= SW_MAX_LAN_PORTS
; i
++)
1106 swConfigurePort(Adapter
, i
);
1109 DRV_INFO("%s: type (%x) not supported", __FUNCTION__
, DI
.usDMAId
);
1115 * This function is used to set given LED
1118 * Adapter pointer to ADAPTER_STRUCT struct
1119 * bLED1 TRUE for LED1 and FALSE for LED0
1120 * nSel emum type LED_SELECTOR
1125 void swSetLED(PADAPTER_STRUCT Adapter
, BOOLEAN bLED1
, LED_SELECTOR nSel
)
1129 switch (DI
.usDMAId
) {
1130 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1132 /* there is no LED for HPNA */
1137 uReg
= KS8695_READ_REG(KS8695_WAN_CONTROL
);
1139 uReg
&= 0xffffff8f; /* 6:4 */
1140 uReg
|= (UINT
)(nSel
& 0x07) << 4;
1143 uReg
&= 0xfffffff8; /* 2:0 */
1144 uReg
|= (UINT
)(nSel
& 0x07);
1146 KS8695_WRITE_REG(KS8695_WAN_CONTROL
, uReg
);
1147 /* need 20 cpu clock delay for switch related registers */
1148 DelayInMicroseconds(10);
1153 uReg
= KS8695_READ_REG(KS8695_SWITCH_CTRL0
);
1155 uReg
&= 0xf1ffffff; /* 27:25 */
1156 uReg
|= (UINT
)(nSel
& 0x07) << 25;
1159 uReg
&= 0xfe3fffff; /* 24:22 */
1160 uReg
|= (UINT
)(nSel
& 0x07) << 22;
1162 KS8695_WRITE_REG(KS8695_SWITCH_CTRL0
, uReg
);
1163 /* need 20 cpu clock delay for switch related registers */
1164 DelayInMicroseconds(10);
1171 * This function is used to start auto negotiation process
1174 * Adapter pointer to ADAPTER_STRUCT struct
1175 * uPort port to start
1180 void swAutoNegoStart(PADAPTER_STRUCT Adapter
, UINT uPort
)
1182 UINT uReg
, uOff
, uShift
= 0;
1185 DRV_INFO("%s: port=%d, bAutoNegoInProgress=%d", __FUNCTION__
, uPort
, DI
.bAutoNegoInProgress
[uPort
]);
1188 switch (DI
.usDMAId
) {
1189 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1191 /* there is no auto nego for HPNA */
1196 uOff
= KS8695_WAN_CONTROL
;
1204 uOff
= KS8695_SWITCH_AUTO1
;
1209 uOff
= KS8695_SWITCH_AUTO1
;
1213 uOff
= KS8695_SWITCH_AUTO0
;
1219 uOff
= KS8695_SWITCH_AUTO0
;
1225 /* if not auto nego */
1226 if (SW_PHY_AUTO
!= DI
.usCType
[uPort
]) {
1229 DI
.bAutoNegoInProgress
[uPort
] = TRUE
;
1230 uReg
= KS8695_READ_REG(uOff
);
1231 uReg
|= ((UINT
)SW_AUTONEGO_RESTART
<< uShift
);
1232 KS8695_WRITE_REG(uOff
, uReg
);
1233 /* need 20 cpu clock delay for switch related registers */
1234 DelayInMicroseconds(10);
1238 * swAutoNegoAdvertisement
1239 * This function is used to set PHY Advertisement.
1242 * Adapter pointer to ADAPTER_STRUCT structure.
1243 * uPort port to advertise
1248 void swAutoNegoAdvertisement(PADAPTER_STRUCT Adapter
, UINT uPort
)
1250 UINT uReg
, uOff
, uShift
= 0;
1253 DRV_INFO("%s", __FUNCTION__
);
1256 switch (DI
.usDMAId
) {
1257 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1259 /* there is no auto nego feature for HPNA DMA, but I'll assume that
1260 if SW_PHY_AUTO is set, use 100/FD as default
1262 uReg
= KS8695_READ_REG(KS8695_MISC_CONTROL
) & 0xfffffffc;
1263 if (SW_PHY_AUTO
== DI
.usCType
[uPort
]) {
1267 if (SW_PHY_100BASE_TX
== DI
.usCType
[uPort
] ||
1268 SW_PHY_100BASE_TX_FD
== DI
.usCType
[uPort
]) {
1271 if (SW_PHY_10BASE_T_FD
== DI
.usCType
[uPort
] ||
1272 SW_PHY_100BASE_TX_FD
== DI
.usCType
[uPort
]) {
1276 KS8695_WRITE_REG(REG_MISC_CONTROL
, uReg
);
1277 /* need 20 cpu clock delay for switch related registers */
1278 DelayInMicroseconds(10);
1283 uOff
= KS8695_WAN_CONTROL
;
1291 uOff
= KS8695_SWITCH_AUTO1
;
1295 uOff
= KS8695_SWITCH_AUTO1
;
1300 uOff
= KS8695_SWITCH_AUTO0
;
1305 uOff
= KS8695_SWITCH_AUTO0
;
1311 uReg
= KS8695_READ_REG(uOff
);
1312 /* clear corresponding bits first */
1313 uReg
&= ~(SW_AUTONEGO_ADV_MASK
<< uShift
);
1314 if (SW_PHY_AUTO
== DI
.usCType
[uPort
])
1316 uReg
|= (SW_AUTONEGO_ADV_100FD
| SW_AUTONEGO_ADV_100HD
|
1317 SW_AUTONEGO_ADV_10FD
| SW_AUTONEGO_ADV_10HD
) << uShift
;
1322 switch (DI
.usCType
[uPort
])
1324 case SW_PHY_100BASE_TX_FD
:
1325 uReg
|= SW_AUTONEGO_ADV_100FD
<< uShift
;
1328 case SW_PHY_100BASE_TX
:
1329 uReg
|= SW_AUTONEGO_ADV_100HD
<< uShift
;
1332 case SW_PHY_10BASE_T_FD
:
1333 uReg
|= SW_AUTONEGO_ADV_10FD
<< uShift
;
1336 case SW_PHY_10BASE_T
:
1337 uReg
|= SW_AUTONEGO_ADV_10HD
<< uShift
;
1341 /* Unsupported media type found! */
1342 DRV_WARN("%s> Unsupported media type found!", __FUNCTION__
);
1348 uReg
|= SW_AUTONEGO_ADV_PUASE
<< uShift
;
1350 uReg
&= ~((UINT
)SW_AUTONEGO_RESTART
<< uShift
);
1351 KS8695_WRITE_REG(uOff
, uReg
);
1352 /* need 20 cpu clock delay for switch related registers */
1353 DelayInMicroseconds(10);
1357 * swGetWANLinkStatus
1358 * This function is used to get WAN link status.
1361 * Adapter pointer to ADAPTER_STRUCT structure.
1362 * uPort port to query
1365 * TRUE if link is up
1366 * FALSE if link is down
1368 BOOLEAN
swGetWANLinkStatus(PADAPTER_STRUCT Adapter
)
1372 uReg
= KS8695_READ_REG(KS8695_WAN_CONTROL
);
1373 /* if not linked yet */
1374 if (!(uReg
& ((UINT
)SW_AUTONEGO_STAT_LINK
<< 16))) {
1376 DRV_INFO("WAN link is down");
1381 DRV_INFO("WAN link is up");
1389 * This function is used to get the status of auto negotiation.
1392 * Adapter pointer to ADAPTER_STRUCT structure.
1393 * uPort port to query
1399 int swGetPhyStatus(PADAPTER_STRUCT Adapter
, UINT uPort
)
1401 UINT uReg
, uOff
, uShift
= 0;
1404 DRV_INFO("%s", __FUNCTION__
);
1407 switch (DI
.usDMAId
) {
1408 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1411 uReg
= KS8695_READ_REG(REG_MISC_CONTROL
);
1412 DI
.usLinkSpeed
[uPort
] = (uReg
& 0x00000002) ? SPEED_100
: SPEED_10
;
1413 DI
.bHalfDuplex
[uPort
] = (uReg
& 0x00000001) ? FULL_DUPLEX
: HALF_DUPLEX
;
1414 /* note that there is no register bit corresponding to HPNA's link status
1415 therefore don't report it */
1416 DI
.bLinkActive
[uPort
] = TRUE
;
1421 uOff
= KS8695_WAN_CONTROL
;
1429 uOff
= KS8695_SWITCH_AUTO1
;
1433 uOff
= KS8695_SWITCH_AUTO1
;
1438 uOff
= KS8695_SWITCH_AUTO0
;
1443 uOff
= KS8695_SWITCH_AUTO0
;
1449 uReg
= KS8695_READ_REG(uOff
);
1450 /* if not linked yet */
1451 if (!(uReg
& ((UINT
)SW_AUTONEGO_STAT_LINK
<< uShift
))) {
1452 DI
.bLinkActive
[uPort
] = FALSE
;
1453 DI
.usLinkSpeed
[uPort
] = SPEED_UNKNOWN
;
1454 DI
.bHalfDuplex
[uPort
] = 0;
1455 gpioSet(Adapter
, uPort
, FALSE
);
1458 DI
.bLinkActive
[uPort
] = TRUE
;
1459 if (SW_PHY_AUTO
== DI
.usCType
[uPort
]) {
1460 /* if auto nego complete */
1461 //RLQ, 12/18/2003, bug
1462 if (uReg
& ((UINT
)SW_AUTONEGO_COMPLETE
<< uShift
)) {
1463 /* clear auto nego restart bit */
1464 uReg
&= ~((UINT
)SW_AUTONEGO_RESTART
<< uShift
);
1465 KS8695_WRITE_REG(uOff
, uReg
);
1466 DelayInMicroseconds(10);
1468 DI
.usLinkSpeed
[uPort
] = (uReg
& ((UINT
)SW_AUTONEGO_STAT_SPEED
<< uShift
)) ? SPEED_100
: SPEED_10
;
1469 DI
.bHalfDuplex
[uPort
] = (uReg
& ((UINT
)SW_AUTONEGO_STAT_DUPLEX
<< uShift
)) ? FULL_DUPLEX
: HALF_DUPLEX
;
1470 DI
.bAutoNegoInProgress
[uPort
] = FALSE
;
1472 gpioSet(Adapter
, uPort
, SPEED_100
== DI
.usLinkSpeed
[uPort
]);
1473 /*RLQ, need to verify real duplex mode instead report it correct here */
1474 /* duplex bit may not right if partner doesn't support all mode, do further detection */
1475 if ((uReg
& (SW_AUTONEGO_PART_100FD
| SW_AUTONEGO_PART_100HD
| SW_AUTONEGO_PART_10FD
| SW_AUTONEGO_PART_10HD
) << uShift
)
1476 != (SW_AUTONEGO_PART_100FD
| SW_AUTONEGO_PART_100HD
| SW_AUTONEGO_PART_10FD
| SW_AUTONEGO_PART_10HD
)) {
1477 if (SPEED_100
== DI
.usLinkSpeed
[uPort
]) {
1478 if ((uReg
& (SW_AUTONEGO_PART_100FD
<< uShift
))) {
1479 DI
.bHalfDuplexDetected
[uPort
] = FULL_DUPLEX
;
1480 #ifdef CONFIG_ARCH_KS8695P
1481 forceFlowControl(Adapter
, uPort
, TRUE
);
1482 backPressureEnable(Adapter
, uPort
, FALSE
);
1485 DI
.bHalfDuplexDetected
[uPort
] = HALF_DUPLEX
;
1486 #ifdef CONFIG_ARCH_KS8695P
1487 forceFlowControl(Adapter
, uPort
, FALSE
);
1488 backPressureEnable(Adapter
, uPort
, TRUE
);
1493 if ((uReg
& (SW_AUTONEGO_PART_10FD
<< uShift
))) {
1494 DI
.bHalfDuplexDetected
[uPort
] = FULL_DUPLEX
;
1495 #ifdef CONFIG_ARCH_KS8695P
1496 forceFlowControl(Adapter
, uPort
, TRUE
);
1497 backPressureEnable(Adapter
, uPort
, FALSE
);
1501 DI
.bHalfDuplexDetected
[uPort
] = HALF_DUPLEX
;
1502 #ifdef CONFIG_ARCH_KS8695P
1503 forceFlowControl(Adapter
, uPort
, FALSE
);
1504 backPressureEnable(Adapter
, uPort
, TRUE
);
1510 /* software workaround for flow control, need to know partner's flow control */
1511 if (DMA_WAN
== DI
.usDMAId
) { /* currently do it to WAN only, there is no problem to LAN, will do HPNA later */
1514 /* we need to check partner's control flow setting for the matching, if not, changes ours */
1515 bFlowCtrl
= ((SW_AUTONEGO_PART_PAUSE
<< uShift
) & uReg
) ? TRUE
: FALSE
;
1516 if (bFlowCtrl
!= DI
.bRxFlowCtrl
) { /* Tx same as Rx, so test Rx should be enough */
1517 /* need to change ours accordingly, which will overwrite current one */
1518 macConfigureFlow(Adapter
, bFlowCtrl
);
1522 DRV_INFO("%s> Auto Nego completed", __FUNCTION__
);
1527 /* auto nego in progress */
1528 DRV_INFO("%s> Auto Nego in progress...", __FUNCTION__
);
1530 /* wait for next timer */
1531 DI
.bLinkActive
[uPort
] = FALSE
;
1532 DI
.usLinkSpeed
[uPort
] = SPEED_UNKNOWN
;
1533 DI
.bHalfDuplex
[uPort
] = 0;
1538 DRV_INFO("%s: media type=%d, port=%d", __FUNCTION__
, DI
.usCType
[uPort
], uPort
);
1541 /* manually connection */
1542 if (SW_PHY_10BASE_T_FD
== DI
.usCType
[uPort
] || SW_PHY_100BASE_TX_FD
== DI
.usCType
[uPort
]) {
1543 DI
.bHalfDuplex
[uPort
] = FULL_DUPLEX
;
1544 #ifdef CONFIG_ARCH_KS8695P
1545 forceFlowControl(Adapter
, uPort
, TRUE
);
1546 backPressureEnable(Adapter
, uPort
, FALSE
);
1550 DI
.bHalfDuplex
[uPort
] = HALF_DUPLEX
;
1551 #ifdef CONFIG_ARCH_KS8695P
1552 forceFlowControl(Adapter
, uPort
, FALSE
);
1553 backPressureEnable(Adapter
, uPort
, TRUE
);
1556 if (SW_PHY_100BASE_TX_FD
== DI
.usCType
[uPort
] || SW_PHY_100BASE_TX
== DI
.usCType
[uPort
]) {
1557 DI
.usLinkSpeed
[uPort
] = SPEED_100
;
1558 gpioSet(Adapter
, uPort
, TRUE
);
1561 DI
.usLinkSpeed
[uPort
] = SPEED_10
;
1562 gpioSet(Adapter
, uPort
, FALSE
);
1565 /* software workaround for flow control, need to know partner's flow control */
1566 if (DMA_WAN
== DI
.usDMAId
) { /* currently do it to WAN only, there is no problem to LAN, will do HPNA later */
1567 macConfigureFlow(Adapter
, FULL_DUPLEX
== DI
.bHalfDuplex
[uPort
] ? TRUE
: FALSE
);
1574 * swDetectPhyConnection
1575 * This function is used to start auto negotiation
1578 * Adapter pointer to ADAPTER_STRUCT struct
1579 * uPort port to start
1584 void swDetectPhyConnection(PADAPTER_STRUCT Adapter
, UINT uPort
)
1586 /*if (SW_PHY_AUTO == DI.usCType[uPort] && !DI.bAutoNegoInProgress[uPort] && DI.bLinkChanged[uPort]) {*/
1587 if (LINK_SELECTION_FORCED
!= DI
.byDisableAutoNego
[uPort
] && !DI
.bAutoNegoInProgress
[uPort
] && DI
.bLinkChanged
[uPort
]) {
1588 swAutoNegoStart(Adapter
, uPort
);
1589 DI
.bLinkChanged
[uPort
] = FALSE
;
1590 DI
.bLinkActive
[uPort
] = FALSE
;
1592 swGetPhyStatus(Adapter
, uPort
);
1597 * This function is used to reset phy chipset (powerdown or soft reset).
1600 * Adapter pointer to ADAPTER_STRUCT structure.
1601 * uPort port to start
1606 void swPhyReset(PADAPTER_STRUCT Adapter
, UINT uPort
)
1608 UINT uReg
, uShift
= 0;
1610 /*RLQ, workaround */
1614 DRV_INFO("%s", __FUNCTION__
);
1617 /* IEEE spec. of auto nego bit */
1619 switch (DI
.usDMAId
) {
1620 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1626 uPowerReg
= KS8695_WAN_POWERMAGR
;
1633 uPowerReg
= KS8695_LAN34_POWERMAGR
;
1637 uPowerReg
= KS8695_LAN34_POWERMAGR
;
1642 uPowerReg
= KS8695_LAN12_POWERMAGR
;
1647 uPowerReg
= KS8695_LAN12_POWERMAGR
;
1653 if (DI
.bPowerDownReset
) {
1656 uReg
= KS8695_READ_REG(uPowerReg
);
1657 KS8695_WRITE_REG(uPowerReg
, uReg
| ((UINT
)POWER_POWERDOWN
<< uShift
));
1658 /* need 20 cpu clock delay for switch related registers */
1659 /*DelayInMicroseconds(10);*/
1661 DelayInMilliseconds(50);
1662 } while (nCount
++ < 4);
1663 uReg
&= ~((UINT
)POWER_POWERDOWN
<< uShift
);
1664 /* turn off IEEE auto nego */
1665 uReg
&= ~(uReg1
<< uShift
);
1666 KS8695_WRITE_REG(uPowerReg
, uReg
);
1667 /* need 20 cpu clock delay for switch related registers */
1668 DelayInMicroseconds(10);
1671 uReg
= KS8695_READ_REG(uPowerReg
);
1672 /* turn off IEEE auto nego */
1673 uReg
&= ~(uReg1
<< uShift
);
1674 KS8695_WRITE_REG(uPowerReg
, uReg
);
1675 /* need 20 cpu clock delay for switch related registers */
1676 DelayInMicroseconds(10);
1681 * swConfigureMediaType
1682 * This function is used to set linke media type (forced)
1685 * Adapter pointer to ADAPTER_STRUCT structure.
1686 * uPort port to start
1687 * uSpeed media speed to set
1688 * uDuplex media duplex to set
1694 void swConfigureMediaType(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT uSpeed
, UINT uDuplex
)
1696 UINT32 uReg
, uOffset
;
1699 DRV_INFO("%s", __FUNCTION__
);
1702 switch (DI
.usDMAId
) {
1703 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1705 /* there is no way to force HPNA */
1710 uOffset
= KS8695_WAN_CONTROL
;
1716 if (uPort
>= SW_MAX_LAN_PORTS
) {
1717 DRV_WARN("%s: port (%d) gave is out of range", __FUNCTION__
, uPort
);
1720 #ifndef CONFIG_ARCH_KS8695P
1721 uOffset
= KS8695_SWITCH_PORT1
+ uPort
* 4;
1723 if (SW_MAX_LAN_PORTS
== uPort
)
1724 uOffset
= KS8695_SEP5C1
;
1726 uOffset
= KS8695_SWITCH_PORT1
+ uPort
* 0x0c;
1731 uReg
= KS8695_READ_REG(uOffset
);
1732 /* clear corresponding bits first */
1734 if (LINK_SELECTION_FORCED
== DI
.byDisableAutoNego
[uPort
]) {
1735 uReg
|= SW_PORT_DISABLE_AUTONEG
;
1736 /* force to half duplex */
1737 DI
.bRxFlowCtrl
= FALSE
;
1738 DI
.bTxFlowCtrl
= FALSE
;
1740 uReg
|= SW_PORT_100BASE
;
1742 uReg
|= SW_PORT_FULLDUPLEX
;
1743 DI
.usCType
[uPort
] = SW_PHY_100BASE_TX_FD
;
1746 DI
.usCType
[uPort
] = SW_PHY_100BASE_TX
;
1751 uReg
|= SW_PORT_FULLDUPLEX
;
1752 DI
.usCType
[uPort
] = SW_PHY_10BASE_T_FD
;
1755 DI
.usCType
[uPort
] = SW_PHY_10BASE_T
;
1760 if (DMA_WAN
== DI
.usDMAId
) {
1761 DI
.bRxFlowCtrl
= FLOWCONTROL_DEFAULT
;
1762 DI
.bTxFlowCtrl
= FLOWCONTROL_DEFAULT
;
1764 if (LINK_SELECTION_FULL_AUTO
== DI
.byDisableAutoNego
[uPort
]) {
1765 DI
.usCType
[uPort
] = SW_PHY_AUTO
;
1770 DI
.usCType
[uPort
] = SW_PHY_10BASE_T_FD
; /* 10Base-TX Full Duplex */
1772 /* don't advertise flow control in half duplex case */
1773 if (DMA_WAN
== DI
.usDMAId
) {
1774 DI
.bRxFlowCtrl
= FALSE
;
1775 DI
.bTxFlowCtrl
= FALSE
;
1777 DI
.usCType
[uPort
] = SW_PHY_10BASE_T
; /* 10Base-T Half Duplex */
1784 DI
.usCType
[uPort
] = SW_PHY_100BASE_TX_FD
; /* 100Base-TX Full Duplex */
1786 /* don't advertise flow control in half duplex case */
1787 if (DMA_WAN
== DI
.usDMAId
) {
1788 DI
.bRxFlowCtrl
= FALSE
;
1789 DI
.bTxFlowCtrl
= FALSE
;
1791 DI
.usCType
[uPort
] = SW_PHY_100BASE_TX
; /* 100Base-TX Half Duplex */
1798 KS8695_WRITE_REG(uOffset
, uReg
);
1799 /* need 20 cpu clock delay for switch related registers */
1800 DelayInMicroseconds(10);
1802 DRV_INFO("%s: media type=%d, offset=0x%08x, port=%d", __FUNCTION__
, DI
.usCType
[uPort
], uOffset
, uPort
);
1805 DI
.bLinkChanged
[uPort
] = TRUE
;
1806 DI
.bLinkActive
[uPort
] = FALSE
; /* watchdog routine will check link status if reset this variable!!! */
1807 swPhyReset(Adapter
, uPort
);
1808 swAutoNegoAdvertisement(Adapter
, uPort
);
1809 swDetectPhyConnection(Adapter
, uPort
);
1814 * This function is used to set loopback in PHY layer.
1817 * Adapter pointer to ADAPTER_STRUCT structure.
1818 * uPort port to start
1819 * bLoopback indicates loopback enable or not
1825 BOOLEAN
swPhyLoopback(PADAPTER_STRUCT Adapter
, UINT uPort
, BOOLEAN bLoopback
)
1827 UINT uReg
, uOff
, uShift
= 0;
1829 switch (DI
.usDMAId
) {
1830 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
1836 uOff
= KS8695_WAN_POWERMAGR
;
1844 uOff
= KS8695_LAN34_POWERMAGR
;
1848 uOff
= KS8695_LAN34_POWERMAGR
;
1853 uOff
= KS8695_LAN12_POWERMAGR
;
1858 uOff
= KS8695_LAN12_POWERMAGR
;
1864 uReg
= KS8695_READ_REG(uOff
);
1866 uReg
|= ((UINT
)POWER_LOOPBACK
<< uShift
);
1868 uReg
&= ~((UINT
)POWER_LOOPBACK
<< uShift
);
1869 KS8695_WRITE_REG(uOff
, uReg
);
1870 /* need 20 cpu clock delay for switch related registers */
1871 DelayInMicroseconds(10);
1878 * This function is use to get switch engine Mac address and store it in stSwitchMac.
1881 * Adapter pionter to ADAPTER_STRUCT data structure.
1886 void swGetMacAddress(PADAPTER_STRUCT Adapter
)
1892 DRV_INFO("%s", __FUNCTION__
);
1895 uTmp
= KS8695_READ_REG(KS8695_SWITCH_MAC_LOW
);
1896 for (i
= (MAC_ADDRESS_LEN
- 1); i
> 1; i
--)
1898 DI
.stSwitchMac
[i
] = (UCHAR
)(uTmp
& 0x0ff);
1901 /* read high 2 bytes */
1902 uTmp
= KS8695_READ_REG(KS8695_SWITCH_MAC_HIGH
);
1903 DI
.stSwitchMac
[1] = (UCHAR
)(uTmp
& 0x0ff);
1905 DI
.stSwitchMac
[0] = (UCHAR
)(uTmp
& 0x0ff);
1910 * This function is use to set switch engine Mac address.
1913 * Adapter pionter to ADAPTER_STRUCT data structure.
1914 * pMac pointer to mac address buffer (should be 6)
1919 void swSetMacAddress(PADAPTER_STRUCT Adapter
, UCHAR
*pMac
)
1921 uint32_t uLowAddress
, uHighAddress
;
1924 DRV_INFO("%s", __FUNCTION__
);
1927 memcpy(&DI
.stSwitchMac
, pMac
, MAC_ADDRESS_LEN
);
1928 uLowAddress
= (*(pMac
+ 5) |
1929 (*(pMac
+ 4) << 8) |
1930 (*(pMac
+ 3) << 16)|
1933 uHighAddress
= (*(pMac
+ 1) |
1936 KS8695_WRITE_REG(KS8695_SWITCH_MAC_LOW
, uLowAddress
);
1937 /* need 20 cpu clock delay for switch related registers */
1938 DelayInMicroseconds(10);
1939 KS8695_WRITE_REG(KS8695_SWITCH_MAC_HIGH
, uHighAddress
);
1940 /* need 20 cpu clock delay for switch related registers */
1941 DelayInMicroseconds(10);
1946 * This function is use to get SNMP counters information
1949 * Adapter pionter to ADAPTER_STRUCT data structure.
1954 void swResetSNMPInfo(PADAPTER_STRUCT Adapter
)
1956 memset(&Adapter
->net_stats
, 0, sizeof(Adapter
->net_stats
));
1960 * swCreateLookUpTable
1961 * This function is use to create loopup table.
1964 * Adapter pionter to ADAPTER_STRUCT data structure.
1969 void swCreateLookUpTable(PADAPTER_STRUCT Adapter
)
1971 unsigned int mac
= 0, index
= 0, tmp
= 0, portmap
= 0;
1974 DRV_INFO("%s", __FUNCTION__
);
1980 #ifndef CONFIG_ARCH_KS8695P
1981 for (index
=0; index
<5; index
++)
1983 KS8695_WRITE_REG(KS8695_SWITCH_LUE_HIGH
, 0x200000 + (portmap
<< index
));
1984 DelayInMicroseconds(10);
1986 KS8695_WRITE_REG(KS8695_SWITCH_LUE_LOW
, mac
++);
1987 DelayInMicroseconds(10);
1989 KS8695_WRITE_REG(KS8695_SWITCH_LUE_CTRL
, index
);
1990 DelayInMicroseconds(10);
1994 tmp
= KS8695_READ_REG(KS8695_SWITCH_LUE_CTRL
) & 0x1000;
1998 index
= index
; /* no complain pls */
1999 /* the user can program other MAC addresses for static table */
2000 tmp
= 0x0002; /* e.g. this is the MAC high and low addr for the notebook I am using for test */
2003 KS8695_WRITE_REG(KS8695_SEIAC
,
2004 KS8695_SEIAC_WRITE
| KS8695_SEIAC_TAB_STATIC
| (KS8695_SEIAC_INDEX_MASK
& index
));
2005 DelayInMicroseconds(10);
2007 KS8695_WRITE_REG(KS8695_SEIADH1
, 0x200000 + (portmap
<< index
) + tmp
);
2008 DelayInMicroseconds(10);
2010 KS8695_WRITE_REG(KS8695_SEIADL
, mac
);
2011 DelayInMicroseconds(10);
2016 * swConfigTagRemoval
2017 * This function is use to configure tag removal for ingress to given port.
2020 * Adapter pionter to ADAPTER_STRUCT data structure.
2021 * uPort port for the tag to insert
2022 * bRemoval enable/disable removal
2027 void swConfigTagRemoval(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bRemoval
)
2031 uReg
= KS8695_READ_REG(KS8695_SWITCH_ADVANCED
);
2033 uReg
|= (1L << (22 + uPort
));
2036 uReg
&= ~(1L << (22 + uPort
));
2038 KS8695_WRITE_REG(KS8695_SWITCH_ADVANCED
, uReg
);
2039 /* need 20 cpu clock delay for switch related registers */
2040 DelayInMicroseconds(10);
2044 * swConfigTagInsertion
2045 * This function is use to configure tag insertion for engress to given port.
2048 * Adapter pionter to ADAPTER_STRUCT data structure.
2049 * uPort port for the tag to insert
2050 * bInsert enable/disable insertion
2055 void swConfigTagInsertion(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bInsert
)
2059 uReg
= KS8695_READ_REG(KS8695_SWITCH_ADVANCED
);
2061 uReg
|= (1L << (17 + uPort
));
2064 uReg
&= ~(1L << (17 + uPort
));
2066 KS8695_WRITE_REG(KS8695_SWITCH_ADVANCED
, uReg
);
2067 /* need 20 cpu clock delay for switch related registers */
2068 DelayInMicroseconds(10);
2073 * This function is use to configure GPIO pins required for extra LEDs
2074 * as speed indicators.
2077 * Adapter pionter to ADAPTER_STRUCT data structure.
2082 void gpioConfigure(PADAPTER_STRUCT Adapter
)
2084 #if !defined(CONFIG_MACH_CM4002) && !defined(CONFIG_MACH_CM4008) && \
2085 !defined(CONFIG_MACH_CM41xx)
2089 #ifdef KS8695P_MEDIABOX /* note that flag is defined in platform.h for mediabox platform */
2090 shift
= 1; /* shift one bit to right for mediabox, that is from 3-7 - 5-8 */
2093 uReg
= KS8695_READ_REG(KS8695_GPIO_MODE
);
2094 switch (DI
.usDMAId
) {
2095 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
2101 uReg
|= (0xf0 << shift
); /* GPIO 4-7 for port 1-4 or 5-8 for 1-4 for mediabox, configure them as output */
2106 uReg
|= (0x08 << shift
); /* GPIO 3 for WAN port, or GPIO 4 in mediabox platform */
2109 KS8695_WRITE_REG(KS8695_GPIO_MODE
, uReg
);
2115 * This function is use to set/reset given GPIO pin corresponding to the port.
2118 * Adapter pionter to ADAPTER_STRUCT data structure.
2119 * uPort port for the tag to insert
2120 * bSet enable/disable LED
2125 void gpioSet(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bSet
)
2127 #if !defined(CONFIG_MACH_CM4002) && !defined(CONFIG_MACH_CM4008) && \
2128 !defined(CONFIG_MACH_CM41xx) && !defined(CONFIG_MACH_SE4200)
2132 #ifdef KS8695P_MEDIABOX /* note that flag is defined in platform.h for mediabox platform */
2133 shift
= 1; /* if mediabox, shift one bit to right, that is from bit 4-7 shift to bit 5-8 */
2137 DRV_INFO("%s: port %d, %s", __FUNCTION__
, uPort
, bSet
? "100" : "10");
2140 uReg
= KS8695_READ_REG(KS8695_GPIO_DATA
);
2141 switch (DI
.usDMAId
) {
2142 #if !defined(CONFIG_ARCH_KS8695P) && !defined(KS8695X)
2149 uReg
&= ~(1 << (uPort
+ 4 + shift
)); /* low for LED on */
2151 uReg
|= (1 << (uPort
+ 4 + shift
)); /* high for LED off */
2157 uReg
&= ~(0x08 << shift
); /* low for LED on */
2159 uReg
|= (0x08 << shift
); /* high for LED off */
2162 KS8695_WRITE_REG(KS8695_GPIO_DATA
, uReg
);
2166 #ifdef CONFIG_ARCH_KS8695P
2169 * This function is use to configure VID for given port
2172 * Adapter pionter to ADAPTER_STRUCT data structure.
2173 * uPort uport to turn on/off Led
2174 * bFilter enable/disable ingress VLAN filtering
2175 * bDiscard discard Non PVID packets or not
2180 void configureVID(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bFilter
, UINT bDiscard
)
2184 if (uPort
> SW_MAX_LAN_PORTS
) {
2185 printk("%s: port is out of range\n", __FUNCTION__
);
2188 if (SW_MAX_LAN_PORTS
== uPort
)
2189 off
= KS8695_SEP5C2
;
2191 off
= KS8695_SEP1C2
+ uPort
* 0x0c;
2193 uReg
= KS8695_READ_REG(off
);
2195 uReg
&= ~KS8695_SEPC2_VLAN_FILTER
;
2197 uReg
|= KS8695_SEPC2_VLAN_FILTER
;
2199 uReg
&= ~KS8695_SEPC2_DISCARD_NON_PVID
;
2201 uReg
|= KS8695_SEPC2_DISCARD_NON_PVID
;
2202 KS8695_WRITE_REG(off
, uReg
);
2203 DelayInMicroseconds(10);
2207 * backPressureEnable
2208 * This function is use to enable/disable back pressure for given port
2211 * Adapter pionter to ADAPTER_STRUCT data structure.
2212 * uPort uport to turn on/off Led
2213 * bOn on/off the flow control
2218 void backPressureEnable(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bOn
)
2222 if (uPort
> SW_MAX_LAN_PORTS
) {
2223 printk("%s: port is out of range\n", __FUNCTION__
);
2226 if (SW_MAX_LAN_PORTS
== uPort
)
2227 off
= KS8695_SEP5C2
;
2229 off
= KS8695_SEP1C2
+ uPort
* 0x0c;
2231 uReg
= KS8695_READ_REG(off
);
2233 uReg
&= ~KS8695_SEPC2_BACK_PRESSURE_EN
;
2235 uReg
|= KS8695_SEPC2_BACK_PRESSURE_EN
;
2236 KS8695_WRITE_REG(off
, uReg
);
2237 DelayInMicroseconds(10);
2242 * This function is use to force flow control on the port, regardless of AN result
2245 * Adapter pionter to ADAPTER_STRUCT data structure.
2246 * uPort uport to turn on/off Led
2247 * bOn on/off the flow control
2252 void forceFlowControl(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bOn
)
2256 if (uPort
> SW_MAX_LAN_PORTS
) {
2257 printk("%s: port is out of range\n", __FUNCTION__
);
2260 if (SW_MAX_LAN_PORTS
== uPort
)
2261 off
= KS8695_SEP5C2
;
2263 off
= KS8695_SEP1C2
+ uPort
* 0x0c;
2265 uReg
= KS8695_READ_REG(off
);
2267 uReg
&= ~KS8695_SEPC2_FORCE_FLOW_CTRL
;
2269 uReg
|= KS8695_SEPC2_FORCE_FLOW_CTRL
;
2271 KS8695_WRITE_REG(off
, uReg
);
2272 DelayInMicroseconds(10);
2277 * This function is use to set transmit priority rate control for KS8695P
2280 * Adapter pionter to ADAPTER_STRUCT data structure.
2281 * uPort uport to set
2282 * lrate low rate to set
2283 * hrate high rate to set
2288 void setTxRate(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT lrate
, UINT hrate
)
2292 if (uPort
> SW_MAX_LAN_PORTS
) {
2293 printk("%s: port is out of range\n", __FUNCTION__
);
2296 if (SW_MAX_LAN_PORTS
== uPort
)
2297 off
= KS8695_SEP5C2
;
2299 off
= KS8695_SEP1C2
+ uPort
* 0x0c;
2300 uReg
= KS8695_READ_REG(off
);
2301 /* clear rate bits first */
2302 uReg
&= ~(KS8695_SEPC2_TX_H_RATECTRL_MASK
+ KS8695_SEPC2_TX_L_RATECTRL_MASK
);
2303 uReg
= ((hrate
<< 12) & KS8695_SEPC2_TX_H_RATECTRL_MASK
) + (lrate
& KS8695_SEPC2_TX_L_RATECTRL_MASK
);
2304 KS8695_WRITE_REG(off
, uReg
);
2305 DelayInMicroseconds(10);
2310 * This function is use to set receive priority rate control for KS8695P
2313 * Adapter pionter to ADAPTER_STRUCT data structure.
2314 * uPort uport to set
2315 * lrate low rate to set
2316 * hrate high rate to set
2321 void setRxRate(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT lrate
, UINT hrate
)
2325 if (uPort
> SW_MAX_LAN_PORTS
) {
2326 printk("%s: port is out of range\n", __FUNCTION__
);
2329 if (SW_MAX_LAN_PORTS
== uPort
)
2330 off
= KS8695_SEP5C3
;
2332 off
= KS8695_SEP1C3
+ uPort
* 0x0c;
2333 uReg
= KS8695_READ_REG(off
);
2334 /* clear rate bits first */
2335 uReg
&= ~(KS8695_SEPC3_RX_H_RATECTRL_MASK
+ KS8695_SEPC3_RX_L_RATECTRL_MASK
);
2336 uReg
= ((hrate
<< 20) & KS8695_SEPC3_RX_H_RATECTRL_MASK
) +
2337 ((lrate
<< 8) & KS8695_SEPC3_RX_L_RATECTRL_MASK
);
2338 KS8695_WRITE_REG(off
, uReg
);
2339 DelayInMicroseconds(10);
2343 * enableRxRateFlowControl
2344 * This function is use to enable/disalbe receive priority rate flow control for KS8695P
2347 * Adapter pionter to ADAPTER_STRUCT data structure.
2348 * uPort uport to set
2349 * bEnableLowFlow enable low rate flow control
2350 * bEnableHighFlow enable high rate flow control
2355 void enableRxRateFlowControl(PADAPTER_STRUCT Adapter
, UINT uPort
,
2356 UINT bEnableLowFlow
, UINT bEnableHighFlow
)
2360 if (uPort
> SW_MAX_LAN_PORTS
) {
2361 printk("%s: port is out of range\n", __FUNCTION__
);
2364 if (SW_MAX_LAN_PORTS
== uPort
)
2365 off
= KS8695_SEP5C3
;
2367 off
= KS8695_SEP1C3
+ uPort
* 0x0c;
2368 uReg
= KS8695_READ_REG(off
);
2370 uReg
|= KS8695_SEPC3_RX_L_RATEFLOW_EN
;
2372 uReg
&= ~KS8695_SEPC3_RX_L_RATEFLOW_EN
;
2373 if (bEnableHighFlow
)
2374 uReg
|= KS8695_SEPC3_RX_H_RATEFLOW_EN
;
2376 uReg
&= ~KS8695_SEPC3_RX_H_RATEFLOW_EN
;
2378 KS8695_WRITE_REG(off
, uReg
);
2379 DelayInMicroseconds(10);
2383 * enableRxRateControl
2384 * This function is use to enable/disalbe receive priority rate control for KS8695P
2387 * Adapter pionter to ADAPTER_STRUCT data structure.
2388 * uPort uport to set
2389 * bEnable enable/disable differential priority control
2390 * bEnableLow enable low rate control
2391 * bEnableHigh enable high rate control
2396 void enableRxRateControl(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bEnable
,
2397 UINT bEnableLow
, UINT bEnableHigh
)
2401 if (uPort
> SW_MAX_LAN_PORTS
) {
2402 printk("%s: port is out of range\n", __FUNCTION__
);
2405 if (SW_MAX_LAN_PORTS
== uPort
)
2406 off
= KS8695_SEP5C3
;
2408 off
= KS8695_SEP1C3
+ uPort
* 0x0c;
2409 uReg
= KS8695_READ_REG(off
);
2411 uReg
|= KS8695_SEPC3_RX_DIF_RATECTRL_EN
;
2413 uReg
&= ~KS8695_SEPC3_RX_DIF_RATECTRL_EN
;
2415 uReg
|= KS8695_SEPC3_RX_L_RATECTRL_EN
;
2417 uReg
&= ~KS8695_SEPC3_RX_L_RATECTRL_EN
;
2419 uReg
|= KS8695_SEPC3_RX_H_RATECTRL_EN
;
2421 uReg
&= ~KS8695_SEPC3_RX_H_RATECTRL_EN
;
2423 KS8695_WRITE_REG(off
, uReg
);
2424 DelayInMicroseconds(10);
2428 * enableTxRateControl
2429 * This function is use to enable/disalbe transmit priority rate control for KS8695P
2432 * Adapter pionter to ADAPTER_STRUCT data structure.
2433 * uPort uport to set
2434 * bEnable enable/disable differential priority control
2435 * bEnableLow enable low rate control
2436 * bEnableHigh enable high rate control
2441 void enableTxRateControl(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bEnable
,
2442 UINT bEnableLow
, UINT bEnableHigh
)
2446 if (uPort
> SW_MAX_LAN_PORTS
) {
2447 printk("%s: port is out of range\n", __FUNCTION__
);
2450 if (SW_MAX_LAN_PORTS
== uPort
)
2451 off
= KS8695_SEP5C3
;
2453 off
= KS8695_SEP1C3
+ uPort
* 0x0c;
2454 uReg
= KS8695_READ_REG(off
);
2456 uReg
|= KS8695_SEPC3_TX_DIF_RATECTRL_EN
;
2458 uReg
&= ~KS8695_SEPC3_TX_DIF_RATECTRL_EN
;
2460 uReg
|= KS8695_SEPC3_TX_L_RATECTRL_EN
;
2462 uReg
&= ~KS8695_SEPC3_TX_L_RATECTRL_EN
;
2464 uReg
|= KS8695_SEPC3_TX_H_RATECTRL_EN
;
2466 uReg
&= ~KS8695_SEPC3_TX_H_RATECTRL_EN
;
2468 KS8695_WRITE_REG(off
, uReg
);
2469 DelayInMicroseconds(10);
2473 * dumpDynamicMacTable
2474 * This function is use to dump entries in dynamic MAC table
2477 * Adapter pionter to ADAPTER_STRUCT data structure.
2482 void dumpDynamicMacTable(PADAPTER_STRUCT Adapter
)
2484 u32 reg
, v1
, v2
, timeout
= 1000, i
= 0;
2486 printk("Entry Port FID Mac\n");
2488 reg
= KS8695_SEIAC_READ
| KS8695_SEIAC_TAB_DYNAMIC
| (KS8695_SEIAC_INDEX_MASK
& i
);
2489 KS8695_WRITE_REG(KS8695_SEIAC
, reg
);
2490 DelayInMicroseconds(10);
2492 v1
= KS8695_READ_REG(KS8695_SEIADH2
);
2493 if (v1
& 0x10) { /* bit 68 = (68 - 64) */
2494 /* no valid entries */
2495 printk("0 entry\n");
2498 v2
= KS8695_READ_REG(KS8695_SEIADH1
);
2499 /* if valid entries */
2500 if (!(v2
& 0x00800000)) { /* bit 55 */
2502 entries
= ((v1
& 0xf) << 6) + (v2
>> 26) + 1;
2503 /* currently just dump first 16 entries (max 1K entries) for demon purpose */
2505 printk("%s: more than 16 entries...(v1=0x%08x, v2=0x%08x)\n",
2506 __FUNCTION__
, v1
, v2
);
2510 v1
= KS8695_READ_REG(KS8695_SEIADL
);
2511 printk("%04d %04d %4d %02x:%02x:%02x:%02x:%02x:%02x\n", i
,
2512 (v2
>> 20) & 0x7, (v2
>> 16) & 0xf,
2513 ((v2
>> 8) & 0xff), (v2
& 0xff),
2514 ((v1
>> 24) & 0xff), ((v1
>> 16) & 0xff), ((v1
>> 8) & 0xff), (v1
& 0xff));
2518 DelayInMicroseconds(1);
2519 } while (timeout
-- > 0 || i
>= 16);
2522 printk("%s: timeout error\n", __FUNCTION__
);
2524 printk("%s: more than 16 entries...v2=0x%08x\n",
2530 * disable8021xFlowControl
2531 * This function is use to disable IEEE 802.1x flow control
2534 * Adapter pionter to ADAPTER_STRUCT data structure.
2535 * bTxDisable disable/enable IEEE 802.1x transmit flow control
2536 * bRxDisable disable/enable IEEE 802.1x receive flow control
2541 void disable8021xFlowControl(PADAPTER_STRUCT Adapter
, UINT bTxDisable
, UINT bRxDisable
)
2546 uReg
= KS8695_READ_REG(off
);
2548 uReg
|= KS8695_SEC1_NO_TX_8021X_FLOW_CTRL
;
2550 uReg
&= ~KS8695_SEC1_NO_TX_8021X_FLOW_CTRL
;
2553 uReg
|= KS8695_SEC1_NO_RX_8021X_FLOW_CTRL
;
2555 uReg
&= ~KS8695_SEC1_NO_RX_8021X_FLOW_CTRL
;
2557 KS8695_WRITE_REG(off
, uReg
);
2558 DelayInMicroseconds(10);
2563 * This function is enable/disable phy loopback for given port
2566 * Adapter pionter to ADAPTER_STRUCT data structure.
2568 * bEnable disable/enable phy loopback
2573 void enablePhyLoopback(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bEnable
)
2575 u32 uReg
, off
, shift
;
2577 if (uPort
> SW_MAX_LAN_PORTS
) {
2578 printk("%s: port is out of range\n", __FUNCTION__
);
2581 if (SW_MAX_LAN_PORTS
== uPort
) {
2582 off
= KS8695_WAN_POWERMAGR
;
2586 off
= KS8695_LPPM12
;
2588 off
= KS8695_LPPM34
;
2590 shift
= uPort
% 2 ? 0: 1;
2591 uReg
= KS8695_READ_REG(off
);
2593 uReg
|= (KS8695_LPPM_PHY_LOOPBACK
<< (shift
* 16));
2595 uReg
&= ~(KS8695_LPPM_PHY_LOOPBACK
<< (shift
* 16));
2597 KS8695_WRITE_REG(off
, uReg
);
2598 DelayInMicroseconds(10);
2602 * enableRemoteLoopback
2603 * This function is enable/disable remote loopback for given port
2606 * Adapter pionter to ADAPTER_STRUCT data structure.
2608 * bEnable disable/enable remote loopback
2613 void enableRemoteLoopback(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bEnable
)
2615 u32 uReg
, off
, shift
;
2617 if (uPort
> SW_MAX_LAN_PORTS
) {
2618 printk("%s: port is out of range\n", __FUNCTION__
);
2621 if (SW_MAX_LAN_PORTS
== uPort
) {
2622 off
= KS8695_WAN_POWERMAGR
;
2626 off
= KS8695_LPPM12
;
2628 off
= KS8695_LPPM34
;
2630 shift
= uPort
% 2 ? 0: 1;
2631 uReg
= KS8695_READ_REG(off
);
2633 uReg
|= (KS8695_LPPM_RMT_LOOPBACK
<< (shift
* 16));
2635 uReg
&= ~(KS8695_LPPM_RMT_LOOPBACK
<< (shift
* 16));
2637 KS8695_WRITE_REG(off
, uReg
);
2638 DelayInMicroseconds(10);
2643 * This function is enable/disable phy isolation for given port
2646 * Adapter pionter to ADAPTER_STRUCT data structure.
2648 * bEnable disable/enable phy isolation
2653 void enablePhyIsolate(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bEnable
)
2655 u32 uReg
, off
, shift
;
2657 if (uPort
> SW_MAX_LAN_PORTS
) {
2658 printk("%s: port is out of range\n", __FUNCTION__
);
2661 if (SW_MAX_LAN_PORTS
== uPort
) {
2662 off
= KS8695_WAN_POWERMAGR
;
2666 off
= KS8695_LPPM12
;
2668 off
= KS8695_LPPM34
;
2670 shift
= uPort
% 2 ? 0: 1;
2671 uReg
= KS8695_READ_REG(off
);
2673 uReg
|= (KS8695_LPPM_PHY_ISOLATE
<< (shift
* 16));
2675 uReg
&= ~(KS8695_LPPM_PHY_ISOLATE
<< (shift
* 16));
2677 KS8695_WRITE_REG(off
, uReg
);
2678 DelayInMicroseconds(10);
2683 * This function is enable/disable Link for give port
2686 * Adapter pionter to ADAPTER_STRUCT data structure.
2688 * bEnable disable/enable phy isolation
2693 void forcePhyLink(PADAPTER_STRUCT Adapter
, UINT uPort
, UINT bEnable
)
2695 u32 uReg
, off
, shift
;
2697 if (uPort
> SW_MAX_LAN_PORTS
) {
2698 printk("%s: port is out of range\n", __FUNCTION__
);
2701 if (SW_MAX_LAN_PORTS
== uPort
) {
2702 off
= KS8695_WAN_POWERMAGR
;
2706 off
= KS8695_LPPM12
;
2708 off
= KS8695_LPPM34
;
2710 shift
= uPort
% 2 ? 0: 1;
2711 uReg
= KS8695_READ_REG(off
);
2713 uReg
|= (KS8695_LPPM_FORCE_LINK
<< (shift
* 16));
2715 uReg
&= ~(KS8695_LPPM_FORCE_LINK
<< (shift
* 16));
2717 KS8695_WRITE_REG(off
, uReg
);
2718 DelayInMicroseconds(10);
2722 * dumpStaticMacTable
2723 * This function is use to dump entries in static MAC table
2726 * Adapter pionter to ADAPTER_STRUCT data structure.
2731 void dumpStaticMacTable(PADAPTER_STRUCT Adapter
)
2733 u32 reg
, v1
, v2
, i
= 0;
2735 printk("Entry Port FID Mac\n");
2736 for (i
= 0; i
< 8; i
++) {
2737 reg
= KS8695_SEIAC_READ
| KS8695_SEIAC_TAB_STATIC
| (KS8695_SEIAC_INDEX_MASK
& i
);
2738 KS8695_WRITE_REG(KS8695_SEIAC
, reg
);
2739 DelayInMicroseconds(10);
2741 v2
= KS8695_READ_REG(KS8695_SEIADH1
);
2742 /* if table entry is valid */
2743 if (v2
& 0x00200000) {
2744 v1
= KS8695_READ_REG(KS8695_SEIADL
);
2745 printk("%04d 0x%02x %4d %02x:%02x:%02x:%02x:%02x:%02x\n", i
,
2746 (v2
>> 16) & 0x1f, (v2
>> 24) & 0xf,
2747 ((v2
>> 8) & 0xff), (v2
& 0xff),
2748 ((v1
>> 24) & 0xff), ((v1
>> 16) & 0xff), ((v1
>> 8) & 0xff), (v1
& 0xff));