📄 ks8695end.c
字号:
* Returns:
* NONE
*/
void macStartRx(PEND_DEVICE pDrvCtrl, BOOLEAN bStart)
{
UINT32 uReg;
uReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
if (bStart) {
/* start RX machine */
uReg |= DMA_START;
DI.bRxStarted = TRUE;
} else {
/* Stop RX machine */
uReg &= ~DMA_START;
DI.bRxStarted = FALSE;
DRV_LOG(DRV_DEBUG_RX, "macStartRx, stopped\n", 1, 2, 3, 4, 5, 6);
}
KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uReg);
/* if there descriptors available for rx, tick off Rx engine */
if (bStart) {
if (DI.RxDescEmpty < DI.nRxDescTotal) {
KS8695_WRITE_REG(REG_RXSTART + DI.nOffset, 1);
}
}
else {
/* clear corresponding ISR bits after stopped */
KS8695_WRITE_REG(REG_INT_STATUS, DI.uIntMask);
}
CACHE_PIPE_FLUSH();
}
/*
* macStartTx
* This routine will start/stop TX machine.
*
* Inputs:
* pDrvCtrl pionter to END_DEVICE data structure.
* bStart TRUE if start Tx machine, FALSE if stop it
*
* Returns:
* NONE
*/
void macStartTx(PEND_DEVICE pDrvCtrl, BOOLEAN bStart)
{
UINT32 uReg;
uReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
if (bStart) {
/* start TX machine */
uReg |= DMA_START;
KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uReg);
DI.bTxStarted = TRUE;
} else {
/* Stop TX machine */
uReg &= ~DMA_START;
KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uReg);
DI.bTxStarted = FALSE;
CACHE_PIPE_FLUSH();
#ifndef NO_TASK_DELAY
taskDelay(2);
#else
delayEx(200000);
#endif
/* clear corresponding ISR bits after stopped */
/*KS8695_WRITE_REG(REG_INT_STATUS, DI.uIntMask);*/
}
}
/*
* macStopAll
* This function is use to stop both Tx/Rx.
*
* Argument(s)
* pDrvCtrl pionter to END_DEVICE data structure.
*
* Return(s)
* NONE
*/
LOCAL void macStopAll(PEND_DEVICE pDrvCtrl)
{
/* stop Rx and Tx */
macStartRx(pDrvCtrl, FALSE);
macStartTx(pDrvCtrl, FALSE);
/* disable interrupt!!! */
macEnableInterrupt(pDrvCtrl, FALSE);
}
/* Interrupt Bit definitions */
#define IB_WAN_LINK 31
#define IB_WAN_RX_STOPPED 25
#ifdef KS8695
#define IB_HPNA_TX 23
#define IB_HPNA_RX_STOPPED 18
#endif
#define IB_LAN_TX 17
#define IB_LAN_RX_STOPPED 12
#define IRQ_WAN_LEVEL 12
#define IRQ_LAN_LEVEL 10
#ifdef KS8695
#define IRQ_HPNA_LEVEL 8
#endif
/* move to source file later */
LOCAL INTCFG stDMAIntCfg[32] = {
{ 0, -1 }, /* -1 don't touch, it's not ours */
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 }, /* bit 11 */
{ 0, 0x0b }, /* bit 12, LAN */
{ 0, 0x0b },
{ 0, 0x0a },
{ 0, 0x0a },
{ 0, 0x0f },
{ 0, 0x0f },
#ifdef KS8695
{ 0, IRQ_HPNA_LEVEL }, /* bit 18, HPNA */
{ 0, IRQ_HPNA_LEVEL },
{ 0, IRQ_HPNA_LEVEL },
{ 0, IRQ_HPNA_LEVEL },
{ 0, IRQ_HPNA_LEVEL },
{ 0, IRQ_HPNA_LEVEL },
#else
{ 0, -1 }, /* bit 18, KS8695P doesn't have HPNA port */
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
{ 0, -1 },
#endif
{ 0, -1 }, /* bit 24 */
{ 0, 0x0b }, /* bit 25, WAN */
{ 0, 0x0b },
{ 0, 0x0a },
{ 0, 0x0a },
{ 0, 0x0f },
{ 0, 0x0f },
{ 0, IRQ_WAN_LEVEL } /* WAN link */
};
/*
* macConfigureInterrupt
* This routine is used to configure interrupt priority
*
* Inputs:
* pDrvCtrl pionter to END_DEVICE data structure.
*
* Returns:
* NONE
*/
void macConfigureInterrupt(PEND_DEVICE pDrvCtrl)
{
int i;
UINT uIMR, uIPR = 0;
DRV_LOG(DRV_DEBUG_LOAD, "macConfigureInterrupt\n", 1, 2, 3, 4, 5, 6);
/* use linkSem */
semTake(DI.linkSem, WAIT_FOREVER);
uIMR = KS8695_READ_REG(REG_INT_CONTL);
switch (DI.usDMAId) {
case DMA_LAN:
for (i = IB_LAN_RX_STOPPED; i <= IB_LAN_TX; i++) {
if (stDMAIntCfg[i].bFIQ) {
uIMR |= (1L << i);
DI.bUseFIQ = TRUE;
}
else {
uIMR &= ~(1L << i);
uIPR |= ((UINT)(stDMAIntCfg[i].byPriority) & 0xf) << (i - IB_LAN_RX_STOPPED + 1) * 4;
}
}
KS8695_WRITE_REG(REG_INT_LAN_PRIORITY, uIPR);
break;
#ifdef KS8695
case DMA_HPNA:
for (i = IB_HPNA_RX_STOPPED; i <= IB_HPNA_TX; i++) {
if (stDMAIntCfg[i].bFIQ) {
uIMR |= (1L << i);
DI.bUseFIQ = TRUE;
}
else {
uIMR &= ~(1L << i);
uIPR |= ((UINT)(stDMAIntCfg[i].byPriority) & 0xf) << (i - IB_HPNA_RX_STOPPED + 1) * 4;
}
}
KS8695_WRITE_REG(REG_INT_HPNA_PRIORITY, uIPR);
break;
#endif
case DMA_WAN:
default:
for (i = IB_WAN_RX_STOPPED; i <= IB_WAN_LINK; i++) {
if (stDMAIntCfg[i].bFIQ) {
uIMR |= (1L << i);
DI.bUseFIQ = TRUE;
}
else {
uIMR &= ~(1L << i);
uIPR |= ((UINT)(stDMAIntCfg[i].byPriority) & 0xf) << (i - IB_WAN_RX_STOPPED + 1) * 4;
}
}
KS8695_WRITE_REG(REG_INT_WAN_PRIORITY, uIPR);
break;
}
KS8695_WRITE_REG(REG_INT_CONTL, uIMR);
/* use linkSem */
semGive(DI.linkSem);
}
/*
* macEnableInterrupt
* This routine is used to enable/disable interrupt related to MAC only
*
* Inputs:
* pDrvCtrl pionter to END_DEVICE data structure.
* bEnable enable/disable interrupt
*
* Returns:
* NONE
*/
void macEnableInterrupt(PEND_DEVICE pDrvCtrl, BOOLEAN bEnable)
{
UINT uIER;
semTake(DI.intSem, WAIT_FOREVER);
uIER = KS8695_READ_REG(REG_INT_ENABLE);
switch (DI.usDMAId) {
case DMA_LAN:
#ifdef KS8695
case DMA_HPNA:
#endif
if (bEnable)
uIER |= DI.uIntMask;
else
uIER &= ~DI.uIntMask;
break;
case DMA_WAN:
if (bEnable)
uIER |= (DI.uIntMask | DI.uLinkIntMask);
else
uIER &= ~(DI.uIntMask | DI.uLinkIntMask);
break;
default:
DRV_LOG(DRV_DEBUG_ERROR, "macEnableInterrupt: unsupported option\n", 1, 2, 3, 4, 5, 6);
break;
}
KS8695_WRITE_REG(REG_INT_ENABLE, uIER);
semGive(DI.intSem);
#ifdef USE_POWER_SAVING
ks8695_power_saving(bEnable);
#endif
}
/*
* swSetMacAddress
* This function is use to set switch engine Mac address.
*
* Argument(s)
* pDrvCtrl pionter to END_DEVICE data structure.
* pMac pointer to mac address buffer (should be at least 6 bytes)
*
* Return(s)
* NONE
*/
void swSetMacAddress(PEND_DEVICE pDrvCtrl, UCHAR *pMac)
{
UINT32 uLowAddress, uHighAddress;
DRV_LOG(DRV_DEBUG_LOAD, "swSetMacAddress\n", 1, 2, 3, 4, 5, 6);
memcpy(&DI.stSwitchMac, pMac, MAC_ADDRESS_LEN);
uLowAddress = (*(pMac + 5) |
(*(pMac + 4) << 8) |
(*(pMac + 3) << 16)|
*(pMac + 3) << 24);
uHighAddress = (*(pMac + 1) |
*pMac << 8);
KS8695_WRITE_REG(REG_SWITCH_MAC_LOW, uLowAddress);
/* need 20 cpu clock delay for switch related registers */
SW_WRITE_DELAY();
KS8695_WRITE_REG(REG_SWITCH_MAC_HIGH, uHighAddress);
/* need 20 cpu clock delay for switch related registers */
SW_WRITE_DELAY();
}
/*
* swResetSNMPInfo
* This function is use to get SNMP counters information
*
* Argument(s)
* pDrvCtrl pionter to END_DEVICE data structure.
*
* Return(s)
* NONE
*/
void swResetSNMPInfo(PEND_DEVICE pDrvCtrl)
{
memset((void *)&pDrvCtrl->stats, 0, sizeof(pDrvCtrl->stats));
}
/*
* swCreateLookUpTable
* This function is use to create loopup table.
*
* Argument(s)
* pDrvCtrl pionter to END_DEVICE data structure.
*
* Return(s)
* NONE
*/
void swCreateLookUpTable(PEND_DEVICE pDrvCtrl)
{
unsigned int mac = 0, index = 0, tmp = 0, portmap = 0;
DRV_LOG(DRV_DEBUG_LOAD, "swCreateLookUpTable\n", 1, 2, 3, 4, 5, 6);
mac = 0x01020304;
portmap = 0x10000;
#if defined(KS8695) || defined(KS8695X)
for (index=0; index<5; index++)
{
KS8695_WRITE_REG(KS8695_SWITCH_LUE_HIGH, 0x200000 + (portmap << index));
SW_WRITE_DELAY();
KS8695_WRITE_REG(KS8695_SWITCH_LUE_LOW, mac++);
SW_WRITE_DELAY();
KS8695_WRITE_REG(KS8695_SWITCH_LUE_CTRL, index);
SW_WRITE_DELAY();
do
{
tmp = KS8695_READ_REG(KS8695_SWITCH_LUE_CTRL) & 0x1000;
} while (tmp);
}
#else
index = index; /* no complain pls */
/* the user can program other MAC addresses for LOCAL table */
tmp = 0x0002; /* e.g. this is the MAC high and low addr for the notebook I am using for test */
mac = 0xa55d1590;
KS8695_WRITE_REG(KS8695_SEIAC,
KS8695_SEIAC_WRITE | KS8695_SEIAC_TAB_STATIC | (KS8695_SEIAC_INDEX_MASK & index));
SW_WRITE_DELAY();
KS8695_WRITE_REG(KS8695_SEIADH1, 0x200000 + (portmap << index) + tmp);
SW_WRITE_DELAY();
KS8695_WRITE_REG(KS8695_SEIADL, mac);
SW_WRITE_DELAY();
#endif
}
/*
* swConfigTagRemoval
* This function is use to configure tag removal for ingress to given port.
*
* Argument(s)
* pDrvCtrl pionter to END_DEVICE data structure.
* uPort port for the tag to insert
* bRemoval enable/disable removal
*
* Return(s)
* NONE
*/
void swConfigTagRemoval(PEND_DEVICE pDrvCtrl, UINT uPort, UINT bRemoval)
{
UINT32 uReg;
uReg = KS8695_READ_REG(REG_SWITCH_ADVANCED);
if (bRemoval) {
uReg |= (1L << (22 + uPort));
}
else {
uReg &= ~(1L << (22 + uPort));
}
KS8695_WRITE_REG(REG_SWITCH_ADVANCED, uReg);
/* need 20 cpu clock delay for switch related registers */
SW_WRITE_DELAY();
}
/*
* swConfigTagInsertion
* This function is use to configure tag insertion for engress to given port.
*
* Argument(s)
* pDrvCtrl pionter to END_DEVICE data structure.
* uPort port for the tag to insert
* bInsert enable/disable insertion
*
* Return(s)
* NONE
*/
void swConfigTagInsertion(PEND_DEVICE pDrvCtrl, UINT uPort, UINT bInsert)
{
UINT32 uReg;
uReg = KS8695_READ_REG(REG_SWITCH_ADVANCED);
if (bInsert) {
uReg |= (1L << (17 + uPort));
}
else {
uReg &= ~(1L << (17 + uPort));
}
KS8695_WRITE_REG(REG_SWITCH_ADVANCED, uReg);
/* need 20 cpu clock delay for switch related registers */
SW_WRITE_DELAY();
}
/*
* swEnableSwitch
* This function is used to enable/disable switch
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE struct
* enable enable/disable switch
*
* Return(s)
* NONE.
*/
void swEnableSwitch(PEND_DEVICE pDrvCtrl, UINT enable)
{
UINT uReg;
uReg = KS8695_READ_REG(REG_SWITCH_CTRL0);
if (enable) {
uReg |= SW_CTRL0_SWITCH_ENABLE;
} else {
uReg &= ~SW_CTRL0_SWITCH_ENABLE;
}
KS8695_WRITE_REG(REG_SWITCH_CTRL0, uReg);
/* need 20 cpu clock delay for switch related registers */
SW_WRITE_DELAY();
}
/*
* ks8695_ChipInit
* This function is used to do chip initialization.
*
* Argument(s)
* pDrvCtrl pointer to EN D_DEVICE structure.
* bResetPhy flag indicates whether to reset PHY as well
*
* Return(s)
* OK if success
* ERROR otherwise
*/
LOCAL STATUS ks8695_ChipInit(PEND_DEVICE pDrvCtrl, UINT8 bResetPhy)
{
UINT bStatus;
UINT i;
DRV_LOG(DRV_DEBUG_LOAD, "ks8695_ChipInit\n", 1, 2, 3, 4, 5, 6);
if (bResetPhy) {
/* phy related initialization */
i = 0;
swPhyReset(pDrvCtrl, i);
swAutoNegoAdvertisement(pDrvCtrl, i);
if (DMA_LAN == DI.usDMAId) {
for (i = 1; i < SW_MAX_LAN_PORTS; i++) {
swPhyReset(pDrvCtrl, i);
swAutoNeg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -