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
29PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
30extern IDI_CALL Requests[MAX_ADAPTER];
31extern int create_adapter_proc(diva_os_xdi_adapter_t *a);
32extern 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*/
41DivaIdiReqFunc(0)
42DivaIdiReqFunc(1)
43DivaIdiReqFunc(2)
44DivaIdiReqFunc(3)
45DivaIdiReqFunc(4)
46DivaIdiReqFunc(5)
47DivaIdiReqFunc(6)
48DivaIdiReqFunc(7)
49DivaIdiReqFunc(8)
50DivaIdiReqFunc(9)
51DivaIdiReqFunc(10)
52DivaIdiReqFunc(11)
53DivaIdiReqFunc(12)
54DivaIdiReqFunc(13)
55DivaIdiReqFunc(14)
56DivaIdiReqFunc(15)
57DivaIdiReqFunc(16)
58DivaIdiReqFunc(17)
59DivaIdiReqFunc(18)
60DivaIdiReqFunc(19)
61DivaIdiReqFunc(20)
62DivaIdiReqFunc(21)
63DivaIdiReqFunc(22)
64DivaIdiReqFunc(23)
65DivaIdiReqFunc(24)
66DivaIdiReqFunc(25)
67DivaIdiReqFunc(26)
68DivaIdiReqFunc(27)
69DivaIdiReqFunc(28)
70DivaIdiReqFunc(29)
71DivaIdiReqFunc(30)
72DivaIdiReqFunc(31)
73
74/*
75**  LOCALS
76*/
77static LIST_HEAD(adapter_queue);
78
79typedef 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
86typedef struct _diva_supported_cards_info {
87	int CardOrdinal;
88	diva_init_card_proc_t init_card;
89} diva_supported_cards_info_t;
90
91static 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
135static void diva_init_request_array(void);
136static void *divas_create_pci_card(int handle, void *pci_dev_handle);
137
138static diva_os_spin_lock_t adapter_lock;
139
140static 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
153static 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   -------------------------------------------------------------------------- */
166void *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   -------------------------------------------------------------------------- */
248int 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   -------------------------------------------------------------------------- */
260static 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   -------------------------------------------------------------------------- */
279void 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   -------------------------------------------------------------------------- */
323static 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   -------------------------------------------------------------------------- */
369void 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*/
389void *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*/
426void 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
437int
438diva_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*/
480int
481diva_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
516irqreturn_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
534static 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
570void 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
606void 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
615int 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
655void xdiFreeFile(void *handle)
656{
657}
658