/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */

#define DEBUG

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/mips-boards/simint.h>

#include "mipsnet.h"		/* actual device IO mapping */

#define MIPSNET_VERSION "2005-06-20"

#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))

static char mipsnet_string[] = "mipsnet";

/*
 * Copy data from the MIPSNET rx data port
 */
static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
			int len)
{
	uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
	if (available_len < len)
		return -EFAULT;

	for (; len > 0; len--, kdata++) {
		*kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
	}

	return inl(mipsnet_reg_address(dev, rxDataCount));
}

static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
	struct sk_buff *skb)
{
	int count_to_go = skb->len;
	char *buf_ptr = skb->data;

	pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
	         dev->name, __FUNCTION__, skb->len);

	outl(skb->len, mipsnet_reg_address(dev, txDataCount));

	pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
	         dev->name, __FUNCTION__, skb->len);

	for (; count_to_go; buf_ptr++, count_to_go--) {
		outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
	}

	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;

	return skb->len;
}

static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
	pr_debug("%s:%s(): transmitting %d bytes\n",
	         dev->name, __FUNCTION__, skb->len);

	/* Only one packet at a time. Once TXDONE interrupt is serviced, the
	 * queue will be restarted.
	 */
	netif_stop_queue(dev);
	mipsnet_put_todevice(dev, skb);

	return 0;
}

static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
{
	struct sk_buff *skb;
	size_t len = count;

	if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
		dev->stats.rx_dropped++;
		return -ENOMEM;
	}

	skb_reserve(skb, 2);
	if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
		return -EFAULT;

	skb->protocol = eth_type_trans(skb, dev);
	skb->ip_summed = CHECKSUM_UNNECESSARY;

	pr_debug("%s:%s(): pushing RXed data to kernel\n",
	         dev->name, __FUNCTION__);
	netif_rx(skb);

	dev->stats.rx_packets++;
	dev->stats.rx_bytes += len;

	return count;
}

static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;

	irqreturn_t retval = IRQ_NONE;
	uint64_t interruptFlags;

	if (irq == dev->irq) {
		pr_debug("%s:%s(): irq %d for device\n",
		         dev->name, __FUNCTION__, irq);

		retval = IRQ_HANDLED;

		interruptFlags =
		    inl(mipsnet_reg_address(dev, interruptControl));
		pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
		         __FUNCTION__, interruptFlags);

		if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
			pr_debug("%s:%s(): got TXDone\n",
			         dev->name, __FUNCTION__);
			outl(MIPSNET_INTCTL_TXDONE,
			     mipsnet_reg_address(dev, interruptControl));
			// only one packet at a time, we are done.
			netif_wake_queue(dev);
		} else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
			pr_debug("%s:%s(): got RX data\n",
			         dev->name, __FUNCTION__);
			mipsnet_get_fromdev(dev,
			            inl(mipsnet_reg_address(dev, rxDataCount)));
			pr_debug("%s:%s(): clearing RX int\n",
			         dev->name, __FUNCTION__);
			outl(MIPSNET_INTCTL_RXDONE,
			     mipsnet_reg_address(dev, interruptControl));

		} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
			pr_debug("%s:%s(): got test interrupt\n",
			         dev->name, __FUNCTION__);
			// TESTBIT is cleared on read.
			//    And takes effect after a write with 0
			outl(0, mipsnet_reg_address(dev, interruptControl));
		} else {
			pr_debug("%s:%s(): no valid fags 0x%016llx\n",
			         dev->name, __FUNCTION__, interruptFlags);
			// Maybe shared IRQ, just ignore, no clearing.
			retval = IRQ_NONE;
		}

	} else {
		printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
		       dev->name, __FUNCTION__, irq);
		retval = IRQ_NONE;
	}
	return retval;
}				//mipsnet_interrupt()

static int mipsnet_open(struct net_device *dev)
{
	int err;
	pr_debug("%s: mipsnet_open\n", dev->name);

	err = request_irq(dev->irq, &mipsnet_interrupt,
			  IRQF_SHARED, dev->name, (void *) dev);

	if (err) {
		pr_debug("%s: %s(): can't get irq %d\n",
		         dev->name, __FUNCTION__, dev->irq);
		release_region(dev->base_addr, MIPSNET_IO_EXTENT);
		return err;
	}

	pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
	         dev->name, __FUNCTION__, dev->base_addr, dev->irq);


	netif_start_queue(dev);

	// test interrupt handler
	outl(MIPSNET_INTCTL_TESTBIT,
	     mipsnet_reg_address(dev, interruptControl));


	return 0;
}

static int mipsnet_close(struct net_device *dev)
{
	pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
	netif_stop_queue(dev);
	return 0;
}

static void mipsnet_set_mclist(struct net_device *dev)
{
	// we don't do anything
	return;
}

static int __init mipsnet_probe(struct device *dev)
{
	struct net_device *netdev;
	int err;

	netdev = alloc_etherdev(0);
	if (!netdev) {
		err = -ENOMEM;
		goto out;
	}

	dev_set_drvdata(dev, netdev);

	netdev->open			= mipsnet_open;
	netdev->stop			= mipsnet_close;
	netdev->hard_start_xmit		= mipsnet_xmit;
	netdev->set_multicast_list	= mipsnet_set_mclist;

	/*
	 * TODO: probe for these or load them from PARAM
	 */
	netdev->base_addr = 0x4200;
	netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 +
	              inl(mipsnet_reg_address(netdev, interruptInfo));

	// Get the io region now, get irq on open()
	if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
		pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
		         "for dev is not availble.\n", netdev->name,
		         __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
		err = -EBUSY;
		goto out_free_netdev;
	}

	/*
	 * Lacking any better mechanism to allocate a MAC address we use a
	 * random one ...
	 */
	random_ether_addr(netdev->dev_addr);

	err = register_netdev(netdev);
	if (err) {
		printk(KERN_ERR "MIPSNet: failed to register netdev.\n");
		goto out_free_region;
	}

	return 0;

out_free_region:
	release_region(netdev->base_addr, MIPSNET_IO_EXTENT);

out_free_netdev:
	free_netdev(netdev);

out:
	return err;
}

static int __devexit mipsnet_device_remove(struct device *device)
{
	struct net_device *dev = dev_get_drvdata(device);

	unregister_netdev(dev);
	release_region(dev->base_addr, MIPSNET_IO_EXTENT);
	free_netdev(dev);
	dev_set_drvdata(device, NULL);

	return 0;
}

static struct device_driver mipsnet_driver = {
	.name	= mipsnet_string,
	.bus	= &platform_bus_type,
	.probe	= mipsnet_probe,
	.remove	= __devexit_p(mipsnet_device_remove),
};

static int __init mipsnet_init_module(void)
{
	int err;

	printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. "
	       "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION);

	err = driver_register(&mipsnet_driver);
	if (err)
		printk(KERN_ERR "Driver registration failed\n");

	return err;
}

static void __exit mipsnet_exit_module(void)
{
	pr_debug("MIPSNet Ethernet driver exiting\n");

	driver_unregister(&mipsnet_driver);
}

module_init(mipsnet_init_module);
module_exit(mipsnet_exit_module);
