Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / isdn / hardware / eicon / diva.c
diff --git a/kernel/drivers/isdn/hardware/eicon/diva.c b/kernel/drivers/isdn/hardware/eicon/diva.c
new file mode 100644 (file)
index 0000000..d91dd58
--- /dev/null
@@ -0,0 +1,657 @@
+/* $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)
+{
+}