📄 capifunc.c
字号:
/* $Id: capifunc.c,v 1.61.4.7 2005/02/11 19:40:25 armin Exp $ * * ISDN interface module for Eicon active cards DIVA. * CAPI Interface common functions * * 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 "os_capi.h"#include "di_defs.h"#include "capi20.h"#include "divacapi.h"#include "divasync.h"#include "capifunc.h"#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL;APPL *application = (APPL *) NULL;byte max_appl = MAX_APPL;byte max_adapter = 0;static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL;byte UnMapController(byte);char DRIVERRELEASE_CAPI[32];extern void AutomaticLaw(DIVA_CAPI_ADAPTER *);extern void callback(ENTITY *);extern word api_remove_start(void);extern word CapiRelease(word);extern word CapiRegister(word);extern word api_put(APPL *, CAPI_MSG *);static diva_os_spin_lock_t api_lock;static LIST_HEAD(cards);static dword notify_handle;static void DIRequest(ENTITY * e);static DESCRIPTOR MAdapter;static DESCRIPTOR DAdapter;static byte ControllerMap[MAX_DESCRIPTORS + 1];static void diva_register_appl(struct capi_ctr *, __u16, capi_register_params *);static void diva_release_appl(struct capi_ctr *, __u16);static char *diva_procinfo(struct capi_ctr *);static u16 diva_send_message(struct capi_ctr *, diva_os_message_buffer_s *);extern void diva_os_set_controller_struct(struct capi_ctr *);extern void DIVA_DIDD_Read(DESCRIPTOR *, int);/* * debug */static void no_printf(unsigned char *, ...);#include "debuglib.c"static void xlog(char *x, ...){#ifndef DIVA_NO_DEBUGLIB va_list ap; if (myDriverDebugHandle.dbgMask & DL_XLOG) { va_start(ap, x); if (myDriverDebugHandle.dbg_irq) { myDriverDebugHandle.dbg_irq(myDriverDebugHandle.id, DLI_XLOG, x, ap); } else if (myDriverDebugHandle.dbg_old) { myDriverDebugHandle.dbg_old(myDriverDebugHandle.id, x, ap); } va_end(ap); }#endif}/* * info for proc */static char *diva_procinfo(struct capi_ctr *ctrl){ return (ctrl->serial);}/* * stop debugging */static void stop_dbg(void){ DbgDeregister(); memset(&MAdapter, 0, sizeof(MAdapter)); dprintf = no_printf;}/* * dummy debug function */static void no_printf(unsigned char *x, ...){}/* * Controller mapping */byte MapController(byte Controller){ byte i; byte MappedController = 0; byte ctrl = Controller & 0x7f; /* mask external controller bit off */ for (i = 1; i < max_adapter + 1; i++) { if (ctrl == ControllerMap[i]) { MappedController = (byte) i; break; } } if (i > max_adapter) { ControllerMap[0] = ctrl; MappedController = 0; } return (MappedController | (Controller & 0x80)); /* put back external controller bit */}/* * Controller unmapping */byte UnMapController(byte MappedController){ byte Controller; byte ctrl = MappedController & 0x7f; /* mask external controller bit off */ if (ctrl <= max_adapter) { Controller = ControllerMap[ctrl]; } else { Controller = 0; } return (Controller | (MappedController & 0x80)); /* put back external controller bit */}/* * find a new free id */static int find_free_id(void){ int num = 0; DIVA_CAPI_ADAPTER *a; while (num < MAX_DESCRIPTORS) { a = &adapter[num]; if (!a->Id) break; num++; } return(num + 1);}/* * find a card structure by controller number */static diva_card *find_card_by_ctrl(word controller){ struct list_head *tmp; diva_card *card; list_for_each(tmp, &cards) { card = list_entry(tmp, diva_card, list); if (ControllerMap[card->Id] == controller) { if (card->remove_in_progress) card = NULL; return(card); } } return (diva_card *) 0;}/* * Buffer RX/TX */void *TransmitBufferSet(APPL * appl, dword ref){ appl->xbuffer_used[ref] = TRUE; DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1)) return (void *) ref;}void *TransmitBufferGet(APPL * appl, void *p){ if (appl->xbuffer_internal[(dword) p]) return appl->xbuffer_internal[(dword) p]; return appl->xbuffer_ptr[(dword) p];}void TransmitBufferFree(APPL * appl, void *p){ appl->xbuffer_used[(dword) p] = FALSE; DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))}void *ReceiveBufferGet(APPL * appl, int Num){ return &appl->ReceiveBuffer[Num * appl->MaxDataLength];}/* * api_remove_start/complete for cleanup */void api_remove_complete(void){ DBG_PRV1(("api_remove_complete"))}/* * main function called by message.c */void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...){ word i, j; word length = 12, dlength = 0; byte *write; CAPI_MSG msg; byte *string = NULL; va_list ap; diva_os_message_buffer_s *dmb; diva_card *card = NULL; dword tmp; if (!appl) return; DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)", appl->Id, command, (byte *) format)) PUT_WORD(&msg.header.appl_id, appl->Id); PUT_WORD(&msg.header.command, command); if ((byte) (command >> 8) == 0x82) Number = appl->Number++; PUT_WORD(&msg.header.number, Number); PUT_DWORD(&msg.header.controller, Id); write = (byte *) & msg; write += 12; va_start(ap, format); for (i = 0; format[i]; i++) { switch (format[i]) { case 'b': tmp = va_arg(ap, dword); *(byte *) write = (byte) (tmp & 0xff); write += 1; length += 1; break; case 'w': tmp = va_arg(ap, dword); PUT_WORD(write, (tmp & 0xffff)); write += 2; length += 2; break; case 'd': tmp = va_arg(ap, dword); PUT_DWORD(write, tmp); write += 4; length += 4; break; case 's': case 'S': string = va_arg(ap, byte *); length += string[0] + 1; for (j = 0; j <= string[0]; j++) *write++ = string[j]; break; } } va_end(ap); PUT_WORD(&msg.header.length, length); msg.header.controller = UnMapController(msg.header.controller); if (command == _DATA_B3_I) dlength = GET_WORD( ((byte *) & msg.info.data_b3_ind.Data_Length)); if (!(dmb = diva_os_alloc_message_buffer(length + dlength, (void **) &write))) { DBG_ERR(("sendf: alloc_message_buffer failed, incoming msg dropped.")) return; } /* copy msg header to sk_buff */ memcpy(write, (byte *) & msg, length); /* if DATA_B3_IND, copy data too */ if (command == _DATA_B3_I) { dword data = GET_DWORD(&msg.info.data_b3_ind.Data); memcpy(write + length, (void *) data, dlength); }#ifndef DIVA_NO_DEBUGLIB if (myDriverDebugHandle.dbgMask & DL_XLOG) { switch (command) { default: xlog("\x00\x02", &msg, 0x81, length); break; case _DATA_B3_R | CONFIRM: if (myDriverDebugHandle.dbgMask & DL_BLK) xlog("\x00\x02", &msg, 0x81, length); break; case _DATA_B3_I: if (myDriverDebugHandle.dbgMask & DL_BLK) { xlog("\x00\x02", &msg, 0x81, length); for (i = 0; i < dlength; i += 256) { DBG_BLK((((char *) GET_DWORD(&msg.info.data_b3_ind.Data)) + i, ((dlength - i) < 256) ? (dlength - i) : 256)) if (!(myDriverDebugHandle.dbgMask & DL_PRV0)) break; /* not more if not explicitely requested */ } } break; } }#endif /* find the card structure for this controller */ if (!(card = find_card_by_ctrl(write[8] & 0x7f))) { DBG_ERR(("sendf - controller %d not found, incoming msg dropped", write[8] & 0x7f)) diva_os_free_message_buffer(dmb); return; } /* send capi msg to capi layer */ capi_ctr_handle_message(&card->capi_ctrl, appl->Id, dmb);}/* * cleanup adapter */static void clean_adapter(int id, struct list_head *free_mem_q){ DIVA_CAPI_ADAPTER *a; int i, k; a = &adapter[id]; k = li_total_channels - a->li_channels; if (k == 0) { if (li_config_table) { list_add((struct list_head *)li_config_table, free_mem_q); li_config_table = NULL; } } else { if (a->li_base < k) { memmove(&li_config_table[a->li_base], &li_config_table[a->li_base + a->li_channels], (k - a->li_base) * sizeof(LI_CONFIG)); for (i = 0; i < k; i++) { memmove(&li_config_table[i].flag_table[a->li_base], &li_config_table[i].flag_table[a->li_base + a->li_channels], k - a->li_base); memmove(&li_config_table[i]. coef_table[a->li_base], &li_config_table[i].coef_table[a->li_base + a->li_channels], k - a->li_base); } } } li_total_channels = k; for (i = id; i < max_adapter; i++) { if (adapter[i].request) adapter[i].li_base -= a->li_channels; } if (a->plci) list_add((struct list_head *)a->plci, free_mem_q); memset(a, 0x00, sizeof(DIVA_CAPI_ADAPTER)); while ((max_adapter != 0) && !adapter[max_adapter - 1].request) max_adapter--;}/* * remove a card, but ensures consistent state of LI tables * in the time adapter is removed */static void divacapi_remove_card(DESCRIPTOR * d){ diva_card *card = NULL; diva_os_spin_lock_magic_t old_irql; LIST_HEAD(free_mem_q); struct list_head *link; struct list_head *tmp; /* * Set "remove in progress flag". * Ensures that there is no call from sendf to CAPI in * the time CAPI controller is about to be removed. */ diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card"); list_for_each(tmp, &cards) { card = list_entry(tmp, diva_card, list); if (card->d.request == d->request) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -