#include <linux/init.h> #include <linux/inet.h> #include <linux/skbuff.h> #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/spinlock.h> #include <linux/string.h> #include <linux/kernel.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/ip.h> #include <linux/ppp_channel.h> //#include <linux/if_ppp.h> #include <linux/atmppp.h> #include <linux/ppp_defs.h> #include <linux/atm.h> #include <linux/atmdev.h> #include <linux/capability.h> #include "pktGen.h" #include "../xdsl_types.h" #include "../xdsl_ctrl.h" /* stream info */ #define ETHER_ADDR_LEN 6 #define PKT_TYPE_RRXMPDU cpu_to_be16(ETH_P_SLOW) #ifdef CONFIG_RTL_ETH_PRIV_SKB_ADV #define MBUF_LEN 1536 #else #define MBUF_LEN 1700 #endif #define TRANSFER_UNFINISH 0 #define TRANSFER_FINISHED 1 #define TRANSFER_FAILED 2 extern void xdsl_ctrl_receive( void *recv_pkt, unsigned long size); #if defined(CONFIG_XDSL_CTRL_ON_SOC) extern uint8 dslcmd_rxbuf[ DSL_MAX_BUF_SIZE ]; int xdsl_2cpu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); char dmac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; static struct packet_type xdsl_packet_type __read_mostly = { .type = PKT_TYPE_RRXMPDU, .func = xdsl_2cpu_recv, }; #else int xdsl_2dsp_event_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); static DEFINE_RWLOCK(devs_lock); static char smac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; static char dmac[6] = {0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb}; static struct packet_type xdsl_packet_type __read_mostly = { .type = PKT_TYPE_RRXMPDU, .func = xdsl_2dsp_event_recv, }; #endif static int cmd_get_status; static struct net_device * eth_dev; int xdsl_ctrl_phy_setup(void) { eth_dev = dev_get_by_name(&init_net, ETH_WANIF); if (!eth_dev) { printk("Can't find Xdsl Eth Device"); return -EINVAL; } xdsl_packet_type.dev = eth_dev; dev_add_pack(&xdsl_packet_type); return 0; } ctrl_pkt_t *get_ctrl_pkt_by_phy(void *data) { struct sk_buff *skb; char *buf; ctrl_pkt_t *ctrlp; skb = (struct sk_buff*)data; buf = (char*)(skb->data); ctrlp = (ctrl_pkt_t*)(buf); return ctrlp; } int xdsl_ctrl_phy_free(void *mp) { struct sk_buff *skb; skb = (struct sk_buff*) mp; kfree_skb(skb); return 0; } /* Test Downstream Mulitcast , port 0 to port 1*/ struct sk_buff* alloc_ctrl_packet(ctrl_pkt_t *ctrlp) { struct sk_buff *send_skb; PktConf_t conf; int pktLen; // add the length ofmac address and protocol id unsigned short skb_len = 14 + sizeof(ctrl_pkt_t); send_skb = dev_alloc_skb(skb_len); if (!send_skb) { return NULL; } skb_put(send_skb, skb_len); memset(send_skb->data, 0 ,skb_len); /* setup environment */ /* Generate and input a UDP-multicast packet*/ memset(&conf, 0, sizeof(PktConf_t)); conf.payload.length = sizeof(ctrl_pkt_t); conf.payload.content = (int8*)(ctrlp); conf.conf_ethtype = PKT_TYPE_RRXMPDU; memcpy(conf.conf_smac, eth_dev->dev_addr, ETHER_ADDR_LEN); memcpy(conf.conf_dmac, dmac, ETHER_ADDR_LEN); pktLen = pktGen(&conf, send_skb->data); /* generate pkt in buff */ return send_skb; } int xdsl_ctrl_phy_set(ctrl_pkt_t *ctrlp, unsigned char sleep) { struct sk_buff *new_skb; new_skb = alloc_ctrl_packet(ctrlp); if (new_skb && (eth_dev->flags && IFF_UP)){ new_skb->dev = eth_dev; #if defined(CONFIG_COMPAT_NET_DEV_OPS) eth_dev->hard_start_xmit(new_skb, eth_dev); #else eth_dev->netdev_ops->ndo_start_xmit(new_skb,eth_dev); #endif } else { printk("net device : %s not open\n", eth_dev->name); dev_kfree_skb_any(new_skb); } return 0; } #if defined(CONFIG_XDSL_CTRL_ON_SOC) spinlock_t data_lock, rx_lock; int data_seq_num = 0; int xdsl_ctrl_phy_get(ctrl_pkt_t *ctrlp, unsigned char sleep) { struct sk_buff *new_skb; int retry_cnt = 60000; new_skb = alloc_ctrl_packet(ctrlp); if (new_skb && (eth_dev->flags & IFF_UP)) { new_skb->dev = eth_dev; #if defined(CONFIG_COMPAT_NET_DEV_OPS) eth_dev->hard_start_xmit(new_skb, eth_dev); #else eth_dev->netdev_ops->ndo_start_xmit(new_skb, eth_dev); #endif cmd_get_status = TRANSFER_UNFINISH; while (cmd_get_status == TRANSFER_UNFINISH){ schedule_timeout_interruptible(10); retry_cnt--; if (retry_cnt<=0){ break; } } if (retry_cnt<=0){ printk("xdsl_ctrl_phy_get cmd fail\n"); return -1; } } else { printk("netdevice: %s not open\n", eth_dev->name); dev_kfree_skb_any(new_skb); return -1; } if (cmd_get_status == TRANSFER_FINISHED) return 0; else return -1; } int xdsl_2cpu_event_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { char *buf; ctrl_pkt_t *ctrlp; struct net_device* ndev; printk("xdsl_2cpu_event_recv\n"); if (!skb) return -1; buf = (char*)(skb->data); ctrlp = (ctrl_pkt_t*)(buf); switch (ctrlp->command) { case 2: { printk("VDSL LINK UP\n"); ndev = dev_get_by_name(&init_net, "ptm0"); if (!ndev) return -1; netif_carrier_on(ndev); break; } case 3: { printk("VDSL LINK DOWN\n"); ndev = dev_get_by_name(&init_net, "ptm0"); if (!ndev) return -1; netif_carrier_off(ndev); break; } default: return -1; } dev_put(ndev); xdsl_ctrl_phy_free(skb); return 0; } int xdsl_2cpu_data_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { char *buf; char *mac; ctrl_pkt_t *ctrlp; spin_lock(&data_lock); if (skb){ mac = skb_mac_header(skb) + 6; memcpy(dmac, mac, ETHER_ADDR_LEN); buf = (char*)(skb->data); ctrlp = (ctrl_pkt_t*)(buf); if (ctrlp->protocol == XDSL_CMD_DATA){ memset(dslcmd_rxbuf, 0, sizeof(dslcmd_rxbuf)); memcpy(&dslcmd_rxbuf[data_seq_num*DSL_RXBUF_MAX_SIZE], ctrlp->rxbuf, ctrlp->argsize); data_seq_num++; } if (ctrlp->protocol == XDSL_CMD_DATA_EOF){ memset(dslcmd_rxbuf, 0, sizeof(dslcmd_rxbuf)); memcpy(&dslcmd_rxbuf[data_seq_num*DSL_RXBUF_MAX_SIZE], ctrlp->rxbuf, ctrlp->argsize); data_seq_num = 0; cmd_get_status = TRANSFER_FINISHED; } } spin_unlock(&data_lock); xdsl_ctrl_phy_free(skb); return 0; } int xdsl_2cpu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { int ret; char *buf; char *mac; ctrl_pkt_t *ctrlp; if (skb){ buf = (char*)(skb->data); ctrlp = (ctrl_pkt_t*)(buf); mac = skb_mac_header(skb) + 6; memcpy(dmac, mac, ETHER_ADDR_LEN); if ((ctrlp->protocol==XDSL_CMD_DATA) || (ctrlp->protocol==XDSL_CMD_DATA_EOF)){ ret = xdsl_2cpu_data_recv(skb, dev, pt, orig_dev); } else { ret = xdsl_2cpu_event_recv(skb, dev, pt, orig_dev); } } return 0; } #endif #if defined(CONFIG_XDSL_CTRL_ON_DSL) static DEFINE_SPINLOCK(recv_lock); int xdsl_2dsp_event_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { int i; char *mac; spin_lock(&recv_lock); if (skb){ mac = skb_mac_header(skb) + 6; memcpy(dmac, mac, ETHER_ADDR_LEN); xdsl_ctrl_receive( skb, skb->len ); } spin_unlock(&recv_lock); return 0; } #endif