| // SPDX-License-Identifier: GPL-2.0 |
| /* $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) |
| { |
| } |