/*
 * Linux ARCnet driver - COM20020 PCMCIA support
 *
 * Written 1994-1999 by Avery Pennarun,
 *    based on an ISA version by David Woodhouse.
 * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
 *    which was derived from pcnet_cs.c by David Hinds.
 * Some additional portions derived from skeleton.c by Donald Becker.
 *
 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
 *  for sponsoring the further development of this driver.
 *
 * **********************
 *
 * The original copyright of skeleton.c was as follows:
 *
 * skeleton.c Written 1993 by Donald Becker.
 * Copyright 1993 United States Government as represented by the
 * Director, National Security Agency.  This software may only be used
 * and distributed according to the terms of the GNU General Public License as
 * modified by SRC, incorporated herein by reference.
 *
 * **********************
 * Changes:
 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
 * - reorganize kmallocs in com20020_attach, checking all for failure
 *   and releasing the previous allocations if one fails
 * **********************
 *
 * For more details, see drivers/net/arcnet.c
 *
 * **********************
 */

#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/io.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>

#include "arcdevice.h"
#include "com20020.h"

static void regdump(struct net_device *dev)
{
#ifdef DEBUG
	int ioaddr = dev->base_addr;
	int count;

	netdev_dbg(dev, "register dump:\n");
	for (count = 0; count < 16; count++) {
		if (!(count % 16))
			pr_cont("%04X:", ioaddr + count);
		pr_cont(" %02X", arcnet_inb(ioaddr, count));
	}
	pr_cont("\n");

	netdev_dbg(dev, "buffer0 dump:\n");
	/* set up the address register */
	count = 0;
	arcnet_outb((count >> 8) | RDDATAflag | AUTOINCflag,
		    ioaddr, COM20020_REG_W_ADDR_HI);
	arcnet_outb(count & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);

	for (count = 0; count < 256 + 32; count++) {
		if (!(count % 16))
			pr_cont("%04X:", count);

		/* copy the data */
		pr_cont(" %02X", arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA));
	}
	pr_cont("\n");
#endif
}

/*====================================================================*/

/* Parameters that can be set with 'insmod' */

static int node;
static int timeout = 3;
static int backplane;
static int clockp;
static int clockm;

module_param(node, int, 0);
module_param(timeout, int, 0);
module_param(backplane, int, 0);
module_param(clockp, int, 0);
module_param(clockm, int, 0);

MODULE_LICENSE("GPL");

/*====================================================================*/

static int com20020_config(struct pcmcia_device *link);
static void com20020_release(struct pcmcia_device *link);

static void com20020_detach(struct pcmcia_device *p_dev);

/*====================================================================*/

static int com20020_probe(struct pcmcia_device *p_dev)
{
	struct com20020_dev *info;
	struct net_device *dev;
	struct arcnet_local *lp;
	int ret = -ENOMEM;

	dev_dbg(&p_dev->dev, "com20020_attach()\n");

	/* Create new network device */
	info = kzalloc(sizeof(*info), GFP_KERNEL);
	if (!info)
		goto fail_alloc_info;

	dev = alloc_arcdev("");
	if (!dev)
		goto fail_alloc_dev;

	lp = netdev_priv(dev);
	lp->timeout = timeout;
	lp->backplane = backplane;
	lp->clockp = clockp;
	lp->clockm = clockm & 3;
	lp->hw.owner = THIS_MODULE;

	/* fill in our module parameters as defaults */
	dev->dev_addr[0] = node;

	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
	p_dev->resource[0]->end = 16;
	p_dev->config_flags |= CONF_ENABLE_IRQ;

	info->dev = dev;
	p_dev->priv = info;

	ret = com20020_config(p_dev);
	if (ret)
		goto fail_config;

	return 0;

fail_config:
	free_arcdev(dev);
fail_alloc_dev:
	kfree(info);
fail_alloc_info:
	return ret;
} /* com20020_attach */

