|  | /* $Id: diva.c,v 1.21.4.1 2004/05/08 14:33:43 armin Exp $ */ | 
|  |  | 
|  | #define CARDTYPE_H_WANT_DATA            1 | 
|  | #define CARDTYPE_H_WANT_IDI_DATA        0 | 
|  | #define CARDTYPE_H_WANT_RESOURCE_DATA   0 | 
|  | #define CARDTYPE_H_WANT_FILE_DATA       0 | 
|  |  | 
|  | #include "platform.h" | 
|  | #include "debuglib.h" | 
|  | #include "cardtype.h" | 
|  | #include "pc.h" | 
|  | #include "di_defs.h" | 
|  | #include "di.h" | 
|  | #include "io.h" | 
|  | #include "pc_maint.h" | 
|  | #include "xdi_msg.h" | 
|  | #include "xdi_adapter.h" | 
|  | #include "diva_pci.h" | 
|  | #include "diva.h" | 
|  |  | 
|  | #ifdef CONFIG_ISDN_DIVAS_PRIPCI | 
|  | #include "os_pri.h" | 
|  | #endif | 
|  | #ifdef CONFIG_ISDN_DIVAS_BRIPCI | 
|  | #include "os_bri.h" | 
|  | #include "os_4bri.h" | 
|  | #endif | 
|  |  | 
|  | PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; | 
|  | extern IDI_CALL Requests[MAX_ADAPTER]; | 
|  | extern int create_adapter_proc(diva_os_xdi_adapter_t * a); | 
|  | extern void remove_adapter_proc(diva_os_xdi_adapter_t * a); | 
|  |  | 
|  | #define DivaIdiReqFunc(N) \ | 
|  | static void DivaIdiRequest##N(ENTITY *e) \ | 
|  | { if ( IoAdapters[N] ) (* IoAdapters[N]->DIRequest)(IoAdapters[N], e) ; } | 
|  |  | 
|  | /* | 
|  | **  Create own 32 Adapters | 
|  | */ | 
|  | DivaIdiReqFunc(0) | 
|  | DivaIdiReqFunc(1) | 
|  | DivaIdiReqFunc(2) | 
|  | DivaIdiReqFunc(3) | 
|  | DivaIdiReqFunc(4) | 
|  | DivaIdiReqFunc(5) | 
|  | DivaIdiReqFunc(6) | 
|  | DivaIdiReqFunc(7) | 
|  | DivaIdiReqFunc(8) | 
|  | DivaIdiReqFunc(9) | 
|  | DivaIdiReqFunc(10) | 
|  | DivaIdiReqFunc(11) | 
|  | DivaIdiReqFunc(12) | 
|  | DivaIdiReqFunc(13) | 
|  | DivaIdiReqFunc(14) | 
|  | DivaIdiReqFunc(15) | 
|  | DivaIdiReqFunc(16) | 
|  | DivaIdiReqFunc(17) | 
|  | DivaIdiReqFunc(18) | 
|  | DivaIdiReqFunc(19) | 
|  | DivaIdiReqFunc(20) | 
|  | DivaIdiReqFunc(21) | 
|  | DivaIdiReqFunc(22) | 
|  | DivaIdiReqFunc(23) | 
|  | DivaIdiReqFunc(24) | 
|  | DivaIdiReqFunc(25) | 
|  | DivaIdiReqFunc(26) | 
|  | DivaIdiReqFunc(27) | 
|  | DivaIdiReqFunc(28) | 
|  | DivaIdiReqFunc(29) | 
|  | DivaIdiReqFunc(30) | 
|  | DivaIdiReqFunc(31) | 
|  |  | 
|  | /* | 
|  | **  LOCALS | 
|  | */ | 
|  | static LIST_HEAD(adapter_queue); | 
|  |  | 
|  | typedef struct _diva_get_xlog { | 
|  | word command; | 
|  | byte req; | 
|  | byte rc; | 
|  | byte data[sizeof(struct mi_pc_maint)]; | 
|  | } diva_get_xlog_t; | 
|  |  | 
|  | typedef struct _diva_supported_cards_info { | 
|  | int CardOrdinal; | 
|  | diva_init_card_proc_t init_card; | 
|  | } diva_supported_cards_info_t; | 
|  |  | 
|  | static diva_supported_cards_info_t divas_supported_cards[] = { | 
|  | #ifdef CONFIG_ISDN_DIVAS_PRIPCI | 
|  | /* | 
|  | PRI Cards | 
|  | */ | 
|  | {CARDTYPE_DIVASRV_P_30M_PCI, diva_pri_init_card}, | 
|  | /* | 
|  | PRI Rev.2 Cards | 
|  | */ | 
|  | {CARDTYPE_DIVASRV_P_30M_V2_PCI, diva_pri_init_card}, | 
|  | /* | 
|  | PRI Rev.2 VoIP Cards | 
|  | */ | 
|  | {CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card}, | 
|  | #endif | 
|  | #ifdef CONFIG_ISDN_DIVAS_BRIPCI | 
|  | /* | 
|  | 4BRI Rev 1 Cards | 
|  | */ | 
|  | {CARDTYPE_DIVASRV_Q_8M_PCI, diva_4bri_init_card}, | 
|  | {CARDTYPE_DIVASRV_VOICE_Q_8M_PCI, diva_4bri_init_card}, | 
|  | /* | 
|  | 4BRI Rev 2 Cards | 
|  | */ | 
|  | {CARDTYPE_DIVASRV_Q_8M_V2_PCI, diva_4bri_init_card}, | 
|  | {CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI, diva_4bri_init_card}, | 
|  | /* | 
|  | 4BRI Based BRI Rev 2 Cards | 
|  | */ | 
|  | {CARDTYPE_DIVASRV_B_2M_V2_PCI, diva_4bri_init_card}, | 
|  | {CARDTYPE_DIVASRV_B_2F_PCI, diva_4bri_init_card}, | 
|  | {CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card}, | 
|  | /* | 
|  | BRI | 
|  | */ | 
|  | {CARDTYPE_MAESTRA_PCI, diva_bri_init_card}, | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | EOL | 
|  | */ | 
|  | {-1} | 
|  | }; | 
|  |  | 
|  | static void diva_init_request_array(void); | 
|  | static void *divas_create_pci_card(int handle, void *pci_dev_handle); | 
|  |  | 
|  | static diva_os_spin_lock_t adapter_lock; | 
|  |  | 
|  | static int diva_find_free_adapters(int base, int nr) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | for (i = 0; i < nr; i++) { | 
|  | if (IoAdapters[base + i]) { | 
|  | return (-1); | 
|  | } | 
|  | } | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | static diva_os_xdi_adapter_t *diva_q_get_next(struct list_head * what) | 
|  | { | 
|  | diva_os_xdi_adapter_t *a = NULL; | 
|  |  | 
|  | if (what && (what->next != &adapter_queue)) | 
|  | a = list_entry(what->next, diva_os_xdi_adapter_t, link); | 
|  |  | 
|  | return(a); | 
|  | } | 
|  |  | 
|  | /* -------------------------------------------------------------------------- | 
|  | Add card to the card list | 
|  | -------------------------------------------------------------------------- */ | 
|  | void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal) | 
|  | { | 
|  | diva_os_spin_lock_magic_t old_irql; | 
|  | diva_os_xdi_adapter_t *pdiva, *pa; | 
|  | int i, j, max, nr; | 
|  |  | 
|  | for (i = 0; divas_supported_cards[i].CardOrdinal != -1; i++) { | 
|  | if (divas_supported_cards[i].CardOrdinal == CardOrdinal) { | 
|  | if (!(pdiva = divas_create_pci_card(i, pdev))) { | 
|  | return NULL; | 
|  | } | 
|  | switch (CardOrdinal) { | 
|  | case CARDTYPE_DIVASRV_Q_8M_PCI: | 
|  | case CARDTYPE_DIVASRV_VOICE_Q_8M_PCI: | 
|  | case CARDTYPE_DIVASRV_Q_8M_V2_PCI: | 
|  | case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI: | 
|  | max = MAX_ADAPTER - 4; | 
|  | nr = 4; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | max = MAX_ADAPTER; | 
|  | nr = 1; | 
|  | } | 
|  |  | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card"); | 
|  |  | 
|  | for (i = 0; i < max; i++) { | 
|  | if (!diva_find_free_adapters(i, nr)) { | 
|  | pdiva->controller = i + 1; | 
|  | pdiva->xdi_adapter.ANum = pdiva->controller; | 
|  | IoAdapters[i] = &pdiva->xdi_adapter; | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card"); | 
|  | create_adapter_proc(pdiva);	/* add adapter to proc file system */ | 
|  |  | 
|  | DBG_LOG(("add %s:%d", | 
|  | CardProperties | 
|  | [CardOrdinal].Name, | 
|  | pdiva->controller)) | 
|  |  | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card"); | 
|  | pa = pdiva; | 
|  | for (j = 1; j < nr; j++) {	/* slave adapters, if any */ | 
|  | pa = diva_q_get_next(&pa->link); | 
|  | if (pa && !pa->interface.cleanup_adapter_proc) { | 
|  | pa->controller = i + 1 + j; | 
|  | pa->xdi_adapter.ANum = pa->controller; | 
|  | IoAdapters[i + j] = &pa->xdi_adapter; | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card"); | 
|  | DBG_LOG(("add slave adapter (%d)", | 
|  | pa->controller)) | 
|  | create_adapter_proc(pa);	/* add adapter to proc file system */ | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card"); | 
|  | } else { | 
|  | DBG_ERR(("slave adapter problem")) | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card"); | 
|  | return (pdiva); | 
|  | } | 
|  | } | 
|  |  | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card"); | 
|  |  | 
|  | /* | 
|  | Not able to add adapter - remove it and return error | 
|  | */ | 
|  | DBG_ERR(("can not alloc request array")) | 
|  | diva_driver_remove_card(pdiva); | 
|  |  | 
|  | return NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /* -------------------------------------------------------------------------- | 
|  | Called on driver load, MAIN, main, DriverEntry | 
|  | -------------------------------------------------------------------------- */ | 
|  | int divasa_xdi_driver_entry(void) | 
|  | { | 
|  | diva_os_initialize_spin_lock(&adapter_lock, "adapter"); | 
|  | memset(&IoAdapters[0], 0x00, sizeof(IoAdapters)); | 
|  | diva_init_request_array(); | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | /* -------------------------------------------------------------------------- | 
|  | Remove adapter from list | 
|  | -------------------------------------------------------------------------- */ | 
|  | static diva_os_xdi_adapter_t *get_and_remove_from_queue(void) | 
|  | { | 
|  | diva_os_spin_lock_magic_t old_irql; | 
|  | diva_os_xdi_adapter_t *a = NULL; | 
|  |  | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "driver_unload"); | 
|  |  | 
|  | if (!list_empty(&adapter_queue)) { | 
|  | a = list_entry(adapter_queue.next, diva_os_xdi_adapter_t, link); | 
|  | list_del(adapter_queue.next); | 
|  | } | 
|  |  | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload"); | 
|  | return (a); | 
|  | } | 
|  |  | 
|  | /* -------------------------------------------------------------------------- | 
|  | Remove card from the card list | 
|  | -------------------------------------------------------------------------- */ | 
|  | void diva_driver_remove_card(void *pdiva) | 
|  | { | 
|  | diva_os_spin_lock_magic_t old_irql; | 
|  | diva_os_xdi_adapter_t *a[4]; | 
|  | diva_os_xdi_adapter_t *pa; | 
|  | int i; | 
|  |  | 
|  | pa = a[0] = (diva_os_xdi_adapter_t *) pdiva; | 
|  | a[1] = a[2] = a[3] = NULL; | 
|  |  | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "remode adapter"); | 
|  |  | 
|  | for (i = 1; i < 4; i++) { | 
|  | if ((pa = diva_q_get_next(&pa->link)) | 
|  | && !pa->interface.cleanup_adapter_proc) { | 
|  | a[i] = pa; | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | for (i = 0; ((i < 4) && a[i]); i++) { | 
|  | list_del(&a[i]->link); | 
|  | } | 
|  |  | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload"); | 
|  |  | 
|  | (*(a[0]->interface.cleanup_adapter_proc)) (a[0]); | 
|  |  | 
|  | for (i = 0; i < 4; i++) { | 
|  | if (a[i]) { | 
|  | if (a[i]->controller) { | 
|  | DBG_LOG(("remove adapter (%d)", | 
|  | a[i]->controller)) IoAdapters[a[i]->controller - 1] = NULL; | 
|  | remove_adapter_proc(a[i]); | 
|  | } | 
|  | diva_os_free(0, a[i]); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* -------------------------------------------------------------------------- | 
|  | Create diva PCI adapter and init internal adapter structures | 
|  | -------------------------------------------------------------------------- */ | 
|  | static void *divas_create_pci_card(int handle, void *pci_dev_handle) | 
|  | { | 
|  | diva_supported_cards_info_t *pI = &divas_supported_cards[handle]; | 
|  | diva_os_spin_lock_magic_t old_irql; | 
|  | diva_os_xdi_adapter_t *a; | 
|  |  | 
|  | DBG_LOG(("found %d-%s", pI->CardOrdinal, CardProperties[pI->CardOrdinal].Name)) | 
|  |  | 
|  | if (!(a = (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) { | 
|  | DBG_ERR(("A: can't alloc adapter")); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | memset(a, 0x00, sizeof(*a)); | 
|  |  | 
|  | a->CardIndex = handle; | 
|  | a->CardOrdinal = pI->CardOrdinal; | 
|  | a->Bus = DIVAS_XDI_ADAPTER_BUS_PCI; | 
|  | a->xdi_adapter.cardType = a->CardOrdinal; | 
|  | a->resources.pci.bus = diva_os_get_pci_bus(pci_dev_handle); | 
|  | a->resources.pci.func = diva_os_get_pci_func(pci_dev_handle); | 
|  | a->resources.pci.hdev = pci_dev_handle; | 
|  |  | 
|  | /* | 
|  | Add master adapter first, so slave adapters will receive higher | 
|  | numbers as master adapter | 
|  | */ | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card"); | 
|  | list_add_tail(&a->link, &adapter_queue); | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card"); | 
|  |  | 
|  | if ((*(pI->init_card)) (a)) { | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card"); | 
|  | list_del(&a->link); | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card"); | 
|  | diva_os_free(0, a); | 
|  | DBG_ERR(("A: can't get adapter resources")); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return (a); | 
|  | } | 
|  |  | 
|  | /* -------------------------------------------------------------------------- | 
|  | Called on driver unload FINIT, finit, Unload | 
|  | -------------------------------------------------------------------------- */ | 
|  | void divasa_xdi_driver_unload(void) | 
|  | { | 
|  | diva_os_xdi_adapter_t *a; | 
|  |  | 
|  | while ((a = get_and_remove_from_queue())) { | 
|  | if (a->interface.cleanup_adapter_proc) { | 
|  | (*(a->interface.cleanup_adapter_proc)) (a); | 
|  | } | 
|  | if (a->controller) { | 
|  | IoAdapters[a->controller - 1] = NULL; | 
|  | remove_adapter_proc(a); | 
|  | } | 
|  | diva_os_free(0, a); | 
|  | } | 
|  | diva_os_destroy_spin_lock(&adapter_lock, "adapter"); | 
|  | } | 
|  |  | 
|  | /* | 
|  | **  Receive and process command from user mode utility | 
|  | */ | 
|  | void *diva_xdi_open_adapter(void *os_handle, const void __user *src, | 
|  | int length, | 
|  | divas_xdi_copy_from_user_fn_t cp_fn) | 
|  | { | 
|  | diva_xdi_um_cfg_cmd_t msg; | 
|  | diva_os_xdi_adapter_t *a = NULL; | 
|  | diva_os_spin_lock_magic_t old_irql; | 
|  | struct list_head *tmp; | 
|  |  | 
|  | if (length < sizeof(diva_xdi_um_cfg_cmd_t)) { | 
|  | DBG_ERR(("A: A(?) open, msg too small (%d < %d)", | 
|  | length, sizeof(diva_xdi_um_cfg_cmd_t))) | 
|  | return NULL; | 
|  | } | 
|  | if ((*cp_fn) (os_handle, &msg, src, sizeof(msg)) <= 0) { | 
|  | DBG_ERR(("A: A(?) open, write error")) | 
|  | return NULL; | 
|  | } | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter"); | 
|  | list_for_each(tmp, &adapter_queue) { | 
|  | a = list_entry(tmp, diva_os_xdi_adapter_t, link); | 
|  | if (a->controller == (int)msg.adapter) | 
|  | break; | 
|  | a = NULL; | 
|  | } | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter"); | 
|  |  | 
|  | if (!a) { | 
|  | DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter)) | 
|  | } | 
|  |  | 
|  | return (a); | 
|  | } | 
|  |  | 
|  | /* | 
|  | **  Easy cleanup mailbox status | 
|  | */ | 
|  | void diva_xdi_close_adapter(void *adapter, void *os_handle) | 
|  | { | 
|  | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter; | 
|  |  | 
|  | a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY; | 
|  | if (a->xdi_mbox.data) { | 
|  | diva_os_free(0, a->xdi_mbox.data); | 
|  | a->xdi_mbox.data = NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | int | 
|  | diva_xdi_write(void *adapter, void *os_handle, const void __user *src, | 
|  | int length, divas_xdi_copy_from_user_fn_t cp_fn) | 
|  | { | 
|  | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter; | 
|  | void *data; | 
|  |  | 
|  | if (a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY) { | 
|  | DBG_ERR(("A: A(%d) write, mbox busy", a->controller)) | 
|  | return (-1); | 
|  | } | 
|  |  | 
|  | if (length < sizeof(diva_xdi_um_cfg_cmd_t)) { | 
|  | DBG_ERR(("A: A(%d) write, message too small (%d < %d)", | 
|  | a->controller, length, | 
|  | sizeof(diva_xdi_um_cfg_cmd_t))) | 
|  | return (-3); | 
|  | } | 
|  |  | 
|  | if (!(data = diva_os_malloc(0, length))) { | 
|  | DBG_ERR(("A: A(%d) write, ENOMEM", a->controller)) | 
|  | return (-2); | 
|  | } | 
|  |  | 
|  | length = (*cp_fn) (os_handle, data, src, length); | 
|  | if (length > 0) { | 
|  | if ((*(a->interface.cmd_proc)) | 
|  | (a, (diva_xdi_um_cfg_cmd_t *) data, length)) { | 
|  | length = -3; | 
|  | } | 
|  | } else { | 
|  | DBG_ERR(("A: A(%d) write error (%d)", a->controller, | 
|  | length)) | 
|  | } | 
|  |  | 
|  | diva_os_free(0, data); | 
|  |  | 
|  | return (length); | 
|  | } | 
|  |  | 
|  | /* | 
|  | **  Write answers to user mode utility, if any | 
|  | */ | 
|  | int | 
|  | diva_xdi_read(void *adapter, void *os_handle, void __user *dst, | 
|  | int max_length, divas_xdi_copy_to_user_fn_t cp_fn) | 
|  | { | 
|  | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter; | 
|  | int ret; | 
|  |  | 
|  | if (!(a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY)) { | 
|  | DBG_ERR(("A: A(%d) rx mbox empty", a->controller)) | 
|  | return (-1); | 
|  | } | 
|  | if (!a->xdi_mbox.data) { | 
|  | a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY; | 
|  | DBG_ERR(("A: A(%d) rx ENOMEM", a->controller)) | 
|  | return (-2); | 
|  | } | 
|  |  | 
|  | if (max_length < a->xdi_mbox.data_length) { | 
|  | DBG_ERR(("A: A(%d) rx buffer too short(%d < %d)", | 
|  | a->controller, max_length, | 
|  | a->xdi_mbox.data_length)) | 
|  | return (-3); | 
|  | } | 
|  |  | 
|  | ret = (*cp_fn) (os_handle, dst, a->xdi_mbox.data, | 
|  | a->xdi_mbox.data_length); | 
|  | if (ret > 0) { | 
|  | diva_os_free(0, a->xdi_mbox.data); | 
|  | a->xdi_mbox.data = NULL; | 
|  | a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY; | 
|  | } | 
|  |  | 
|  | return (ret); | 
|  | } | 
|  |  | 
|  |  | 
|  | irqreturn_t diva_os_irq_wrapper(int irq, void *context) | 
|  | { | 
|  | diva_os_xdi_adapter_t *a = context; | 
|  | diva_xdi_clear_interrupts_proc_t clear_int_proc; | 
|  |  | 
|  | if (!a || !a->xdi_adapter.diva_isr_handler) | 
|  | return IRQ_NONE; | 
|  |  | 
|  | if ((clear_int_proc = a->clear_interrupts_proc)) { | 
|  | (*clear_int_proc) (a); | 
|  | a->clear_interrupts_proc = NULL; | 
|  | return IRQ_HANDLED; | 
|  | } | 
|  |  | 
|  | (*(a->xdi_adapter.diva_isr_handler)) (&a->xdi_adapter); | 
|  | return IRQ_HANDLED; | 
|  | } | 
|  |  | 
|  | static void diva_init_request_array(void) | 
|  | { | 
|  | Requests[0] = DivaIdiRequest0; | 
|  | Requests[1] = DivaIdiRequest1; | 
|  | Requests[2] = DivaIdiRequest2; | 
|  | Requests[3] = DivaIdiRequest3; | 
|  | Requests[4] = DivaIdiRequest4; | 
|  | Requests[5] = DivaIdiRequest5; | 
|  | Requests[6] = DivaIdiRequest6; | 
|  | Requests[7] = DivaIdiRequest7; | 
|  | Requests[8] = DivaIdiRequest8; | 
|  | Requests[9] = DivaIdiRequest9; | 
|  | Requests[10] = DivaIdiRequest10; | 
|  | Requests[11] = DivaIdiRequest11; | 
|  | Requests[12] = DivaIdiRequest12; | 
|  | Requests[13] = DivaIdiRequest13; | 
|  | Requests[14] = DivaIdiRequest14; | 
|  | Requests[15] = DivaIdiRequest15; | 
|  | Requests[16] = DivaIdiRequest16; | 
|  | Requests[17] = DivaIdiRequest17; | 
|  | Requests[18] = DivaIdiRequest18; | 
|  | Requests[19] = DivaIdiRequest19; | 
|  | Requests[20] = DivaIdiRequest20; | 
|  | Requests[21] = DivaIdiRequest21; | 
|  | Requests[22] = DivaIdiRequest22; | 
|  | Requests[23] = DivaIdiRequest23; | 
|  | Requests[24] = DivaIdiRequest24; | 
|  | Requests[25] = DivaIdiRequest25; | 
|  | Requests[26] = DivaIdiRequest26; | 
|  | Requests[27] = DivaIdiRequest27; | 
|  | Requests[28] = DivaIdiRequest28; | 
|  | Requests[29] = DivaIdiRequest29; | 
|  | Requests[30] = DivaIdiRequest30; | 
|  | Requests[31] = DivaIdiRequest31; | 
|  | } | 
|  |  | 
|  | void diva_xdi_display_adapter_features(int card) | 
|  | { | 
|  | dword features; | 
|  | if (!card || ((card - 1) >= MAX_ADAPTER) || !IoAdapters[card - 1]) { | 
|  | return; | 
|  | } | 
|  | card--; | 
|  | features = IoAdapters[card]->Properties.Features; | 
|  |  | 
|  | DBG_LOG(("FEATURES FOR ADAPTER: %d", card + 1)) | 
|  | DBG_LOG((" DI_FAX3          :  %s", | 
|  | (features & DI_FAX3) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_MODEM         :  %s", | 
|  | (features & DI_MODEM) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_POST          :  %s", | 
|  | (features & DI_POST) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_V110          :  %s", | 
|  | (features & DI_V110) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_V120          :  %s", | 
|  | (features & DI_V120) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_POTS          :  %s", | 
|  | (features & DI_POTS) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_CODEC         :  %s", | 
|  | (features & DI_CODEC) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_MANAGE        :  %s", | 
|  | (features & DI_MANAGE) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_V_42          :  %s", | 
|  | (features & DI_V_42) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_EXTD_FAX      :  %s", | 
|  | (features & DI_EXTD_FAX) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_AT_PARSER     :  %s", | 
|  | (features & DI_AT_PARSER) ? "Y" : "N")) | 
|  | DBG_LOG((" DI_VOICE_OVER_IP :  %s", | 
|  | (features & DI_VOICE_OVER_IP) ? "Y" : "N")) | 
|  | } | 
|  |  | 
|  | void diva_add_slave_adapter(diva_os_xdi_adapter_t * a) | 
|  | { | 
|  | diva_os_spin_lock_magic_t old_irql; | 
|  |  | 
|  | diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add_slave"); | 
|  | list_add_tail(&a->link, &adapter_queue); | 
|  | diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add_slave"); | 
|  | } | 
|  |  | 
|  | int diva_card_read_xlog(diva_os_xdi_adapter_t * a) | 
|  | { | 
|  | diva_get_xlog_t *req; | 
|  | byte *data; | 
|  |  | 
|  | if (!a->xdi_adapter.Initialized || !a->xdi_adapter.DIRequest) { | 
|  | return (-1); | 
|  | } | 
|  | if (!(data = diva_os_malloc(0, sizeof(struct mi_pc_maint)))) { | 
|  | return (-1); | 
|  | } | 
|  | memset(data, 0x00, sizeof(struct mi_pc_maint)); | 
|  |  | 
|  | if (!(req = diva_os_malloc(0, sizeof(*req)))) { | 
|  | diva_os_free(0, data); | 
|  | return (-1); | 
|  | } | 
|  | req->command = 0x0400; | 
|  | req->req = LOG; | 
|  | req->rc = 0x00; | 
|  |  | 
|  | (*(a->xdi_adapter.DIRequest)) (&a->xdi_adapter, (ENTITY *) req); | 
|  |  | 
|  | if (!req->rc || req->req) { | 
|  | diva_os_free(0, data); | 
|  | diva_os_free(0, req); | 
|  | return (-1); | 
|  | } | 
|  |  | 
|  | memcpy(data, &req->req, sizeof(struct mi_pc_maint)); | 
|  |  | 
|  | diva_os_free(0, req); | 
|  |  | 
|  | a->xdi_mbox.data_length = sizeof(struct mi_pc_maint); | 
|  | a->xdi_mbox.data = data; | 
|  | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | 
|  |  | 
|  | return (0); | 
|  | } | 
|  |  | 
|  | void xdiFreeFile(void *handle) | 
|  | { | 
|  | } |