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 <asm/systemsim.h>
62 #define MAMBO_BOGUS_NET_PROBE 119
63 #define MAMBO_BOGUS_NET_SEND 120
64 #define MAMBO_BOGUS_NET_RECV 121
66 static inline int MamboBogusNetProbe(int devno, void *buf)
68 return callthru2(MAMBO_BOGUS_NET_PROBE,
69 (unsigned long)devno, (unsigned long)buf);
72 static inline int MamboBogusNetSend(int devno, void *buf, ulong size)
74 return callthru3(MAMBO_BOGUS_NET_SEND,
76 (unsigned long)buf, (unsigned long)size);
79 static inline int MamboBogusNetRecv(int devno, void *buf, ulong size)
81 return callthru3(MAMBO_BOGUS_NET_RECV,
83 (unsigned long)buf, (unsigned long)size);
87 mambonet_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
89 #define INIT_BOTTOM_HALF(x,y,z) INIT_WORK(x, y, (void*)z)
90 #define SCHEDULE_BOTTOM_HALF(x) schedule_delayed_work(x, 1)
91 #define KILL_BOTTOM_HALF(x) cancel_delayed_work(x); flush_scheduled_work()
93 #define MAMBO_MTU 1500
95 struct netdev_private {
98 struct work_struct poll_task;
99 struct net_device_stats stats;
102 static int mambonet_probedev(int devno, void *buf)
104 struct device_node *mambo;
105 struct device_node *net;
108 mambo = find_path_device("/mambo");
113 net = find_path_device("/mambo/bogus-net@0");
117 reg = (unsigned int *)get_property(net, "reg", 0);
123 return MamboBogusNetProbe(devno, buf);
126 static int mambonet_send(int devno, void *buf, ulong size)
128 return MamboBogusNetSend(devno, buf, size);
131 static int mambonet_recv(int devno, void *buf, ulong size)
133 return MamboBogusNetRecv(devno, buf, size);
136 static int mambonet_start_xmit(struct sk_buff *skb, struct net_device *dev)
138 struct netdev_private *priv = (struct netdev_private *)dev->priv;
139 int devno = priv->devno;
143 /* we might need to checksum or something */
144 mambonet_send(devno, skb->data, skb->len);
146 dev->last_rx = jiffies;
147 priv->stats.rx_bytes += skb->len;
148 priv->stats.tx_bytes += skb->len;
149 priv->stats.rx_packets++;
150 priv->stats.tx_packets++;
157 static int mambonet_poll(struct net_device *dev, int *budget)
159 struct netdev_private *np = dev->priv;
160 int devno = np->devno;
165 int max_frames = min(*budget, dev->quota);
168 while ((ns = mambonet_recv(devno, buffer, 1600)) > 0) {
169 if ((skb = dev_alloc_skb(ns + 2)) != NULL) {
171 skb_reserve(skb, 2); /* 16 byte align the IP
173 #ifdef HAS_IP_COPYSUM
174 eth_copy_and_sum(skb, buffer, ns, 0);
177 memcpy(skb_put(skb, ns), buffer, ns);
179 skb->protocol = eth_type_trans(skb, dev);
182 netif_receive_skb(skb);
186 dev->last_rx = jiffies;
187 np->stats.rx_packets++;
188 np->stats.rx_bytes += ns;
190 printk("Failed to allocated skbuff, "
191 "dropping packet\n");
192 np->stats.rx_dropped++;
193 /* wait for another cycle */
197 if (frames > max_frames) {
203 dev->quota -= frames;
205 if ((!ret) && (dev->irq))
206 netif_rx_complete(dev);
211 static void mambonet_timer(struct net_device *dev)
214 struct netdev_private *priv = (struct netdev_private *)dev->priv;
216 mambonet_poll(dev, &budget);
218 if (!priv->closing) {
219 SCHEDULE_BOTTOM_HALF(&priv->poll_task);
223 static struct net_device_stats *get_stats(struct net_device *dev)
225 struct netdev_private *priv = (struct netdev_private *)dev->priv;
226 return (struct net_device_stats *)&(priv->stats);
230 mambonet_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
232 struct net_device *dev = dev_instance;
233 if (netif_rx_schedule_prep(dev)) {
234 __netif_rx_schedule(dev);
239 static int mambonet_open(struct net_device *dev)
241 struct netdev_private *priv;
247 * we can't start polling in mambonet_init, because I don't think
248 * workqueues are usable that early. so start polling now.
252 ret = request_irq(dev->irq, &mambonet_interrupt, 0,
256 netif_start_queue(dev);
258 printk(KERN_ERR "mambonet: request irq failed\n");
261 MamboBogusNetProbe(priv->devno, NULL); /* probe with NULL to activate interrupts */
269 static int mambonet_close(struct net_device *dev)
271 struct netdev_private *priv;
273 netif_stop_queue(dev);
276 free_irq(dev->irq, dev);
281 KILL_BOTTOM_HALF(&priv->poll_task);
289 static struct net_device_stats mambonet_stats;
291 static struct net_device_stats *mambonet_get_stats(struct net_device *dev)
293 return &mambonet_stats;
296 static int mambonet_set_mac_address(struct net_device *dev, void *p)
300 static int mambonet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
304 static int nextdevno = 0; /* running count of device numbers */
306 /* Initialize the rest of the device. */
307 int __init do_mambonet_probe(struct net_device *dev)
309 struct netdev_private *priv;
310 int devno = nextdevno++;
313 printk("eth%d: bogus network driver initialization\n", devno);
315 irq = mambonet_probedev(devno, dev->dev_addr);
318 printk("No IRQ retreived\n");
322 printk("%s: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", dev->name,
323 dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
324 dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
326 SET_MODULE_OWNER(dev);
329 dev->mtu = MAMBO_MTU;
330 dev->open = mambonet_open;
331 dev->poll = mambonet_poll;
333 dev->stop = mambonet_close;
334 dev->hard_start_xmit = mambonet_start_xmit;
335 dev->get_stats = mambonet_get_stats;
336 dev->set_mac_address = mambonet_set_mac_address;
337 dev->do_ioctl = mambonet_ioctl;
339 dev->priv = kmalloc(sizeof(struct netdev_private), GFP_KERNEL);
340 if (dev->priv == NULL)
342 memset(dev->priv, 0, sizeof(struct netdev_private));
347 dev->get_stats = get_stats;
350 INIT_BOTTOM_HALF(&priv->poll_task, (void *)mambonet_timer,
357 struct net_device *__init mambonet_probe(int unit)
359 struct net_device *dev = alloc_etherdev(0);
363 return ERR_PTR(-ENODEV);
365 sprintf(dev->name, "eth%d", unit);
366 netdev_boot_setup_check(dev);
368 err = do_mambonet_probe(dev);
373 err = register_netdev(dev);
384 int __init init_mambonet(void)
390 module_init(init_mambonet);
391 MODULE_LICENSE("GPL");