/*
 * Copyright 2008  by Karsten Keil <kkeil@novell.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/mISDNif.h>
#include "core.h"

static u_int debug;

MODULE_AUTHOR("Karsten Keil");
MODULE_LICENSE("GPL");
module_param(debug, uint, S_IRUGO | S_IWUSR);

static LIST_HEAD(devices);
static DEFINE_RWLOCK(device_lock);
static u64		device_ids;
#define MAX_DEVICE_ID	63

static LIST_HEAD(Bprotocols);
static DEFINE_RWLOCK(bp_lock);

struct mISDNdevice
*get_mdevice(u_int id)
{
	struct mISDNdevice	*dev;

	read_lock(&device_lock);
	list_for_each_entry(dev, &devices, D.list)
		if (dev->id == id) {
			read_unlock(&device_lock);
			return dev;
		}
	read_unlock(&device_lock);
	return NULL;
}

int
get_mdevice_count(void)
{
	struct mISDNdevice	*dev;
	int			cnt = 0;

	read_lock(&device_lock);
	list_for_each_entry(dev, &devices, D.list)
		cnt++;
	read_unlock(&device_lock);
	return cnt;
}

static int
get_free_devid(void)
{
	u_int	i;

	for (i = 0; i <= MAX_DEVICE_ID; i++)
		if (!test_and_set_bit(i, (u_long *)&device_ids))
			return i;
	return -1;
}

int
mISDN_register_device(struct mISDNdevice *dev, char *name)
{
	u_long	flags;
	int	err;

	dev->id = get_free_devid();
	if (dev->id < 0)
		return -EBUSY;
	if (name && name[0])
		strcpy(dev->name, name);
	else
		sprintf(dev->name, "mISDN%d", dev->id);
	if (debug & DEBUG_CORE)
		printk(KERN_DEBUG "mISDN_register %s %d\n",
			dev->name, dev->id);
	err = create_stack(dev);
	if (err)
		return err;
	write_lock_irqsave(&device_lock, flags);
	list_add_tail(&dev->D.list, &devices);
	write_unlock_irqrestore(&device_lock, flags);
	return 0;
}
EXPORT_SYMBOL(mISDN_register_device);

void
mISDN_unregister_device(struct mISDNdevice *dev) {
	u_long	flags;

	if (debug & DEBUG_CORE)
		printk(KERN_DEBUG "mISDN_unregister %s %d\n",
			dev->name, dev->id);
	write_lock_irqsave(&device_lock, flags);
	list_del(&dev->D.list);
	write_unlock_irqrestore(&device_lock, flags);
	test_and_clear_bit(dev->id, (u_long *)&device_ids);
	delete_stack(dev);
}
EXPORT_SYMBOL(mISDN_unregister_device);

u_int
get_all_Bprotocols(void)
{
	struct Bprotocol	*bp;
	u_int	m = 0;

	read_lock(&bp_lock);
	list_for_each_entry(bp, &Bprotocols, list)
		m |= bp->Bprotocols;
	read_unlock(&bp_lock);
	return m;
}

struct Bprotocol *
get_Bprotocol4mask(u_int m)
{
	struct Bprotocol	*bp;

	read_lock(&bp_lock);
	list_for_each_entry(bp, &Bprotocols, list)
		if (bp->Bprotocols & m) {
			read_unlock(&bp_lock);
			return bp;
		}
	read_unlock(&bp_lock);
	return NULL;
}

struct Bprotocol *
get_Bprotocol4id(u_int id)
{
	u_int	m;

	if (id < ISDN_P_B_START || id > 63) {
		printk(KERN_WARNING "%s id not in range  %d\n",
		    __func__, id);
		return NULL;
	}
	m = 1 << (id & ISDN_P_B_MASK);
	return get_Bprotocol4mask(m);
}

int
mISDN_register_Bprotocol(struct Bprotocol *bp)
{
	u_long			flags;
	struct Bprotocol	*old;

	if (debug & DEBUG_CORE)
		printk(KERN_DEBUG "%s: %s/%x\n", __func__,
		    bp->name, bp->Bprotocols);
	old = get_Bprotocol4mask(bp->Bprotocols);
	if (old) {
		printk(KERN_WARNING
		    "register duplicate protocol old %s/%x new %s/%x\n",
		    old->name, old->Bprotocols, bp->name, bp->Bprotocols);
		return -EBUSY;
	}
	write_lock_irqsave(&bp_lock, flags);
	list_add_tail(&bp->list, &Bprotocols);
	write_unlock_irqrestore(&bp_lock, flags);
	return 0;
}
EXPORT_SYMBOL(mISDN_register_Bprotocol);

void
mISDN_unregister_Bprotocol(struct Bprotocol *bp)
{
	u_long	flags;

	if (debug & DEBUG_CORE)
		printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name,
			bp->Bprotocols);
	write_lock_irqsave(&bp_lock, flags);
	list_del(&bp->list);
	write_unlock_irqrestore(&bp_lock, flags);
}
EXPORT_SYMBOL(mISDN_unregister_Bprotocol);

static int
mISDNInit(void)
{
	int	err;

	printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
		MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
	mISDN_initstack(&debug);
	err = mISDN_inittimer(&debug);
	if (err)
		goto error;
	err = l1_init(&debug);
	if (err) {
		mISDN_timer_cleanup();
		goto error;
	}
	err = Isdnl2_Init(&debug);
	if (err) {
		mISDN_timer_cleanup();
		l1_cleanup();
		goto error;
	}
	err = misdn_sock_init(&debug);
	if (err) {
		mISDN_timer_cleanup();
		l1_cleanup();
		Isdnl2_cleanup();
	}
error:
	return err;
}

static void mISDN_cleanup(void)
{
	misdn_sock_cleanup();
	mISDN_timer_cleanup();
	l1_cleanup();
	Isdnl2_cleanup();

	if (!list_empty(&devices))
		printk(KERN_ERR "%s devices still registered\n", __func__);

	if (!list_empty(&Bprotocols))
		printk(KERN_ERR "%s Bprotocols still registered\n", __func__);
	printk(KERN_DEBUG "mISDNcore unloaded\n");
}

module_init(mISDNInit);
module_exit(mISDN_cleanup);

