2 * Bogus Network Driver for PowerPC Full System Simulator
4 * (C) Copyright IBM Corporation 2003-2005
8 * Author: JimiX <jimix@watson.ibm.com>
9 * Maintained By: Eric Van Hensbergen <ericvh@gmail.com>
11 * inspired by drivers/net/ibmveth.c
12 * written by Dave Larson
14 * Some code is from the IBM Full System Simulator Group in ARL
15 * Author: Patrick Bohrer <IBM Austin Research Lab>
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2, or (at your option)
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to:
29 * Free Software Foundation
30 * 51 Franklin Street, Fifth Floor
31 * Boston, MA 02111-1301 USA
35 #include <linux/kernel.h>
36 #include <linux/sched.h>
37 #include <linux/interrupt.h>
39 #include <linux/types.h>
40 #include <linux/string.h>
41 #include <linux/socket.h>
42 #include <linux/errno.h>
43 #include <linux/fcntl.h>
45 #include <linux/init.h>
47 #include <asm/system.h>
48 #include <asm/uaccess.h>
51 #include <linux/inet.h>
52 #include <linux/netdevice.h>
53 #include <linux/etherdevice.h>
54 #include <linux/skbuff.h>
56 #include <linux/if_ether.h> /* For the statistics structure. */
57 #include <linux/if_arp.h> /* For ARPHRD_ETHER */
58 #include <linux/workqueue.h>
60 #include <linux/version.h>
61 #include <asm/systemsim.h>
63 #define MAMBO_BOGUS_NET_PROBE 119
64 #define MAMBO_BOGUS_NET_SEND 120
65 #define MAMBO_BOGUS_NET_RECV 121
67 static inline int MamboBogusNetProbe(int devno, void *buf)
69 return callthru2(MAMBO_BOGUS_NET_PROBE,
70 (unsigned long)devno, (unsigned long)buf);
73 static inline int MamboBogusNetSend(int devno, void *buf, ulong size)
75 return callthru3(MAMBO_BOGUS_NET_SEND,
77 (unsigned long)buf, (unsigned long)size);
80 static inline int MamboBogusNetRecv(int devno, void *buf, ulong size)
82 return callthru3(MAMBO_BOGUS_NET_RECV,
84 (unsigned long)buf, (unsigned long)size);
88 mambonet_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
90 #define INIT_BOTTOM_HALF(x,y,z) INIT_WORK(x, y, (void*)z)
91 #define SCHEDULE_BOTTOM_HALF(x) schedule_delayed_work(x, 1)
92 #define KILL_BOTTOM_HALF(x) cancel_delayed_work(x); flush_scheduled_work()
94 #define MAMBO_MTU 1500
96 struct netdev_private {
99 struct work_struct poll_task;
100 struct net_device_stats stats;
103 static int mambonet_probedev(int devno, void *buf)
105 struct device_node *mambo;
106 struct device_node *net;
109 mambo = find_path_device("/mambo");
114 net = find_path_device("/mambo/bogus-net@0");
118 reg = (unsigned int *)get_property(net, "reg", 0);
124 return MamboBogusNetProbe(devno, buf);
127 static int mambonet_send(int devno, void *buf, ulong size)
129 return MamboBogusNetSend(devno, buf, size);
132 static int mambonet_recv(int devno, void *buf, ulong size)
134 return MamboBogusNetRecv(devno, buf, size);
137 static int mambonet_start_xmit(struct sk_buff *skb, struct net_device *dev)
139 struct netdev_private *priv = (struct netdev_private *)dev->priv;
140 int devno = priv->devno;
144 /* we might need to checksum or something */
145 mambonet_send(devno, skb->data, skb->len);
147 dev->last_rx = jiffies;
148 priv->stats.rx_bytes += skb->len;
149 priv->stats.tx_bytes += skb->len;
150 priv->stats.rx_packets++;
151 priv->stats.tx_packets++;
158 static int mambonet_poll(struct net_device *dev, int *budget)
160 struct netdev_private *np = dev->priv;
161 int devno = np->devno;
166 int max_frames = min(*budget, dev->quota);
169 while ((ns = mambonet_recv(devno, buffer, 1600)) > 0) {
170 if ((skb = dev_alloc_skb(ns + 2)) != NULL) {
172 skb_reserve(skb, 2); /* 16 byte align the IP
174 #ifdef HAS_IP_COPYSUM
175 eth_copy_and_sum(skb, buffer, ns, 0);
178 memcpy(skb_put(skb, ns), buffer, ns);
180 skb->protocol = eth_type_trans(skb, dev);
183 netif_receive_skb(skb);
187 dev->last_rx = jiffies;
188 np->stats.rx_packets++;
189 np->stats.rx_bytes += ns;
191 printk("Failed to allocated skbuff, "
192 "dropping packet\n");
193 np->stats.rx_dropped++;
194 /* wait for another cycle */
198 if (frames > max_frames) {
204 dev->quota -= frames;
206 if ((!ret) && (dev->irq))
207 netif_rx_complete(dev);
212 static void mambonet_timer(struct net_device *dev)
215 struct netdev_private *priv = (struct netdev_private *)dev->priv;
217 mambonet_poll(dev, &budget);
219 if (!priv->closing) {
220 SCHEDULE_BOTTOM_HALF(&priv->poll_task);
224 static struct net_device_stats *get_stats(struct net_device *dev)
226 struct netdev_private *priv = (struct netdev_private *)dev->priv;
227 return (struct net_device_stats *)&(priv->stats);
231 mambonet_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
233 struct net_device *dev = dev_instance;
234 if (netif_rx_schedule_prep(dev)) {
235 __netif_rx_schedule(dev);
240 static int mambonet_open(struct net_device *dev)
242 struct netdev_private *priv;
248 * we can't start polling in mambonet_init, because I don't think
249 * workqueues are usable that early. so start polling now.
253 ret = request_irq(dev->irq, &mambonet_interrupt, 0,
257 netif_start_queue(dev);
259 printk(KERN_ERR "mambonet: request irq failed\n");
262 MamboBogusNetProbe(priv->devno, NULL); /* probe with NULL to activate interrupts */
270 static int mambonet_close(struct net_device *dev)
272 struct netdev_private *priv;
274 netif_stop_queue(dev);
277 free_irq(dev->irq, dev);
282 KILL_BOTTOM_HALF(&priv->poll_task);
290 static struct net_device_stats mambonet_stats;
292 static struct net_device_stats *mambonet_get_stats(struct net_device *dev)
294 return &mambonet_stats;
297 static int mambonet_set_mac_address(struct net_device *dev, void *p)
301 static int mambonet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
305 static int nextdevno = 0; /* running count of device numbers */
307 /* Initialize the rest of the device. */
308 int __init do_mambonet_probe(struct net_device *dev)
310 struct netdev_private *priv;
311 int devno = nextdevno++;
314 printk("eth%d: bogus network driver initialization\n", devno);
316 irq = mambonet_probedev(devno, dev->dev_addr);
319 printk("No IRQ retreived\n");
323 printk("%s: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", dev->name,
324 dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
325 dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
327 SET_MODULE_OWNER(dev);
330 dev->mtu = MAMBO_MTU;
331 dev->open = mambonet_open;
332 dev->poll = mambonet_poll;
334 dev->stop = mambonet_close;
335 dev->hard_start_xmit = mambonet_start_xmit;
336 dev->get_stats = mambonet_get_stats;
337 dev->set_mac_address = mambonet_set_mac_address;
338 dev->do_ioctl = mambonet_ioctl;
340 dev->priv = kmalloc(sizeof(struct netdev_private), GFP_KERNEL);
341 if (dev->priv == NULL)
343 memset(dev->priv, 0, sizeof(struct netdev_private));
348 dev->get_stats = get_stats;
351 INIT_BOTTOM_HALF(&priv->poll_task, (void *)mambonet_timer,
358 struct net_device *__init mambonet_probe(int unit)
360 struct net_device *dev = alloc_etherdev(0);
364 return ERR_PTR(-ENODEV);
366 sprintf(dev->name, "eth%d", unit);
367 netdev_boot_setup_check(dev);
369 err = do_mambonet_probe(dev);
374 err = register_netdev(dev);
385 int __init init_mambonet(void)
391 module_init(init_mambonet);
392 MODULE_LICENSE("GPL");