1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 */ 6 7#define DEBUG 8 9#include <linux/init.h> 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/netdevice.h> 13#include <linux/etherdevice.h> 14#include <linux/netdevice.h> 15#include <linux/platform_device.h> 16#include <asm/io.h> 17#include <asm/mips-boards/simint.h> 18 19#include "mipsnet.h" /* actual device IO mapping */ 20 21#define MIPSNET_VERSION "2005-06-20" 22 23#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field)) 24 25struct mipsnet_priv { 26 struct net_device_stats stats; 27}; 28 29static char mipsnet_string[] = "mipsnet"; 30 31/* 32 * Copy data from the MIPSNET rx data port 33 */ 34static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata, 35 int len) 36{ 37 uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount)); 38 if (available_len < len) 39 return -EFAULT; 40 41 for (; len > 0; len--, kdata++) { 42 *kdata = inb(mipsnet_reg_address(dev, rxDataBuffer)); 43 } 44 45 return inl(mipsnet_reg_address(dev, rxDataCount)); 46} 47 48static inline ssize_t mipsnet_put_todevice(struct net_device *dev, 49 struct sk_buff *skb) 50{ 51 int count_to_go = skb->len; 52 char *buf_ptr = skb->data; 53 struct mipsnet_priv *mp = netdev_priv(dev); 54 55 pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n", 56 dev->name, __FUNCTION__, skb->len); 57 58 outl(skb->len, mipsnet_reg_address(dev, txDataCount)); 59 60 pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n", 61 dev->name, __FUNCTION__, skb->len); 62 63 for (; count_to_go; buf_ptr++, count_to_go--) { 64 outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer)); 65 } 66 67 mp->stats.tx_packets++; 68 mp->stats.tx_bytes += skb->len; 69 70 return skb->len; 71} 72 73static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev) 74{ 75 pr_debug("%s:%s(): transmitting %d bytes\n", 76 dev->name, __FUNCTION__, skb->len); 77 78 /* Only one packet at a time. Once TXDONE interrupt is serviced, the 79 * queue will be restarted. 80 */ 81 netif_stop_queue(dev); 82 mipsnet_put_todevice(dev, skb); 83 84 return 0; 85} 86 87static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count) 88{ 89 struct sk_buff *skb; 90 size_t len = count; 91 struct mipsnet_priv *mp = netdev_priv(dev); 92 93 if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) { 94 mp->stats.rx_dropped++; 95 return -ENOMEM; 96 } 97 98 skb_reserve(skb, 2); 99 if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len)) 100 return -EFAULT; 101 102 skb->protocol = eth_type_trans(skb, dev); 103 skb->ip_summed = CHECKSUM_UNNECESSARY; 104 105 pr_debug("%s:%s(): pushing RXed data to kernel\n", 106 dev->name, __FUNCTION__); 107 netif_rx(skb); 108 109 mp->stats.rx_packets++; 110 mp->stats.rx_bytes += len; 111 112 return count; 113} 114 115static irqreturn_t mipsnet_interrupt(int irq, void *dev_id) 116{ 117 struct net_device *dev = dev_id; 118 119 irqreturn_t retval = IRQ_NONE; 120 uint64_t interruptFlags; 121 122 if (irq == dev->irq) { 123 pr_debug("%s:%s(): irq %d for device\n", 124 dev->name, __FUNCTION__, irq); 125 126 retval = IRQ_HANDLED; 127 128 interruptFlags = 129 inl(mipsnet_reg_address(dev, interruptControl)); 130 pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name, 131 __FUNCTION__, interruptFlags); 132 133 if (interruptFlags & MIPSNET_INTCTL_TXDONE) { 134 pr_debug("%s:%s(): got TXDone\n", 135 dev->name, __FUNCTION__); 136 outl(MIPSNET_INTCTL_TXDONE, 137 mipsnet_reg_address(dev, interruptControl)); 138 // only one packet at a time, we are done. 139 netif_wake_queue(dev); 140 } else if (interruptFlags & MIPSNET_INTCTL_RXDONE) { 141 pr_debug("%s:%s(): got RX data\n", 142 dev->name, __FUNCTION__); 143 mipsnet_get_fromdev(dev, 144 inl(mipsnet_reg_address(dev, rxDataCount))); 145 pr_debug("%s:%s(): clearing RX int\n", 146 dev->name, __FUNCTION__); 147 outl(MIPSNET_INTCTL_RXDONE, 148 mipsnet_reg_address(dev, interruptControl)); 149 150 } else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) { 151 pr_debug("%s:%s(): got test interrupt\n", 152 dev->name, __FUNCTION__); 153 // TESTBIT is cleared on read. 154 // And takes effect after a write with 0 155 outl(0, mipsnet_reg_address(dev, interruptControl)); 156 } else { 157 pr_debug("%s:%s(): no valid fags 0x%016llx\n", 158 dev->name, __FUNCTION__, interruptFlags); 159 // Maybe shared IRQ, just ignore, no clearing. 160 retval = IRQ_NONE; 161 } 162 163 } else { 164 printk(KERN_INFO "%s: %s(): irq %d for unknown device\n", 165 dev->name, __FUNCTION__, irq); 166 retval = IRQ_NONE; 167 } 168 return retval; 169} //mipsnet_interrupt() 170 171static int mipsnet_open(struct net_device *dev) 172{ 173 int err; 174 pr_debug("%s: mipsnet_open\n", dev->name); 175 176 err = request_irq(dev->irq, &mipsnet_interrupt, 177 IRQF_SHARED, dev->name, (void *) dev); 178 179 if (err) { 180 pr_debug("%s: %s(): can't get irq %d\n", 181 dev->name, __FUNCTION__, dev->irq); 182 release_region(dev->base_addr, MIPSNET_IO_EXTENT); 183 return err; 184 } 185 186 pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n", 187 dev->name, __FUNCTION__, dev->base_addr, dev->irq); 188 189 190 netif_start_queue(dev); 191 192 // test interrupt handler 193 outl(MIPSNET_INTCTL_TESTBIT, 194 mipsnet_reg_address(dev, interruptControl)); 195 196 197 return 0; 198} 199 200static int mipsnet_close(struct net_device *dev) 201{ 202 pr_debug("%s: %s()\n", dev->name, __FUNCTION__); 203 netif_stop_queue(dev); 204 return 0; 205} 206 207static struct net_device_stats *mipsnet_get_stats(struct net_device *dev) 208{ 209 struct mipsnet_priv *mp = netdev_priv(dev); 210 211 return &mp->stats; 212} 213 214static void mipsnet_set_mclist(struct net_device *dev) 215{ 216 // we don't do anything 217 return; 218} 219 220static int __init mipsnet_probe(struct device *dev) 221{ 222 struct net_device *netdev; 223 int err; 224 225 netdev = alloc_etherdev(sizeof(struct mipsnet_priv)); 226 if (!netdev) { 227 err = -ENOMEM; 228 goto out; 229 } 230 231 dev_set_drvdata(dev, netdev); 232 233 netdev->open = mipsnet_open; 234 netdev->stop = mipsnet_close; 235 netdev->hard_start_xmit = mipsnet_xmit; 236 netdev->get_stats = mipsnet_get_stats; 237 netdev->set_multicast_list = mipsnet_set_mclist; 238 239 /* 240 * TODO: probe for these or load them from PARAM 241 */ 242 netdev->base_addr = 0x4200; 243 netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 + 244 inl(mipsnet_reg_address(netdev, interruptInfo)); 245 246 // Get the io region now, get irq on open() 247 if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) { 248 pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} " 249 "for dev is not availble.\n", netdev->name, 250 __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT); 251 err = -EBUSY; 252 goto out_free_netdev; 253 } 254 255 /* 256 * Lacking any better mechanism to allocate a MAC address we use a 257 * random one ... 258 */ 259 random_ether_addr(netdev->dev_addr); 260 261 err = register_netdev(netdev); 262 if (err) { 263 printk(KERN_ERR "MIPSNet: failed to register netdev.\n"); 264 goto out_free_region; 265 } 266 267 return 0; 268 269out_free_region: 270 release_region(netdev->base_addr, MIPSNET_IO_EXTENT); 271 272out_free_netdev: 273 free_netdev(netdev); 274 275out: 276 return err; 277} 278 279static int __devexit mipsnet_device_remove(struct device *device) 280{ 281 struct net_device *dev = dev_get_drvdata(device); 282 283 unregister_netdev(dev); 284 release_region(dev->base_addr, MIPSNET_IO_EXTENT); 285 free_netdev(dev); 286 dev_set_drvdata(device, NULL); 287 288 return 0; 289} 290 291static struct device_driver mipsnet_driver = { 292 .name = mipsnet_string, 293 .bus = &platform_bus_type, 294 .probe = mipsnet_probe, 295 .remove = __devexit_p(mipsnet_device_remove), 296}; 297 298static int __init mipsnet_init_module(void) 299{ 300 int err; 301 302 printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. " 303 "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION); 304 305 err = driver_register(&mipsnet_driver); 306 if (err) 307 printk(KERN_ERR "Driver registration failed\n"); 308 309 return err; 310} 311 312static void __exit mipsnet_exit_module(void) 313{ 314 pr_debug("MIPSNet Ethernet driver exiting\n"); 315 316 driver_unregister(&mipsnet_driver); 317} 318 319module_init(mipsnet_init_module); 320module_exit(mipsnet_exit_module); 321