2428 lines
70 KiB
C
2428 lines
70 KiB
C
#include <linux/skbuff.h>
|
||
#include <linux/netdevice.h>
|
||
#include <linux/phy.h>
|
||
#include <linux/proc_fs.h>
|
||
#include <linux/seq_file.h>
|
||
#include <linux/spinlock_types.h>
|
||
#include <linux/net.h>
|
||
#include <net/udp.h>
|
||
#include <net/arp.h>
|
||
#include <net/inet_common.h>
|
||
#include "debug_info.h"
|
||
#include "log.h"
|
||
|
||
#if defined(PLATFORM_MV78460)
|
||
#include "mv_netdev.h"
|
||
#elif defined(PLATFORM_P1010)
|
||
#include "gianfar.h"
|
||
#endif
|
||
|
||
#include "hook.h"
|
||
|
||
#define P1010_CPU_COUNT_PER_MS (50000)
|
||
|
||
#define SEND_SEQ_POS (0x2C)
|
||
#define RECV_SEQ_POS (SEND_SEQ_POS - 0x0E)
|
||
|
||
static int DbgFS_RtpPortShow(struct seq_file* seq, void* token);
|
||
static int DbgFS_GianfarSipPortShow(struct seq_file* seq, void* token);
|
||
static int DbgFS_SipArpShow(struct seq_file* seq, void* token);
|
||
static int DbgFS_NICCfgShow(struct seq_file* seq, void* token);
|
||
static int DbgFS_EthIrqShow(struct seq_file* seq, void* token);
|
||
static int DbgFS_EthIrqHelp(struct seq_file* seq, void* token);
|
||
static int DbgFS_EthIrqIoctl(struct seq_file* seq, char* cmd, char* params);
|
||
|
||
#ifdef PLATFORM_MV78460
|
||
static unsigned char g_spbxNetId = ETH_INTERFACE_2;
|
||
#else
|
||
static unsigned char g_spbxNetId = ETH_INTERFACE_0;
|
||
#endif
|
||
|
||
static PNIC_RCV_RTP_DATA g_pRcvRtpHook = NULL;
|
||
static spinlock_t g_RegHookLock;
|
||
PNIC_PRIVATE g_NICInfo[MAX_ETH_PORT];
|
||
|
||
typedef enum __DBGFS_ID
|
||
{
|
||
DBG_SIP_CH,
|
||
DBG_SIP_ARP,
|
||
DBG_RTP_PORT,
|
||
DBG_NIC_CFG,
|
||
DBG_ETH_IRQ,
|
||
} DBGFS_ID;
|
||
|
||
static DBGFS_PRIV g_DbgFSConfig[] =
|
||
{
|
||
{
|
||
"sip_ch", 0, NULL, NULL,
|
||
DbgFS_GianfarSipPortShow, NULL, NULL
|
||
},
|
||
|
||
{
|
||
"sip_arp", 0, NULL, NULL,
|
||
DbgFS_SipArpShow, NULL, NULL
|
||
},
|
||
{
|
||
"rtp_port", 0, NULL, NULL,
|
||
DbgFS_RtpPortShow, NULL, NULL
|
||
},
|
||
{
|
||
"nic_config", 0, NULL, NULL,
|
||
DbgFS_NICCfgShow, NULL, NULL
|
||
},
|
||
{
|
||
"eth_irq", 0, NULL, NULL,
|
||
DbgFS_EthIrqShow, DbgFS_EthIrqIoctl, DbgFS_EthIrqHelp
|
||
},
|
||
};
|
||
|
||
int NIC_GetInfo(const char* pNIC, PNIC_INFO pInfo)
|
||
{
|
||
int iRet = 0;
|
||
struct socket* sock;
|
||
struct ifreq ifr;
|
||
mm_segment_t oldCfg;
|
||
struct net_device* dev;
|
||
|
||
if(!pNIC || !pInfo)
|
||
{
|
||
LOG_EX(LOG_Error, "Input Params Error:%p, %p", pNIC, pInfo);
|
||
return -1;
|
||
}
|
||
|
||
memset(pInfo, 0, sizeof(NIC_INFO));
|
||
|
||
memset(&ifr, 0, sizeof(ifr));
|
||
strcpy(ifr.ifr_name, pNIC);
|
||
|
||
iRet = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
|
||
|
||
if(iRet < 0 || NULL == sock)
|
||
{
|
||
LOG_EX(LOG_Error, "sock_create_kern Error:%d\n", iRet);
|
||
return -1;
|
||
}
|
||
|
||
dev = dev_get_by_name(sock_net(sock->sk), pNIC);
|
||
|
||
if(dev == NULL)
|
||
{
|
||
LOG_EX(LOG_Error, "dev_get_by_name Error\n");
|
||
return -1;
|
||
}
|
||
|
||
pInfo->devIfIndex = dev->ifindex;
|
||
memcpy(pInfo->macAddr, dev->dev_addr, 6);
|
||
|
||
oldCfg = get_fs();
|
||
set_fs(KERNEL_DS);
|
||
|
||
if((iRet = inet_ioctl(sock, SIOCGIFADDR, (unsigned long)&ifr)) != 0)
|
||
{
|
||
LOG_EX(LOG_Error, "Get Ip Addr Error: %d\n", iRet);
|
||
}
|
||
|
||
pInfo->ipAddr = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr;
|
||
|
||
if((iRet = inet_ioctl(sock, SIOCGIFBRDADDR, (unsigned long)&ifr)) != 0)
|
||
{
|
||
LOG_EX(LOG_Error, "Get Board Addr Error: %d\n", iRet);
|
||
}
|
||
|
||
pInfo->boardAddr = ((struct sockaddr_in*)&ifr.ifr_broadaddr)->sin_addr.s_addr;
|
||
|
||
if((iRet = inet_ioctl(sock, SIOCGIFNETMASK, (unsigned long)&ifr)) != 0)
|
||
{
|
||
LOG_EX(LOG_Error, "Get Netmask Addr Error: %d\n", iRet);
|
||
}
|
||
|
||
pInfo->netMask = ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr;
|
||
|
||
set_fs(oldCfg);
|
||
|
||
sock_release(sock);
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(NIC_GetInfo);
|
||
|
||
int make_arp_request_ex(unsigned int ethId, __be32 dest_ip)
|
||
{
|
||
struct sk_buff* skb = NULL;
|
||
NIC_INFO nicInfo;
|
||
|
||
if(!IS_VALUABLED_ETH(ethId))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if(g_NICInfo[ethId] == NULL)
|
||
{
|
||
return -2;
|
||
}
|
||
|
||
if(g_NICInfo[ethId]->opened_ref == 0)
|
||
{
|
||
return -3;
|
||
}
|
||
|
||
memset(&nicInfo, 0, sizeof(NIC_INFO));
|
||
|
||
NIC_GetInfo(g_NICInfo[ethId]->ndev->name, &nicInfo);
|
||
|
||
skb = arp_create(ARPOP_REQUEST,
|
||
ETH_P_ARP,
|
||
dest_ip,
|
||
g_NICInfo[ethId]->ndev,
|
||
nicInfo.ipAddr,
|
||
NULL,
|
||
nicInfo.macAddr,
|
||
NULL);
|
||
|
||
if(skb)
|
||
{
|
||
arp_xmit(skb);
|
||
}
|
||
else
|
||
{
|
||
return -3;
|
||
}
|
||
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(make_arp_request_ex);
|
||
|
||
|
||
int make_arp_request(unsigned int ethId, __be32 dest_ip)
|
||
{
|
||
struct sk_buff* skb = NULL;
|
||
|
||
if(!IS_VALUABLED_ETH(ethId))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if(g_NICInfo[ethId] == NULL)
|
||
{
|
||
return -2;
|
||
}
|
||
|
||
if(g_NICInfo[ethId]->opened_ref == 0)
|
||
{
|
||
return -3;
|
||
}
|
||
|
||
skb = arp_create(ARPOP_REQUEST,
|
||
ETH_P_ARP,
|
||
dest_ip,
|
||
g_NICInfo[ethId]->ndev,
|
||
g_NICInfo[ethId]->chIpAddr,
|
||
NULL,
|
||
g_NICInfo[ethId]->ndev->dev_addr,
|
||
NULL);
|
||
|
||
if(skb)
|
||
{
|
||
arp_xmit(skb);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(make_arp_request);
|
||
|
||
int get_eth_mac(unsigned char* haddr, ETH_INTERFACE ethId)
|
||
{
|
||
struct net_device* pDev = NULL;
|
||
|
||
if(!IS_VALUABLED_ETH(ethId))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if(g_NICInfo[ethId] == NULL)
|
||
{
|
||
return -2;
|
||
}
|
||
|
||
if(g_NICInfo[ethId]->opened_ref == 0)
|
||
{
|
||
return -3;
|
||
}
|
||
|
||
if(haddr)
|
||
{
|
||
pDev = g_NICInfo[ethId]->ndev;
|
||
memcpy(haddr, pDev->dev_addr, pDev->addr_len);
|
||
return pDev->addr_len;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(get_eth_mac);
|
||
|
||
int get_mac_form_ip(unsigned char* haddr, ETH_INTERFACE ethId, __be32 ipaddr, int id)
|
||
{
|
||
struct neighbour* n;
|
||
PNIC_PRIVATE pEthInfo = NULL;
|
||
__be32 oldip = ipaddr;
|
||
|
||
if(!IS_VALUABLED_ETH(ethId))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
pEthInfo = g_NICInfo[ethId];
|
||
|
||
if(pEthInfo == NULL)
|
||
{
|
||
return -2;
|
||
}
|
||
|
||
if(id == 4 || id == 3)
|
||
{
|
||
printk("ethId = %d, ipaddr = 0x%08X\n", ethId, ipaddr);
|
||
}
|
||
//memset(haddr, 0xFF, ETH_ALEN);
|
||
|
||
if(pEthInfo->chGWIpAddr != 0)
|
||
{
|
||
if((ntohl(ipaddr) & pEthInfo->chGWMask) != (pEthInfo->chIpAddr & pEthInfo->chGWMask))
|
||
{
|
||
if(id == 4 || id == 3)
|
||
{
|
||
printk("ipaddr = 0x%08X, pEthInfo->chGWMask = 0x%08X, pEthInfo->chIpAddr = 0x%08X\n",
|
||
ipaddr, pEthInfo->chGWMask, pEthInfo->chIpAddr);
|
||
}
|
||
|
||
ipaddr = pEthInfo->chGWIpAddr;
|
||
}
|
||
}
|
||
|
||
if(id == 4 || id == 3)
|
||
{
|
||
printk("eth %d ipaddr 0x%08X get ip 0x%08X arp call by %d\n",
|
||
ethId, oldip, ipaddr, id);
|
||
}
|
||
|
||
if(haddr != NULL)
|
||
{
|
||
n = __neigh_lookup(&arp_tbl, &ipaddr, pEthInfo->ndev, 1);
|
||
|
||
if(n != NULL)
|
||
{
|
||
n->used = jiffies;
|
||
|
||
if(n->nud_state & NUD_VALID)
|
||
{
|
||
memcpy(haddr, n->ha, pEthInfo->ndev->addr_len);
|
||
neigh_release(n);
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
neigh_release(n);
|
||
}
|
||
}
|
||
else if(id == 4 || id == 3)
|
||
{
|
||
printk("__neigh_lookup is null\n");
|
||
}
|
||
}
|
||
|
||
if(id == 4 || id == 3)
|
||
{
|
||
printk("eth %d ipaddr 0x%08X get ip 0x%08X arp call by %d Error\n",
|
||
ethId, oldip, ipaddr, id);
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
EXPORT_SYMBOL(get_mac_form_ip);
|
||
|
||
unsigned short get_ip_checksum(unsigned short* buffer, int size)
|
||
{
|
||
unsigned long cksum = 0;
|
||
|
||
while(size > 1)
|
||
{
|
||
cksum += *buffer++;
|
||
size -= sizeof(unsigned short);
|
||
}
|
||
|
||
if(size)
|
||
{
|
||
cksum += *(unsigned short*)buffer;
|
||
}
|
||
|
||
cksum = (cksum >> 16) + (cksum & 0xffff);
|
||
cksum += (cksum >> 16);
|
||
|
||
return (unsigned short)(~cksum);
|
||
}
|
||
EXPORT_SYMBOL(get_ip_checksum);
|
||
|
||
#define RECV_RFC2833_RECV_NEW (0)
|
||
#define RECV_RFC2833_RECV_REP (1)
|
||
#define RECV_RFC2833_RECV_DROP (2)
|
||
#define RECV_RFC2833_RECV_UNRECV (4)
|
||
|
||
#define CHK_CH_STATUS (1 << 0)
|
||
#define CHK_CH_DSTTARGET (1 << 1)
|
||
#define CHK_CH_NEEDSWITCH (1 << 2)
|
||
#define CHK_CH_SWITCH_OK (1 << 3)
|
||
#define CHK_CH_SWITCH_ERR (1 << 4)
|
||
#define CHK_CH_RFC2833 (1 << 5)
|
||
#define CHK_CH_NEEDSWITCH_SAMEBOARD (1 << 6)
|
||
#define CHK_CH_RECVUDP (1 << 7)
|
||
#define CHK_CH_DROP_WAITARP (1 << 8)
|
||
|
||
static SIP_CH_INFO g_SIPChInfo;
|
||
static int g_DebugRFC2833 = 0;
|
||
static int g_CheckRFC2833 = 0;
|
||
|
||
static SIP_CH_DETIAL g_SIPDetial[MAX_SIP_CH];
|
||
|
||
|
||
const char g_DTMFTable[17] =
|
||
{
|
||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||
'*', '#',
|
||
'A', 'B', 'C', 'D',
|
||
'F' // Flash
|
||
};
|
||
|
||
static struct sk_buff* switch_to_sip(int sipCh,
|
||
struct sk_buff* skb,
|
||
ETH_INTERFACE ethId,
|
||
PCH_PORT_INFO pPort);
|
||
|
||
static int CheckMacAddress(PCH_PORT_INFO pPort, ETH_INTERFACE ethId);
|
||
|
||
static int DbgFS_SipArpShow(struct seq_file* seq, void* token)
|
||
{
|
||
unsigned int opt = g_DbgFSConfig[DBG_SIP_ARP].params;
|
||
unsigned char mac[12];
|
||
int ret, i = 0;
|
||
|
||
if(token == SEQ_START_TOKEN)
|
||
{
|
||
for(i = 0; i < 3; i++)
|
||
{
|
||
if(g_NICInfo[i] != NULL)
|
||
{
|
||
ret = get_mac_form_ip(mac, i,
|
||
htonl(g_NICInfo[i]->chGWIpAddr), 2);
|
||
|
||
seq_printf(seq, "eth %d request arp %d.%d.%d.%d is %02X:%02X:%02X:%02X:%02X:%02X ret %d\n",
|
||
g_NICInfo[i]->port,
|
||
(g_NICInfo[i]->chGWIpAddr >> 24) & 0xFF,
|
||
(g_NICInfo[i]->chGWIpAddr >> 16) & 0xFF,
|
||
(g_NICInfo[i]->chGWIpAddr >> 8) & 0xFF,
|
||
g_NICInfo[i]->chGWIpAddr & 0xFF,
|
||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ret);
|
||
}
|
||
}
|
||
|
||
if(opt >= 0 && opt < g_SIPChInfo.iTotalCh)
|
||
{
|
||
PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + opt;
|
||
|
||
seq_printf(seq, "pCh->portB2B.chStatus = %d, pCh->portB2B.chStatus = %d\n",
|
||
pCh->portB2B.chStatus, pCh->portRTP.chStatus);
|
||
|
||
if(pCh->portB2B.chStatus == 2)
|
||
{
|
||
ret = get_mac_form_ip(mac, 0,
|
||
htonl(pCh->portB2B.chLinkInfo.dstTarget.ipAddr), 3);
|
||
|
||
seq_printf(seq, "eth %d request arp %d.%d.%d.%d is %02X:%02X:%02X:%02X:%02X:%02X ret %d\n",
|
||
0,
|
||
(pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF,
|
||
(pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF,
|
||
(pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF,
|
||
pCh->portB2B.chLinkInfo.dstTarget.ipAddr & 0xFF,
|
||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ret);
|
||
}
|
||
|
||
if(pCh->portRTP.chStatus == 2)
|
||
{
|
||
ret = get_mac_form_ip(mac, pCh->sipETHId,
|
||
htonl(pCh->portRTP.chLinkInfo.dstTarget.ipAddr), 4);
|
||
|
||
seq_printf(seq, "eth %d request arp %d.%d.%d.%d is %02X:%02X:%02X:%02X:%02X:%02X ret %d\n",
|
||
pCh->sipETHId,
|
||
(pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF,
|
||
(pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF,
|
||
(pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF,
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipAddr & 0xFF,
|
||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], ret);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
seq_printf(seq, "opt = %d\n", opt);
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
static int DbgFS_GianfarSipPortShow(struct seq_file* seq, void* token)
|
||
{
|
||
unsigned int opt = g_DbgFSConfig[DBG_SIP_CH].params;
|
||
int i = 0;
|
||
|
||
if(token == SEQ_START_TOKEN)
|
||
{
|
||
if(opt == 1)
|
||
{
|
||
seq_printf(seq, "g_DebugRFC2833 Off\n");
|
||
g_DebugRFC2833 = 0;
|
||
}
|
||
else if(opt == 2)
|
||
{
|
||
seq_printf(seq, "g_DebugRFC2833 On\n");
|
||
g_DebugRFC2833 = 1;
|
||
}
|
||
else if(opt == 3)
|
||
{
|
||
seq_printf(seq, "g_CheckRFC2833 Off\n");
|
||
g_CheckRFC2833 = 0;
|
||
}
|
||
else if(opt == 4)
|
||
{
|
||
seq_printf(seq, "g_CheckRFC2833 On\n");
|
||
g_CheckRFC2833 = 1;
|
||
}
|
||
else if(opt == 5)
|
||
{
|
||
seq_printf(seq, "g_CheckRFC2833 Clean\n");
|
||
|
||
for(i = 0; i < g_SIPChInfo.iTotalCh; i++)
|
||
{
|
||
g_SIPChInfo.pSipChDetial[i].sipDebug.ethx_rfc2833_error = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
seq_printf(seq, "g_CheckRFC2833 = %d, g_DebugRFC2833 = %d\n",
|
||
g_CheckRFC2833, g_DebugRFC2833);
|
||
}
|
||
|
||
seq_printf(seq, "SPI Info:\n");
|
||
|
||
for(i = 0; i < 3; i++)
|
||
{
|
||
if(g_NICInfo[i] != NULL)
|
||
{
|
||
seq_printf(seq,
|
||
"ucc=%p, index=%d ipaddr=%d.%d.%d.%d gw=%d.%d.%d.%d gw mask=%d.%d.%d.%d\n",
|
||
g_NICInfo[i], g_NICInfo[i]->port,
|
||
(g_NICInfo[i]->chIpAddr >> 24) & 0xFF,
|
||
(g_NICInfo[i]->chIpAddr >> 16) & 0xFF,
|
||
(g_NICInfo[i]->chIpAddr >> 8) & 0xFF,
|
||
g_NICInfo[i]->chIpAddr & 0xFF,
|
||
(g_NICInfo[i]->chGWIpAddr >> 24) & 0xFF,
|
||
(g_NICInfo[i]->chGWIpAddr >> 16) & 0xFF,
|
||
(g_NICInfo[i]->chGWIpAddr >> 8) & 0xFF,
|
||
g_NICInfo[i]->chGWIpAddr & 0xFF,
|
||
(g_NICInfo[i]->chGWMask >> 24) & 0xFF,
|
||
(g_NICInfo[i]->chGWMask >> 16) & 0xFF,
|
||
(g_NICInfo[i]->chGWMask >> 8) & 0xFF,
|
||
g_NICInfo[i]->chGWMask & 0xFF);
|
||
}
|
||
}
|
||
|
||
seq_printf(seq, "Total Ch: %d\n", g_SIPChInfo.iTotalCh);
|
||
seq_printf(seq, "Port Base: %d\n", g_SIPChInfo.iPortBase);
|
||
seq_printf(seq, "Port Step: %d\n", g_SIPChInfo.iPortStep);
|
||
seq_printf(seq, "RTP Port Base: %d\n", g_SIPChInfo.iRTPPortBase);
|
||
|
||
for(i = 0; i < g_SIPChInfo.iTotalCh; i++)
|
||
{
|
||
PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + i;
|
||
|
||
if(pCh->portB2B.chStatus != 2 &&
|
||
pCh->portRTP.chStatus != 2)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
seq_printf(seq, "++++++++++++++++Ch %d Info+++++++++++++\n", i);
|
||
seq_printf(seq, "B2B Status: %d\n", pCh->portB2B.chStatus);
|
||
seq_printf(seq, "B2B IP Port: %d\n", pCh->portB2B.ipPort);
|
||
|
||
seq_printf(seq, "B2B Link IP: %d.%d.%d.%d\n",
|
||
(pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF,
|
||
(pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF,
|
||
(pCh->portB2B.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF,
|
||
pCh->portB2B.chLinkInfo.dstTarget.ipAddr & 0xFF);
|
||
seq_printf(seq, "B2B Link Port: %d\n", pCh->portB2B.chLinkInfo.dstTarget.ipPort);
|
||
seq_printf(seq, "B2B Link Mac: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
|
||
pCh->portB2B.chLinkInfo.dstTarget.ethAddr[0],
|
||
pCh->portB2B.chLinkInfo.dstTarget.ethAddr[1],
|
||
pCh->portB2B.chLinkInfo.dstTarget.ethAddr[2],
|
||
pCh->portB2B.chLinkInfo.dstTarget.ethAddr[3],
|
||
pCh->portB2B.chLinkInfo.dstTarget.ethAddr[4],
|
||
pCh->portB2B.chLinkInfo.dstTarget.ethAddr[5]);
|
||
|
||
seq_printf(seq, "RTP Status: %d\n", pCh->portRTP.chStatus);
|
||
seq_printf(seq, "RTP ETH: %d\n", pCh->sipETHId);
|
||
seq_printf(seq, "RTP IP Port: %d\n", pCh->portRTP.ipPort);
|
||
seq_printf(seq, "RTP Link IP: %d.%d.%d.%d\n",
|
||
(pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 24) & 0xFF,
|
||
(pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 16) & 0xFF,
|
||
(pCh->portRTP.chLinkInfo.dstTarget.ipAddr >> 8) & 0xFF,
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipAddr & 0xFF);
|
||
seq_printf(seq, "RTP Link Port: %d\n", pCh->portRTP.chLinkInfo.dstTarget.ipPort);
|
||
seq_printf(seq, "RTP Link Mac: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
|
||
pCh->portRTP.chLinkInfo.dstTarget.ethAddr[0],
|
||
pCh->portRTP.chLinkInfo.dstTarget.ethAddr[1],
|
||
pCh->portRTP.chLinkInfo.dstTarget.ethAddr[2],
|
||
pCh->portRTP.chLinkInfo.dstTarget.ethAddr[3],
|
||
pCh->portRTP.chLinkInfo.dstTarget.ethAddr[4],
|
||
pCh->portRTP.chLinkInfo.dstTarget.ethAddr[5]);
|
||
|
||
seq_printf(seq, "RTP Stun Tag: %d\n", pCh->portRTP.chLinkInfo.stunTags);
|
||
|
||
seq_printf(seq, "ETH(spbx) Recv: %d\n", pCh->sipDebug.cnt_eth0_recv);
|
||
seq_printf(seq, "ETH(spbx) Switch: %d\n", pCh->sipDebug.cnt_eth0_2_ethx);
|
||
seq_printf(seq, "ETH(spbx) Mask: 0x%08X\n", pCh->sipDebug.mask_eth0_2_ethx);
|
||
seq_printf(seq, "ETH(spbx) lost: %d\n", pCh->sipDebug.eth0_seq_error);
|
||
seq_printf(seq, "ETH(spbx) drop: %d\n\n", pCh->sipDebug.eth0_drop_src);
|
||
|
||
|
||
seq_printf(seq, "ETH(sip) Recv: %d\n", pCh->sipDebug.cnt_ethx_recv);
|
||
seq_printf(seq, "ETH(sip) Switch: %d\n", pCh->sipDebug.cnt_ethx_2_eth0);
|
||
seq_printf(seq, "ETH(sip) Mask: 0x%08X\n", pCh->sipDebug.mask_ethx_2_eth0);
|
||
seq_printf(seq, "ETH(sip) lost: %d\n", pCh->sipDebug.ethx_seq_error);
|
||
seq_printf(seq, "ETH(sip) drop: %d\n\n", pCh->sipDebug.ethx_drop_src);
|
||
|
||
if(g_CheckRFC2833)
|
||
{
|
||
seq_printf(seq, "ETH(sip) Error Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_error);
|
||
seq_printf(seq, "ETH(sip) Drv Err Dtmf: %d\n", pCh->sipDebug.drv_rcv_rfc2833_error);
|
||
}
|
||
|
||
seq_printf(seq, "ETH(sip) Rcv Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_recv);
|
||
seq_printf(seq, "ETH(sip) Rcv lost Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_rcv_lost);
|
||
seq_printf(seq, "ETH(sip) Snd lost Dtmf: %d\n", pCh->sipDebug.ethx_rfc2833_snd_lost);
|
||
seq_printf(seq, "ETH(sip) Drv Rcv Dtmf: %d\n\n", pCh->sipDebug.drv_rcv_rfc2833_recv);
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static char GetDTMFValue(char dtmf)
|
||
{
|
||
switch(dtmf)
|
||
{
|
||
case '0':
|
||
return 0;
|
||
|
||
case '1':
|
||
return 1;
|
||
|
||
case '2':
|
||
return 2;
|
||
|
||
case '3':
|
||
return 3;
|
||
|
||
case '4':
|
||
return 4;
|
||
|
||
case '5':
|
||
return 5;
|
||
|
||
case '6':
|
||
return 6;
|
||
|
||
case '7':
|
||
return 7;
|
||
|
||
case '8':
|
||
return 8;
|
||
|
||
case '9':
|
||
return 9;
|
||
|
||
case '*':
|
||
return 10;
|
||
|
||
case '#':
|
||
return 11;
|
||
|
||
case 'A':
|
||
case 'a':
|
||
return 12;
|
||
|
||
case 'B':
|
||
case 'b':
|
||
return 13;
|
||
|
||
case 'C':
|
||
case 'c':
|
||
return 14;
|
||
|
||
case 'D':
|
||
case 'd':
|
||
return 15;
|
||
|
||
case 'F':
|
||
case 'f':
|
||
return 16;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
static void InitIPAddrInfo(PIP_ADDR_INFO pAddrInfo)
|
||
{
|
||
if(pAddrInfo)
|
||
{
|
||
memset(pAddrInfo->ethAddr, 0xFF, ETH_ALEN);
|
||
pAddrInfo->ipAddr = 0;
|
||
pAddrInfo->ipPort = -1;
|
||
}
|
||
}
|
||
|
||
static void InitChDTMFRecvInfoBuf(PCH_DTMF_INFO pChDtmf, int i)
|
||
{
|
||
pChDtmf->dtmfRecvBuf[i].refStatus = RFC2833_RECV_IDLE;
|
||
pChDtmf->dtmfRecvBuf[i].dtmfValue = 0xFF;
|
||
pChDtmf->dtmfRecvBuf[i].refCount = 0;
|
||
pChDtmf->dtmfRecvBuf[i].synIdentifier = 0;
|
||
pChDtmf->dtmfRecvBuf[i].timeStamps = 0;
|
||
pChDtmf->dtmfRecvBuf[i].seqNumber = 0;
|
||
pChDtmf->dtmfRecvBuf[i].payloadType = 0xFF;
|
||
}
|
||
|
||
|
||
static void InitChDTMFRecvInfo(PCH_DTMF_INFO pChDtmf)
|
||
{
|
||
int i = 0;
|
||
|
||
for(i = 0; i < MAX_DTMF_RECV_BUF; i++)
|
||
{
|
||
// pChDtmf->dtmfRecvValue[i] = 0xFF;
|
||
pChDtmf->dtmfRecvBuf[i].refStatus = RFC2833_RECV_IDLE;
|
||
pChDtmf->dtmfRecvBuf[i].dtmfValue = 0xFF;
|
||
pChDtmf->dtmfRecvBuf[i].refCount = 0;
|
||
pChDtmf->dtmfRecvBuf[i].synIdentifier = 0;
|
||
pChDtmf->dtmfRecvBuf[i].timeStamps = 0;
|
||
pChDtmf->dtmfRecvBuf[i].seqNumber = 0;
|
||
pChDtmf->dtmfRecvBuf[i].payloadType = 0xFF;
|
||
}
|
||
}
|
||
|
||
static void InitChDTMFInfo(PCH_DTMF_INFO pChDtmf)
|
||
{
|
||
if(pChDtmf)
|
||
{
|
||
pChDtmf->refSendMask = 0;
|
||
pChDtmf->drvRfc2833ChkVal = 0;
|
||
pChDtmf->nicRfc2833ChkVal = 0;
|
||
pChDtmf->dtmfSendBuf.dtmfValue = 0xFF;
|
||
pChDtmf->dtmfSendBuf.refCount = 7;
|
||
pChDtmf->dtmfSendBuf.refStatus = RFC2833_SEND_IDLE;
|
||
pChDtmf->dtmfSendBuf.synIdentifier = 0;
|
||
pChDtmf->dtmfSendBuf.timeStamps = 0;
|
||
pChDtmf->dtmfSendBuf.payloadType = 101;
|
||
pChDtmf->curSendIndex = -1;
|
||
pChDtmf->srcIp = 0;
|
||
pChDtmf->srcPort = 0;
|
||
|
||
InitChDTMFRecvInfo(pChDtmf);
|
||
}
|
||
}
|
||
|
||
static void InitChPortInfo(PCH_PORT_INFO pPort, PORT_TYPE portType)
|
||
{
|
||
if(pPort)
|
||
{
|
||
pPort->portType = portType;
|
||
pPort->ipPort = -1;
|
||
pPort->chStatus = CH_STATUS_UNKONWN;
|
||
pPort->chLinkInfo.linkCh = -1;
|
||
}
|
||
}
|
||
|
||
static void InitSIPChDetial(PSIP_CH_DETIAL pCh)
|
||
{
|
||
int rlt = 0;
|
||
|
||
if(pCh)
|
||
{
|
||
memset(pCh, 0, sizeof(SIP_CH_DETIAL));
|
||
|
||
pCh->chId = -1;
|
||
pCh->sipETHId = -1;
|
||
|
||
InitChPortInfo(&pCh->portB2B, PORT_TYPE_B2B);
|
||
InitChPortInfo(&pCh->portIPR, PORT_TYPE_IPR);
|
||
InitChPortInfo(&pCh->portT38, PORT_TYPE_T38);
|
||
InitChPortInfo(&pCh->portRTP, PORT_TYPE_SIPRTP);
|
||
InitChDTMFInfo(&pCh->rfc2833DTMF);
|
||
|
||
kfifo_free(&pCh->dtmfSendFifo);
|
||
|
||
rlt = kfifo_alloc(&pCh->dtmfSendFifo, MAX_DTMF_SEND_BUF, GFP_KERNEL);
|
||
|
||
kfifo_free(&pCh->dtmfRecvFifo);
|
||
|
||
rlt = kfifo_alloc(&pCh->dtmfRecvFifo, MAX_DTMF_RECV_BUF * 4, GFP_KERNEL);
|
||
}
|
||
}
|
||
|
||
int config_sip_ch(unsigned int maxSIPCh,
|
||
unsigned int portBase,
|
||
unsigned int portStep,
|
||
unsigned int rtpPortBase)
|
||
{
|
||
int i = 0;
|
||
|
||
if(maxSIPCh > MAX_SIP_CH)
|
||
{
|
||
maxSIPCh = MAX_SIP_CH;
|
||
}
|
||
|
||
if(maxSIPCh > 0)
|
||
{
|
||
for(i = 0; i < maxSIPCh; i++)
|
||
{
|
||
InitSIPChDetial(&g_SIPChInfo.pSipChDetial[i]);
|
||
|
||
g_SIPChInfo.pSipChDetial[i].sipDebug.ethx_rfc2833_error = 0;
|
||
}
|
||
|
||
|
||
|
||
g_SIPChInfo.iTotalCh = maxSIPCh;
|
||
g_SIPChInfo.iPortBase = portBase;
|
||
g_SIPChInfo.iPortStep = portStep;
|
||
g_SIPChInfo.iRTPPortBase = rtpPortBase;
|
||
|
||
return 0;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
EXPORT_SYMBOL(config_sip_ch);
|
||
|
||
int config_sip_port(unsigned int chId,
|
||
unsigned int ethId,
|
||
unsigned short chPort,
|
||
unsigned short sipChPort)
|
||
{
|
||
if(ethId == g_spbxNetId)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if(g_NICInfo[ethId] == NULL)
|
||
{
|
||
return -2;
|
||
}
|
||
|
||
if(g_SIPChInfo.pSipChDetial != NULL
|
||
&& chId < g_SIPChInfo.iTotalCh)
|
||
{
|
||
PSIP_CH_DETIAL pChDetail = g_SIPChInfo.pSipChDetial + chId;
|
||
|
||
pChDetail->chId = chId;
|
||
pChDetail->sipETHId = ethId;
|
||
|
||
pChDetail->portIPR.ipPort = chPort + 0;
|
||
pChDetail->portB2B.ipPort = chPort + 1;
|
||
pChDetail->portT38.ipPort = chPort + 2;
|
||
pChDetail->portRTP.ipPort = sipChPort;
|
||
|
||
pChDetail->portIPR.chStatus = CH_STATUS_CONFIGUREED;
|
||
pChDetail->portB2B.chStatus = CH_STATUS_CONFIGUREED;
|
||
pChDetail->portT38.chStatus = CH_STATUS_CONFIGUREED;
|
||
pChDetail->portRTP.chStatus = CH_STATUS_CONFIGUREED;
|
||
|
||
return 0;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
EXPORT_SYMBOL(config_sip_port);
|
||
|
||
int eth_sip_link(unsigned int sipCh,
|
||
__be32 dst_ipAddr,
|
||
__be16 dst_ipPort,
|
||
__be16 stun_tags)
|
||
{
|
||
PSIP_CH_DETIAL pCh = NULL;
|
||
unsigned char macAddr[24];
|
||
|
||
if(g_SIPChInfo.pSipChDetial == NULL || sipCh >= g_SIPChInfo.iTotalCh)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
pCh = &g_SIPChInfo.pSipChDetial[sipCh];
|
||
|
||
if(g_NICInfo[pCh->sipETHId] == NULL)
|
||
{
|
||
return -2;
|
||
}
|
||
|
||
if(g_NICInfo[pCh->sipETHId]->opened_ref == 0)
|
||
{
|
||
return -3;
|
||
}
|
||
|
||
if(pCh->portRTP.chStatus == CH_STATUS_UNKONWN)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
make_arp_request(pCh->sipETHId, htonl(dst_ipAddr));
|
||
get_mac_form_ip(macAddr, pCh->sipETHId, htonl(dst_ipAddr), 21);
|
||
|
||
memset(pCh->portRTP.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN);
|
||
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipAddr = dst_ipAddr;
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipPort = dst_ipPort;
|
||
pCh->portRTP.chLinkInfo.toRTPCh.isUpdate = 0;
|
||
pCh->portRTP.chLinkInfo.fromRTPCh.isUpdate = 0;
|
||
pCh->portRTP.chLinkInfo.stunTags = stun_tags;
|
||
|
||
pCh->portRTP.chStatus = CH_STATUS_LINKED;
|
||
|
||
pCh->sipDebug.cnt_ethx_recv = 0;
|
||
pCh->sipDebug.cnt_ethx_2_eth0 = 0;
|
||
pCh->sipDebug.mask_ethx_2_eth0 = 0;
|
||
|
||
pCh->sipDebug.ethx_seq_index = 0;
|
||
pCh->sipDebug.ethx_seq_error = 0;
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(eth_sip_link);
|
||
|
||
int eth_link(unsigned int chId, PORT_TYPE portType,
|
||
__be32 dst_ipAddr,
|
||
__be16 dst_ipPort)
|
||
{
|
||
|
||
PSIP_CH_DETIAL pCh = NULL;
|
||
unsigned char macAddr[24];
|
||
|
||
if(g_SIPChInfo.pSipChDetial == NULL || chId >= g_SIPChInfo.iTotalCh)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
pCh = &g_SIPChInfo.pSipChDetial[chId];
|
||
|
||
if(g_NICInfo[pCh->sipETHId] == NULL)
|
||
{
|
||
return -2;
|
||
}
|
||
|
||
if(g_NICInfo[pCh->sipETHId]->opened_ref == 0)
|
||
{
|
||
return -3;
|
||
}
|
||
|
||
make_arp_request(g_spbxNetId, htonl(dst_ipAddr));
|
||
get_mac_form_ip(macAddr, g_spbxNetId, htonl(dst_ipAddr), 20);
|
||
|
||
if(portType == PORT_TYPE_B2B)
|
||
{
|
||
memset(pCh->portB2B.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN);
|
||
|
||
pCh->portB2B.chLinkInfo.dstTarget.ipAddr = dst_ipAddr;
|
||
pCh->portB2B.chLinkInfo.dstTarget.ipPort = dst_ipPort;
|
||
pCh->portB2B.chLinkInfo.toRTPCh.isUpdate = 0;
|
||
pCh->portB2B.chLinkInfo.fromRTPCh.isUpdate = 0;
|
||
|
||
pCh->portB2B.chStatus = CH_STATUS_LINKED;
|
||
}
|
||
else if(portType == PORT_TYPE_IPR)
|
||
{
|
||
memset(pCh->portIPR.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN);
|
||
pCh->portIPR.chLinkInfo.dstTarget.ipAddr = dst_ipAddr;
|
||
pCh->portIPR.chLinkInfo.dstTarget.ipPort = dst_ipPort;
|
||
pCh->portIPR.chLinkInfo.toRTPCh.isUpdate = 0;
|
||
pCh->portIPR.chLinkInfo.fromRTPCh.isUpdate = 0;
|
||
|
||
pCh->portIPR.chStatus = CH_STATUS_LINKED;
|
||
}
|
||
else if(portType == PORT_TYPE_T38)
|
||
{
|
||
memset(pCh->portT38.chLinkInfo.dstTarget.ethAddr, 0xFF, ETH_ALEN);
|
||
pCh->portT38.chLinkInfo.dstTarget.ipAddr = dst_ipAddr;
|
||
pCh->portT38.chLinkInfo.dstTarget.ipPort = dst_ipPort;
|
||
pCh->portT38.chLinkInfo.toRTPCh.isUpdate = 0;
|
||
pCh->portT38.chLinkInfo.fromRTPCh.isUpdate = 0;
|
||
|
||
pCh->portT38.chStatus = CH_STATUS_LINKED;
|
||
}
|
||
|
||
kfifo_reset(&pCh->dtmfSendFifo);
|
||
kfifo_reset(&pCh->dtmfRecvFifo);
|
||
|
||
InitChDTMFInfo(&pCh->rfc2833DTMF);
|
||
|
||
pCh->sipDebug.cnt_eth0_2_ethx = 0;
|
||
pCh->sipDebug.cnt_eth0_recv = 0;
|
||
pCh->sipDebug.mask_eth0_2_ethx = 0;
|
||
|
||
pCh->sipDebug.eth0_seq_index = 0;
|
||
pCh->sipDebug.eth0_seq_error = 0;
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(eth_link);
|
||
|
||
static void InitSIPLinkReset(PCH_PORT_INFO pPort)
|
||
{
|
||
if(pPort)
|
||
{
|
||
pPort->chStatus = CH_STATUS_IDLE;
|
||
pPort->chLinkInfo.linkCh = -1;
|
||
|
||
InitIPAddrInfo(&pPort->chLinkInfo.dstTarget);
|
||
|
||
pPort->chLinkInfo.fromRTPCh.isUpdate = 0;
|
||
pPort->chLinkInfo.toRTPCh.isUpdate = 0;
|
||
pPort->chLinkInfo.stunTags = 0;
|
||
|
||
memset(&pPort->chLinkInfo.fromRTPCh.headValue, 0, sizeof(PACKAGE_HEAD));
|
||
memset(&pPort->chLinkInfo.toRTPCh.headValue, 0, sizeof(PACKAGE_HEAD));
|
||
|
||
memset(pPort->chLinkInfo.dstTarget.ethAddr, 0xFF, 6);
|
||
}
|
||
}
|
||
|
||
int eth_unlink(unsigned int chId, int portType)
|
||
{
|
||
PSIP_CH_DETIAL pCh = NULL;
|
||
|
||
if(g_SIPChInfo.pSipChDetial == NULL || chId >= g_SIPChInfo.iTotalCh)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
pCh = &g_SIPChInfo.pSipChDetial[chId];
|
||
|
||
switch(portType)
|
||
{
|
||
case PORT_TYPE_IPR:
|
||
if(pCh->portIPR.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
InitSIPLinkReset(&pCh->portIPR);
|
||
}
|
||
|
||
break;
|
||
|
||
case PORT_TYPE_B2B:
|
||
if(pCh->portB2B.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
InitSIPLinkReset(&pCh->portB2B);
|
||
}
|
||
|
||
break;
|
||
|
||
case PORT_TYPE_T38:
|
||
if(pCh->portT38.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
InitSIPLinkReset(&pCh->portT38);
|
||
}
|
||
|
||
break;
|
||
|
||
case PORT_TYPE_SIPRTP:
|
||
if(pCh->portRTP.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
InitSIPLinkReset(&pCh->portRTP);
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
kfifo_reset(&pCh->dtmfSendFifo);
|
||
kfifo_reset(&pCh->dtmfRecvFifo);
|
||
|
||
InitChDTMFInfo(&pCh->rfc2833DTMF);
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(eth_unlink);
|
||
|
||
int sip_recv_dtmf(unsigned int sipCh)
|
||
{
|
||
char value = -1, rlt = 0;
|
||
PSIP_CH_DETIAL pCh = NULL;
|
||
|
||
if(g_SIPChInfo.pSipChDetial == NULL || sipCh >= g_SIPChInfo.iTotalCh)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
pCh = &g_SIPChInfo.pSipChDetial[sipCh];
|
||
|
||
if(pCh->portRTP.chStatus != CH_STATUS_LINKED)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
#ifdef PLATFORM_MV78460
|
||
rlt = kfifo_get(&pCh->dtmfRecvFifo, &value);
|
||
|
||
if(rlt != 0)
|
||
#else
|
||
rlt = kfifo_out(&pCh->dtmfRecvFifo, &value, 4);
|
||
|
||
if(rlt == 4)
|
||
#endif
|
||
{
|
||
if(g_CheckRFC2833)
|
||
{
|
||
if(pCh->rfc2833DTMF.drvRfc2833ChkVal != value)
|
||
{
|
||
pCh->sipDebug.drv_rcv_rfc2833_error++;
|
||
|
||
if(sipCh == 0 && g_DebugRFC2833 != 0)
|
||
{
|
||
printk("ch %d rcv 2833 Error: rcv %d need %d\n",
|
||
sipCh,
|
||
value, pCh->rfc2833DTMF.drvRfc2833ChkVal);
|
||
}
|
||
}
|
||
|
||
if(value == 11)
|
||
{
|
||
pCh->rfc2833DTMF.drvRfc2833ChkVal = 0;
|
||
}
|
||
else
|
||
{
|
||
pCh->rfc2833DTMF.drvRfc2833ChkVal++;
|
||
}
|
||
}
|
||
|
||
pCh->sipDebug.drv_rcv_rfc2833_recv++;
|
||
|
||
return (int)g_DTMFTable[value & 0x0F];
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
}
|
||
EXPORT_SYMBOL(sip_recv_dtmf);
|
||
|
||
int sip_send_dtmf(unsigned int sipCh, char* pDtmfChar, int numChars)
|
||
{
|
||
int i = 0;
|
||
PSIP_CH_DETIAL pCh = NULL;
|
||
|
||
if(g_SIPChInfo.pSipChDetial == NULL || sipCh >= g_SIPChInfo.iTotalCh
|
||
|| numChars > MAX_DTMF_SEND_BUF)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if(pDtmfChar == NULL)
|
||
{
|
||
if(kfifo_is_empty(&pCh->dtmfSendFifo))
|
||
{
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
return kfifo_len(&pCh->dtmfSendFifo);
|
||
}
|
||
}
|
||
|
||
pCh = &g_SIPChInfo.pSipChDetial[sipCh];
|
||
|
||
pCh->rfc2833DTMF.dtmfSendBuf.refStatus = RFC2833_SEND_IDLE;
|
||
|
||
//kfifo_reset(&pCh->dtmfSendFifo);
|
||
|
||
// GetDTMFValue
|
||
|
||
for(i = 0; i < numChars; i++)
|
||
{
|
||
char dtmf = GetDTMFValue(pDtmfChar[i]);
|
||
|
||
#ifdef PLATFORM_MV78460
|
||
if(kfifo_put(&pCh->dtmfSendFifo, &dtmf) == 0)
|
||
#else
|
||
if(kfifo_in(&pCh->dtmfSendFifo, &dtmf, 1) != 1)
|
||
#endif
|
||
{
|
||
pCh->sipDebug.ethx_rfc2833_snd_lost++;
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
return i;
|
||
}
|
||
EXPORT_SYMBOL(sip_send_dtmf);
|
||
|
||
static int recv_dtmf_from_sip(int sipCh, struct sk_buff* skb)
|
||
{
|
||
unsigned short seqNumber;
|
||
unsigned int timeStamp, syncId;
|
||
unsigned char dtmfIndex;
|
||
unsigned char endFlag;
|
||
int i = 0;
|
||
int bRecved = RECV_RFC2833_RECV_UNRECV;
|
||
struct iphdr* iphdr = (struct iphdr*)skb->data;
|
||
struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4);
|
||
|
||
PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + sipCh;
|
||
|
||
if(pCh->portRTP.chLinkInfo.stunTags != 0)
|
||
{
|
||
dtmfIndex = *(unsigned char*)(skb->data + 40 + 4);
|
||
endFlag = *(unsigned char*)(skb->data + 41 + 4);
|
||
seqNumber = ntohs(*(unsigned short*)(skb->data + 30 + 4));
|
||
timeStamp = ntohl(*(unsigned int*)(skb->data + 32 + 4));
|
||
syncId = ntohl(*(unsigned int*)(skb->data + 36 + 4));
|
||
}
|
||
else
|
||
{
|
||
dtmfIndex = *(unsigned char*)(skb->data + 40);
|
||
endFlag = *(unsigned char*)(skb->data + 41);
|
||
seqNumber = ntohs(*(unsigned short*)(skb->data + 30));
|
||
timeStamp = ntohl(*(unsigned int*)(skb->data + 32));
|
||
syncId = ntohl(*(unsigned int*)(skb->data + 36));
|
||
}
|
||
|
||
// ?????RFC2833
|
||
for(i = 0; i < MAX_DTMF_RECV_BUF; i++)
|
||
{
|
||
if(pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus != RFC2833_RECV_IDLE
|
||
&& pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber != 0)
|
||
{
|
||
if(pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber + 1000 < seqNumber
|
||
|| (endFlag & 0x80))
|
||
{
|
||
InitChDTMFRecvInfoBuf(&pCh->rfc2833DTMF, i);
|
||
}
|
||
}
|
||
|
||
// <20>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD>
|
||
if(pCh->rfc2833DTMF.dtmfRecvBuf[i].synIdentifier == syncId
|
||
&& (endFlag & 0x80))
|
||
{
|
||
InitChDTMFRecvInfoBuf(&pCh->rfc2833DTMF, i);
|
||
|
||
return RECV_RFC2833_RECV_DROP;
|
||
}
|
||
}
|
||
|
||
for(i = 0; i < MAX_DTMF_RECV_BUF; i++)
|
||
{
|
||
// ͬһ<CDAC><D2BB>DTMF
|
||
if(pCh->rfc2833DTMF.dtmfRecvBuf[i].synIdentifier == syncId
|
||
&& pCh->rfc2833DTMF.dtmfRecvBuf[i].timeStamps == timeStamp
|
||
&& abs(seqNumber - pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber) < 100
|
||
)
|
||
{
|
||
if(pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus == RFC2833_RECVING)
|
||
{
|
||
if(pCh->rfc2833DTMF.dtmfRecvBuf[i].dtmfValue == dtmfIndex)
|
||
{
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber = seqNumber;
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].refCount++;
|
||
bRecved = RECV_RFC2833_RECV_REP;
|
||
|
||
if((pCh->rfc2833DTMF.dtmfRecvBuf[i].refCount >= 2)
|
||
&& (pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus != RFC2833_RECV_LOCK))
|
||
{
|
||
#ifdef PLATFORM_MV78460
|
||
if(kfifo_put(&pCh->dtmfRecvFifo, &dtmfIndex) == 0)
|
||
#else
|
||
if(kfifo_in(&pCh->dtmfRecvFifo, &dtmfIndex, 4) != 4)
|
||
#endif
|
||
{
|
||
printk("ch %d RFC2833 FIFO Full, lost dtmf %c(%d)\n",
|
||
sipCh, g_DTMFTable[dtmfIndex], dtmfIndex);
|
||
|
||
pCh->sipDebug.ethx_rfc2833_rcv_lost++;
|
||
}
|
||
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus = RFC2833_RECV_LOCK;
|
||
|
||
pCh->sipDebug.ethx_rfc2833_recv++;
|
||
|
||
if(sipCh == 0 && g_DebugRFC2833 != 0)
|
||
{
|
||
printk("ch %d recv rfc2833 %c(%d) ssrc = 0x%08X time = 0x%08X seq = %d \
|
||
ip = 0x%08X, Port = %d, dstip = 0x%08X, dstPort = %d, len = %d \
|
||
link_ip = 0x%08X, link_port = %d\n",
|
||
sipCh, g_DTMFTable[dtmfIndex], dtmfIndex,
|
||
syncId, timeStamp, seqNumber,
|
||
iphdr->saddr, udphdr->source,
|
||
iphdr->daddr, udphdr->dest, iphdr->tot_len,
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipAddr,
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipPort);
|
||
}
|
||
|
||
if(g_CheckRFC2833)
|
||
{
|
||
if(pCh->rfc2833DTMF.nicRfc2833ChkVal != dtmfIndex)
|
||
{
|
||
pCh->sipDebug.ethx_rfc2833_error++;
|
||
|
||
if(sipCh == 0 && g_DebugRFC2833 != 0)
|
||
{
|
||
printk("ch %d array %d rcv 2833 Error: rcv %d need %d, \
|
||
ip = 0x%08X, Port = %d, srcip = 0x%08X, srcPort = %d, \
|
||
link_ip = 0x%08X, link_port = %d\
|
||
ssrc = 0x%08X time = 0x%08X seq = %d\n",
|
||
sipCh,
|
||
i,
|
||
dtmfIndex,
|
||
pCh->rfc2833DTMF.nicRfc2833ChkVal,
|
||
iphdr->saddr, udphdr->source,
|
||
pCh->rfc2833DTMF.srcIp,
|
||
pCh->rfc2833DTMF.srcPort,
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipAddr,
|
||
pCh->portRTP.chLinkInfo.dstTarget.ipPort,
|
||
syncId, timeStamp, seqNumber);
|
||
}
|
||
}
|
||
|
||
if(pCh->rfc2833DTMF.nicRfc2833ChkVal == 11)
|
||
{
|
||
pCh->rfc2833DTMF.nicRfc2833ChkVal = 0;
|
||
}
|
||
else
|
||
{
|
||
pCh->rfc2833DTMF.nicRfc2833ChkVal++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
bRecved = RECV_RFC2833_RECV_DROP;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
bRecved = RECV_RFC2833_RECV_DROP;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(bRecved == RECV_RFC2833_RECV_UNRECV)
|
||
{
|
||
for(i = 0; i < MAX_DTMF_RECV_BUF; i++)
|
||
{
|
||
if(pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus == RFC2833_RECV_IDLE
|
||
&& (endFlag & 0x80) == 0)
|
||
{
|
||
InitChDTMFRecvInfoBuf(&pCh->rfc2833DTMF, i);
|
||
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].seqNumber = seqNumber;
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].synIdentifier = syncId;
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].timeStamps = timeStamp;
|
||
pCh->rfc2833DTMF.srcIp = iphdr->saddr;
|
||
pCh->rfc2833DTMF.srcPort = udphdr->source;
|
||
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].dtmfValue = dtmfIndex;
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].refCount = 1;
|
||
pCh->rfc2833DTMF.dtmfRecvBuf[i].refStatus = RFC2833_RECVING;
|
||
|
||
bRecved = RECV_RFC2833_RECV_NEW;
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return bRecved;
|
||
}
|
||
|
||
static int CheckMacAddress(PCH_PORT_INFO pPort, ETH_INTERFACE ethId)
|
||
{
|
||
if(pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF
|
||
)
|
||
{
|
||
return get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr,
|
||
ethId,
|
||
htonl(pPort->chLinkInfo.dstTarget.ipAddr), 30);
|
||
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static struct sk_buff* switch_to_sip(int sipCh,
|
||
struct sk_buff* skb,
|
||
ETH_INTERFACE ethId,
|
||
PCH_PORT_INFO pPort)
|
||
{
|
||
PPACKAGE_HEAD pHead = NULL;
|
||
PRFC2833_INFO pDTMF = NULL;
|
||
unsigned char* pPayload = NULL;
|
||
|
||
PSIP_CH_DETIAL pCh = &g_SIPChInfo.pSipChDetial[sipCh];
|
||
struct sk_buff* skbSIP = skb_clone(skb, GFP_ATOMIC);
|
||
PNIC_PRIVATE pEthInfo = g_NICInfo[ethId];
|
||
|
||
if(skbSIP == NULL)
|
||
{
|
||
return NULL;
|
||
|
||
}
|
||
|
||
dev_kfree_skb_any(skb);
|
||
skbSIP->dev = pEthInfo->ndev;
|
||
|
||
eth_header(skbSIP, pEthInfo->ndev, ETH_P_IP, NULL, NULL, skbSIP->len);
|
||
pHead = (PPACKAGE_HEAD)skbSIP->data;
|
||
|
||
if(pPort->chLinkInfo.toRTPCh.isUpdate == 0)
|
||
{
|
||
if(pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF
|
||
)
|
||
{
|
||
get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr,
|
||
ethId,
|
||
htonl(pPort->chLinkInfo.dstTarget.ipAddr), 5);
|
||
}
|
||
|
||
memcpy(pHead->ethHead.h_dest,
|
||
pPort->chLinkInfo.dstTarget.ethAddr, ETH_ALEN);
|
||
|
||
pHead->ipHead.saddr = htonl(pEthInfo->chIpAddr);
|
||
pHead->ipHead.daddr = htonl(pPort->chLinkInfo.dstTarget.ipAddr);
|
||
pHead->udpHead.source = htons(g_SIPChInfo.iRTPPortBase + sipCh);
|
||
pHead->udpHead.dest = htons(pPort->chLinkInfo.dstTarget.ipPort);
|
||
|
||
memcpy(&pPort->chLinkInfo.toRTPCh.headValue,
|
||
pHead,
|
||
sizeof(PACKAGE_HEAD));
|
||
|
||
pPort->chLinkInfo.toRTPCh.isUpdate = 1;
|
||
}
|
||
else
|
||
{
|
||
PACKAGE_HEAD ipHead = *pHead;
|
||
|
||
if((pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF)
|
||
|| pCh->sipDebug.cnt_eth0_2_ethx % 1000 == 0
|
||
)
|
||
{
|
||
if(get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr,
|
||
ethId,
|
||
htonl(pPort->chLinkInfo.dstTarget.ipAddr), 6) == 0)
|
||
{
|
||
|
||
memcpy(&pPort->chLinkInfo.toRTPCh.headValue,
|
||
pPort->chLinkInfo.dstTarget.ethAddr,
|
||
ETH_ALEN);
|
||
}
|
||
}
|
||
|
||
memcpy(pHead,
|
||
&pPort->chLinkInfo.toRTPCh.headValue,
|
||
sizeof(PACKAGE_HEAD));
|
||
|
||
pHead->ipHead.id = ipHead.ipHead.id;
|
||
pHead->ipHead.frag_off = ipHead.ipHead.frag_off;
|
||
pHead->ipHead.tot_len = ipHead.ipHead.tot_len;
|
||
pHead->udpHead.len = ipHead.udpHead.len;
|
||
}
|
||
|
||
if(!kfifo_is_empty(&pCh->dtmfSendFifo))
|
||
{
|
||
if(pCh->rfc2833DTMF.dtmfSendBuf.refStatus == RFC2833_SEND_IDLE)
|
||
{
|
||
#ifdef PLATFORM_MV78460
|
||
int rlt = kfifo_get(&pCh->dtmfSendFifo,
|
||
&pCh->rfc2833DTMF.dtmfSendBuf.dtmfValue);
|
||
|
||
if(rlt != 0)
|
||
#else
|
||
int rlt = kfifo_out(&pCh->dtmfSendFifo,
|
||
&pCh->rfc2833DTMF.dtmfSendBuf.dtmfValue, 1);
|
||
|
||
if(rlt == 1)
|
||
#endif
|
||
{
|
||
pCh->rfc2833DTMF.dtmfSendBuf.synIdentifier = 0;
|
||
pCh->rfc2833DTMF.dtmfSendBuf.timeStamps = 0;
|
||
pCh->rfc2833DTMF.dtmfSendBuf.refCount = 7;
|
||
|
||
pCh->rfc2833DTMF.dtmfSendBuf.payloadType = 101;
|
||
pCh->rfc2833DTMF.dtmfSendBuf.refStatus = RFC2833_SEND_BEGING;
|
||
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
if(pCh->rfc2833DTMF.dtmfSendBuf.refStatus != RFC2833_SEND_IDLE)
|
||
{
|
||
pDTMF = &pCh->rfc2833DTMF.dtmfSendBuf;
|
||
|
||
pPayload = (unsigned char*)(skbSIP->data + 42);
|
||
|
||
pHead->udpHead.len = htons(24);
|
||
pHead->udpHead.check = 0;
|
||
pHead->ipHead.tot_len = htons(44);
|
||
pPayload[1] = 101;
|
||
|
||
if(pDTMF->refCount == 7)
|
||
{
|
||
pPayload[1] |= 1 << 7;
|
||
pDTMF->timeStamps = *(int*)(&pPayload[4]);
|
||
}
|
||
|
||
memcpy(&pPayload[4], &pDTMF->timeStamps, 4);
|
||
|
||
pPayload[12] = pDTMF->dtmfValue;
|
||
pPayload[13] = 0x0a;
|
||
|
||
if(pDTMF->refCount <= 3)
|
||
{
|
||
pPayload[13] |= 1 << 7;
|
||
pPayload[2] = (pCh->rfc2833DTMF.dtmfSendBuf.seqNumber + 1) >> 8;
|
||
pPayload[3] = (pCh->rfc2833DTMF.dtmfSendBuf.seqNumber + 1) & 0xFF;
|
||
pPayload[14] = ((8 - 3) * 80) >> 8;
|
||
pPayload[15] = ((8 - 3) * 80) & 0xFF;
|
||
}
|
||
else
|
||
{
|
||
pCh->rfc2833DTMF.dtmfSendBuf.seqNumber = ntohs(*(unsigned short*)(&pPayload[2]));
|
||
pPayload[14] = ((8 - pDTMF->refCount) * 80) >> 8;
|
||
pPayload[15] = ((8 - pDTMF->refCount) * 80) & 0xFF;
|
||
}
|
||
|
||
// pskb_trim(skbSIP, skbSIP->len - 76);
|
||
pskb_trim(skbSIP, 58);
|
||
|
||
pDTMF->refCount--;
|
||
|
||
if(pDTMF->refCount > 0)
|
||
{
|
||
pDTMF->refStatus = RFC2833_SENDING;
|
||
}
|
||
else
|
||
{
|
||
pDTMF->refStatus = RFC2833_SEND_IDLE;
|
||
|
||
if(pCh->rfc2833DTMF.refSendMask > 0)
|
||
{
|
||
pCh->rfc2833DTMF.refSendMask &= ~(pCh->rfc2833DTMF.curSendIndex << 1);
|
||
}
|
||
|
||
pCh->rfc2833DTMF.refSendMask = 0;
|
||
}
|
||
}
|
||
|
||
if(pCh->portRTP.chLinkInfo.stunTags != 0)
|
||
{
|
||
unsigned short* pTags = NULL;
|
||
|
||
skb_push(skbSIP, 4);
|
||
memmove(skbSIP->data, pHead, 42);
|
||
|
||
pHead = (PPACKAGE_HEAD)skbSIP->data;
|
||
|
||
pTags = (unsigned short*)(skbSIP->data + 42);
|
||
|
||
*pTags = htons(pCh->portRTP.chLinkInfo.stunTags);
|
||
pTags++;
|
||
*pTags = htons(pHead->udpHead.len - 8);
|
||
|
||
pHead->udpHead.len += htons(4);
|
||
pHead->ipHead.tot_len += htons(4);
|
||
}
|
||
|
||
pHead->udpHead.check = 0;
|
||
pHead->ipHead.check = 0;
|
||
pHead->ipHead.check =
|
||
get_ip_checksum((unsigned short*)&pHead->ipHead, 20);
|
||
|
||
if(eth_tx_skb(skbSIP, pEthInfo->ndev) == NETDEV_TX_OK)
|
||
{
|
||
pCh->sipDebug.cnt_eth0_2_ethx++;
|
||
}
|
||
|
||
return skbSIP;
|
||
}
|
||
|
||
static struct sk_buff* switch_from_sip(int sipCh,
|
||
struct sk_buff* skb,
|
||
PCH_PORT_INFO pPort)
|
||
{
|
||
PPACKAGE_HEAD pHead = NULL;
|
||
struct sk_buff* skbSIP = skb_clone(skb, GFP_ATOMIC);
|
||
PNIC_PRIVATE pEthInfo = g_NICInfo[g_spbxNetId];
|
||
PSIP_CH_DETIAL pCh = &g_SIPChInfo.pSipChDetial[sipCh];
|
||
|
||
if(skbSIP == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
dev_kfree_skb_any(skb);
|
||
skbSIP->dev = pEthInfo->ndev;
|
||
|
||
eth_header(skbSIP, pEthInfo->ndev, ETH_P_IP, NULL, NULL, skb->len);
|
||
pHead = (PPACKAGE_HEAD)skbSIP->data;
|
||
|
||
if(pPort->chLinkInfo.fromRTPCh.isUpdate == 0)
|
||
{
|
||
if(pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF
|
||
)
|
||
{
|
||
get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr,
|
||
g_spbxNetId,
|
||
htonl(pPort->chLinkInfo.dstTarget.ipAddr), 7);
|
||
}
|
||
|
||
memcpy(pHead->ethHead.h_dest,
|
||
pPort->chLinkInfo.dstTarget.ethAddr, ETH_ALEN);
|
||
|
||
pHead->ipHead.saddr = htonl(pEthInfo->chIpAddr);
|
||
pHead->ipHead.daddr = htonl(pPort->chLinkInfo.dstTarget.ipAddr);
|
||
pHead->udpHead.source = htons(pPort->ipPort);
|
||
pHead->udpHead.dest = htons(pPort->chLinkInfo.dstTarget.ipPort);
|
||
|
||
memcpy(&pPort->chLinkInfo.fromRTPCh.headValue,
|
||
pHead,
|
||
sizeof(PACKAGE_HEAD));
|
||
|
||
pPort->chLinkInfo.fromRTPCh.isUpdate = 1;
|
||
}
|
||
else
|
||
{
|
||
PACKAGE_HEAD ipHead = *pHead;
|
||
|
||
if((pPort->chLinkInfo.dstTarget.ethAddr[0] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[1] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[2] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[3] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[4] == 0xFF
|
||
&& pPort->chLinkInfo.dstTarget.ethAddr[5] == 0xFF)
|
||
|| pCh->sipDebug.cnt_ethx_2_eth0 % 1000 == 0
|
||
)
|
||
{
|
||
if(get_mac_form_ip(pPort->chLinkInfo.dstTarget.ethAddr,
|
||
g_spbxNetId,
|
||
htonl(pPort->chLinkInfo.dstTarget.ipAddr), 8) == 0)
|
||
{
|
||
memcpy(&pPort->chLinkInfo.fromRTPCh.headValue,
|
||
pPort->chLinkInfo.dstTarget.ethAddr,
|
||
ETH_ALEN);
|
||
}
|
||
}
|
||
|
||
memcpy(pHead,
|
||
&pPort->chLinkInfo.fromRTPCh.headValue,
|
||
sizeof(PACKAGE_HEAD));
|
||
|
||
pHead->ipHead.id = ipHead.ipHead.id;
|
||
pHead->ipHead.frag_off = ipHead.ipHead.frag_off;
|
||
pHead->ipHead.tot_len = ipHead.ipHead.tot_len;
|
||
pHead->udpHead.len = ipHead.udpHead.len;
|
||
}
|
||
|
||
if(pCh->portRTP.chLinkInfo.stunTags != 0)
|
||
{
|
||
unsigned short* pTags = (unsigned short*)(skbSIP->data + 42);
|
||
unsigned short* pLen = (unsigned short*)(skbSIP->data + 44);
|
||
|
||
if(*pTags == pCh->portRTP.chLinkInfo.stunTags
|
||
&& *pLen == pHead->udpHead.len - 12)
|
||
{
|
||
memcpy(&skbSIP->data[42], &skbSIP->data[46], *pLen);
|
||
pskb_trim(skbSIP, skbSIP->len - 4);
|
||
pHead->udpHead.len -= 4;
|
||
pHead->ipHead.tot_len -= 4;
|
||
}
|
||
}
|
||
|
||
pHead->udpHead.check = 0;
|
||
pHead->ipHead.check = 0;
|
||
pHead->ipHead.check =
|
||
get_ip_checksum((unsigned short*)&pHead->ipHead, 20);
|
||
|
||
if(eth_tx_skb(skbSIP, pEthInfo->ndev) == NETDEV_TX_OK)
|
||
{
|
||
pCh->sipDebug.cnt_ethx_2_eth0++;
|
||
}
|
||
|
||
return skbSIP;
|
||
}
|
||
|
||
//static int ipstack_hook_udp_recv_sip(struct sk_buff* skb, int* rlt)
|
||
static int ipstack_hook_udp_recv_sip(struct sk_buff* skb, PNIC_PRIVATE pp)
|
||
{
|
||
unsigned char dtmfIndex;
|
||
struct iphdr* iphdr = (struct iphdr*)skb->data;
|
||
struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4);
|
||
char payloadType = 0;// *(char*)(skb->data + 29) & 0x7F;
|
||
PNIC_PRIVATE pEthInfo = g_NICInfo[g_spbxNetId];
|
||
int ucc = pp->port;
|
||
struct sk_buff* skbSIP;
|
||
unsigned short seq_index = ntohs(*(unsigned short*)&skb->data[RECV_SEQ_POS]);
|
||
unsigned char* pUdpData = (unsigned char*)(skb->data + 28);
|
||
int udp_len = ntohs(udphdr->len);
|
||
int sipCh;
|
||
|
||
// stun package
|
||
if((pUdpData[0] & 0xC0) == 0
|
||
&& pUdpData[4] == 0x21
|
||
&& pUdpData[5] == 0x12
|
||
&& pUdpData[6] == 0xA4
|
||
&& pUdpData[7] == 0x42)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
// not this nic package
|
||
if(ntohl(iphdr->daddr) != g_NICInfo[ucc]->chIpAddr)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
sipCh = (ntohs(udphdr->dest) - g_SIPChInfo.iRTPPortBase);
|
||
// SPI Ch Package
|
||
if(sipCh >= 0 && sipCh < g_SIPChInfo.iTotalCh)
|
||
{
|
||
PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + sipCh;
|
||
|
||
pCh->sipDebug.cnt_ethx_recv++;
|
||
|
||
if(pCh->sipDebug.ethx_seq_index == 0
|
||
|| pCh->sipDebug.ethx_seq_index == 0xFFFF)
|
||
{
|
||
pCh->sipDebug.ethx_seq_index = seq_index;
|
||
}
|
||
else
|
||
{
|
||
if(pCh->sipDebug.ethx_seq_index != seq_index - 1)
|
||
{
|
||
pCh->sipDebug.ethx_seq_error++;
|
||
}
|
||
|
||
pCh->sipDebug.ethx_seq_index = seq_index;
|
||
}
|
||
|
||
pCh->sipDebug.mask_ethx_2_eth0 = CHK_CH_RECVUDP;
|
||
|
||
if(pCh->portRTP.chStatus != CH_STATUS_LINKED)
|
||
{
|
||
dev_kfree_skb_any(skb);
|
||
return udp_len;
|
||
}
|
||
|
||
if(pCh->portRTP.chLinkInfo.dstTarget.ipAddr != ntohl(iphdr->saddr)
|
||
|| pCh->portRTP.chLinkInfo.dstTarget.ipPort != ntohs(udphdr->source))
|
||
{
|
||
pCh->sipDebug.ethx_drop_src++;
|
||
dev_kfree_skb_any(skb);
|
||
return udp_len;
|
||
}
|
||
|
||
if(pCh->portRTP.chLinkInfo.stunTags != 0)
|
||
{
|
||
payloadType = *(char*)(skb->data + 29 + 4) & 0x7F;
|
||
dtmfIndex = *(unsigned char*)(skb->data + 40 + 4);
|
||
}
|
||
else
|
||
{
|
||
payloadType = *(char*)(skb->data + 29) & 0x7F;
|
||
dtmfIndex = *(unsigned char*)(skb->data + 40);
|
||
}
|
||
|
||
if(payloadType >= 96 && dtmfIndex < 17) // RFC2833 DTMF
|
||
{
|
||
recv_dtmf_from_sip(sipCh, skb);
|
||
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_RFC2833;
|
||
|
||
dev_kfree_skb_any(skb);
|
||
|
||
return udp_len;
|
||
}
|
||
else
|
||
{
|
||
if(pCh->portT38.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS | CHK_CH_NEEDSWITCH;
|
||
|
||
if(CheckMacAddress(&pCh->portT38, g_spbxNetId) == -1)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP;
|
||
dev_kfree_skb_any(skb);
|
||
return udp_len;
|
||
}
|
||
|
||
skbSIP = switch_from_sip(sipCh, skb, &pCh->portT38);
|
||
|
||
if(skbSIP != NULL)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK;
|
||
//*rlt = 1;
|
||
}
|
||
else
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR;
|
||
}
|
||
|
||
return udp_len;
|
||
}
|
||
else
|
||
{
|
||
if(pCh->portB2B.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS;
|
||
|
||
if(pCh->portB2B.chLinkInfo.dstTarget.ipAddr == pEthInfo->chIpAddr)
|
||
{
|
||
int b2bCh = (pCh->portB2B.chLinkInfo.dstTarget.ipPort
|
||
- g_SIPChInfo.iPortBase) / g_SIPChInfo.iPortStep;
|
||
|
||
pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_NEEDSWITCH_SAMEBOARD;
|
||
|
||
if(b2bCh >= 0 && b2bCh <= g_SIPChInfo.iTotalCh)
|
||
{
|
||
PSIP_CH_DETIAL pB2BCh = g_SIPChInfo.pSipChDetial + b2bCh;
|
||
|
||
if(pB2BCh->portB2B.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
if(CheckMacAddress(&pB2BCh->portRTP, pB2BCh->sipETHId) == -1)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP;
|
||
dev_kfree_skb_any(skb);
|
||
return udphdr->len;
|
||
}
|
||
|
||
skbSIP = switch_to_sip(b2bCh, skb, pB2BCh->sipETHId,
|
||
&pB2BCh->portRTP);
|
||
|
||
if(skbSIP != NULL)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK;
|
||
//*rlt = 1;
|
||
}
|
||
else
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR;
|
||
}
|
||
|
||
return udp_len;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS | CHK_CH_NEEDSWITCH;
|
||
|
||
if(CheckMacAddress(&pCh->portB2B, g_spbxNetId) == -1)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP;
|
||
dev_kfree_skb_any(skb);
|
||
return udp_len;
|
||
}
|
||
|
||
//
|
||
skbSIP = switch_from_sip(sipCh, skb, &pCh->portB2B);
|
||
|
||
if(skbSIP != NULL)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK;
|
||
//*rlt = 1;
|
||
}
|
||
else
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR;
|
||
}
|
||
|
||
return udp_len;
|
||
}
|
||
}
|
||
|
||
if(pCh->portIPR.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_STATUS | CHK_CH_NEEDSWITCH;
|
||
|
||
if(CheckMacAddress(&pCh->portIPR, g_spbxNetId) == -1)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_DROP_WAITARP;
|
||
dev_kfree_skb_any(skb);
|
||
return udp_len;
|
||
}
|
||
|
||
skbSIP = switch_from_sip(sipCh, skb, &pCh->portIPR);
|
||
|
||
if(skbSIP != NULL)
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_OK;
|
||
//*rlt = 1;
|
||
}
|
||
else
|
||
{
|
||
pCh->sipDebug.mask_ethx_2_eth0 |= CHK_CH_SWITCH_ERR;
|
||
}
|
||
|
||
return udp_len;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int ipstack_hook_udp_recv_spbx(struct sk_buff* skb, PNIC_PRIVATE pp)
|
||
{
|
||
int ret = 0;
|
||
struct iphdr* iphdr = (struct iphdr*)skb->data;
|
||
struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4);
|
||
unsigned char* pUdpData = (unsigned char*)(skb->data + 28);
|
||
unsigned short seq_index = ntohs(*(unsigned short*)&skb->data[RECV_SEQ_POS]);
|
||
struct sk_buff* skbSIP;
|
||
int udp_len = ntohs(udphdr->len);
|
||
|
||
int sipCh;
|
||
|
||
// stun package
|
||
if((pUdpData[0] & 0xC0) == 0
|
||
&& pUdpData[4] == 0x21
|
||
&& pUdpData[5] == 0x12
|
||
&& pUdpData[6] == 0xA4
|
||
&& pUdpData[7] == 0x42)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
// not this nic package
|
||
if(ntohl(iphdr->daddr) != g_NICInfo[pp->port]->chIpAddr)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
sipCh = (ntohs(udphdr->dest) - g_SIPChInfo.iPortBase) / g_SIPChInfo.iPortStep;
|
||
|
||
// SPI Ch Package
|
||
if(sipCh >= 0 && sipCh < g_SIPChInfo.iTotalCh)
|
||
{
|
||
PSIP_CH_DETIAL pCh = g_SIPChInfo.pSipChDetial + sipCh;
|
||
|
||
pCh->sipDebug.mask_eth0_2_ethx = CHK_CH_RECVUDP;
|
||
pCh->sipDebug.cnt_eth0_recv++;
|
||
|
||
if(pCh->sipDebug.eth0_seq_index == 0
|
||
|| pCh->sipDebug.ethx_seq_index == 0xFFFF)
|
||
{
|
||
pCh->sipDebug.eth0_seq_index = seq_index;
|
||
}
|
||
else
|
||
{
|
||
if(pCh->sipDebug.eth0_seq_index != seq_index - 1)
|
||
{
|
||
pCh->sipDebug.eth0_seq_error++;
|
||
}
|
||
|
||
pCh->sipDebug.eth0_seq_index = seq_index;
|
||
}
|
||
|
||
if(pCh->sipETHId == g_spbxNetId)
|
||
{
|
||
dev_kfree_skb_any(skb);
|
||
return udp_len;
|
||
}
|
||
|
||
if(pCh->portRTP.chStatus == CH_STATUS_LINKED)
|
||
{
|
||
pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_STATUS;
|
||
|
||
if(ntohl(iphdr->saddr) == pCh->portB2B.chLinkInfo.dstTarget.ipAddr
|
||
|| ntohl(iphdr->saddr) == pCh->portIPR.chLinkInfo.dstTarget.ipAddr
|
||
|| ntohl(iphdr->saddr) == pCh->portT38.chLinkInfo.dstTarget.ipAddr)
|
||
{
|
||
pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_NEEDSWITCH;
|
||
|
||
if(CheckMacAddress(&pCh->portRTP, pCh->sipETHId) == -1)
|
||
{
|
||
pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_DROP_WAITARP;
|
||
dev_kfree_skb_any(skb);
|
||
return udp_len;
|
||
}
|
||
|
||
skbSIP = switch_to_sip(sipCh, skb, pCh->sipETHId, &pCh->portRTP);
|
||
|
||
if(skbSIP != NULL)
|
||
{
|
||
pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_SWITCH_OK;
|
||
return udp_len;
|
||
}
|
||
|
||
pCh->sipDebug.mask_eth0_2_ethx |= CHK_CH_SWITCH_ERR;
|
||
}
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int ipstack_hook_udp_recv(struct sk_buff* skb, PNIC_PRIVATE pp)
|
||
{
|
||
struct iphdr* iphdr = (struct iphdr*)skb->data;
|
||
struct udphdr* udphdr = (struct udphdr*)(skb->data + iphdr->ihl * 4);
|
||
unsigned long flags;
|
||
int port = ntohs(udphdr->dest);
|
||
int rcvBytes = 0;
|
||
|
||
if(pp->port == g_spbxNetId)
|
||
{
|
||
if(port >= g_SIPChInfo.iPortBase &&
|
||
port < g_SIPChInfo.iPortBase +
|
||
(g_SIPChInfo.iTotalCh * g_SIPChInfo.iPortStep))
|
||
{
|
||
return ipstack_hook_udp_recv_spbx(skb, pp);
|
||
}
|
||
else if(port >= pp->rtpCfg.rtpBasePort &&
|
||
port < pp->rtpCfg.rtpBasePort +
|
||
(pp->rtpCfg.rtpCfgCh * pp->rtpCfg.rtpPortStep))
|
||
{
|
||
if(g_pRcvRtpHook != NULL)
|
||
{
|
||
int ch = (port - pp->rtpCfg.rtpBasePort) / pp->rtpCfg.rtpPortStep;
|
||
|
||
if(ch < 0 || ch >= pp->rtpCfg.rtpCfgCh)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
spin_lock_irqsave(&g_RegHookLock, flags);
|
||
|
||
rcvBytes = g_pRcvRtpHook(pp->port, ch, (unsigned char*)iphdr, iphdr->tot_len);
|
||
|
||
spin_unlock_irqrestore(&g_RegHookLock, flags);
|
||
|
||
if(rcvBytes > 0)
|
||
{
|
||
dev_kfree_skb_any(skb);
|
||
}
|
||
|
||
return rcvBytes;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(ntohs(udphdr->dest) >= g_SIPChInfo.iRTPPortBase &&
|
||
ntohs(udphdr->dest) < (g_SIPChInfo.iRTPPortBase + g_SIPChInfo.iTotalCh))
|
||
{
|
||
return ipstack_hook_udp_recv_sip(skb, pp);
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void ipstack_hook_init(void)
|
||
{
|
||
int i;
|
||
|
||
g_SIPChInfo.iTotalCh = 0;
|
||
|
||
g_SIPChInfo.pSipChDetial = g_SIPDetial;
|
||
|
||
g_SIPChInfo.iPortBase = -1;
|
||
g_SIPChInfo.iPortStep = -1;
|
||
|
||
InitDebugInfoProc("hook_netdrv");
|
||
|
||
for(i = 0; i < sizeof(g_DbgFSConfig) / sizeof(g_DbgFSConfig[0]); i++)
|
||
{
|
||
if(DebugFsRegister(&g_DbgFSConfig[i]) != ERR_DBGFS_NO_ERROR)
|
||
{
|
||
LOG_EX(LOG_Error, "%d Regisetr %s Error\n",
|
||
i, g_DbgFSConfig[i].name);
|
||
}
|
||
}
|
||
|
||
spin_lock_init(&g_RegHookLock) ;
|
||
}
|
||
|
||
void ipstack_hook_exit(void)
|
||
{
|
||
int i;
|
||
|
||
g_SIPChInfo.iTotalCh = 0;
|
||
g_SIPChInfo.iPortBase = -1;
|
||
g_SIPChInfo.iPortStep = -1;
|
||
|
||
for(i = 0; i < sizeof(g_DbgFSConfig) / sizeof(g_DbgFSConfig[0]); i++)
|
||
{
|
||
DebugFsUnRegister(&g_DbgFSConfig[i]);
|
||
}
|
||
|
||
DeInitDebugInfoProc();
|
||
}
|
||
|
||
ETH_IRQ_MODE eth_get_irq_mode(int ethId)
|
||
{
|
||
#if defined(PLATFORM_MV78460)
|
||
struct eth_port* pp = NULL;
|
||
#elif defined(PLATFORM_P1010)
|
||
struct gfar_private* pp = NULL;
|
||
#endif
|
||
if(ethId < 0 || ethId >= MAX_ETH_PORT)
|
||
{
|
||
return IRQ_MODE_ERROR;
|
||
}
|
||
|
||
pp = GET_ETH_PRIVATE(ethId);
|
||
|
||
if(pp == NULL)
|
||
{
|
||
return IRQ_MODE_ERROR;
|
||
}
|
||
|
||
return pp->devPrivate.irqMode;
|
||
}
|
||
EXPORT_SYMBOL(eth_get_irq_mode);
|
||
|
||
const char* eth_get_irq_aliase(ETH_IRQ_MODE irqMode)
|
||
{
|
||
switch(irqMode)
|
||
{
|
||
case IRQ_MODE_1MS:
|
||
return "IRQ_MODE_1MS";
|
||
case IRQ_MODE_MAC:
|
||
return "IRQ_MODE_MAC";
|
||
default:
|
||
return "IRQ_MODE_ERROR";
|
||
}
|
||
|
||
return "IRQ_MODE_UNKNOWN";
|
||
}
|
||
EXPORT_SYMBOL(eth_get_irq_aliase);
|
||
|
||
int config_eth_rtp(int ethId,
|
||
unsigned short maxCh,
|
||
unsigned short port_base,
|
||
unsigned short port_step)
|
||
{
|
||
g_NICInfo[ethId]->rtpCfg.rtpBasePort = port_base;
|
||
g_NICInfo[ethId]->rtpCfg.rtpCfgCh = maxCh;
|
||
g_NICInfo[ethId]->rtpCfg.rtpPortStep = port_step;
|
||
}
|
||
EXPORT_SYMBOL(config_eth_rtp);
|
||
|
||
PNIC_PRIVATE eth_get_hook_info(int ethId)
|
||
{
|
||
if(ethId >= 0 && ethId <= MAX_ETH_PORT)
|
||
{
|
||
return g_NICInfo[ethId];
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
EXPORT_SYMBOL(eth_get_hook_info);
|
||
|
||
void register_rcv_rtp_hook(PNIC_RCV_RTP_DATA phook)
|
||
{
|
||
unsigned long flags;
|
||
|
||
spin_lock_irqsave(&g_RegHookLock, flags);
|
||
g_pRcvRtpHook = phook;
|
||
spin_unlock_irqrestore(&g_RegHookLock, flags);
|
||
}
|
||
EXPORT_SYMBOL(register_rcv_rtp_hook);
|
||
|
||
void unregister_rcv_rtp_hook(void)
|
||
{
|
||
unsigned long flags;
|
||
|
||
spin_lock_irqsave(&g_RegHookLock, flags);
|
||
g_pRcvRtpHook = NULL;
|
||
spin_unlock_irqrestore(&g_RegHookLock, flags);
|
||
}
|
||
EXPORT_SYMBOL(unregister_rcv_rtp_hook);
|
||
|
||
int config_eth_ipaddr(unsigned int ethId, __be32 ipaddr, __be32 gwaddr, __be32 gwmask)
|
||
{
|
||
PNIC_PRIVATE pGfar = NULL;
|
||
|
||
if(ethId < MAX_ETH_PORT)
|
||
{
|
||
pGfar = g_NICInfo[ethId];
|
||
|
||
if(pGfar == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
pGfar->chIpAddr = ipaddr;
|
||
pGfar->chGWIpAddr = gwaddr;
|
||
pGfar->chGWMask = gwmask;
|
||
|
||
if(gwaddr != 0)
|
||
{
|
||
make_arp_request(ethId, gwaddr);
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(config_eth_ipaddr);
|
||
|
||
void eth_set_hook_info(int ethId, PNIC_PRIVATE pp)
|
||
{
|
||
if(ethId >= 0 && ethId <= MAX_ETH_PORT)
|
||
{
|
||
g_NICInfo[ethId] = pp;
|
||
}
|
||
}
|
||
|
||
void eth_init_hook_info(void)
|
||
{
|
||
int i;
|
||
for(i = 0; i < MAX_ETH_PORT; i++)
|
||
{
|
||
g_NICInfo[i] = NULL;
|
||
}
|
||
}
|
||
|
||
static int DbgFS_RtpPortShow(struct seq_file* seq, void* token)
|
||
{
|
||
int i = 0;
|
||
|
||
if(token == SEQ_START_TOKEN)
|
||
{
|
||
for(i = 0; i < MAX_ETH_PORT; i++)
|
||
{
|
||
if(g_NICInfo[i])
|
||
{
|
||
seq_printf(seq, "Eth%d: Port Base = %d, Port Step = %d, CfgCh = %d\n",
|
||
i,
|
||
g_NICInfo[i]->rtpCfg.rtpBasePort,
|
||
g_NICInfo[i]->rtpCfg.rtpPortStep,
|
||
g_NICInfo[i]->rtpCfg.rtpCfgCh);
|
||
}
|
||
else
|
||
{
|
||
seq_printf(seq, "ETH%d: unused\n", i);
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int DbgFS_NICCfgShow(struct seq_file* seq, void* token)
|
||
{
|
||
int i = 0;
|
||
|
||
if(token == SEQ_START_TOKEN)
|
||
{
|
||
for(i = 0; i < MAX_ETH_PORT; i++)
|
||
{
|
||
if(g_NICInfo[i] != NULL)
|
||
{
|
||
seq_printf(seq, "ETH%d: \n", i);
|
||
|
||
seq_printf(seq, "IP Addr : %d.%d.%d.%d\n",
|
||
(g_NICInfo[i]->chIpAddr >> 24) & 0xFF,
|
||
(g_NICInfo[i]->chIpAddr >> 16) & 0xFF,
|
||
(g_NICInfo[i]->chIpAddr >> 8) & 0xFF,
|
||
g_NICInfo[i]->chIpAddr & 0xFF);
|
||
|
||
seq_printf(seq, "GW Addr : %d.%d.%d.%d\n",
|
||
(g_NICInfo[i]->chGWIpAddr >> 24) & 0xFF,
|
||
(g_NICInfo[i]->chGWIpAddr >> 16) & 0xFF,
|
||
(g_NICInfo[i]->chGWIpAddr >> 8) & 0xFF,
|
||
g_NICInfo[i]->chGWIpAddr & 0xFF);
|
||
|
||
seq_printf(seq, "Netmask Addr : %d.%d.%d.%d\n",
|
||
(g_NICInfo[i]->chGWMask >> 24) & 0xFF,
|
||
(g_NICInfo[i]->chGWMask >> 16) & 0xFF,
|
||
(g_NICInfo[i]->chGWMask >> 8) & 0xFF,
|
||
g_NICInfo[i]->chGWMask & 0xFF);
|
||
|
||
seq_printf(seq, "Mac Addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||
g_NICInfo[i]->ndev->dev_addr[0],
|
||
g_NICInfo[i]->ndev->dev_addr[1],
|
||
g_NICInfo[i]->ndev->dev_addr[2],
|
||
g_NICInfo[i]->ndev->dev_addr[3],
|
||
g_NICInfo[i]->ndev->dev_addr[4],
|
||
g_NICInfo[i]->ndev->dev_addr[5]);
|
||
}
|
||
else
|
||
{
|
||
seq_printf(seq, "ETH%d: unused\n", i);
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int DbgFS_EthIrqShow(struct seq_file* seq, void* token)
|
||
{
|
||
unsigned int eth_id = g_DbgFSConfig[DBG_ETH_IRQ].params;
|
||
|
||
if(token == SEQ_START_TOKEN)
|
||
{
|
||
if(IS_VALUABLED_ETH(eth_id))
|
||
{
|
||
ETH_IRQ_MODE irqMode = eth_get_irq_mode(eth_id);
|
||
seq_printf(seq, "ETH%d current work on %s(%d) irq mode.\n",
|
||
eth_id, (char*)eth_get_irq_aliase(irqMode), (int)irqMode);
|
||
}
|
||
else
|
||
{
|
||
seq_printf(seq, "Error eth id: %d\n", eth_id);
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int DbgFS_EthIrqHelp(struct seq_file* seq, void* token)
|
||
{
|
||
printk("==============Options Helps=============\n");
|
||
printk("usage: echo \"<eth_id>\" > /proc/hook_netdrv/eth_irq\n");
|
||
|
||
printk("eth_id:\n");
|
||
printk("\t[0..%d]: Show eth0..eth:%d Current IrqMode.\n", MAX_ETH_PORT, MAX_ETH_PORT);
|
||
|
||
printk("\nusage: echo \"set <irq_mode>\" > /proc/hook_netdrv/eth_irq\n");
|
||
|
||
printk("irq_mode:\n");
|
||
printk("\t[1ms]: Set ethx receive and send used 1ms irq.\n");
|
||
printk("\t[mac]: Set ethx receive and send used chipset irq.\n");
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int DbgFS_EthIrqIoctl(struct seq_file* seq, char* cmd, char* params)
|
||
{
|
||
unsigned int eth_id = g_DbgFSConfig[DBG_ETH_IRQ].params;
|
||
int ret = 0;
|
||
char tmpBuf[64];
|
||
|
||
if(!IS_VALUABLED_ETH(eth_id))
|
||
{
|
||
LOG_EX(LOG_Error, "Error: Current ETH is %d\n", eth_id);
|
||
return -ERR_PARA_OUTOFRANGE;
|
||
}
|
||
|
||
if(strcmp(cmd, "set") == 0)
|
||
{
|
||
ETH_IRQ_MODE irqMode;
|
||
|
||
ret = GetStringParamValue(params, 0, tmpBuf, 64);
|
||
|
||
if(ret != ERR_DBGFS_NO_ERROR)
|
||
{
|
||
LOG_EX(LOG_Error, "get %d params(%s) error\n", 0, params);
|
||
return -ERR_PARA_OUTOFRANGE;
|
||
}
|
||
|
||
if(strcmp(tmpBuf, "1ms") == 0)
|
||
{
|
||
ret = eth_switch_irq_to_1ms(eth_id);
|
||
irqMode = IRQ_MODE_1MS;
|
||
}
|
||
else if(strcmp(tmpBuf, "mac") == 0)
|
||
{
|
||
ret = eth_switch_irq_to_mac(eth_id);
|
||
irqMode = IRQ_MODE_MAC;
|
||
}
|
||
else
|
||
{
|
||
LOG_EX(LOG_Error, "Error IRQ_MODE(1ms/mac) (%s)\n", tmpBuf);
|
||
return 0;
|
||
}
|
||
|
||
LOG_EX((ret == 0) ? LOG_Info : LOG_Error,
|
||
"ETH%d Switch IRQ Mode To %s %s\n", eth_id,
|
||
(char*)eth_get_irq_aliase(irqMode),
|
||
(ret == 0) ? "OK" : "Error");
|
||
}
|
||
else
|
||
{
|
||
LOG_EX(LOG_Error, "Unknown command (%s)\n", cmd);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int SetLocalNICId(int id)
|
||
{
|
||
if(id >= 0 && id < MAX_ETH_PORT)
|
||
{
|
||
g_spbxNetId = id;
|
||
|
||
return 0;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
EXPORT_SYMBOL(SetLocalNICId);
|
||
|
||
unsigned long long get_cpu_tick(void)
|
||
{
|
||
uint32_t h = 0;
|
||
uint32_t l = 0;
|
||
uint32_t h1 = 0;
|
||
|
||
asm volatile("1: \n"
|
||
"mftbu %0 \n"
|
||
"mftb %1 \n"
|
||
"mftbu %2 \n"
|
||
"cmpw %0,%2 \n"
|
||
"bne 1b \n"
|
||
:"=r"(h), "=r"(l), "=r"(h1):);
|
||
|
||
return (((unsigned long long)h) << 32) | l;
|
||
}
|
||
EXPORT_SYMBOL(get_cpu_tick);
|
||
|
||
unsigned long long cpu_tick_to_ms(unsigned long long tick)
|
||
{
|
||
return div64_u64(tick, P1010_CPU_COUNT_PER_MS);
|
||
}
|
||
EXPORT_SYMBOL(get_cpu_tick_of_ms);
|
||
|