📄 ks8695end.c
字号:
*
* Argument(s)
* count loop count to delay
*
* Return(s)
* NONE.
*/
LOCAL void delayEx(UINT32 count)
{
int i;
while (count--) {
i++;
}
}
#endif
#if 0
/*
* delayTicks
* This function is use to delay given ticks.
*
* Argument(s)
* ticks ticks to delay
*
* Return(s)
* NONE.
*/
LOCAL void delayTicks(UINT ticks)
{
ULONG currentTicks;
if (ticks) {
currentTicks = tickGet();
while (tickGet() < (currentTicks + ticks));
}
}
/*
* delayOneSec
* This function is use to delay a second.
*
* Argument(s)
* NONE
*
* Return(s)
* NONE.
*/
LOCAL void delayOneSec(void)
{
delayTicks(sysClkRateGet());
}
#endif
#ifdef DRV_DEBUG
/*
* logValue
* This function is use to print register value using logging mechanims.
*
* Argument(s)
* prompt pointer to the prompt string
* value register value to prompt for debug
* hex hex or decimal value
* flag log bit flag
*
* Return(s)
* NONE.
*/
LOCAL void logValue(char *prompt, UINT32 value, int hex, UINT32 flag)
{
char buf[128];
if (hex)
sprintf(buf, "%s=0x%08x\n", prompt, value);
else
sprintf(buf, "%s=%d\n", prompt, value);
DRV_LOG(flag, buf, 1, 2, 3, 4, 5, 6);
}
#endif
/*
* printStr
* This function is use to delay a second.
*
* Argument(s)
* str pointer to a string to print out in sync manner (for debug)
*
* Return(s)
* NONE.
*/
LOCAL void printStr(char *str)
{
int i, len;
len = strlen(str);
if (len) {
KS8695_WRITE_REG(REG_GPIO_DATA, 0x0000ffdf);
for (i = 0; i < len; i++) {
KS8695_WRITE_REG(REG_UART_TX_HOLDING, *(str + i));
}
KS8695_WRITE_REG(REG_UART_TX_HOLDING,0x0a);
KS8695_WRITE_REG(REG_UART_TX_HOLDING,0x0d);
}
}
/*
* ks8695_set_multi
* This function is used to set Multicast and Promiscuous mode. It is
* called whenever the multicast address list or the network interface
* flags are updated. This routine is resposible for configuring the
* hardware for proper multicast, promiscuous mode, and all-multi behavior.
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE struct
*
* Return(s)
* NONE.
*/
LOCAL void ks8695_set_multi(PEND_DEVICE pDrvCtrl)
{
uint32_t uReg;
BOOLEAN bRxStarted;
DRV_LOG(DRV_DEBUG_IOCTL, "ks8695_set_multi\n", 1, 2, 3, 4, 5, 6);
bRxStarted = DI.bRxStarted;
#if 0
if (bRxStarted) {
macStartRx(pDrvCtrl, FALSE);
}
#endif
/* read RX mode register in order to set hardware filter mode */
uReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
uReg |= DMA_UNICAST | DMA_BROADCAST;
uReg &= ~(DMA_PROMISCUOUS | DMA_MULTICAST);
/* Set promiscuous mode if it's asked for. */
if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) {
DRV_LOG(DRV_DEBUG_IOCTL, "Promiscuous mode on!\n", 1, 2, 3, 4, 5, 6);
uReg |= DMA_PROMISCUOUS;
}
if (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_ALLMULTI | IFF_MULTICAST)) {
DRV_LOG(DRV_DEBUG_IOCTL, "Multicast mode on!\n", 1, 2, 3, 4, 5, 6);
uReg |= DMA_MULTICAST;
}
KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uReg);
if (bRxStarted) {
#if 0
macStartRx(pDrvCtrl, TRUE);
#endif
}
ks8695_relink(pDrvCtrl);
}
/*
* ResetDma
* This function is use to reset DMA in case Tx DMA was sucked due to
* heavy traffic condition.
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE struct
*
* Return(s)
* 0 if success
* negative value if failed
*/
LOCAL __inline void ResetDma(PEND_DEVICE pDrvCtrl)
{
UINT uRxReg;
if (KS8695_FLAGS_ISSET(&pDrvCtrl->end, IFF_RUNNING)) {
logMsg("ResetDma, not running!\n", 1, 2, 3, 4, 5, 6);
return;
}
logMsg("ResetDma: not implented yet\n", 1, 2, 3, 4, 5, 6);
return;
END_FLAGS_CLR(&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
macStopAll(pDrvCtrl);
CleanRxRing(pDrvCtrl);
InitRxRing(pDrvCtrl);
CleanTxRing(pDrvCtrl);
InitTxRing(pDrvCtrl);
ReceiveBufferFill(pDrvCtrl);
ks8695_ChipInit(pDrvCtrl, FALSE);
KS8695_WRITE_REG(REG_INT_STATUS, DI.uIntMask);
/* read RX mode register */
uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) {
uRxReg |= DMA_PROMISCUOUS;
}
if (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_ALLMULTI | IFF_MULTICAST)) {
uRxReg |= DMA_MULTICAST;
}
uRxReg |= DMA_BROADCAST;
/* write RX mode register */
KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);
KS8695_WRITE_REG(REG_RXBASE + DI.nOffset, DI.RxDescDMA);
KS8695_WRITE_REG(REG_TXBASE + DI.nOffset, DI.TxDescDMA);
macEnableInterrupt(pDrvCtrl, TRUE);
macStartRx(pDrvCtrl, TRUE);
macStartTx(pDrvCtrl, TRUE);
DI.bTxNoResource = FALSE;
END_FLAGS_SET(&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
}
/*
* hook_irqs
* This function is used to hook irqs associated to given DMA type
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
* req request or free interrupts
*
* Return(s)
* OK if success
* ERROR if failed
*/
LOCAL int hook_irqs(PEND_DEVICE pDrvCtrl, int req)
{
STATUS result;
int i;
switch (DI.usDMAId) {
default:
break;
case DMA_WAN:
if (DI.uLinkIntMask & INT_WAN_LINK) {
if (req) {
result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(31), ks8695IntLink, (int)pDrvCtrl);
if (ERROR == result) {
DRV_LOG(DRV_DEBUG_ERROR, "intConnect failed\n", 1, 2, 3, 4, 5, 6);
intEnable(INT_LVL_WMLCS);
return result;
}
}
else {
intDisable(INT_LVL_WMLCS);
}
}
break;
}
/* each DMA has 6 interrupt bits associated, except WAN which has one extra, INT_WAN_LINK */
for (i = 0; i < 6; i++) {
if (DI.uIntMask & (1L << (DI.uIntShift + i))) {
if (req) {
switch ((1 << i))
{
default:
case INT_TX_BIT:
result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxComp, (int)pDrvCtrl);
break;
case INT_RX_BIT:
result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxAvail, (int)pDrvCtrl);
break;
case INT_TX_UNAVAIL_BIT:
result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxUnavail, (int)pDrvCtrl);
break;
case INT_RX_UNAVAIL_BIT:
result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxUnavail, (int)pDrvCtrl);
break;
case INT_TX_STOPPED_BIT:
result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxStop, (int)pDrvCtrl);
break;
case INT_RX_STOPPED_BIT:
result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxStop, (int)pDrvCtrl);
break;
}
if (ERROR == result) {
DRV_LOG(DRV_DEBUG_ERROR, "intConnect failed\n", 1, 2, 3, 4, 5, 6);
/* disconnect any one connected previously before failing it */
while (--i >= 0) {
intDisable(i + DI.uIntShift);
}
return result;
}
intEnable(i + DI.uIntShift);
}
else {
intDisable(i + DI.uIntShift);
}
}
}
return OK;
}
/*
* ks8695_dump_packet
* This function is use to dump given packet for debugging.
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
* data pointer to the beginning of the packet to dump
* len length of the packet
* flag debug flag
*
* Return(s)
* NONE.
*/
__inline void ks8695_dump_packet(PEND_DEVICE pDrvCtrl, unsigned char *data, int len, UINT flag)
{
/* we may need to have locking mechamism to use this function, since Rx call it within INT context
and Tx call it in normal context */
if (flag && len >= 18) {
if (flag & DEBUG_PACKET_LEN) {
printf("Pkt Len=%d\n", len);
}
if (flag & DEBUG_PACKET_HEADER) {
printf("DA=%02x:%02x:%02x:%02x:%02x:%02x\n",
*data, *(data + 1), *(data + 2), *(data + 3), *(data + 4), *(data + 5));
printf("SA=%02x:%02x:%02x:%02x:%02x:%02x\n",
*(data + 6), *(data + 7), *(data + 8), *(data + 9), *(data + 10), *(data + 11));
printf("Type=%04x (%d)\n", ntohs(*(unsigned short *)(data + 12)), ntohs(*(unsigned short *)(data + 12)));
}
if (flag & DEBUG_PACKET_CONTENT) {
int j = 0, k;
/* skip DA/SA/TYPE */
/*
data += ENET_HEADER_SIZE;
len -= ENET_HEADER_SIZE;
*/
do {
printf("\n %04d ", j);
for (k = 0; (k < 16 && len); k++, data++, len--) {
printf("%02x ", *data);
}
j += 16;
} while (len > 0);
/* last dump crc field */
/*printf("\nCRC=%04x\n", ntohl(*(unsigned int *)data));*/
printf("\n");
}
}
}
#ifdef USE_DUMP_REG
/*
* ks8695_dump_reg
* This function is use to dump registers of given range!
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
* offset register offset to dump
* length length of registers to dump
*
* Return(s)
* NONE.
*/
LOCAL void ks8695_dump_reg(PEND_DEVICE pDrvCtrl, UINT32 offset, UINT32 length)
{
int i;
UINT32 val;
printf("-reg- --value(hex)-- --value(dec)---\n");
for (i = offset; i <= (offset + length); i += 4) {
val = KS8695_READ_REG(i);
printf("0x%04x 0x%08x %12d\n", i, val, val);
}
}
/*
* ks8695_dump_reg_set
* This function is use to dump registers of given range!
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
* set bit for which set to dump
*
* Return(s)
* NONE.
*/
LOCAL void ks8695_dump_reg_set(PEND_DEVICE pDrvCtrl, UINT32 set)
{
if (set & SET_DMA_DUMP) {
ks8695_dump_reg(pDrvCtrl, DI.nOffset + REG_TXCTRL, REG_STATION_HIGH);
}
if (set & SET_DMA_STATION_DUMP) {
ks8695_dump_reg(pDrvCtrl, DI.nOffset + REG_MAC0_LOW, (REG_MAC15_HIGH - REG_MAC0_LOW));
}
if (set & SET_UART_DUMP) {
ks8695_dump_reg(pDrvCtrl, REG_UART_RX_BUFFER, (REG_UART_STATUS - REG_UART_RX_BUFFER));
}
if (set & SET_INT_DUMP) {
/*ks8695_dump_reg(pDrvCtrl, REG_INT_CONTL, (REG_IRQ_PEND_PRIORITY - REG_INT_CONTL));*/
ks8695_dump_reg(pDrvCtrl, REG_INT_CONTL, (REG_INT_LAN_PRIORITY - REG_INT_CONTL));
}
if (set & SET_TIMER_DUMP) {
ks8695_dump_reg(pDrvCtrl, REG_TIMER_CTRL, (REG_TIMER0_PCOUNT -REG_TIMER_CTRL));
}
if (set & SET_GPIO_DUMP) {
ks8695_dump_reg(pDrvCtrl, REG_GPIO_MODE, (REG_GPIO_DATA - REG_GPIO_MODE));
}
if (set & SET_SWITCH_DUMP) {
ks8695_dump_reg(pDrvCtrl, REG_SWITCH_CTRL0, (REG_LAN34_POWERMAGR - REG_SWITCH_CTRL0));
}
if (set & SET_MISC_DUMP) {
ks8695_dump_reg(pDrvCtrl, REG_DEVICE_ID, (REG_WAN_PHY_STATUS - REG_DEVICE_ID));
}
if (set & SET_SNMP_DUMP) {
#ifdef USE_READSNMPREG
UINT32 val, i;
for (i = 0; i <= REG_SNMP_MAX ; i++) {
val = swReadSNMPReg(pDrvCtrl, i);
printf("0x%04x = %10d\n", i, val);
}
#endif /*USE_READSNMPREG*/
}
}
#endif
/*
* ks8695_relink
* This function is use to setup link in case some dynamic configuration
* is applied via ifconfig! if driver is opened!
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure.
*
* Return(s)
* NONE.
*/
LOCAL void ks8695_relink(PEND_DEVICE pDrvCtrl)
{
/* reset the flag even if auto nego is in progress
to make sure we don't miss it!!! */
if (DMA_LAN != DI.usDMAId) {
swDetectPhyConnection(pDrvCtrl, 0);
}
else {
int i;
for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
swDetectPhyConnection(pDrvCtrl, i);
}
}
}
/*
* SoftwareInit
* This function initializes the pDrvCtrl private data structure.
*
* Argument(s)
* pDrvCtrl pointer to END_DEVICE structure
*
* Return(s)
* OK if success
* ERROR if failed
*/
LOCAL int SoftwareInit(PEND_DEVICE pDrvCtrl)
{
/* Initial Receive Buffer Length */
if ((ETHERMTU + ENET_HEADER_SIZE + ETH_CRC_LENGTH + 2) <= KS8695_MIN_FBUF - 4 - pDrvCtrl->offset) {
DI.uRxBufferLen = KS8695_MIN_FBUF; /* 0x600 */
}
else if ((ETHERMTU + ENET_HEADER_SIZE + ETH_CRC_LENGTH + 2) <= BUFFER_1568 - 4 - pDrvCtrl->offset) {
DI.uRxBufferLen = BUFFER_1568; /* 0x620 */
}
else {
DI.uRxBufferLen = BUFFER_2048; /* 0x800 */
}
/* please update link status within watchdog routine */
DI.bLinkChanged[0] = TRUE;
if (DMA_LAN == DI.usDMAId) { /* if LAN driver, 3 more ports */
DI.bLinkChanged[1] = TRUE;
DI.bLinkChanged[2] = TRUE;
DI.bLinkChanged[3] = TRUE;
}
return OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -