Path: blob/master/drivers/isdn/hardware/eicon/idifunc.c
15115 views
/* $Id: idifunc.c,v 1.14.4.4 2004/08/28 20:03:53 armin Exp $1*2* Driver for Eicon DIVA Server ISDN cards.3* User Mode IDI Interface4*5* Copyright 2000-2003 by Armin Schindler ([email protected])6* Copyright 2000-2003 Cytronics & Melware ([email protected])7*8* This software may be used and distributed according to the terms9* of the GNU General Public License, incorporated herein by reference.10*/1112#include "platform.h"13#include "di_defs.h"14#include "divasync.h"15#include "um_xdi.h"16#include "um_idi.h"1718#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)19#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)2021extern char *DRIVERRELEASE_IDI;2223extern void DIVA_DIDD_Read(void *, int);24extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int);25extern void diva_user_mode_idi_remove_adapter(int);2627static dword notify_handle;28static DESCRIPTOR DAdapter;29static DESCRIPTOR MAdapter;3031static void no_printf(unsigned char *x, ...)32{33/* dummy debug function */34}3536#include "debuglib.c"3738/*39* stop debug40*/41static void stop_dbg(void)42{43DbgDeregister();44memset(&MAdapter, 0, sizeof(MAdapter));45dprintf = no_printf;46}4748typedef struct _udiva_card {49struct list_head list;50int Id;51DESCRIPTOR d;52} udiva_card;5354static LIST_HEAD(cards);55static diva_os_spin_lock_t ll_lock;5657/*58* find card in list59*/60static udiva_card *find_card_in_list(DESCRIPTOR * d)61{62udiva_card *card;63struct list_head *tmp;64diva_os_spin_lock_magic_t old_irql;6566diva_os_enter_spin_lock(&ll_lock, &old_irql, "find card");67list_for_each(tmp, &cards) {68card = list_entry(tmp, udiva_card, list);69if (card->d.request == d->request) {70diva_os_leave_spin_lock(&ll_lock, &old_irql,71"find card");72return (card);73}74}75diva_os_leave_spin_lock(&ll_lock, &old_irql, "find card");76return ((udiva_card *) NULL);77}7879/*80* new card81*/82static void um_new_card(DESCRIPTOR * d)83{84int adapter_nr = 0;85udiva_card *card = NULL;86IDI_SYNC_REQ sync_req;87diva_os_spin_lock_magic_t old_irql;8889if (!(card = diva_os_malloc(0, sizeof(udiva_card)))) {90DBG_ERR(("cannot get buffer for card"));91return;92}93memcpy(&card->d, d, sizeof(DESCRIPTOR));94sync_req.xdi_logical_adapter_number.Req = 0;95sync_req.xdi_logical_adapter_number.Rc =96IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER;97card->d.request((ENTITY *) & sync_req);98adapter_nr =99sync_req.xdi_logical_adapter_number.info.logical_adapter_number;100card->Id = adapter_nr;101if (!(diva_user_mode_idi_create_adapter(d, adapter_nr))) {102diva_os_enter_spin_lock(&ll_lock, &old_irql, "add card");103list_add_tail(&card->list, &cards);104diva_os_leave_spin_lock(&ll_lock, &old_irql, "add card");105} else {106DBG_ERR(("could not create user mode idi card %d",107adapter_nr));108diva_os_free(0, card);109}110}111112/*113* remove card114*/115static void um_remove_card(DESCRIPTOR * d)116{117diva_os_spin_lock_magic_t old_irql;118udiva_card *card = NULL;119120if (!(card = find_card_in_list(d))) {121DBG_ERR(("cannot find card to remove"));122return;123}124diva_user_mode_idi_remove_adapter(card->Id);125diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove card");126list_del(&card->list);127diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove card");128DBG_LOG(("idi proc entry removed for card %d", card->Id));129diva_os_free(0, card);130}131132/*133* remove all adapter134*/135static void DIVA_EXIT_FUNCTION remove_all_idi_proc(void)136{137udiva_card *card;138diva_os_spin_lock_magic_t old_irql;139140rescan:141diva_os_enter_spin_lock(&ll_lock, &old_irql, "remove all");142if (!list_empty(&cards)) {143card = list_entry(cards.next, udiva_card, list);144list_del(&card->list);145diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove all");146diva_user_mode_idi_remove_adapter(card->Id);147diva_os_free(0, card);148goto rescan;149}150diva_os_leave_spin_lock(&ll_lock, &old_irql, "remove all");151}152153/*154* DIDD notify callback155*/156static void *didd_callback(void *context, DESCRIPTOR * adapter,157int removal)158{159if (adapter->type == IDI_DADAPTER) {160DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));161return (NULL);162} else if (adapter->type == IDI_DIMAINT) {163if (removal) {164stop_dbg();165} else {166memcpy(&MAdapter, adapter, sizeof(MAdapter));167dprintf = (DIVA_DI_PRINTF) MAdapter.request;168DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT);169}170} else if ((adapter->type > 0) && (adapter->type < 16)) { /* IDI Adapter */171if (removal) {172um_remove_card(adapter);173} else {174um_new_card(adapter);175}176}177return (NULL);178}179180/*181* connect DIDD182*/183static int DIVA_INIT_FUNCTION connect_didd(void)184{185int x = 0;186int dadapter = 0;187IDI_SYNC_REQ req;188DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];189190DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));191192for (x = 0; x < MAX_DESCRIPTORS; x++) {193if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */194dadapter = 1;195memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));196req.didd_notify.e.Req = 0;197req.didd_notify.e.Rc =198IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;199req.didd_notify.info.callback = (void *)didd_callback;200req.didd_notify.info.context = NULL;201DAdapter.request((ENTITY *) & req);202if (req.didd_notify.e.Rc != 0xff) {203stop_dbg();204return (0);205}206notify_handle = req.didd_notify.info.handle;207} else if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */208memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));209dprintf = (DIVA_DI_PRINTF) MAdapter.request;210DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT);211} else if ((DIDD_Table[x].type > 0)212&& (DIDD_Table[x].type < 16)) { /* IDI Adapter found */213um_new_card(&DIDD_Table[x]);214}215}216217if (!dadapter) {218stop_dbg();219}220221return (dadapter);222}223224/*225* Disconnect from DIDD226*/227static void DIVA_EXIT_FUNCTION disconnect_didd(void)228{229IDI_SYNC_REQ req;230231stop_dbg();232233req.didd_notify.e.Req = 0;234req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;235req.didd_notify.info.handle = notify_handle;236DAdapter.request((ENTITY *) & req);237}238239/*240* init241*/242int DIVA_INIT_FUNCTION idifunc_init(void)243{244diva_os_initialize_spin_lock(&ll_lock, "idifunc");245246if (diva_user_mode_idi_init()) {247DBG_ERR(("init: init failed."));248return (0);249}250251if (!connect_didd()) {252diva_user_mode_idi_finit();253DBG_ERR(("init: failed to connect to DIDD."));254return (0);255}256return (1);257}258259/*260* finit261*/262void DIVA_EXIT_FUNCTION idifunc_finit(void)263{264diva_user_mode_idi_finit();265disconnect_didd();266remove_all_idi_proc();267}268269270