static void com20020_detach(struct pcmcia_device *link)
{
	struct com20020_dev *info = link->priv;
	struct net_device *dev = info->dev;

	dev_dbg(&link->dev, "detach...\n");

	dev_dbg(&link->dev, "com20020_detach\n");

	dev_dbg(&link->dev, "unregister...\n");

	unregister_netdev(dev);

	/* this is necessary because we register our IRQ separately
	 * from card services.
	 */
	if (dev->irq)
		free_irq(dev->irq, dev);

	com20020_release(link);

	/* Unlink device structure, free bits */
	dev_dbg(&link->dev, "unlinking...\n");
	if (link->priv) {
		dev = info->dev;
		if (dev) {
			dev_dbg(&link->dev, "kfree...\n");
			free_arcdev(dev);
		}
		dev_dbg(&link->dev, "kfree2...\n");
		kfree(info);
	}

} /* com20020_detach */

static int com20020_config(struct pcmcia_device *link)
{
	struct arcnet_local *lp;
	struct com20020_dev *info;
	struct net_device *dev;
	int i, ret;
	int ioaddr;

	info = link->priv;
	dev = info->dev;

	dev_dbg(&link->dev, "config...\n");

	dev_dbg(&link->dev, "com20020_config\n");

	dev_dbg(&link->dev, "baseport1 is %Xh\n",
		(unsigned int)link->resource[0]->start);

	i = -ENODEV;
	link->io_lines = 16;

	if (!link->resource[0]->start) {
		for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) {
			link->resource[0]->start = ioaddr;
			i = pcmcia_request_io(link);
			if (i == 0)
				break;
		}
	} else {
		i = pcmcia_request_io(link);
	}

	if (i != 0) {
		dev_dbg(&link->dev, "requestIO failed totally!\n");
		goto failed;
	}

	ioaddr = dev->base_addr = link->resource[0]->start;
	dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);

	dev_dbg(&link->dev, "request IRQ %d\n",
		link->irq);
	if (!link->irq) {
		dev_dbg(&link->dev, "requestIRQ failed totally!\n");
		goto failed;
	}

	dev->irq = link->irq;

	ret = pcmcia_enable_device(link);
	if (ret)
		goto failed;

	if (com20020_check(dev)) {
		regdump(dev);
		goto failed;
	}

	lp = netdev_priv(dev);
	lp->card_name = "PCMCIA COM20020";
	lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */

	SET_NETDEV_DEV(dev, &link->dev);

	i = com20020_found(dev, 0);	/* calls register_netdev */

	if (i != 0) {
		dev_notice(&link->dev,
			   "com20020_found() failed\n");
		goto failed;
	}

	netdev_dbg(dev, "port %#3lx, irq %d\n",
		   dev->base_addr, dev->irq);
	return 0;

failed:
	dev_dbg(&link->dev, "com20020_config failed...\n");
	com20020_release(link);
	return -ENODEV;
} /* com20020_config */

static void com20020_release(struct pcmcia_device *link)
{
	dev_dbg(&link->dev, "com20020_release\n");
	pcmcia_disable_device(link);
}

static int com20020_suspend(struct pcmcia_device *link)
{
	struct com20020_dev *info = link->priv;
	struct net_device *dev = info->dev;

	if (link->open)
		netif_device_detach(dev);

	return 0;
}

static int com20020_resume(struct pcmcia_device *link)
{
	struct com20020_dev *info = link->priv;
	struct net_device *dev = info->dev;

	if (link->open) {
		int ioaddr = dev->base_addr;
		struct arcnet_local *lp = netdev_priv(dev);

		arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG);
		udelay(5);
		arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
	}

	return 0;
}

static const struct pcmcia_device_id com20020_ids[] = {
	PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
				"PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
	PCMCIA_DEVICE_PROD_ID12("SoHard AG",
				"SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
	PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, com20020_ids);

static struct pcmcia_driver com20020_cs_driver = {
	.owner		= THIS_MODULE,
	.name		= "com20020_cs",
	.probe		= com20020_probe,
	.remove		= com20020_detach,
	.id_table	= com20020_ids,
	.suspend	= com20020_suspend,
	.resume		= com20020_resume,
};
module_pcmcia_driver(com20020_cs_driver);
