Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
[linux-2.6] / drivers / isdn / hardware / eicon / diva.c
1 /* $Id: diva.c,v 1.21.4.1 2004/05/08 14:33:43 armin Exp $ */
2
3 #define CARDTYPE_H_WANT_DATA            1
4 #define CARDTYPE_H_WANT_IDI_DATA        0
5 #define CARDTYPE_H_WANT_RESOURCE_DATA   0
6 #define CARDTYPE_H_WANT_FILE_DATA       0
7
8 #include "platform.h"
9 #include "debuglib.h"
10 #include "cardtype.h"
11 #include "pc.h"
12 #include "di_defs.h"
13 #include "di.h"
14 #include "io.h"
15 #include "pc_maint.h"
16 #include "xdi_msg.h"
17 #include "xdi_adapter.h"
18 #include "diva_pci.h"
19 #include "diva.h"
20
21 #ifdef CONFIG_ISDN_DIVAS_PRIPCI
22 #include "os_pri.h"
23 #endif
24 #ifdef CONFIG_ISDN_DIVAS_BRIPCI
25 #include "os_bri.h"
26 #include "os_4bri.h"
27 #endif
28
29 PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
30 extern IDI_CALL Requests[MAX_ADAPTER];
31 extern int create_adapter_proc(diva_os_xdi_adapter_t * a);
32 extern void remove_adapter_proc(diva_os_xdi_adapter_t * a);
33
34 #define DivaIdiReqFunc(N) \
35 static void DivaIdiRequest##N(ENTITY *e) \
36 { if ( IoAdapters[N] ) (* IoAdapters[N]->DIRequest)(IoAdapters[N], e) ; }
37
38 /*
39 **  Create own 32 Adapters
40 */
41 DivaIdiReqFunc(0)
42 DivaIdiReqFunc(1)
43 DivaIdiReqFunc(2)
44 DivaIdiReqFunc(3)
45 DivaIdiReqFunc(4)
46 DivaIdiReqFunc(5)
47 DivaIdiReqFunc(6)
48 DivaIdiReqFunc(7)
49 DivaIdiReqFunc(8)
50 DivaIdiReqFunc(9)
51 DivaIdiReqFunc(10)
52 DivaIdiReqFunc(11)
53 DivaIdiReqFunc(12)
54 DivaIdiReqFunc(13)
55 DivaIdiReqFunc(14)
56 DivaIdiReqFunc(15)
57 DivaIdiReqFunc(16)
58 DivaIdiReqFunc(17)
59 DivaIdiReqFunc(18)
60 DivaIdiReqFunc(19)
61 DivaIdiReqFunc(20)
62 DivaIdiReqFunc(21)
63 DivaIdiReqFunc(22)
64 DivaIdiReqFunc(23)
65 DivaIdiReqFunc(24)
66 DivaIdiReqFunc(25)
67 DivaIdiReqFunc(26)
68 DivaIdiReqFunc(27)
69 DivaIdiReqFunc(28)
70 DivaIdiReqFunc(29)
71 DivaIdiReqFunc(30)
72 DivaIdiReqFunc(31)
73
74 /*
75 **  LOCALS
76 */
77 static LIST_HEAD(adapter_queue);
78
79 typedef struct _diva_get_xlog {
80         word command;
81         byte req;
82         byte rc;
83         byte data[sizeof(struct mi_pc_maint)];
84 } diva_get_xlog_t;
85
86 typedef struct _diva_supported_cards_info {
87         int CardOrdinal;
88         diva_init_card_proc_t init_card;
89 } diva_supported_cards_info_t;
90
91 static diva_supported_cards_info_t divas_supported_cards[] = {
92 #ifdef CONFIG_ISDN_DIVAS_PRIPCI
93         /*
94            PRI Cards
95          */
96         {CARDTYPE_DIVASRV_P_30M_PCI, diva_pri_init_card},
97         /*
98            PRI Rev.2 Cards
99          */
100         {CARDTYPE_DIVASRV_P_30M_V2_PCI, diva_pri_init_card},
101         /*
102            PRI Rev.2 VoIP Cards
103          */
104         {CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card},
105 #endif
106 #ifdef CONFIG_ISDN_DIVAS_BRIPCI
107         /*
108            4BRI Rev 1 Cards
109          */
110         {CARDTYPE_DIVASRV_Q_8M_PCI, diva_4bri_init_card},
111         {CARDTYPE_DIVASRV_VOICE_Q_8M_PCI, diva_4bri_init_card},
112         /*
113            4BRI Rev 2 Cards
114          */
115         {CARDTYPE_DIVASRV_Q_8M_V2_PCI, diva_4bri_init_card},
116         {CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI, diva_4bri_init_card},
117         /*
118            4BRI Based BRI Rev 2 Cards
119          */
120         {CARDTYPE_DIVASRV_B_2M_V2_PCI, diva_4bri_init_card},
121         {CARDTYPE_DIVASRV_B_2F_PCI, diva_4bri_init_card},
122         {CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card},
123         /*
124            BRI
125          */
126         {CARDTYPE_MAESTRA_PCI, diva_bri_init_card},
127 #endif
128
129         /*
130            EOL
131          */
132         {-1}
133 };
134
135 static void diva_init_request_array(void);
136 static void *divas_create_pci_card(int handle, void *pci_dev_handle);
137
138 static diva_os_spin_lock_t adapter_lock;
139
140 static int diva_find_free_adapters(int base, int nr)
141 {
142         int i;
143
144         for (i = 0; i < nr; i++) {
145                 if (IoAdapters[base + i]) {
146                         return (-1);
147                 }
148         }
149
150         return (0);
151 }
152
153 static diva_os_xdi_adapter_t *diva_q_get_next(struct list_head * what)
154 {
155         diva_os_xdi_adapter_t *a = NULL;
156
157         if (what && (what->next != &adapter_queue))
158                 a = list_entry(what->next, diva_os_xdi_adapter_t, link);
159
160         return(a);
161 }
162
163 /* --------------------------------------------------------------------------
164     Add card to the card list
165    -------------------------------------------------------------------------- */
166 void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal)
167 {
168         diva_os_spin_lock_magic_t old_irql;
169         diva_os_xdi_adapter_t *pdiva, *pa;
170         int i, j, max, nr;
171
172         for (i = 0; divas_supported_cards[i].CardOrdinal != -1; i++) {
173                 if (divas_supported_cards[i].CardOrdinal == CardOrdinal) {
174                         if (!(pdiva = divas_create_pci_card(i, pdev))) {
175                                 return NULL;
176                         }
177                         switch (CardOrdinal) {
178                         case CARDTYPE_DIVASRV_Q_8M_PCI:
179                         case CARDTYPE_DIVASRV_VOICE_Q_8M_PCI:
180                         case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
181                         case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
182                                 max = MAX_ADAPTER - 4;
183                                 nr = 4;
184                                 break;
185
186                         default:
187                                 max = MAX_ADAPTER;
188                                 nr = 1;
189                         }
190
191                         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
192
193                         for (i = 0; i < max; i++) {
194                                 if (!diva_find_free_adapters(i, nr)) {
195                                         pdiva->controller = i + 1;
196                                         pdiva->xdi_adapter.ANum = pdiva->controller;
197                                         IoAdapters[i] = &pdiva->xdi_adapter;
198                                         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
199                                         create_adapter_proc(pdiva);     /* add adapter to proc file system */
200
201                                         DBG_LOG(("add %s:%d",
202                                                  CardProperties
203                                                  [CardOrdinal].Name,
204                                                  pdiva->controller))
205
206                                         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
207                                         pa = pdiva;
208                                         for (j = 1; j < nr; j++) {      /* slave adapters, if any */
209                                                 pa = diva_q_get_next(&pa->link);
210                                                 if (pa && !pa->interface.cleanup_adapter_proc) {
211                                                         pa->controller = i + 1 + j;
212                                                         pa->xdi_adapter.ANum = pa->controller;
213                                                         IoAdapters[i + j] = &pa->xdi_adapter;
214                                                         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
215                                                         DBG_LOG(("add slave adapter (%d)",
216                                                                  pa->controller))
217                                                         create_adapter_proc(pa);        /* add adapter to proc file system */
218                                                         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
219                                                 } else {
220                                                         DBG_ERR(("slave adapter problem"))
221                                                         break;
222                                                 }
223                                         }
224
225                                         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
226                                         return (pdiva);
227                                 }
228                         }
229
230                         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
231
232                         /*
233                            Not able to add adapter - remove it and return error
234                          */
235                         DBG_ERR(("can not alloc request array"))
236                         diva_driver_remove_card(pdiva);
237
238                         return NULL;
239                 }
240         }
241
242         return NULL;
243 }
244
245 /* --------------------------------------------------------------------------
246     Called on driver load, MAIN, main, DriverEntry
247    -------------------------------------------------------------------------- */
248 int divasa_xdi_driver_entry(void)
249 {
250         diva_os_initialize_spin_lock(&adapter_lock, "adapter");
251         memset(&IoAdapters[0], 0x00, sizeof(IoAdapters));
252         diva_init_request_array();
253
254         return (0);
255 }
256
257 /* --------------------------------------------------------------------------
258     Remove adapter from list
259    -------------------------------------------------------------------------- */
260 static diva_os_xdi_adapter_t *get_and_remove_from_queue(void)
261 {
262         diva_os_spin_lock_magic_t old_irql;
263         diva_os_xdi_adapter_t *a = NULL;
264
265         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "driver_unload");
266
267         if (!list_empty(&adapter_queue)) {
268                 a = list_entry(adapter_queue.next, diva_os_xdi_adapter_t, link);
269                 list_del(adapter_queue.next);
270         }
271
272         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
273         return (a);
274 }
275
276 /* --------------------------------------------------------------------------
277     Remove card from the card list
278    -------------------------------------------------------------------------- */
279 void diva_driver_remove_card(void *pdiva)
280 {
281         diva_os_spin_lock_magic_t old_irql;
282         diva_os_xdi_adapter_t *a[4];
283         diva_os_xdi_adapter_t *pa;
284         int i;
285
286         pa = a[0] = (diva_os_xdi_adapter_t *) pdiva;
287         a[1] = a[2] = a[3] = NULL;
288
289         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "remode adapter");
290
291         for (i = 1; i < 4; i++) {
292                 if ((pa = diva_q_get_next(&pa->link))
293                     && !pa->interface.cleanup_adapter_proc) {
294                         a[i] = pa;
295                 } else {
296                         break;
297                 }
298         }
299
300         for (i = 0; ((i < 4) && a[i]); i++) {
301                 list_del(&a[i]->link);
302         }
303
304         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
305
306         (*(a[0]->interface.cleanup_adapter_proc)) (a[0]);
307
308         for (i = 0; i < 4; i++) {
309                 if (a[i]) {
310                         if (a[i]->controller) {
311                                 DBG_LOG(("remove adapter (%d)",
312                                          a[i]->controller)) IoAdapters[a[i]->controller - 1] = NULL;
313                                 remove_adapter_proc(a[i]);
314                         }
315                         diva_os_free(0, a[i]);
316                 }
317         }
318 }
319
320 /* --------------------------------------------------------------------------
321     Create diva PCI adapter and init internal adapter structures
322    -------------------------------------------------------------------------- */
323 static void *divas_create_pci_card(int handle, void *pci_dev_handle)
324 {
325         diva_supported_cards_info_t *pI = &divas_supported_cards[handle];
326         diva_os_spin_lock_magic_t old_irql;
327         diva_os_xdi_adapter_t *a;
328
329         DBG_LOG(("found %d-%s", pI->CardOrdinal, CardProperties[pI->CardOrdinal].Name))
330
331         if (!(a = (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) {
332                 DBG_ERR(("A: can't alloc adapter"));
333                 return NULL;
334         }
335
336         memset(a, 0x00, sizeof(*a));
337
338         a->CardIndex = handle;
339         a->CardOrdinal = pI->CardOrdinal;
340         a->Bus = DIVAS_XDI_ADAPTER_BUS_PCI;
341         a->xdi_adapter.cardType = a->CardOrdinal;
342         a->resources.pci.bus = diva_os_get_pci_bus(pci_dev_handle);
343         a->resources.pci.func = diva_os_get_pci_func(pci_dev_handle);
344         a->resources.pci.hdev = pci_dev_handle;
345
346         /*
347            Add master adapter first, so slave adapters will receive higher
348            numbers as master adapter
349          */
350         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
351         list_add_tail(&a->link, &adapter_queue);
352         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
353
354         if ((*(pI->init_card)) (a)) {
355                 diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
356                 list_del(&a->link);
357                 diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
358                 diva_os_free(0, a);
359                 DBG_ERR(("A: can't get adapter resources"));
360                 return NULL;
361         }
362
363         return (a);
364 }
365
366 /* --------------------------------------------------------------------------
367     Called on driver unload FINIT, finit, Unload
368    -------------------------------------------------------------------------- */
369 void divasa_xdi_driver_unload(void)
370 {
371         diva_os_xdi_adapter_t *a;
372
373         while ((a = get_and_remove_from_queue())) {
374                 if (a->interface.cleanup_adapter_proc) {
375                         (*(a->interface.cleanup_adapter_proc)) (a);
376                 }
377                 if (a->controller) {
378                         IoAdapters[a->controller - 1] = NULL;
379                         remove_adapter_proc(a);
380                 }
381                 diva_os_free(0, a);
382         }
383         diva_os_destroy_spin_lock(&adapter_lock, "adapter");
384 }
385
386 /*
387 **  Receive and process command from user mode utility
388 */
389 void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
390                             int length,
391                             divas_xdi_copy_from_user_fn_t cp_fn)
392 {
393         diva_xdi_um_cfg_cmd_t msg;
394         diva_os_xdi_adapter_t *a = NULL;
395         diva_os_spin_lock_magic_t old_irql;
396         struct list_head *tmp;
397
398         if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
399                 DBG_ERR(("A: A(?) open, msg too small (%d < %d)",
400                          length, sizeof(diva_xdi_um_cfg_cmd_t)))
401                 return NULL;
402         }
403         if ((*cp_fn) (os_handle, &msg, src, sizeof(msg)) <= 0) {
404                 DBG_ERR(("A: A(?) open, write error"))
405                 return NULL;
406         }
407         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter");
408         list_for_each(tmp, &adapter_queue) {
409                 a = list_entry(tmp, diva_os_xdi_adapter_t, link);
410                 if (a->controller == (int)msg.adapter)
411                         break;
412                 a = NULL;
413         }
414         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter");
415
416         if (!a) {
417                 DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter))
418         }
419
420         return (a);
421 }
422
423 /*
424 **  Easy cleanup mailbox status
425 */
426 void diva_xdi_close_adapter(void *adapter, void *os_handle)
427 {
428         diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
429
430         a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
431         if (a->xdi_mbox.data) {
432                 diva_os_free(0, a->xdi_mbox.data);
433                 a->xdi_mbox.data = NULL;
434         }
435 }
436
437 int
438 diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
439                int length, divas_xdi_copy_from_user_fn_t cp_fn)
440 {
441         diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
442         void *data;
443
444         if (a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY) {
445                 DBG_ERR(("A: A(%d) write, mbox busy", a->controller))
446                 return (-1);
447         }
448
449         if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
450                 DBG_ERR(("A: A(%d) write, message too small (%d < %d)",
451                          a->controller, length,
452                          sizeof(diva_xdi_um_cfg_cmd_t)))
453                 return (-3);
454         }
455
456         if (!(data = diva_os_malloc(0, length))) {
457                 DBG_ERR(("A: A(%d) write, ENOMEM", a->controller))
458                 return (-2);
459         }
460
461         length = (*cp_fn) (os_handle, data, src, length);
462         if (length > 0) {
463                 if ((*(a->interface.cmd_proc))
464                     (a, (diva_xdi_um_cfg_cmd_t *) data, length)) {
465                         length = -3;
466                 }
467         } else {
468                 DBG_ERR(("A: A(%d) write error (%d)", a->controller,
469                          length))
470         }
471
472         diva_os_free(0, data);
473
474         return (length);
475 }
476
477 /*
478 **  Write answers to user mode utility, if any
479 */
480 int
481 diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
482               int max_length, divas_xdi_copy_to_user_fn_t cp_fn)
483 {
484         diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
485         int ret;
486
487         if (!(a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY)) {
488                 DBG_ERR(("A: A(%d) rx mbox empty", a->controller))
489                 return (-1);
490         }
491         if (!a->xdi_mbox.data) {
492                 a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
493                 DBG_ERR(("A: A(%d) rx ENOMEM", a->controller))
494                 return (-2);
495         }
496
497         if (max_length < a->xdi_mbox.data_length) {
498                 DBG_ERR(("A: A(%d) rx buffer too short(%d < %d)",
499                          a->controller, max_length,
500                          a->xdi_mbox.data_length))
501                 return (-3);
502         }
503
504         ret = (*cp_fn) (os_handle, dst, a->xdi_mbox.data,
505                       a->xdi_mbox.data_length);
506         if (ret > 0) {
507                 diva_os_free(0, a->xdi_mbox.data);
508                 a->xdi_mbox.data = NULL;
509                 a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
510         }
511
512         return (ret);
513 }
514
515
516 irqreturn_t diva_os_irq_wrapper(int irq, void *context)
517 {
518         diva_os_xdi_adapter_t *a = context;
519         diva_xdi_clear_interrupts_proc_t clear_int_proc;
520
521         if (!a || !a->xdi_adapter.diva_isr_handler)
522                 return IRQ_NONE;
523
524         if ((clear_int_proc = a->clear_interrupts_proc)) {
525                 (*clear_int_proc) (a);
526                 a->clear_interrupts_proc = NULL;
527                 return IRQ_HANDLED;
528         }
529
530         (*(a->xdi_adapter.diva_isr_handler)) (&a->xdi_adapter);
531         return IRQ_HANDLED;
532 }
533
534 static void diva_init_request_array(void)
535 {
536         Requests[0] = DivaIdiRequest0;
537         Requests[1] = DivaIdiRequest1;
538         Requests[2] = DivaIdiRequest2;
539         Requests[3] = DivaIdiRequest3;
540         Requests[4] = DivaIdiRequest4;
541         Requests[5] = DivaIdiRequest5;
542         Requests[6] = DivaIdiRequest6;
543         Requests[7] = DivaIdiRequest7;
544         Requests[8] = DivaIdiRequest8;
545         Requests[9] = DivaIdiRequest9;
546         Requests[10] = DivaIdiRequest10;
547         Requests[11] = DivaIdiRequest11;
548         Requests[12] = DivaIdiRequest12;
549         Requests[13] = DivaIdiRequest13;
550         Requests[14] = DivaIdiRequest14;
551         Requests[15] = DivaIdiRequest15;
552         Requests[16] = DivaIdiRequest16;
553         Requests[17] = DivaIdiRequest17;
554         Requests[18] = DivaIdiRequest18;
555         Requests[19] = DivaIdiRequest19;
556         Requests[20] = DivaIdiRequest20;
557         Requests[21] = DivaIdiRequest21;
558         Requests[22] = DivaIdiRequest22;
559         Requests[23] = DivaIdiRequest23;
560         Requests[24] = DivaIdiRequest24;
561         Requests[25] = DivaIdiRequest25;
562         Requests[26] = DivaIdiRequest26;
563         Requests[27] = DivaIdiRequest27;
564         Requests[28] = DivaIdiRequest28;
565         Requests[29] = DivaIdiRequest29;
566         Requests[30] = DivaIdiRequest30;
567         Requests[31] = DivaIdiRequest31;
568 }
569
570 void diva_xdi_display_adapter_features(int card)
571 {
572         dword features;
573         if (!card || ((card - 1) >= MAX_ADAPTER) || !IoAdapters[card - 1]) {
574                 return;
575         }
576         card--;
577         features = IoAdapters[card]->Properties.Features;
578
579         DBG_LOG(("FEATURES FOR ADAPTER: %d", card + 1))
580         DBG_LOG((" DI_FAX3          :  %s",
581                      (features & DI_FAX3) ? "Y" : "N"))
582         DBG_LOG((" DI_MODEM         :  %s",
583                      (features & DI_MODEM) ? "Y" : "N"))
584         DBG_LOG((" DI_POST          :  %s",
585                      (features & DI_POST) ? "Y" : "N"))
586         DBG_LOG((" DI_V110          :  %s",
587                      (features & DI_V110) ? "Y" : "N"))
588         DBG_LOG((" DI_V120          :  %s",
589                      (features & DI_V120) ? "Y" : "N"))
590         DBG_LOG((" DI_POTS          :  %s",
591                      (features & DI_POTS) ? "Y" : "N"))
592         DBG_LOG((" DI_CODEC         :  %s",
593                      (features & DI_CODEC) ? "Y" : "N"))
594         DBG_LOG((" DI_MANAGE        :  %s",
595                      (features & DI_MANAGE) ? "Y" : "N"))
596         DBG_LOG((" DI_V_42          :  %s",
597                      (features & DI_V_42) ? "Y" : "N"))
598         DBG_LOG((" DI_EXTD_FAX      :  %s",
599                      (features & DI_EXTD_FAX) ? "Y" : "N"))
600         DBG_LOG((" DI_AT_PARSER     :  %s",
601                      (features & DI_AT_PARSER) ? "Y" : "N"))
602         DBG_LOG((" DI_VOICE_OVER_IP :  %s",
603                      (features & DI_VOICE_OVER_IP) ? "Y" : "N"))
604 }
605
606 void diva_add_slave_adapter(diva_os_xdi_adapter_t * a)
607 {
608         diva_os_spin_lock_magic_t old_irql;
609
610         diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add_slave");
611         list_add_tail(&a->link, &adapter_queue);
612         diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add_slave");
613 }
614
615 int diva_card_read_xlog(diva_os_xdi_adapter_t * a)
616 {
617         diva_get_xlog_t *req;
618         byte *data;
619
620         if (!a->xdi_adapter.Initialized || !a->xdi_adapter.DIRequest) {
621                 return (-1);
622         }
623         if (!(data = diva_os_malloc(0, sizeof(struct mi_pc_maint)))) {
624                 return (-1);
625         }
626         memset(data, 0x00, sizeof(struct mi_pc_maint));
627
628         if (!(req = diva_os_malloc(0, sizeof(*req)))) {
629                 diva_os_free(0, data);
630                 return (-1);
631         }
632         req->command = 0x0400;
633         req->req = LOG;
634         req->rc = 0x00;
635
636         (*(a->xdi_adapter.DIRequest)) (&a->xdi_adapter, (ENTITY *) req);
637
638         if (!req->rc || req->req) {
639                 diva_os_free(0, data);
640                 diva_os_free(0, req);
641                 return (-1);
642         }
643
644         memcpy(data, &req->req, sizeof(struct mi_pc_maint));
645
646         diva_os_free(0, req);
647
648         a->xdi_mbox.data_length = sizeof(struct mi_pc_maint);
649         a->xdi_mbox.data = data;
650         a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
651
652         return (0);
653 }
654
655 void xdiFreeFile(void *handle)
656 {
657 }