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