/*
 * SBE 2T3E3 synchronous serial card driver for Linux
 *
 * Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License
 * as published by the Free Software Foundation.
 *
 * This code is based on a driver written by SBE Inc.
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/hdlc.h>
#include <linux/if_arp.h>
#include <linux/interrupt.h>
#include "2t3e3.h"

static void check_leds(unsigned long arg)
{
	struct card *card = (struct card *)arg;
	struct channel *channel0 = &card->channels[0];
	static int blinker;

	update_led(channel0, ++blinker);
	if (has_two_ports(channel0->pdev))
		update_led(&card->channels[1], blinker);

	card->timer.expires = jiffies + HZ / 10;
	add_timer(&card->timer);
}

static void t3e3_remove_channel(struct channel *channel)
{
	struct pci_dev *pdev = channel->pdev;
	struct net_device *dev = channel->dev;

	/* system hangs if board asserts irq while module is unloaded */
	cpld_stop_intr(channel);
	free_irq(dev->irq, dev);
	dc_drop_descriptor_list(channel);
	unregister_hdlc_device(dev);
	free_netdev(dev);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
}

static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
{
	struct net_device *dev;
	unsigned int val;
	int err;

	err = pci_enable_device(pdev);
	if (err)
		return err;

	err = pci_request_regions(pdev, "SBE 2T3E3");
	if (err)
		goto disable;

	dev = alloc_hdlcdev(channel);
	if (!dev) {
		printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
		goto free_regions;
	}

	t3e3_sc_init(channel);
	dev_to_priv(dev) = channel;

	channel->pdev = pdev;
	channel->dev = dev;
	channel->card = card;
	channel->addr = pci_resource_start(pdev, 0);
	if (pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P1)
		channel->h.slot = 1;
	else
		channel->h.slot = 0;

	if (setup_device(dev, channel))
		goto free_regions;

	pci_read_config_dword(channel->pdev, 0x40, &val); /* mask sleep mode */
	pci_write_config_dword(channel->pdev, 0x40, val & 0x3FFFFFFF);

	pci_read_config_byte(channel->pdev, PCI_CACHE_LINE_SIZE, &channel->h.cache_size);
	pci_read_config_dword(channel->pdev, PCI_COMMAND, &channel->h.command);
	t3e3_init(channel);

	if (request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev)) {
		printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
		goto free_regions;
	}

	pci_set_drvdata(pdev, channel);
	return 0;

free_regions:
	pci_release_regions(pdev);
disable:
	pci_disable_device(pdev);
	return err;
}

static void __devexit t3e3_remove_card(struct pci_dev *pdev)
{
	struct channel *channel0 = pci_get_drvdata(pdev);
	struct card *card = channel0->card;

	del_timer(&card->timer);
	if (has_two_ports(channel0->pdev)) {
		t3e3_remove_channel(&card->channels[1]);
		pci_dev_put(card->channels[1].pdev);
	}
	t3e3_remove_channel(channel0);
	kfree(card);
}

static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	/* pdev points to channel #0 */
	struct pci_dev *pdev1 = NULL;
	struct card *card;
	int channels = 1, err;

	if (has_two_ports(pdev)) {
		while ((pdev1 = pci_get_subsys(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
					       PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P1,
					       pdev1)))
			if (pdev1->bus == pdev->bus &&
			    pdev1->devfn == pdev->devfn + 8 /* next device on the same bus */)
				break; /* found the second channel */

		if (!pdev1) {
			printk(KERN_ERR "SBE 2T3E3" ": Can't find the second channel\n");
			return -EFAULT;
		}
		channels = 2;
		/* holds the reference for pdev1 */
	}

	card = kzalloc(sizeof(struct card) + channels * sizeof(struct channel), GFP_KERNEL);
	if (!card) {
		printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
		return -ENOBUFS;
	}

	spin_lock_init(&card->bootrom_lock);
	card->bootrom_addr = pci_resource_start(pdev, 0);

	err = t3e3_init_channel(&card->channels[0], pdev, card);
	if (err)
		goto free_card;

	if (channels == 2) {
		err = t3e3_init_channel(&card->channels[1], pdev1, card);
		if (err) {
			t3e3_remove_channel(&card->channels[0]);
			goto free_card;
		}
	}

	/* start LED timer */
	init_timer(&card->timer);
	card->timer.function = check_leds;
	card->timer.expires = jiffies + HZ / 10;
	card->timer.data = (unsigned long)card;
	add_timer(&card->timer);
	return 0;

free_card:
	kfree(card);
	return err;
}

static struct pci_device_id t3e3_pci_tbl[] __devinitdata = {
	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
	  PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_T3E3, 0, 0, 0 },
	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
	  PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P0, 0, 0, 0 },
	/* channel 1 will be initialized after channel 0 */
	{ 0, }
};

static struct pci_driver t3e3_pci_driver = {
	.name     = "SBE T3E3",
	.id_table = t3e3_pci_tbl,
	.probe    = t3e3_init_card,
	.remove   = t3e3_remove_card,
};

static int __init t3e3_init_module(void)
{
	return pci_register_driver(&t3e3_pci_driver);
}

static void __exit t3e3_cleanup_module(void)
{
	pci_unregister_driver(&t3e3_pci_driver);
}

module_init(t3e3_init_module);
module_exit(t3e3_cleanup_module);
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, t3e3_pci_tbl);
