1/* 2 Copyright 2012 Delta Networks, Inc. 3*/ 4 5#include <linux/stddef.h> 6#include <linux/module.h> 7#include <linux/types.h> 8#include <asm/byteorder.h> 9#include <linux/init.h> 10#include <linux/errno.h> 11#include <linux/kernel.h> 12#include <linux/netdevice.h> 13#include <linux/etherdevice.h> 14#include <linux/skbuff.h> 15#include <linux/delay.h> 16#include <linux/timer.h> 17#include <linux/interrupt.h> 18#include <linux/dma-mapping.h> 19#include <linux/bitops.h> 20#include <linux/igmp.h> 21#include <asm/irq.h> 22#include <asm/io.h> 23#include <net/sch_generic.h> 24#include <linux/if_pppox.h> 25#include <linux/ip.h> 26#include <net/checksum.h> 27#include <linux/rtnetlink.h> 28 29#include "include/ipv6_pssthrgh.h" 30 31static struct net_device_ops athr_gmac_net_ops; 32 33extern int ipv6_pssthrgh_enable; 34 35int dni_enet_init(struct net_device *dev) 36{ 37 /* TODO: figure this out, maybe do nothing?? */ 38 return 0; 39} 40 41void dni_enet_destruct(struct net_device *dev) 42{ 43 return; 44} 45 46int dni_enet_open(struct net_device *dev) 47{ 48 return 0; 49} 50 51int dni_enet_stop(struct net_device *dev) 52{ 53 return 0; 54} 55 56static inline struct net_device_stats *dni_enet_get_stats(struct net_device *dev) { 57 return &(DNI_ENET_INFO(dev)->dev_stats); 58} 59 60 61int dni_enet_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) 62{ 63 struct net_device_stats *stats = dni_enet_get_stats(dev); 64 struct net_device *pdev; 65 66#ifdef CONFIG_PSSTHRGH 67 if (!(ipv6_pssthrgh_enable && skb->protocol == htons(ETH_P_IPV6))) { 68 kfree_skb(skb); 69 return NETDEV_TX_OK; 70 } 71#endif 72 73 pdev = DNI_ENET_INFO(dev)->real_dev; 74 75 stats->tx_packets++; /* for statics only */ 76 stats->tx_bytes += skb->len; 77// if(printk_ratelimit()) { 78// int i; 79// for (i=0; i<64; i++) { 80// printk("%02x ", skb->data[i]); 81// if (i % 16 == 15) printk("\n"); 82// } 83// printk("skb->protocol = 0x%04x\n", ntohs(skb->protocol)); 84// } 85 86 pdev->netdev_ops->ndo_start_xmit(skb, pdev); 87 88 return NETDEV_TX_OK; 89} 90 91int dni_enet_set_mac_address(struct net_device *dev, void *addr_struct_p) 92{ 93 struct sockaddr *addr = (struct sockaddr *)(addr_struct_p); 94 int i; 95 96 printk("Setting mac address\n"); 97 if (netif_running(dev)) 98 return -EBUSY; 99 100 memcpy(dev->dev_addr, addr->sa_data, 6); 101 102 printk("%s: Setting MAC address to ", dev->name); 103 for (i = 0; i < 6; i++) 104 printk(" %2.2x", dev->dev_addr[i]); 105 printk(".\n"); 106 return 0; 107} 108 109 110static int __init 111dni_enet_load(void) 112{ 113 struct net_device *real_dev; 114 struct net_device *new_dev; 115 int malloc_size; 116 117 printk("Loading DNI-ENET driver\n"); 118 119// Get the WAN physical interface 120 real_dev = dev_get_by_name(&init_net, "eth0"); 121 if (!real_dev) { 122 printk("Error, cannot find eth0 interface\n"); 123 return -1; 124 } 125 126 rtnl_lock(); 127 128 malloc_size = (sizeof(struct net_device)); 129 130 new_dev = alloc_etherdev(0); 131 if (!new_dev) 132 { 133 printk("unable to allocate mac\n"); 134 return 1; 135 } 136 137 sprintf(new_dev->name, "pas0"); 138 139 athr_gmac_net_ops.ndo_init = dni_enet_init; 140 athr_gmac_net_ops.ndo_uninit = dni_enet_destruct; 141 athr_gmac_net_ops.ndo_get_stats = dni_enet_get_stats; 142 athr_gmac_net_ops.ndo_open = dni_enet_open; 143 athr_gmac_net_ops.ndo_stop = dni_enet_stop; 144 athr_gmac_net_ops.ndo_start_xmit = dni_enet_hard_start_xmit; 145 athr_gmac_net_ops.ndo_set_mac_address = dni_enet_set_mac_address; 146 athr_gmac_net_ops.ndo_change_mtu = NULL; 147 new_dev->tx_queue_len = 1000; 148 149 new_dev->netdev_ops = (const struct net_device_ops *)&athr_gmac_net_ops; 150 151 152// new_dev->features |= NETIF_F_NO_CSUM ; 153 154 new_dev->mtu = real_dev->mtu; 155 156 /* TODO: maybe just assign it to be ETHERNET? */ 157 new_dev->type = real_dev->type; 158 new_dev->hard_header_len = real_dev->hard_header_len; 159 160 new_dev->ml_priv = kmalloc(sizeof(struct dni_enet_info), GFP_KERNEL); 161 memset(new_dev->ml_priv, 0, sizeof(struct dni_enet_info)); 162 163 memcpy(new_dev->broadcast, real_dev->broadcast, 6); 164 165 memcpy(new_dev->dev_addr, real_dev->dev_addr, 6); 166 167// XXX add addr 168// new_dev->dev_addr[5]++; 169 170 new_dev->addr_len = real_dev->addr_len; 171 172 DNI_ENET_INFO(new_dev)->real_dev = real_dev; 173 register_netdevice(new_dev); 174 175 rtnl_unlock(); 176 177 return 0; 178} 179 180module_init(dni_enet_load); 181 182static void __exit 183dni_enet_unload(void) 184{ 185 printk("unloaded...\n"); 186} 187 188MODULE_AUTHOR("Delta Networks, Inc."); 189MODULE_DESCRIPTION("Support for Pass Through Ethernet device"); 190#ifdef MODULE_LICENSE 191MODULE_LICENSE("DNI"); 192#endif 193module_exit(dni_enet_unload); 194 195