1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: Virtual Ethernet Driver for Linux
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
23 3. Neither the name of SYSTEC electronic GmbH nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without prior written permission. For written
26 permission, please contact info@systec-electronic.com.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
43 If a provision of this License is or becomes illegal, invalid or
44 unenforceable in any jurisdiction, that shall not affect:
45 1. the validity or enforceability in that jurisdiction of any other
46 provision of this License; or
47 2. the validity or enforceability in other jurisdictions of that or
48 any other provision of this License.
50 -------------------------------------------------------------------------
52 $RCSfile: VirtualEthernetLinux.c,v $
56 $Revision: 1.8 $ $Date: 2008/11/20 17:06:51 $
62 -------------------------------------------------------------------------
66 2006/06/12 -ar: start of the implementation, version 1.00
68 2006/09/18 d.k.: integration into EPL DLLk module
72 void netif_carrier_off(struct net_device *dev);
73 void netif_carrier_on(struct net_device *dev);
75 ****************************************************************************/
77 #include <linux/version.h>
78 #include <linux/module.h>
79 #include <linux/netdevice.h>
80 #include <linux/etherdevice.h>
81 #include <linux/kernel.h>
82 #include <linux/init.h>
83 #include <linux/if_arp.h>
86 #include <net/protocol.h>
87 #include <net/pkt_sched.h>
88 #include <linux/if_ether.h>
91 #include <linux/udp.h>
93 #include <linux/types.h>
94 #include <linux/skbuff.h> /* for struct sk_buff */
96 #include "kernel/VirtualEthernet.h"
97 #include "kernel/EplDllkCal.h"
98 #include "kernel/EplDllk.h"
100 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
102 /***************************************************************************/
105 /* G L O B A L D E F I N I T I O N S */
108 /***************************************************************************/
110 //---------------------------------------------------------------------------
112 //---------------------------------------------------------------------------
114 #ifndef EPL_VETH_TX_TIMEOUT
115 //#define EPL_VETH_TX_TIMEOUT (2*HZ)
116 #define EPL_VETH_TX_TIMEOUT 0 // d.k.: we use no timeout
119 //---------------------------------------------------------------------------
121 //---------------------------------------------------------------------------
123 //---------------------------------------------------------------------------
124 // modul globale vars
125 //---------------------------------------------------------------------------
127 static struct net_device *pVEthNetDevice_g = NULL;
129 //---------------------------------------------------------------------------
130 // local function prototypes
131 //---------------------------------------------------------------------------
133 static int VEthOpen(struct net_device *pNetDevice_p);
134 static int VEthClose(struct net_device *pNetDevice_p);
135 static int VEthXmit(struct sk_buff *pSkb_p, struct net_device *pNetDevice_p);
136 static struct net_device_stats *VEthGetStats(struct net_device *pNetDevice_p);
137 static void VEthTimeout(struct net_device *pNetDevice_p);
138 static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p);
140 //=========================================================================//
142 // P U B L I C F U N C T I O N S //
144 //=========================================================================//
146 //---------------------------------------------------------------------------
162 //---------------------------------------------------------------------------
164 static int VEthOpen(struct net_device *pNetDevice_p)
166 tEplKernel Ret = kEplSuccessful;
169 // struct net_device_stats* pStats = netdev_priv(pNetDevice_p);
171 //start the interface queue for the network subsystem
172 netif_start_queue(pNetDevice_p);
174 // register callback function in DLL
175 Ret = EplDllkRegAsyncHandler(VEthRecvFrame);
177 EPL_DBGLVL_VETH_TRACE1
178 ("VEthOpen: EplDllkRegAsyncHandler returned 0x%02X\n", Ret);
183 static int VEthClose(struct net_device *pNetDevice_p)
185 tEplKernel Ret = kEplSuccessful;
187 EPL_DBGLVL_VETH_TRACE0("VEthClose\n");
189 Ret = EplDllkDeregAsyncHandler(VEthRecvFrame);
191 //stop the interface queue for the network subsystem
192 netif_stop_queue(pNetDevice_p);
196 static int VEthXmit(struct sk_buff *pSkb_p, struct net_device *pNetDevice_p)
198 tEplKernel Ret = kEplSuccessful;
199 tEplFrameInfo FrameInfo;
202 struct net_device_stats *pStats = netdev_priv(pNetDevice_p);
205 pNetDevice_p->trans_start = jiffies;
207 FrameInfo.m_pFrame = (tEplFrame *) pSkb_p->data;
208 FrameInfo.m_uiFrameSize = pSkb_p->len;
210 //call send fkt on DLL
211 Ret = EplDllkCalAsyncSend(&FrameInfo, kEplDllAsyncReqPrioGeneric);
212 if (Ret != kEplSuccessful) {
213 EPL_DBGLVL_VETH_TRACE1
214 ("VEthXmit: EplDllkCalAsyncSend returned 0x%02X\n", Ret);
215 netif_stop_queue(pNetDevice_p);
218 EPL_DBGLVL_VETH_TRACE0("VEthXmit: frame passed to DLL\n");
219 dev_kfree_skb(pSkb_p);
221 //set stats for the device
222 pStats->tx_packets++;
223 pStats->tx_bytes += FrameInfo.m_uiFrameSize;
231 static struct net_device_stats *VEthGetStats(struct net_device *pNetDevice_p)
233 EPL_DBGLVL_VETH_TRACE0("VEthGetStats\n");
235 return netdev_priv(pNetDevice_p);
238 static void VEthTimeout(struct net_device *pNetDevice_p)
240 EPL_DBGLVL_VETH_TRACE0("VEthTimeout(\n");
242 // $$$ d.k.: move to extra function, which is called by DLL when new space is available in TxFifo
243 if (netif_queue_stopped(pNetDevice_p)) {
244 netif_wake_queue(pNetDevice_p);
248 static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p)
250 tEplKernel Ret = kEplSuccessful;
251 struct net_device *pNetDevice = pVEthNetDevice_g;
252 struct net_device_stats *pStats = netdev_priv(pNetDevice);
253 struct sk_buff *pSkb;
255 EPL_DBGLVL_VETH_TRACE1("VEthRecvFrame: FrameSize=%u\n",
256 pFrameInfo_p->m_uiFrameSize);
258 pSkb = dev_alloc_skb(pFrameInfo_p->m_uiFrameSize + 2);
260 pStats->rx_dropped++;
263 pSkb->dev = pNetDevice;
265 skb_reserve(pSkb, 2);
267 memcpy((void *)skb_put(pSkb, pFrameInfo_p->m_uiFrameSize),
268 pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize);
270 pSkb->protocol = eth_type_trans(pSkb, pNetDevice);
271 pSkb->ip_summed = CHECKSUM_UNNECESSARY;
273 // call netif_rx with skb
276 EPL_DBGLVL_VETH_TRACE1("VEthRecvFrame: SrcMAC=0x%llx\n",
277 AmiGetQword48FromBe(pFrameInfo_p->m_pFrame->
280 // update receive statistics
281 pStats->rx_packets++;
282 pStats->rx_bytes += pFrameInfo_p->m_uiFrameSize;
288 tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p)
290 tEplKernel Ret = kEplSuccessful;
292 // allocate net device structure with priv pointing to stats structure
294 alloc_netdev(sizeof(struct net_device_stats), EPL_VETH_NAME,
296 // pVEthNetDevice_g = alloc_etherdev(sizeof (struct net_device_stats));
298 if (pVEthNetDevice_g == NULL) {
299 Ret = kEplNoResource;
303 pVEthNetDevice_g->open = VEthOpen;
304 pVEthNetDevice_g->stop = VEthClose;
305 pVEthNetDevice_g->get_stats = VEthGetStats;
306 pVEthNetDevice_g->hard_start_xmit = VEthXmit;
307 pVEthNetDevice_g->tx_timeout = VEthTimeout;
308 pVEthNetDevice_g->watchdog_timeo = EPL_VETH_TX_TIMEOUT;
309 pVEthNetDevice_g->destructor = free_netdev;
311 // copy own MAC address to net device structure
312 memcpy(pVEthNetDevice_g->dev_addr, pInitParam_p->m_be_abSrcMac, 6);
314 //register VEth to the network subsystem
315 if (register_netdev(pVEthNetDevice_g)) {
316 EPL_DBGLVL_VETH_TRACE0
317 ("VEthAddInstance: Could not register VEth...\n");
319 EPL_DBGLVL_VETH_TRACE0
320 ("VEthAddInstance: Register VEth successfull...\n");
327 tEplKernel PUBLIC VEthDelInstance(void)
329 tEplKernel Ret = kEplSuccessful;
331 if (pVEthNetDevice_g != NULL) {
332 //unregister VEth from the network subsystem
333 unregister_netdev(pVEthNetDevice_g);
334 // destructor was set to free_netdev,
335 // so we do not need to call free_netdev here
336 pVEthNetDevice_g = NULL;
342 #endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)