/* $Id: idifunc.c,v 1.14.4.4 2004/08/28 20:03:53 armin Exp $
 *
 * Driver for Eicon DIVA Server ISDN cards.
 * User Mode IDI Interface
 *
 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
 *
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 */

#include "platform.h"
#include "di_defs.h"
#include "divasync.h"
#include "um_xdi.h"
#include "um_idi.h"

#define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
#define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)

extern char *DRIVERRELEASE_IDI;

extern void DIVA_DIDD_Read(void *, int);
extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int);
extern void diva_user_mode_idi_remove_adapter(int);

static dword notify_handle;
static DESCRIPTOR DAdapter;
static DESCRIPTOR MAdapter;

static void no_printf(unsigned char *x, ...)
{
	/* dummy debug function */
}

#include "debuglib.c"

/*
 * stop debug
 */
static void stop_dbg(void)
{
	DbgDeregister();
	memset(&MAdapter, 0, sizeof(MAdapter));
	dprintf = no_printf;
}

typedef struct _udiva_card {
	struct list_head list;
	int Id;
	DESCRIPTOR d;
} udiva_card;

static LIST_HEAD(cards);
static diva_os_spin_lock_t ll_lock;

/*
 * find card in list
 */
static udiva_card *find_card_in_list(DESCRIPTOR *d)
{
	udiva_card *card;
	struct list_head *tmp;
	diva_os_spin_lock_magic_t old_irql;

	diva_os_enter_spin_lock(&ll_lock, &old_irql, "find card");
	list_for_each(tmp, &cards) {
		card = list_entry(tmp, udiva_card, list);
		if (card->d.request == d->request) {
			diva_os_leave_spin_lock(&ll_lock, &old_irql,
						"find card");
			return (card);
		}
	}
	diva_os_leave_spin_lock(&ll_lock, &old_irql, "find card");
	return ((udiva_card *) NULL);
}

/*
 * new card
 */
static void um_new_card(DESCRIPTOR *d)
{
	int adapter_nr = 0;
	udiva_card *card = NULL;
	IDI_SYNC_REQ sync_req;
	diva_os_spin_lock_magic_t old_irql;

	if (!(card = diva_os_malloc(0, sizeof(udiva_card)))) {
		DBG_ERR(("cannot get buffer for card"));
		return;
	}
	memcpy(&card->d, d, sizeof(DESCRIPTOR));
	sync_req.xdi_logical_adapter_number.Req = 0;
	sync_req.xdi_logical_adapter_number.Rc =
		IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER;
	card->d.request((ENTITY *)&sync_req);
	adapter_nr =
		sync_req.xdi_logical_adapter_number.info.logical_adapter_number;
	card->Id = adapter_nr;
	if (!(diva_user_mode_idi_create_adapter(d, adapter_nr))) {
		diva_os_enter_spin_lock(&ll_lock, &old_irql, "add card");
		list_add_tail(&card->list, &cards);
		diva_os_leave_spin_lock(&ll_lock, &old_irql, "add card");
	} else {
		DBG_ERR(("could not create user mode idi card %d",
			 adapter_nr));
		diva_os_free(0, card);
	}
}

/*
 * remove card
 */
static void um_remove_card(DESCRIPTOR *d)
{
	diva_os_spin_lock_magic_t old_irql;
	udiva_card *card = NULL;

	if (!(card = find_card_in_list(d))) {
		DBG_ERR(("cannot find card to remove"));
		return;
	}
	diva_user_mode_idi_remove_adapter(card->Id);
	diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove card");
	list_del(&card->list);
	diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove card");
	DBG_LOG(("idi proc entry removed for card %d", card->Id));
	diva_os_free(0, card);
}

/*
 * remove all adapter
 */
static void __exit remove_all_idi_proc(void)
{
	udiva_card *card;
	diva_os_spin_lock_magic_t old_irql;

rescan:
	diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove all");
	if (!list_empty(&cards)) {
		card = list_entry(cards.next, udiva_card, list);
		list_del(&card->list);
		diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove all");
		diva_user_mode_idi_remove_adapter(card->Id);
		diva_os_free(0, card);
		goto rescan;
	}
	diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove all");
}

/*
 * DIDD notify callback
 */
static void *didd_callback(void *context, DESCRIPTOR *adapter,
			   int removal)
{
	if (adapter->type == IDI_DADAPTER) {
		DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
		return (NULL);
	} else if (adapter->type == IDI_DIMAINT) {
		if (removal) {
			stop_dbg();
		} else {
			memcpy(&MAdapter, adapter, sizeof(MAdapter));
			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
			DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT);
		}
	} else if ((adapter->type > 0) && (adapter->type < 16)) {	/* IDI Adapter */
		if (removal) {
			um_remove_card(adapter);
		} else {
			um_new_card(adapter);
		}
	}
	return (NULL);
}

/*
 * connect DIDD
 */
static int __init connect_didd(void)
{
	int x = 0;
	int dadapter = 0;
	IDI_SYNC_REQ req;
	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];

	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));

	for (x = 0; x < MAX_DESCRIPTORS; x++) {
		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
			dadapter = 1;
			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
			req.didd_notify.e.Req = 0;
			req.didd_notify.e.Rc =
				IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
			req.didd_notify.info.callback = (void *)didd_callback;
			req.didd_notify.info.context = NULL;
			DAdapter.request((ENTITY *)&req);
			if (req.didd_notify.e.Rc != 0xff) {
				stop_dbg();
				return (0);
			}
			notify_handle = req.didd_notify.info.handle;
		} else if (DIDD_Table[x].type == IDI_DIMAINT) {	/* MAINT found */
			memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
			DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT);
		} else if ((DIDD_Table[x].type > 0)
			   && (DIDD_Table[x].type < 16)) {	/* IDI Adapter found */
			um_new_card(&DIDD_Table[x]);
		}
	}

	if (!dadapter) {
		stop_dbg();
	}

	return (dadapter);
}

/*
 *  Disconnect from DIDD
 */
static void __exit disconnect_didd(void)
{
	IDI_SYNC_REQ req;

	stop_dbg();

	req.didd_notify.e.Req = 0;
	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
	req.didd_notify.info.handle = notify_handle;
	DAdapter.request((ENTITY *)&req);
}

/*
 * init
 */
int __init idifunc_init(void)
{
	diva_os_initialize_spin_lock(&ll_lock, "idifunc");

	if (diva_user_mode_idi_init()) {
		DBG_ERR(("init: init failed."));
		return (0);
	}

	if (!connect_didd()) {
		diva_user_mode_idi_finit();
		DBG_ERR(("init: failed to connect to DIDD."));
		return (0);
	}
	return (1);
}

/*
 * finit
 */
void __exit idifunc_finit(void)
{
	diva_user_mode_idi_finit();
	disconnect_didd();
	remove_all_idi_proc();
}
