]> rtime.felk.cvut.cz Git - socketcan-devel.git/blob - kernel/2.6/drivers/net/can/vcan.c
Changed banner strings.
[socketcan-devel.git] / kernel / 2.6 / drivers / net / can / vcan.c
1 /*
2  * vcan.c
3  *
4  * Copyright (c) 2002-2005 Volkswagen Group Electronic Research
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions, the following disclaimer and
12  *    the referenced file 'COPYING'.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of Volkswagen nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * Alternatively, provided that this notice is retained in full, this
21  * software may be distributed under the terms of the GNU General
22  * Public License ("GPL") version 2 as distributed in the 'COPYING'
23  * file from the main directory of the linux kernel source.
24  *
25  * The provided data structures and external interfaces from this code
26  * are not restricted to be used by modules with a GPL compatible license.
27  *
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 FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39  * DAMAGE.
40  *
41  * Send feedback to <socketcan-users@lists.berlios.de>
42  *
43  */
44
45 #include <linux/autoconf.h>
46 #include <linux/module.h>
47 #include <linux/init.h>
48 #include <linux/netdevice.h>
49 #include <linux/if_arp.h>
50
51 #include <linux/can.h>
52 #include <linux/can/version.h>
53
54 RCSID("$Id$");
55
56 static __initdata const char banner[] = KERN_INFO "CAN: virtual CAN interface " VERSION "\n"; 
57
58 MODULE_DESCRIPTION("virtual CAN interface");
59 MODULE_LICENSE("Dual BSD/GPL");
60 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
61
62 #ifdef CONFIG_CAN_DEBUG_DEVICES
63 static int debug = 0;
64 module_param(debug, int, S_IRUGO);
65 #define DBG(args...)       (debug & 1 ? \
66                                (printk(KERN_DEBUG "VCAN %s: ", __func__), \
67                                 printk(args)) : 0)
68 #define DBG_FRAME(args...) (debug & 2 ? can_debug_cframe(args) : 0)
69 #define DBG_SKB(skb)       (debug & 4 ? can_debug_skb(skb) : 0)
70 #else
71 #define DBG(args...)
72 #define DBG_FRAME(args...)
73 #define DBG_SKB(skb)
74 #endif
75
76 /* Indicate if this VCAN driver should do a real loopback, or if this */
77 /* should be done in af_can.c */
78 #undef  DO_LOOPBACK
79
80 #define NDEVICES 4
81
82 static struct net_device *vcan_devs[NDEVICES];
83
84 static int vcan_open(struct net_device *dev)
85 {
86         DBG("%s: interface up\n", dev->name);
87
88         netif_start_queue(dev);
89         return 0;
90 }
91
92 static int vcan_stop(struct net_device *dev)
93 {
94         DBG("%s: interface down\n", dev->name);
95
96         netif_stop_queue(dev);
97         return 0;
98 }
99
100 #ifdef DO_LOOPBACK
101
102 static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
103 {
104         struct net_device_stats *stats = netdev_priv(dev);
105         stats->rx_packets++;
106         stats->rx_bytes += skb->len;
107
108         skb->protocol  = htons(ETH_P_CAN);
109         skb->dev       = dev;
110         skb->ip_summed = CHECKSUM_UNNECESSARY;
111
112         DBG("received skbuff on interface %d\n", dev->ifindex);
113         DBG_SKB(skb);
114
115         netif_rx(skb);
116 }
117
118 #endif
119
120 static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
121 {
122         struct net_device_stats *stats = netdev_priv(dev);
123
124         DBG("sending skbuff on interface %s\n", dev->name);
125         DBG_SKB(skb);
126         DBG_FRAME("VCAN: transmit CAN frame", (struct can_frame *)skb->data);
127
128         stats->tx_packets++;
129         stats->tx_bytes += skb->len;
130
131 #ifdef DO_LOOPBACK
132         if (*(struct sock **)skb->cb) { /* loopback required */
133                 if (atomic_read(&skb->users) != 1) {
134                         struct sk_buff *old_skb = skb;
135                         skb = skb_clone(old_skb, GFP_ATOMIC);
136                         DBG("  freeing old skbuff %p, using new skbuff %p\n",
137                             old_skb, skb);
138                         kfree_skb(old_skb);
139                         if (!skb) {
140                                 return 0;
141                         }
142                 } else
143                         skb_orphan(skb);
144
145                 vcan_rx(skb, dev); /* with packet counting */
146         } else {
147                 /* no looped packets => no counting */
148                 kfree_skb(skb);
149         }
150 #else
151         /* only count, when the CAN-core made a loopback */
152         if (*(struct sock **)skb->cb) {
153                 stats->rx_packets++;
154                 stats->rx_bytes += skb->len;
155         }
156         kfree_skb(skb);
157 #endif
158         return 0;
159 }
160
161 static int vcan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
162 {
163         return -EOPNOTSUPP;
164 }
165
166 static int vcan_rebuild_header(struct sk_buff *skb)
167 {
168         DBG("skbuff %p\n", skb);
169         DBG_SKB(skb);
170         return 0;
171 }
172
173 static int vcan_header(struct sk_buff *skb, struct net_device *dev,
174                        unsigned short type, void *daddr, void *saddr,
175                        unsigned int len)
176 {
177         DBG("skbuff %p, device %p\n", skb, dev);
178         DBG_SKB(skb);
179         return 0;
180 }
181
182
183 static struct net_device_stats *vcan_get_stats(struct net_device *dev)
184 {
185         struct net_device_stats *stats = netdev_priv(dev);
186         return stats;
187 }
188
189 static void vcan_init(struct net_device *dev)
190 {
191         DBG("dev %s\n", dev->name);
192
193         ether_setup(dev);
194
195         memset(dev->priv, 0, sizeof(struct net_device_stats));
196
197         dev->type              = ARPHRD_CAN;
198         dev->mtu               = sizeof(struct can_frame);
199 #ifdef DO_LOOPBACK
200         dev->flags             = IFF_LOOPBACK;
201 #endif
202
203         dev->open              = vcan_open;
204         dev->stop              = vcan_stop;
205         dev->set_config        = NULL;
206         dev->hard_start_xmit   = vcan_tx;
207         dev->do_ioctl          = vcan_ioctl;
208         dev->get_stats         = vcan_get_stats;
209         dev->hard_header       = vcan_header;
210         dev->rebuild_header    = vcan_rebuild_header;
211         dev->hard_header_cache = NULL;
212
213         SET_MODULE_OWNER(dev);
214 }
215
216 static __init int vcan_init_module(void)
217 {
218         int i, ndev = 0, result;
219
220         printk(banner);
221
222         for (i = 0; i < NDEVICES; i++) {
223                 if (!(vcan_devs[i] = alloc_netdev(sizeof(struct net_device_stats),
224                                                   "vcan%d", vcan_init)))
225                         printk(KERN_ERR "vcan: error allocating net_device\n");
226                 else if ((result = register_netdev(vcan_devs[i])) < 0) {
227                         printk(KERN_ERR "vcan: error %d registering interface %s\n",
228                                result, vcan_devs[i]->name);
229                         free_netdev(vcan_devs[i]);
230                 } else {
231                         DBG("successfully registered interface %s\n",
232                             vcan_devs[i]->name);
233                         ndev++;
234                 }
235         }
236         return ndev ? 0 : -ENODEV;
237 }
238
239 static __exit void vcan_cleanup_module(void)
240 {
241         int i;
242         for (i = 0; i < NDEVICES; i++) {
243                 unregister_netdev(vcan_devs[i]);
244                 free_netdev(vcan_devs[i]);
245         }
246 }
247
248 module_init(vcan_init_module);
249 module_exit(vcan_cleanup_module);