/*
 * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
 *
 * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
 *
 * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
 *
 * This software may be used and distributed according to the terms of
 * the GNU General Public License (GPL), incorporated herein by reference.
 */

#define DRV_VERSION	"0.3"
#define DRV_RELDATE	"10/12/2005"

#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
#include <asm/natfeat.h>
#include <asm/virtconvert.h>

enum {
	GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */
	XIF_INTLEVEL,	/* no parameters, return Interrupt Level in d0 */
	XIF_IRQ,	/* acknowledge interrupt from host */
	XIF_START,	/* (ethX), called on 'ifup', start receiver thread */
	XIF_STOP,	/* (ethX), called on 'ifdown', stop the thread */
	XIF_READLENGTH,	/* (ethX), return size of network data block to read */
	XIF_READBLOCK,	/* (ethX, buffer, size), read block of network data */
	XIF_WRITEBLOCK,	/* (ethX, buffer, size), write block of network data */
	XIF_GET_MAC,	/* (ethX, buffer, size), return MAC HW addr in buffer */
	XIF_GET_IPHOST,	/* (ethX, buffer, size), return IP address of host */
	XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */
	XIF_GET_NETMASK	/* (ethX, buffer, size), return IP netmask */
};

#define MAX_UNIT	8

/* These identify the driver base version and may not be removed. */
static const char version[] __devinitdata =
	KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE
	" S.Opichal, M.Jurik, P.Stehlik\n"
	KERN_INFO " http://aranym.org/\n";

MODULE_AUTHOR("Milan Jurik");
MODULE_DESCRIPTION("Atari NFeth driver");
MODULE_LICENSE("GPL");
/*
MODULE_PARM(nfeth_debug, "i");
MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
*/


static long nfEtherID;
static int nfEtherIRQ;

struct nfeth_private {
	int ethX;
};

static struct net_device *nfeth_dev[MAX_UNIT];

static int nfeth_open(struct net_device *dev)
{
	struct nfeth_private *priv = netdev_priv(dev);
	int res;

	res = nf_call(nfEtherID + XIF_START, priv->ethX);
	netdev_dbg(dev, "%s: %d\n", __func__, res);

	/* Ready for data */
	netif_start_queue(dev);

	return 0;
}

static int nfeth_stop(struct net_device *dev)
{
	struct nfeth_private *priv = netdev_priv(dev);

	/* No more data */
	netif_stop_queue(dev);

	nf_call(nfEtherID + XIF_STOP, priv->ethX);

	return 0;
}

/*
 * Read a packet out of the adapter and pass it to the upper layers
 */
static inline void recv_packet(struct net_device *dev)
{
	struct nfeth_private *priv = netdev_priv(dev);
	unsigned short pktlen;
	struct sk_buff *skb;

	/* read packet length (excluding 32 bit crc) */
	pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);

	netdev_dbg(dev, "%s: %u\n", __func__, pktlen);

	if (!pktlen) {
		netdev_dbg(dev, "%s: pktlen == 0\n", __func__);
		dev->stats.rx_errors++;
		return;
	}

	skb = dev_alloc_skb(pktlen + 2);
	if (!skb) {
		netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n",
			   __func__);
		dev->stats.rx_dropped++;
		return;
	}

	skb->dev = dev;
	skb_reserve(skb, 2);		/* 16 Byte align  */
	skb_put(skb, pktlen);		/* make room */
	nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data),
		pktlen);

	skb->protocol = eth_type_trans(skb, dev);
	netif_rx(skb);
	dev->last_rx = jiffies;
	dev->stats.rx_packets++;
	dev->stats.rx_bytes += pktlen;

	/* and enqueue packet */
	return;
}

static irqreturn_t nfeth_interrupt(int irq, void *dev_id)
{
	int i, m, mask;

	mask = nf_call(nfEtherID + XIF_IRQ, 0);
	for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
		if (mask & m && nfeth_dev[i]) {
			recv_packet(nfeth_dev[i]);
			nf_call(nfEtherID + XIF_IRQ, m);
		}
	}
	return IRQ_HANDLED;
}

static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
{
	unsigned int len;
	char *data, shortpkt[ETH_ZLEN];
	struct nfeth_private *priv = netdev_priv(dev);

	data = skb->data;
	len = skb->len;
	if (len < ETH_ZLEN) {
		memset(shortpkt, 0, ETH_ZLEN);
		memcpy(shortpkt, data, len);
		data = shortpkt;
		len = ETH_ZLEN;
	}

	netdev_dbg(dev, "%s: send %u bytes\n", __func__, len);
	nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
		len);

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

	dev_kfree_skb(skb);
	return 0;
}

static void nfeth_tx_timeout(struct net_device *dev)
{
	dev->stats.tx_errors++;
	netif_wake_queue(dev);
}

static const struct net_device_ops nfeth_netdev_ops = {
	.ndo_open		= nfeth_open,
	.ndo_stop		= nfeth_stop,
	.ndo_start_xmit		= nfeth_xmit,
	.ndo_tx_timeout		= nfeth_tx_timeout,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_change_mtu		= eth_change_mtu,
	.ndo_set_mac_address	= eth_mac_addr,
};

static struct net_device * __init nfeth_probe(int unit)
{
	struct net_device *dev;
	struct nfeth_private *priv;
	char mac[ETH_ALEN], host_ip[32], local_ip[32];
	int err;

	if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN))
		return NULL;

	dev = alloc_etherdev(sizeof(struct nfeth_private));
	if (!dev)
		return NULL;

	dev->irq = nfEtherIRQ;
	dev->netdev_ops = &nfeth_netdev_ops;

	dev->flags |= NETIF_F_NO_CSUM;
	memcpy(dev->dev_addr, mac, ETH_ALEN);

	priv = netdev_priv(dev);
	priv->ethX = unit;

	err = register_netdev(dev);
	if (err) {
		free_netdev(dev);
		return NULL;
	}

	nf_call(nfEtherID + XIF_GET_IPHOST, unit,
		host_ip, sizeof(host_ip));
	nf_call(nfEtherID + XIF_GET_IPATARI, unit,
		local_ip, sizeof(local_ip));

	netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip,
		    local_ip, mac);

	return dev;
}

static int __init nfeth_init(void)
{
	long ver;
	int error, i;

	nfEtherID = nf_get_id("ETHERNET");
	if (!nfEtherID)
		return -ENODEV;

	ver = nf_call(nfEtherID + GET_VERSION);
	pr_info("API %lu\n", ver);

	nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
	error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
			    "eth emu", nfeth_interrupt);
	if (error) {
		pr_err("request for irq %d failed %d", nfEtherIRQ, error);
		return error;
	}

	for (i = 0; i < MAX_UNIT; i++)
		nfeth_dev[i] = nfeth_probe(i);

	return 0;
}

static void __exit nfeth_cleanup(void)
{
	int i;

	for (i = 0; i < MAX_UNIT; i++) {
		if (nfeth_dev[i]) {
			unregister_netdev(nfeth_dev[0]);
			free_netdev(nfeth_dev[0]);
		}
	}
	free_irq(nfEtherIRQ, nfeth_interrupt);
}

module_init(nfeth_init);
module_exit(nfeth_cleanup);
