1 #include "platform.h"
2 #include "pc.h"
3 #include "di_defs.h"
4 #include "debug_if.h"
5 #include "divasync.h"
6 #include "kst_ifc.h"
7 #include "maintidi.h"
8 #include "man_defs.h"
9 
10 /*
11   LOCALS
12 */
13 #define DBG_MAGIC (0x47114711L)
14 
15 static void DI_register(void *arg);
16 static void DI_deregister(pDbgHandle hDbg);
17 static void DI_format(int do_lock, word id, int type, char *format, va_list argument_list);
18 static void DI_format_locked(word id, int type, char *format, va_list argument_list);
DI_format_old(word id,char * format,va_list ap)19 static void DI_format_old(word id, char *format, va_list ap) { }
DiProcessEventLog(unsigned short id,unsigned long msgID,va_list ap)20 static void DiProcessEventLog(unsigned short id, unsigned long msgID, va_list ap) { }
21 static void single_p(byte *P, word *PLength, byte Id);
22 static void diva_maint_xdi_cb(ENTITY *e);
23 static word SuperTraceCreateReadReq(byte *P, const char *path);
24 static int diva_mnt_cmp_nmbr(const char *nmbr);
25 static void diva_free_dma_descriptor(IDI_CALL request, int nr);
26 static int diva_get_dma_descriptor(IDI_CALL request, dword *dma_magic);
27 void diva_mnt_internal_dprintf(dword drv_id, dword type, char *p, ...);
28 
29 static dword MaxDumpSize = 256;
30 static dword MaxXlogSize = 2 + 128;
31 static char  TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH + 1];
32 static int TraceFilterIdent   = -1;
33 static int TraceFilterChannel = -1;
34 
35 typedef struct _diva_maint_client {
36 	dword       sec;
37 	dword       usec;
38 	pDbgHandle  hDbg;
39 	char        drvName[128];
40 	dword       dbgMask;
41 	dword       last_dbgMask;
42 	IDI_CALL    request;
43 	_DbgHandle_ Dbg;
44 	int         logical;
45 	int         channels;
46 	diva_strace_library_interface_t *pIdiLib;
47 	BUFFERS     XData;
48 	char        xbuffer[2048 + 512];
49 	byte        *pmem;
50 	int         request_pending;
51 	int         dma_handle;
52 } diva_maint_client_t;
53 static diva_maint_client_t clients[MAX_DESCRIPTORS];
54 
55 static void diva_change_management_debug_mask(diva_maint_client_t *pC, dword old_mask);
56 
57 static void diva_maint_error(void *user_context,
58 			     diva_strace_library_interface_t *hLib,
59 			     int Adapter,
60 			     int error,
61 			     const char *file,
62 			     int line);
63 static void diva_maint_state_change_notify(void *user_context,
64 					   diva_strace_library_interface_t *hLib,
65 					   int Adapter,
66 					   diva_trace_line_state_t *channel,
67 					   int notify_subject);
68 static void diva_maint_trace_notify(void *user_context,
69 				    diva_strace_library_interface_t *hLib,
70 				    int Adapter,
71 				    void *xlog_buffer,
72 				    int length);
73 
74 
75 
76 typedef struct MSG_QUEUE {
77 	dword	Size;		/* total size of queue (constant)	*/
78 	byte	*Base;		/* lowest address (constant)		*/
79 	byte	*High;		/* Base + Size (constant)		*/
80 	byte	*Head;		/* first message in queue (if any)	*/
81 	byte	*Tail;		/* first free position			*/
82 	byte	*Wrap;		/* current wraparound position		*/
83 	dword	Count;		/* current no of bytes in queue		*/
84 } MSG_QUEUE;
85 
86 typedef struct MSG_HEAD {
87 	volatile dword	Size;		/* size of data following MSG_HEAD	*/
88 #define	MSG_INCOMPLETE	0x8000	/* ored to Size until queueCompleteMsg	*/
89 } MSG_HEAD;
90 
91 #define queueCompleteMsg(p) do { ((MSG_HEAD *)p - 1)->Size &= ~MSG_INCOMPLETE; } while (0)
92 #define queueCount(q)	((q)->Count)
93 #define MSG_NEED(size)							\
94 	((sizeof(MSG_HEAD) + size + sizeof(dword) - 1) & ~(sizeof(dword) - 1))
95 
queueInit(MSG_QUEUE * Q,byte * Buffer,dword sizeBuffer)96 static void queueInit(MSG_QUEUE *Q, byte *Buffer, dword sizeBuffer) {
97 	Q->Size = sizeBuffer;
98 	Q->Base = Q->Head = Q->Tail = Buffer;
99 	Q->High = Buffer + sizeBuffer;
100 	Q->Wrap = NULL;
101 	Q->Count = 0;
102 }
103 
queueAllocMsg(MSG_QUEUE * Q,word size)104 static byte *queueAllocMsg(MSG_QUEUE *Q, word size) {
105 	/* Allocate 'size' bytes at tail of queue which will be filled later
106 	 * directly with callers own message header info and/or message.
107 	 * An 'alloced' message is marked incomplete by oring the 'Size' field
108 	 * with MSG_INCOMPLETE.
109 	 * This must be reset via queueCompleteMsg() after the message is filled.
110 	 * As long as a message is marked incomplete queuePeekMsg() will return
111 	 * a 'queue empty' condition when it reaches such a message.  */
112 
113 	MSG_HEAD *Msg;
114 	word need = MSG_NEED(size);
115 
116 	if (Q->Tail == Q->Head) {
117 		if (Q->Wrap || need > Q->Size) {
118 			return NULL; /* full */
119 		}
120 		goto alloc; /* empty */
121 	}
122 
123 	if (Q->Tail > Q->Head) {
124 		if (Q->Tail + need <= Q->High) goto alloc; /* append */
125 		if (Q->Base + need > Q->Head) {
126 			return NULL; /* too much */
127 		}
128 		/* wraparound the queue (but not the message) */
129 		Q->Wrap = Q->Tail;
130 		Q->Tail = Q->Base;
131 		goto alloc;
132 	}
133 
134 	if (Q->Tail + need > Q->Head) {
135 		return NULL; /* too much */
136 	}
137 
138 alloc:
139 	Msg = (MSG_HEAD *)Q->Tail;
140 
141 	Msg->Size = size | MSG_INCOMPLETE;
142 
143 	Q->Tail	 += need;
144 	Q->Count += size;
145 
146 
147 
148 	return ((byte *)(Msg + 1));
149 }
150 
queueFreeMsg(MSG_QUEUE * Q)151 static void queueFreeMsg(MSG_QUEUE *Q) {
152 /* Free the message at head of queue */
153 
154 	word size = ((MSG_HEAD *)Q->Head)->Size & ~MSG_INCOMPLETE;
155 
156 	Q->Head  += MSG_NEED(size);
157 	Q->Count -= size;
158 
159 	if (Q->Wrap) {
160 		if (Q->Head >= Q->Wrap) {
161 			Q->Head = Q->Base;
162 			Q->Wrap = NULL;
163 		}
164 	} else if (Q->Head >= Q->Tail) {
165 		Q->Head = Q->Tail = Q->Base;
166 	}
167 }
168 
queuePeekMsg(MSG_QUEUE * Q,word * size)169 static byte *queuePeekMsg(MSG_QUEUE *Q, word *size) {
170 	/* Show the first valid message in queue BUT DON'T free the message.
171 	 * After looking on the message contents it can be freed queueFreeMsg()
172 	 * or simply remain in message queue.  */
173 
174 	MSG_HEAD *Msg = (MSG_HEAD *)Q->Head;
175 
176 	if (((byte *)Msg == Q->Tail && !Q->Wrap) ||
177 	    (Msg->Size & MSG_INCOMPLETE)) {
178 		return NULL;
179 	} else {
180 		*size = Msg->Size;
181 		return ((byte *)(Msg + 1));
182 	}
183 }
184 
185 /*
186   Message queue header
187 */
188 static MSG_QUEUE *dbg_queue;
189 static byte *dbg_base;
190 static int                 external_dbg_queue;
191 static diva_os_spin_lock_t dbg_q_lock;
192 static diva_os_spin_lock_t dbg_adapter_lock;
193 static int                 dbg_q_busy;
194 static volatile dword      dbg_sequence;
195 static dword               start_sec;
196 static dword               start_usec;
197 
198 /*
199   INTERFACE:
200   Initialize run time queue structures.
201   base:    base of the message queue
202   length:  length of the message queue
203   do_init: perfor queue reset
204 
205   return:  zero on success, -1 on error
206 */
diva_maint_init(byte * base,unsigned long length,int do_init)207 int diva_maint_init(byte *base, unsigned long length, int do_init) {
208 	if (dbg_queue || (!base) || (length < (4096 * 4))) {
209 		return (-1);
210 	}
211 
212 	TraceFilter[0]     =  0;
213 	TraceFilterIdent   = -1;
214 	TraceFilterChannel = -1;
215 
216 	dbg_base = base;
217 
218 	diva_os_get_time(&start_sec, &start_usec);
219 
220 	*(dword *)base  = (dword)DBG_MAGIC; /* Store Magic */
221 	base   += sizeof(dword);
222 	length -= sizeof(dword);
223 
224 	*(dword *)base = 2048; /* Extension Field Length */
225 	base   += sizeof(dword);
226 	length -= sizeof(dword);
227 
228 	strcpy(base, "KERNEL MODE BUFFER\n");
229 	base   += 2048;
230 	length -= 2048;
231 
232 	*(dword *)base = 0; /* Terminate extension */
233 	base   += sizeof(dword);
234 	length -= sizeof(dword);
235 
236 	*(void **)base  =  (void *)(base + sizeof(void *)); /* Store Base  */
237 	base   += sizeof(void *);
238 	length -= sizeof(void *);
239 
240 	dbg_queue = (MSG_QUEUE *)base;
241 	queueInit(dbg_queue, base + sizeof(MSG_QUEUE), length - sizeof(MSG_QUEUE) - 512);
242 	external_dbg_queue = 0;
243 
244 	if (!do_init) {
245 		external_dbg_queue = 1; /* memory was located on the external device */
246 	}
247 
248 
249 	if (diva_os_initialize_spin_lock(&dbg_q_lock, "dbg_init")) {
250 		dbg_queue = NULL;
251 		dbg_base = NULL;
252 		external_dbg_queue = 0;
253 		return (-1);
254 	}
255 
256 	if (diva_os_initialize_spin_lock(&dbg_adapter_lock, "dbg_init")) {
257 		diva_os_destroy_spin_lock(&dbg_q_lock, "dbg_init");
258 		dbg_queue = NULL;
259 		dbg_base = NULL;
260 		external_dbg_queue = 0;
261 		return (-1);
262 	}
263 
264 	return (0);
265 }
266 
267 /*
268   INTERFACE:
269   Finit at unload time
270   return address of internal queue or zero if queue
271   was external
272 */
diva_maint_finit(void)273 void *diva_maint_finit(void) {
274 	void *ret = (void *)dbg_base;
275 	int i;
276 
277 	dbg_queue = NULL;
278 	dbg_base  = NULL;
279 
280 	if (ret) {
281 		diva_os_destroy_spin_lock(&dbg_q_lock, "dbg_finit");
282 		diva_os_destroy_spin_lock(&dbg_adapter_lock, "dbg_finit");
283 	}
284 
285 	if (external_dbg_queue) {
286 		ret = NULL;
287 	}
288 	external_dbg_queue = 0;
289 
290 	for (i = 1; i < ARRAY_SIZE(clients); i++) {
291 		if (clients[i].pmem) {
292 			diva_os_free(0, clients[i].pmem);
293 		}
294 	}
295 
296 	return (ret);
297 }
298 
299 /*
300   INTERFACE:
301   Return amount of messages in debug queue
302 */
diva_dbg_q_length(void)303 dword diva_dbg_q_length(void) {
304 	return (dbg_queue ? queueCount(dbg_queue)	: 0);
305 }
306 
307 /*
308   INTERFACE:
309   Lock message queue and return the pointer to the first
310   entry.
311 */
diva_maint_get_message(word * size,diva_os_spin_lock_magic_t * old_irql)312 diva_dbg_entry_head_t *diva_maint_get_message(word *size,
313 					      diva_os_spin_lock_magic_t *old_irql) {
314 	diva_dbg_entry_head_t *pmsg = NULL;
315 
316 	diva_os_enter_spin_lock(&dbg_q_lock, old_irql, "read");
317 	if (dbg_q_busy) {
318 		diva_os_leave_spin_lock(&dbg_q_lock, old_irql, "read_busy");
319 		return NULL;
320 	}
321 	dbg_q_busy = 1;
322 
323 	if (!(pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, size))) {
324 		dbg_q_busy = 0;
325 		diva_os_leave_spin_lock(&dbg_q_lock, old_irql, "read_empty");
326 	}
327 
328 	return (pmsg);
329 }
330 
331 /*
332   INTERFACE:
333   acknowledge last message and unlock queue
334 */
diva_maint_ack_message(int do_release,diva_os_spin_lock_magic_t * old_irql)335 void diva_maint_ack_message(int do_release,
336 			    diva_os_spin_lock_magic_t *old_irql) {
337 	if (!dbg_q_busy) {
338 		return;
339 	}
340 	if (do_release) {
341 		queueFreeMsg(dbg_queue);
342 	}
343 	dbg_q_busy = 0;
344 	diva_os_leave_spin_lock(&dbg_q_lock, old_irql, "read_ack");
345 }
346 
347 
348 /*
349   INTERFACE:
350   PRT COMP function used to register
351   with MAINT adapter or log in compatibility
352   mode in case older driver version is connected too
353 */
diva_maint_prtComp(char * format,...)354 void diva_maint_prtComp(char *format, ...) {
355 	void    *hDbg;
356 	va_list ap;
357 
358 	if (!format)
359 		return;
360 
361 	va_start(ap, format);
362 
363 	/*
364 	  register to new log driver functions
365 	*/
366 	if ((format[0] == 0) && ((unsigned char)format[1] == 255)) {
367 		hDbg = va_arg(ap, void *); /* ptr to DbgHandle */
368 		DI_register(hDbg);
369 	}
370 
371 	va_end(ap);
372 }
373 
DI_register(void * arg)374 static void DI_register(void *arg) {
375 	diva_os_spin_lock_magic_t old_irql;
376 	dword sec, usec;
377 	pDbgHandle	hDbg;
378 	int id, free_id = -1, best_id = 0;
379 
380 	diva_os_get_time(&sec, &usec);
381 
382 	hDbg = (pDbgHandle)arg;
383 	/*
384 	  Check for bad args, specially for the old obsolete debug handle
385 	*/
386 	if ((hDbg == NULL) ||
387 	    ((hDbg->id == 0) && (((_OldDbgHandle_ *)hDbg)->id == -1)) ||
388 	    (hDbg->Registered != 0)) {
389 		return;
390 	}
391 
392 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "register");
393 
394 	for (id = 1; id < ARRAY_SIZE(clients); id++) {
395 		if (clients[id].hDbg == hDbg) {
396 			/*
397 			  driver already registered
398 			*/
399 			diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "register");
400 			return;
401 		}
402 		if (clients[id].hDbg) { /* slot is busy */
403 			continue;
404 		}
405 		free_id = id;
406 		if (!strcmp(clients[id].drvName, hDbg->drvName)) {
407 			/*
408 			  This driver was already registered with this name
409 			  and slot is still free - reuse it
410 			*/
411 			best_id = 1;
412 			break;
413 		}
414 		if (!clients[id].hDbg) { /* slot is busy */
415 			break;
416 		}
417 	}
418 
419 	if (free_id != -1) {
420 		diva_dbg_entry_head_t *pmsg = NULL;
421 		int len;
422 		char tmp[256];
423 		word size;
424 
425 		/*
426 		  Register new driver with id == free_id
427 		*/
428 		clients[free_id].hDbg = hDbg;
429 		clients[free_id].sec  = sec;
430 		clients[free_id].usec = usec;
431 		strcpy(clients[free_id].drvName, hDbg->drvName);
432 
433 		clients[free_id].dbgMask = hDbg->dbgMask;
434 		if (best_id) {
435 			hDbg->dbgMask |= clients[free_id].last_dbgMask;
436 		} else {
437 			clients[free_id].last_dbgMask = 0;
438 		}
439 
440 		hDbg->Registered = DBG_HANDLE_REG_NEW;
441 		hDbg->id         = (byte)free_id;
442 		hDbg->dbg_end    = DI_deregister;
443 		hDbg->dbg_prt    = DI_format_locked;
444 		hDbg->dbg_ev     = DiProcessEventLog;
445 		hDbg->dbg_irq    = DI_format_locked;
446 		if (hDbg->Version > 0) {
447 			hDbg->dbg_old  = DI_format_old;
448 		}
449 		hDbg->next       = (pDbgHandle)DBG_MAGIC;
450 
451 		/*
452 		  Log driver register, MAINT driver ID is '0'
453 		*/
454 		len = sprintf(tmp, "DIMAINT - drv # %d = '%s' registered",
455 			      free_id, hDbg->drvName);
456 
457 		while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
458 								       (word)(len + 1 + sizeof(*pmsg))))) {
459 			if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
460 				queueFreeMsg(dbg_queue);
461 			} else {
462 				break;
463 			}
464 		}
465 
466 		if (pmsg) {
467 			pmsg->sequence    = dbg_sequence++;
468 			pmsg->time_sec    = sec;
469 			pmsg->time_usec   = usec;
470 			pmsg->facility    = MSG_TYPE_STRING;
471 			pmsg->dli         = DLI_REG;
472 			pmsg->drv_id      = 0; /* id 0 - DIMAINT */
473 			pmsg->di_cpu      = 0;
474 			pmsg->data_length = len + 1;
475 
476 			memcpy(&pmsg[1], tmp, len + 1);
477 			queueCompleteMsg(pmsg);
478 			diva_maint_wakeup_read();
479 		}
480 	}
481 
482 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "register");
483 }
484 
DI_deregister(pDbgHandle hDbg)485 static void DI_deregister(pDbgHandle hDbg) {
486 	diva_os_spin_lock_magic_t old_irql, old_irql1;
487 	dword sec, usec;
488 	int i;
489 	word size;
490 	byte *pmem = NULL;
491 
492 	diva_os_get_time(&sec, &usec);
493 
494 	diva_os_enter_spin_lock(&dbg_adapter_lock, &old_irql1, "read");
495 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "read");
496 
497 	for (i = 1; i < ARRAY_SIZE(clients); i++) {
498 		if (clients[i].hDbg == hDbg) {
499 			diva_dbg_entry_head_t *pmsg;
500 			char tmp[256];
501 			int len;
502 
503 			clients[i].hDbg = NULL;
504 
505 			hDbg->id       = -1;
506 			hDbg->dbgMask  = 0;
507 			hDbg->dbg_end  = NULL;
508 			hDbg->dbg_prt  = NULL;
509 			hDbg->dbg_irq  = NULL;
510 			if (hDbg->Version > 0)
511 				hDbg->dbg_old = NULL;
512 			hDbg->Registered = 0;
513 			hDbg->next     = NULL;
514 
515 			if (clients[i].pIdiLib) {
516 				(*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
517 				clients[i].pIdiLib = NULL;
518 
519 				pmem = clients[i].pmem;
520 				clients[i].pmem = NULL;
521 			}
522 
523 			/*
524 			  Log driver register, MAINT driver ID is '0'
525 			*/
526 			len = sprintf(tmp, "DIMAINT - drv # %d = '%s' de-registered",
527 				      i, hDbg->drvName);
528 
529 			while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
530 									      (word)(len + 1 + sizeof(*pmsg))))) {
531 				if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
532 					queueFreeMsg(dbg_queue);
533 				} else {
534 					break;
535 				}
536 			}
537 
538 			if (pmsg) {
539 				pmsg->sequence    = dbg_sequence++;
540 				pmsg->time_sec    = sec;
541 				pmsg->time_usec   = usec;
542 				pmsg->facility    = MSG_TYPE_STRING;
543 				pmsg->dli         = DLI_REG;
544 				pmsg->drv_id      = 0; /* id 0 - DIMAINT */
545 				pmsg->di_cpu      = 0;
546 				pmsg->data_length = len + 1;
547 
548 				memcpy(&pmsg[1], tmp, len + 1);
549 				queueCompleteMsg(pmsg);
550 				diva_maint_wakeup_read();
551 			}
552 
553 			break;
554 		}
555 	}
556 
557 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "read_ack");
558 	diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "read_ack");
559 
560 	if (pmem) {
561 		diva_os_free(0, pmem);
562 	}
563 }
564 
DI_format_locked(unsigned short id,int type,char * format,va_list argument_list)565 static void DI_format_locked(unsigned short id,
566 			     int type,
567 			     char *format,
568 			     va_list argument_list) {
569 	DI_format(1, id, type, format, argument_list);
570 }
571 
DI_format(int do_lock,unsigned short id,int type,char * format,va_list ap)572 static void DI_format(int do_lock,
573 		      unsigned short id,
574 		      int type,
575 		      char *format,
576 		      va_list ap) {
577 	diva_os_spin_lock_magic_t old_irql;
578 	dword sec, usec;
579 	diva_dbg_entry_head_t *pmsg = NULL;
580 	dword length;
581 	word size;
582 	static char fmtBuf[MSG_FRAME_MAX_SIZE + sizeof(*pmsg) + 1];
583 	char          *data;
584 	unsigned short code;
585 
586 	if (diva_os_in_irq()) {
587 		dbg_sequence++;
588 		return;
589 	}
590 
591 	if ((!format) ||
592 	    ((TraceFilter[0] != 0) && ((TraceFilterIdent < 0) || (TraceFilterChannel < 0)))) {
593 		return;
594 	}
595 
596 
597 
598 	diva_os_get_time(&sec, &usec);
599 
600 	if (do_lock) {
601 		diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "format");
602 	}
603 
604 	switch (type) {
605 	case DLI_MXLOG:
606 	case DLI_BLK:
607 	case DLI_SEND:
608 	case DLI_RECV:
609 		if (!(length = va_arg(ap, unsigned long))) {
610 			break;
611 		}
612 		if (length > MaxDumpSize) {
613 			length = MaxDumpSize;
614 		}
615 		while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
616 								       (word)length + sizeof(*pmsg)))) {
617 			if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
618 				queueFreeMsg(dbg_queue);
619 			} else {
620 				break;
621 			}
622 		}
623 		if (pmsg) {
624 			memcpy(&pmsg[1], format, length);
625 			pmsg->sequence    = dbg_sequence++;
626 			pmsg->time_sec    = sec;
627 			pmsg->time_usec   = usec;
628 			pmsg->facility    = MSG_TYPE_BINARY;
629 			pmsg->dli         = type; /* DLI_XXX */
630 			pmsg->drv_id      = id;   /* driver MAINT id */
631 			pmsg->di_cpu      = 0;
632 			pmsg->data_length = length;
633 			queueCompleteMsg(pmsg);
634 		}
635 		break;
636 
637 	case DLI_XLOG: {
638 		byte *p;
639 		data    = va_arg(ap, char *);
640 		code    = (unsigned short)va_arg(ap, unsigned int);
641 		length	= (unsigned long)va_arg(ap, unsigned int);
642 
643 		if (length > MaxXlogSize)
644 			length = MaxXlogSize;
645 
646 		while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
647 								      (word)length + sizeof(*pmsg) + 2))) {
648 			if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
649 				queueFreeMsg(dbg_queue);
650 			} else {
651 				break;
652 			}
653 		}
654 		if (pmsg) {
655 			p = (byte *)&pmsg[1];
656 			p[0] = (char)(code);
657 			p[1] = (char)(code >> 8);
658 			if (data && length) {
659 				memcpy(&p[2], &data[0], length);
660 			}
661 			length += 2;
662 
663 			pmsg->sequence    = dbg_sequence++;
664 			pmsg->time_sec    = sec;
665 			pmsg->time_usec   = usec;
666 			pmsg->facility    = MSG_TYPE_BINARY;
667 			pmsg->dli         = type; /* DLI_XXX */
668 			pmsg->drv_id      = id;   /* driver MAINT id */
669 			pmsg->di_cpu      = 0;
670 			pmsg->data_length = length;
671 			queueCompleteMsg(pmsg);
672 		}
673 	} break;
674 
675 	case DLI_LOG:
676 	case DLI_FTL:
677 	case DLI_ERR:
678 	case DLI_TRC:
679 	case DLI_REG:
680 	case DLI_MEM:
681 	case DLI_SPL:
682 	case DLI_IRP:
683 	case DLI_TIM:
684 	case DLI_TAPI:
685 	case DLI_NDIS:
686 	case DLI_CONN:
687 	case DLI_STAT:
688 	case DLI_PRV0:
689 	case DLI_PRV1:
690 	case DLI_PRV2:
691 	case DLI_PRV3:
692 		if ((length = (unsigned long)vsprintf(&fmtBuf[0], format, ap)) > 0) {
693 			length += (sizeof(*pmsg) + 1);
694 
695 			while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
696 									       (word)length))) {
697 				if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
698 					queueFreeMsg(dbg_queue);
699 				} else {
700 					break;
701 				}
702 			}
703 
704 			pmsg->sequence    = dbg_sequence++;
705 			pmsg->time_sec    = sec;
706 			pmsg->time_usec   = usec;
707 			pmsg->facility    = MSG_TYPE_STRING;
708 			pmsg->dli         = type; /* DLI_XXX */
709 			pmsg->drv_id      = id;   /* driver MAINT id */
710 			pmsg->di_cpu      = 0;
711 			pmsg->data_length = length - sizeof(*pmsg);
712 
713 			memcpy(&pmsg[1], fmtBuf, pmsg->data_length);
714 			queueCompleteMsg(pmsg);
715 		}
716 		break;
717 
718 	} /* switch type */
719 
720 
721 	if (queueCount(dbg_queue)) {
722 		diva_maint_wakeup_read();
723 	}
724 
725 	if (do_lock) {
726 		diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "format");
727 	}
728 }
729 
730 /*
731   Write driver ID and driver revision to callers buffer
732 */
diva_get_driver_info(dword id,byte * data,int data_length)733 int diva_get_driver_info(dword id, byte *data, int data_length) {
734 	diva_os_spin_lock_magic_t old_irql;
735 	byte *p = data;
736 	int to_copy;
737 
738 	if (!data || !id || (data_length < 17) ||
739 	    (id >= ARRAY_SIZE(clients))) {
740 		return (-1);
741 	}
742 
743 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "driver info");
744 
745 	if (clients[id].hDbg) {
746 		*p++ = 1;
747 		*p++ = (byte)clients[id].sec; /* save seconds */
748 		*p++ = (byte)(clients[id].sec >>  8);
749 		*p++ = (byte)(clients[id].sec >> 16);
750 		*p++ = (byte)(clients[id].sec >> 24);
751 
752 		*p++ = (byte)(clients[id].usec / 1000); /* save mseconds */
753 		*p++ = (byte)((clients[id].usec / 1000) >>  8);
754 		*p++ = (byte)((clients[id].usec / 1000) >> 16);
755 		*p++ = (byte)((clients[id].usec / 1000) >> 24);
756 
757 		data_length -= 9;
758 
759 		if ((to_copy = min(strlen(clients[id].drvName), (size_t)(data_length - 1)))) {
760 			memcpy(p, clients[id].drvName, to_copy);
761 			p += to_copy;
762 			data_length -= to_copy;
763 			if ((data_length >= 4) && clients[id].hDbg->drvTag[0]) {
764 				*p++ = '(';
765 				data_length -= 1;
766 				if ((to_copy = min(strlen(clients[id].hDbg->drvTag), (size_t)(data_length - 2)))) {
767 					memcpy(p, clients[id].hDbg->drvTag, to_copy);
768 					p += to_copy;
769 					data_length -= to_copy;
770 					if (data_length >= 2) {
771 						*p++ = ')';
772 						data_length--;
773 					}
774 				}
775 			}
776 		}
777 	}
778 	*p++ = 0;
779 
780 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "driver info");
781 
782 	return (p - data);
783 }
784 
diva_get_driver_dbg_mask(dword id,byte * data)785 int diva_get_driver_dbg_mask(dword id, byte *data) {
786 	diva_os_spin_lock_magic_t old_irql;
787 	int ret = -1;
788 
789 	if (!data || !id || (id >= ARRAY_SIZE(clients))) {
790 		return (-1);
791 	}
792 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "driver info");
793 
794 	if (clients[id].hDbg) {
795 		ret = 4;
796 		*data++ = (byte)(clients[id].hDbg->dbgMask);
797 		*data++ = (byte)(clients[id].hDbg->dbgMask >>  8);
798 		*data++ = (byte)(clients[id].hDbg->dbgMask >> 16);
799 		*data++ = (byte)(clients[id].hDbg->dbgMask >> 24);
800 	}
801 
802 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "driver info");
803 
804 	return (ret);
805 }
806 
diva_set_driver_dbg_mask(dword id,dword mask)807 int diva_set_driver_dbg_mask(dword id, dword mask) {
808 	diva_os_spin_lock_magic_t old_irql, old_irql1;
809 	int ret = -1;
810 
811 
812 	if (!id || (id >= ARRAY_SIZE(clients))) {
813 		return (-1);
814 	}
815 
816 	diva_os_enter_spin_lock(&dbg_adapter_lock, &old_irql1, "dbg mask");
817 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "dbg mask");
818 
819 	if (clients[id].hDbg) {
820 		dword old_mask = clients[id].hDbg->dbgMask;
821 		mask &= 0x7fffffff;
822 		clients[id].hDbg->dbgMask = mask;
823 		clients[id].last_dbgMask = (clients[id].hDbg->dbgMask | clients[id].dbgMask);
824 		ret = 4;
825 		diva_change_management_debug_mask(&clients[id], old_mask);
826 	}
827 
828 
829 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "dbg mask");
830 
831 	if (clients[id].request_pending) {
832 		clients[id].request_pending = 0;
833 		(*(clients[id].request))((ENTITY *)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
834 	}
835 
836 	diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "dbg mask");
837 
838 	return (ret);
839 }
840 
diva_get_idi_adapter_info(IDI_CALL request,dword * serial,dword * logical)841 static int diva_get_idi_adapter_info(IDI_CALL request, dword *serial, dword *logical) {
842 	IDI_SYNC_REQ sync_req;
843 
844 	sync_req.xdi_logical_adapter_number.Req = 0;
845 	sync_req.xdi_logical_adapter_number.Rc = IDI_SYNC_REQ_XDI_GET_LOGICAL_ADAPTER_NUMBER;
846 	(*request)((ENTITY *)&sync_req);
847 	*logical = sync_req.xdi_logical_adapter_number.info.logical_adapter_number;
848 
849 	sync_req.GetSerial.Req = 0;
850 	sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
851 	sync_req.GetSerial.serial = 0;
852 	(*request)((ENTITY *)&sync_req);
853 	*serial = sync_req.GetSerial.serial;
854 
855 	return (0);
856 }
857 
858 /*
859   Register XDI adapter as MAINT compatible driver
860 */
diva_mnt_add_xdi_adapter(const DESCRIPTOR * d)861 void diva_mnt_add_xdi_adapter(const DESCRIPTOR *d) {
862 	diva_os_spin_lock_magic_t old_irql, old_irql1;
863 	dword sec, usec, logical, serial, org_mask;
864 	int id, free_id = -1;
865 	char tmp[128];
866 	diva_dbg_entry_head_t *pmsg = NULL;
867 	int len;
868 	word size;
869 	byte *pmem;
870 
871 	diva_os_get_time(&sec, &usec);
872 	diva_get_idi_adapter_info(d->request, &serial, &logical);
873 	if (serial & 0xff000000) {
874 		sprintf(tmp, "ADAPTER:%d SN:%u-%d",
875 			(int)logical,
876 			serial & 0x00ffffff,
877 			(byte)(((serial & 0xff000000) >> 24) + 1));
878 	} else {
879 		sprintf(tmp, "ADAPTER:%d SN:%u", (int)logical, serial);
880 	}
881 
882 	if (!(pmem = diva_os_malloc(0, DivaSTraceGetMemotyRequirement(d->channels)))) {
883 		return;
884 	}
885 	memset(pmem, 0x00, DivaSTraceGetMemotyRequirement(d->channels));
886 
887 	diva_os_enter_spin_lock(&dbg_adapter_lock, &old_irql1, "register");
888 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "register");
889 
890 	for (id = 1; id < ARRAY_SIZE(clients); id++) {
891 		if (clients[id].hDbg && (clients[id].request == d->request)) {
892 			diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "register");
893 			diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "register");
894 			diva_os_free(0, pmem);
895 			return;
896 		}
897 		if (clients[id].hDbg) { /* slot is busy */
898 			continue;
899 		}
900 		if (free_id < 0) {
901 			free_id = id;
902 		}
903 		if (!strcmp(clients[id].drvName, tmp)) {
904 			/*
905 			  This driver was already registered with this name
906 			  and slot is still free - reuse it
907 			*/
908 			free_id = id;
909 			break;
910 		}
911 	}
912 
913 	if (free_id < 0) {
914 		diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "register");
915 		diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "register");
916 		diva_os_free(0, pmem);
917 		return;
918 	}
919 
920 	id = free_id;
921 	clients[id].request  = d->request;
922 	clients[id].request_pending = 0;
923 	clients[id].hDbg     = &clients[id].Dbg;
924 	clients[id].sec      = sec;
925 	clients[id].usec     = usec;
926 	strcpy(clients[id].drvName,     tmp);
927 	strcpy(clients[id].Dbg.drvName, tmp);
928 	clients[id].Dbg.drvTag[0] = 0;
929 	clients[id].logical  = (int)logical;
930 	clients[id].channels = (int)d->channels;
931 	clients[id].dma_handle = -1;
932 
933 	clients[id].Dbg.dbgMask    = 0;
934 	clients[id].dbgMask        = clients[id].Dbg.dbgMask;
935 	if (id) {
936 		clients[id].Dbg.dbgMask |= clients[free_id].last_dbgMask;
937 	} else {
938 		clients[id].last_dbgMask = 0;
939 	}
940 	clients[id].Dbg.Registered = DBG_HANDLE_REG_NEW;
941 	clients[id].Dbg.id         = (byte)id;
942 	clients[id].Dbg.dbg_end    = DI_deregister;
943 	clients[id].Dbg.dbg_prt    = DI_format_locked;
944 	clients[id].Dbg.dbg_ev     = DiProcessEventLog;
945 	clients[id].Dbg.dbg_irq    = DI_format_locked;
946 	clients[id].Dbg.next       = (pDbgHandle)DBG_MAGIC;
947 
948 	{
949 		diva_trace_library_user_interface_t diva_maint_user_ifc = { &clients[id],
950 									    diva_maint_state_change_notify,
951 									    diva_maint_trace_notify,
952 									    diva_maint_error };
953 
954 		/*
955 		  Attach to adapter management interface
956 		*/
957 		if ((clients[id].pIdiLib =
958 		     DivaSTraceLibraryCreateInstance((int)logical, &diva_maint_user_ifc, pmem))) {
959 			if (((*(clients[id].pIdiLib->DivaSTraceLibraryStart))(clients[id].pIdiLib->hLib))) {
960 				diva_mnt_internal_dprintf(0, DLI_ERR, "Adapter(%d) Start failed", (int)logical);
961 				(*(clients[id].pIdiLib->DivaSTraceLibraryFinit))(clients[id].pIdiLib->hLib);
962 				clients[id].pIdiLib = NULL;
963 			}
964 		} else {
965 			diva_mnt_internal_dprintf(0, DLI_ERR, "A(%d) management init failed", (int)logical);
966 		}
967 	}
968 
969 	if (!clients[id].pIdiLib) {
970 		clients[id].request = NULL;
971 		clients[id].request_pending = 0;
972 		clients[id].hDbg    = NULL;
973 		diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "register");
974 		diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "register");
975 		diva_os_free(0, pmem);
976 		return;
977 	}
978 
979 	/*
980 	  Log driver register, MAINT driver ID is '0'
981 	*/
982 	len = sprintf(tmp, "DIMAINT - drv # %d = '%s' registered",
983 		      id, clients[id].Dbg.drvName);
984 
985 	while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
986 							       (word)(len + 1 + sizeof(*pmsg))))) {
987 		if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
988 			queueFreeMsg(dbg_queue);
989 		} else {
990 			break;
991 		}
992 	}
993 
994 	if (pmsg) {
995 		pmsg->sequence    = dbg_sequence++;
996 		pmsg->time_sec    = sec;
997 		pmsg->time_usec   = usec;
998 		pmsg->facility    = MSG_TYPE_STRING;
999 		pmsg->dli         = DLI_REG;
1000 		pmsg->drv_id      = 0; /* id 0 - DIMAINT */
1001 		pmsg->di_cpu      = 0;
1002 		pmsg->data_length = len + 1;
1003 
1004 		memcpy(&pmsg[1], tmp, len + 1);
1005 		queueCompleteMsg(pmsg);
1006 		diva_maint_wakeup_read();
1007 	}
1008 
1009 	org_mask = clients[id].Dbg.dbgMask;
1010 	clients[id].Dbg.dbgMask = 0;
1011 
1012 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "register");
1013 
1014 	if (clients[id].request_pending) {
1015 		clients[id].request_pending = 0;
1016 		(*(clients[id].request))((ENTITY *)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
1017 	}
1018 
1019 	diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "register");
1020 
1021 	diva_set_driver_dbg_mask(id, org_mask);
1022 }
1023 
1024 /*
1025   De-Register XDI adapter
1026 */
diva_mnt_remove_xdi_adapter(const DESCRIPTOR * d)1027 void diva_mnt_remove_xdi_adapter(const DESCRIPTOR *d) {
1028 	diva_os_spin_lock_magic_t old_irql, old_irql1;
1029 	dword sec, usec;
1030 	int i;
1031 	word size;
1032 	byte *pmem = NULL;
1033 
1034 	diva_os_get_time(&sec, &usec);
1035 
1036 	diva_os_enter_spin_lock(&dbg_adapter_lock, &old_irql1, "read");
1037 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "read");
1038 
1039 	for (i = 1; i < ARRAY_SIZE(clients); i++) {
1040 		if (clients[i].hDbg && (clients[i].request == d->request)) {
1041 			diva_dbg_entry_head_t *pmsg;
1042 			char tmp[256];
1043 			int len;
1044 
1045 			if (clients[i].pIdiLib) {
1046 				(*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1047 				clients[i].pIdiLib = NULL;
1048 
1049 				pmem = clients[i].pmem;
1050 				clients[i].pmem = NULL;
1051 			}
1052 
1053 			clients[i].hDbg    = NULL;
1054 			clients[i].request_pending = 0;
1055 			if (clients[i].dma_handle >= 0) {
1056 				/*
1057 				  Free DMA handle
1058 				*/
1059 				diva_free_dma_descriptor(clients[i].request, clients[i].dma_handle);
1060 				clients[i].dma_handle = -1;
1061 			}
1062 			clients[i].request = NULL;
1063 
1064 			/*
1065 			  Log driver register, MAINT driver ID is '0'
1066 			*/
1067 			len = sprintf(tmp, "DIMAINT - drv # %d = '%s' de-registered",
1068 				      i, clients[i].Dbg.drvName);
1069 
1070 			memset(&clients[i].Dbg, 0x00, sizeof(clients[i].Dbg));
1071 
1072 			while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
1073 									       (word)(len + 1 + sizeof(*pmsg))))) {
1074 				if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
1075 					queueFreeMsg(dbg_queue);
1076 				} else {
1077 					break;
1078 				}
1079 			}
1080 
1081 			if (pmsg) {
1082 				pmsg->sequence    = dbg_sequence++;
1083 				pmsg->time_sec    = sec;
1084 				pmsg->time_usec   = usec;
1085 				pmsg->facility    = MSG_TYPE_STRING;
1086 				pmsg->dli         = DLI_REG;
1087 				pmsg->drv_id      = 0; /* id 0 - DIMAINT */
1088 				pmsg->di_cpu      = 0;
1089 				pmsg->data_length = len + 1;
1090 
1091 				memcpy(&pmsg[1], tmp, len + 1);
1092 				queueCompleteMsg(pmsg);
1093 				diva_maint_wakeup_read();
1094 			}
1095 
1096 			break;
1097 		}
1098 	}
1099 
1100 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "read_ack");
1101 	diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "read_ack");
1102 
1103 	if (pmem) {
1104 		diva_os_free(0, pmem);
1105 	}
1106 }
1107 
1108 /* ----------------------------------------------------------------
1109    Low level interface for management interface client
1110    ---------------------------------------------------------------- */
1111 /*
1112   Return handle to client structure
1113 */
SuperTraceOpenAdapter(int AdapterNumber)1114 void *SuperTraceOpenAdapter(int AdapterNumber) {
1115 	int i;
1116 
1117 	for (i = 1; i < ARRAY_SIZE(clients); i++) {
1118 		if (clients[i].hDbg && clients[i].request && (clients[i].logical == AdapterNumber)) {
1119 			return (&clients[i]);
1120 		}
1121 	}
1122 
1123 	return NULL;
1124 }
1125 
SuperTraceCloseAdapter(void * AdapterHandle)1126 int SuperTraceCloseAdapter(void *AdapterHandle) {
1127 	return (0);
1128 }
1129 
SuperTraceReadRequest(void * AdapterHandle,const char * name,byte * data)1130 int SuperTraceReadRequest(void *AdapterHandle, const char *name, byte *data) {
1131 	diva_maint_client_t *pC = (diva_maint_client_t *)AdapterHandle;
1132 
1133 	if (pC && pC->pIdiLib && pC->request) {
1134 		ENTITY *e = (ENTITY *)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1135 		byte *xdata = (byte *)&pC->xbuffer[0];
1136 		char tmp = 0;
1137 		word length;
1138 
1139 		if (!strcmp(name, "\\")) { /* Read ROOT */
1140 			name = &tmp;
1141 		}
1142 		length = SuperTraceCreateReadReq(xdata, name);
1143 		single_p(xdata, &length, 0); /* End Of Message */
1144 
1145 		e->Req        = MAN_READ;
1146 		e->ReqCh      = 0;
1147 		e->X->PLength = length;
1148 		e->X->P	= (byte *)xdata;
1149 
1150 		pC->request_pending = 1;
1151 
1152 		return (0);
1153 	}
1154 
1155 	return (-1);
1156 }
1157 
SuperTraceGetNumberOfChannels(void * AdapterHandle)1158 int SuperTraceGetNumberOfChannels(void *AdapterHandle) {
1159 	if (AdapterHandle) {
1160 		diva_maint_client_t *pC = (diva_maint_client_t *)AdapterHandle;
1161 
1162 		return (pC->channels);
1163 	}
1164 
1165 	return (0);
1166 }
1167 
SuperTraceASSIGN(void * AdapterHandle,byte * data)1168 int SuperTraceASSIGN(void *AdapterHandle, byte *data) {
1169 	diva_maint_client_t *pC = (diva_maint_client_t *)AdapterHandle;
1170 
1171 	if (pC && pC->pIdiLib && pC->request) {
1172 		ENTITY *e = (ENTITY *)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1173 		IDI_SYNC_REQ *preq;
1174 		char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
1175 		char features[4];
1176 		word assign_data_length = 1;
1177 
1178 		features[0] = 0;
1179 		pC->xbuffer[0] = 0;
1180 		preq = (IDI_SYNC_REQ *)&buffer[0];
1181 		preq->xdi_extended_features.Req = 0;
1182 		preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
1183 		preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
1184 		preq->xdi_extended_features.info.features = &features[0];
1185 
1186 		(*(pC->request))((ENTITY *)preq);
1187 
1188 		if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
1189 		    (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
1190 			dword uninitialized_var(rx_dma_magic);
1191 			if ((pC->dma_handle = diva_get_dma_descriptor(pC->request, &rx_dma_magic)) >= 0) {
1192 				pC->xbuffer[0] = LLI;
1193 				pC->xbuffer[1] = 8;
1194 				pC->xbuffer[2] = 0x40;
1195 				pC->xbuffer[3] = (byte)pC->dma_handle;
1196 				pC->xbuffer[4] = (byte)rx_dma_magic;
1197 				pC->xbuffer[5] = (byte)(rx_dma_magic >>  8);
1198 				pC->xbuffer[6] = (byte)(rx_dma_magic >> 16);
1199 				pC->xbuffer[7] = (byte)(rx_dma_magic >> 24);
1200 				pC->xbuffer[8] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE & 0xFF);
1201 				pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8);
1202 				pC->xbuffer[10] = 0;
1203 
1204 				assign_data_length = 11;
1205 			}
1206 		} else {
1207 			pC->dma_handle = -1;
1208 		}
1209 
1210 		e->Id          = MAN_ID;
1211 		e->callback    = diva_maint_xdi_cb;
1212 		e->XNum        = 1;
1213 		e->X           = &pC->XData;
1214 		e->Req         = ASSIGN;
1215 		e->ReqCh       = 0;
1216 		e->X->PLength  = assign_data_length;
1217 		e->X->P        = (byte *)&pC->xbuffer[0];
1218 
1219 		pC->request_pending = 1;
1220 
1221 		return (0);
1222 	}
1223 
1224 	return (-1);
1225 }
1226 
SuperTraceREMOVE(void * AdapterHandle)1227 int SuperTraceREMOVE(void *AdapterHandle) {
1228 	diva_maint_client_t *pC = (diva_maint_client_t *)AdapterHandle;
1229 
1230 	if (pC && pC->pIdiLib && pC->request) {
1231 		ENTITY *e = (ENTITY *)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1232 
1233 		e->XNum        = 1;
1234 		e->X           = &pC->XData;
1235 		e->Req         = REMOVE;
1236 		e->ReqCh       = 0;
1237 		e->X->PLength  = 1;
1238 		e->X->P        = (byte *)&pC->xbuffer[0];
1239 		pC->xbuffer[0] = 0;
1240 
1241 		pC->request_pending = 1;
1242 
1243 		return (0);
1244 	}
1245 
1246 	return (-1);
1247 }
1248 
SuperTraceTraceOnRequest(void * hAdapter,const char * name,byte * data)1249 int SuperTraceTraceOnRequest(void *hAdapter, const char *name, byte *data) {
1250 	diva_maint_client_t *pC = (diva_maint_client_t *)hAdapter;
1251 
1252 	if (pC && pC->pIdiLib && pC->request) {
1253 		ENTITY *e = (ENTITY *)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1254 		byte *xdata = (byte *)&pC->xbuffer[0];
1255 		char tmp = 0;
1256 		word length;
1257 
1258 		if (!strcmp(name, "\\")) { /* Read ROOT */
1259 			name = &tmp;
1260 		}
1261 		length = SuperTraceCreateReadReq(xdata, name);
1262 		single_p(xdata, &length, 0); /* End Of Message */
1263 		e->Req          = MAN_EVENT_ON;
1264 		e->ReqCh        = 0;
1265 		e->X->PLength   = length;
1266 		e->X->P = (byte *)xdata;
1267 
1268 		pC->request_pending = 1;
1269 
1270 		return (0);
1271 	}
1272 
1273 	return (-1);
1274 }
1275 
SuperTraceWriteVar(void * AdapterHandle,byte * data,const char * name,void * var,byte type,byte var_length)1276 int SuperTraceWriteVar(void *AdapterHandle,
1277 		       byte *data,
1278 		       const char *name,
1279 		       void *var,
1280 		       byte type,
1281 		       byte var_length) {
1282 	diva_maint_client_t *pC = (diva_maint_client_t *)AdapterHandle;
1283 
1284 	if (pC && pC->pIdiLib && pC->request) {
1285 		ENTITY *e = (ENTITY *)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1286 		diva_man_var_header_t *pVar = (diva_man_var_header_t *)&pC->xbuffer[0];
1287 		word length = SuperTraceCreateReadReq((byte *)pVar, name);
1288 
1289 		memcpy(&pC->xbuffer[length], var, var_length);
1290 		length += var_length;
1291 		pVar->length += var_length;
1292 		pVar->value_length = var_length;
1293 		pVar->type = type;
1294 		single_p((byte *)pVar, &length, 0); /* End Of Message */
1295 
1296 		e->Req = MAN_WRITE;
1297 		e->ReqCh = 0;
1298 		e->X->PLength   = length;
1299 		e->X->P = (byte *)pVar;
1300 
1301 		pC->request_pending = 1;
1302 
1303 		return (0);
1304 	}
1305 
1306 	return (-1);
1307 }
1308 
SuperTraceExecuteRequest(void * AdapterHandle,const char * name,byte * data)1309 int SuperTraceExecuteRequest(void *AdapterHandle,
1310 			     const char *name,
1311 			     byte *data) {
1312 	diva_maint_client_t *pC = (diva_maint_client_t *)AdapterHandle;
1313 
1314 	if (pC && pC->pIdiLib && pC->request) {
1315 		ENTITY *e = (ENTITY *)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1316 		byte *xdata = (byte *)&pC->xbuffer[0];
1317 		word length;
1318 
1319 		length = SuperTraceCreateReadReq(xdata, name);
1320 		single_p(xdata, &length, 0); /* End Of Message */
1321 
1322 		e->Req = MAN_EXECUTE;
1323 		e->ReqCh = 0;
1324 		e->X->PLength = length;
1325 		e->X->P = (byte *)xdata;
1326 
1327 		pC->request_pending = 1;
1328 
1329 		return (0);
1330 	}
1331 
1332 	return (-1);
1333 }
1334 
SuperTraceCreateReadReq(byte * P,const char * path)1335 static word SuperTraceCreateReadReq(byte *P, const char *path) {
1336 	byte var_length;
1337 	byte *plen;
1338 
1339 	var_length = (byte)strlen(path);
1340 
1341 	*P++ = ESC;
1342 	plen = P++;
1343 	*P++ = 0x80; /* MAN_IE */
1344 	*P++ = 0x00; /* Type */
1345 	*P++ = 0x00; /* Attribute */
1346 	*P++ = 0x00; /* Status */
1347 	*P++ = 0x00; /* Variable Length */
1348 	*P++ = var_length;
1349 	memcpy(P, path, var_length);
1350 	P += var_length;
1351 	*plen = var_length + 0x06;
1352 
1353 	return ((word)(var_length + 0x08));
1354 }
1355 
single_p(byte * P,word * PLength,byte Id)1356 static void single_p(byte *P, word *PLength, byte Id) {
1357 	P[(*PLength)++] = Id;
1358 }
1359 
diva_maint_xdi_cb(ENTITY * e)1360 static void diva_maint_xdi_cb(ENTITY *e) {
1361 	diva_strace_context_t *pLib = DIVAS_CONTAINING_RECORD(e, diva_strace_context_t, e);
1362 	diva_maint_client_t *pC;
1363 	diva_os_spin_lock_magic_t old_irql, old_irql1;
1364 
1365 
1366 	diva_os_enter_spin_lock(&dbg_adapter_lock, &old_irql1, "xdi_cb");
1367 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "xdi_cb");
1368 
1369 	pC = (diva_maint_client_t *)pLib->hAdapter;
1370 
1371 	if ((e->complete == 255) || (pC->dma_handle < 0)) {
1372 		if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1373 			diva_mnt_internal_dprintf(0, DLI_ERR, "Trace internal library error");
1374 		}
1375 	} else {
1376 		/*
1377 		  Process combined management interface indication
1378 		*/
1379 		if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1380 			diva_mnt_internal_dprintf(0, DLI_ERR, "Trace internal library error (DMA mode)");
1381 		}
1382 	}
1383 
1384 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "xdi_cb");
1385 
1386 
1387 	if (pC->request_pending) {
1388 		pC->request_pending = 0;
1389 		(*(pC->request))(e);
1390 	}
1391 
1392 	diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "xdi_cb");
1393 }
1394 
1395 
diva_maint_error(void * user_context,diva_strace_library_interface_t * hLib,int Adapter,int error,const char * file,int line)1396 static void diva_maint_error(void *user_context,
1397 			     diva_strace_library_interface_t *hLib,
1398 			     int Adapter,
1399 			     int error,
1400 			     const char *file,
1401 			     int line) {
1402 	diva_mnt_internal_dprintf(0, DLI_ERR,
1403 				  "Trace library error(%d) A(%d) %s %d", error, Adapter, file, line);
1404 }
1405 
print_ie(diva_trace_ie_t * ie,char * buffer,int length)1406 static void print_ie(diva_trace_ie_t *ie, char *buffer, int length) {
1407 	int i;
1408 
1409 	buffer[0] = 0;
1410 
1411 	if (length > 32) {
1412 		for (i = 0; ((i < ie->length) && (length > 3)); i++) {
1413 			sprintf(buffer, "%02x", ie->data[i]);
1414 			buffer += 2;
1415 			length -= 2;
1416 			if (i < (ie->length - 1)) {
1417 				strcpy(buffer, " ");
1418 				buffer++;
1419 				length--;
1420 			}
1421 		}
1422 	}
1423 }
1424 
diva_maint_state_change_notify(void * user_context,diva_strace_library_interface_t * hLib,int Adapter,diva_trace_line_state_t * channel,int notify_subject)1425 static void diva_maint_state_change_notify(void *user_context,
1426 					   diva_strace_library_interface_t *hLib,
1427 					   int Adapter,
1428 					   diva_trace_line_state_t *channel,
1429 					   int notify_subject) {
1430 	diva_maint_client_t *pC = (diva_maint_client_t *)user_context;
1431 	diva_trace_fax_state_t *fax = &channel->fax;
1432 	diva_trace_modem_state_t *modem = &channel->modem;
1433 	char tmp[256];
1434 
1435 	if (!pC->hDbg) {
1436 		return;
1437 	}
1438 
1439 	switch (notify_subject) {
1440 	case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: {
1441 		int view = (TraceFilter[0] == 0);
1442 		/*
1443 		  Process selective Trace
1444 		*/
1445 		if (channel->Line[0] == 'I' && channel->Line[1] == 'd' &&
1446 		    channel->Line[2] == 'l' && channel->Line[3] == 'e') {
1447 			if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) {
1448 				(*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0);
1449 				(*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0);
1450 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d",
1451 							  (int)channel->ChannelNumber);
1452 				TraceFilterIdent   = -1;
1453 				TraceFilterChannel = -1;
1454 				view = 1;
1455 			}
1456 		} else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr(&channel->RemoteAddress[0]) &&
1457 									 diva_mnt_cmp_nmbr(&channel->LocalAddress[0]))) {
1458 
1459 			if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */
1460 				(*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1);
1461 			}
1462 			if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */
1463 				(*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1);
1464 			}
1465 
1466 			TraceFilterIdent   = pC->hDbg->id;
1467 			TraceFilterChannel = (int)channel->ChannelNumber;
1468 
1469 			if (TraceFilterIdent >= 0) {
1470 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d",
1471 							  (int)channel->ChannelNumber);
1472 				view = 1;
1473 			}
1474 		}
1475 		if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) {
1476 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L Ch     = %d",
1477 						  (int)channel->ChannelNumber);
1478 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]);
1479 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L Layer1 = <%s>", &channel->Framing[0]);
1480 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L Layer2 = <%s>", &channel->Layer2[0]);
1481 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L Layer3 = <%s>", &channel->Layer3[0]);
1482 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L RAddr  = <%s>",
1483 						  &channel->RemoteAddress[0]);
1484 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L RSAddr = <%s>",
1485 						  &channel->RemoteSubAddress[0]);
1486 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L LAddr  = <%s>",
1487 						  &channel->LocalAddress[0]);
1488 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L LSAddr = <%s>",
1489 						  &channel->LocalSubAddress[0]);
1490 			print_ie(&channel->call_BC, tmp, sizeof(tmp));
1491 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L BC     = <%s>", tmp);
1492 			print_ie(&channel->call_HLC, tmp, sizeof(tmp));
1493 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L HLC    = <%s>", tmp);
1494 			print_ie(&channel->call_LLC, tmp, sizeof(tmp));
1495 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L LLC    = <%s>", tmp);
1496 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L CR     = 0x%x", channel->CallReference);
1497 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L Disc   = 0x%x",
1498 						  channel->LastDisconnecCause);
1499 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "L Owner  = <%s>", &channel->UserID[0]);
1500 		}
1501 
1502 	} break;
1503 
1504 	case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE:
1505 		if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) {
1506 			{
1507 				int ch = TraceFilterChannel;
1508 				int id = TraceFilterIdent;
1509 
1510 				if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1511 				    (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1512 					if (ch != (int)modem->ChannelNumber) {
1513 						break;
1514 					}
1515 				} else if (TraceFilter[0] != 0) {
1516 					break;
1517 				}
1518 			}
1519 
1520 
1521 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch    = %lu",
1522 						  (int)modem->ChannelNumber);
1523 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu", modem->Event);
1524 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Norm  = %lu", modem->Norm);
1525 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Opts. = 0x%08x", modem->Options);
1526 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Tx    = %lu Bps", modem->TxSpeed);
1527 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rx    = %lu Bps", modem->RxSpeed);
1528 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RT    = %lu mSec",
1529 						  modem->RoundtripMsec);
1530 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Sr    = %lu", modem->SymbolRate);
1531 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rxl   = %d dBm", modem->RxLeveldBm);
1532 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM El    = %d dBm", modem->EchoLeveldBm);
1533 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM SNR   = %lu dB", modem->SNRdb);
1534 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM MAE   = %lu", modem->MAE);
1535 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRet  = %lu",
1536 						  modem->LocalRetrains);
1537 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRet  = %lu",
1538 						  modem->RemoteRetrains);
1539 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRes  = %lu", modem->LocalResyncs);
1540 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRes  = %lu",
1541 						  modem->RemoteResyncs);
1542 			if (modem->Event == 3) {
1543 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Disc  =  %lu", modem->DiscReason);
1544 			}
1545 		}
1546 		if ((modem->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_STATISTICS)) {
1547 			(*(pC->pIdiLib->DivaSTraceGetModemStatistics))(pC->pIdiLib);
1548 		}
1549 		break;
1550 
1551 	case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE:
1552 		if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) {
1553 			{
1554 				int ch = TraceFilterChannel;
1555 				int id = TraceFilterIdent;
1556 
1557 				if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1558 				    (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1559 					if (ch != (int)fax->ChannelNumber) {
1560 						break;
1561 					}
1562 				} else if (TraceFilter[0] != 0) {
1563 					break;
1564 				}
1565 			}
1566 
1567 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch    = %lu", (int)fax->ChannelNumber);
1568 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu",     fax->Event);
1569 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu",     fax->Page_Counter);
1570 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Feat. = 0x%08x",  fax->Features);
1571 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX ID    = <%s>",    &fax->Station_ID[0]);
1572 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Saddr = <%s>",    &fax->Subaddress[0]);
1573 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pwd   = <%s>",    &fax->Password[0]);
1574 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Speed = %lu",     fax->Speed);
1575 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Res.  = 0x%08x",  fax->Resolution);
1576 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Width = %lu",     fax->Paper_Width);
1577 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Length= %lu",     fax->Paper_Length);
1578 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX SLT   = %lu",     fax->Scanline_Time);
1579 			if (fax->Event == 3) {
1580 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Disc  = %lu",     fax->Disc_Reason);
1581 			}
1582 		}
1583 		if ((fax->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_STATISTICS)) {
1584 			(*(pC->pIdiLib->DivaSTraceGetFaxStatistics))(pC->pIdiLib);
1585 		}
1586 		break;
1587 
1588 	case DIVA_SUPER_TRACE_INTERFACE_CHANGE:
1589 		if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_EVENTS) {
1590 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT,
1591 						  "Layer 1 -> [%s]", channel->pInterface->Layer1);
1592 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT,
1593 						  "Layer 2 -> [%s]", channel->pInterface->Layer2);
1594 		}
1595 		break;
1596 
1597 	case DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE:
1598 		if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_STATISTICS) {
1599 			/*
1600 			  Incoming Statistics
1601 			*/
1602 			if (channel->pInterfaceStat->inc.Calls) {
1603 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1604 							  "Inc Calls                     =%lu", channel->pInterfaceStat->inc.Calls);
1605 			}
1606 			if (channel->pInterfaceStat->inc.Connected) {
1607 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1608 							  "Inc Connected                 =%lu", channel->pInterfaceStat->inc.Connected);
1609 			}
1610 			if (channel->pInterfaceStat->inc.User_Busy) {
1611 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1612 							  "Inc Busy                      =%lu", channel->pInterfaceStat->inc.User_Busy);
1613 			}
1614 			if (channel->pInterfaceStat->inc.Call_Rejected) {
1615 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1616 							  "Inc Rejected                  =%lu", channel->pInterfaceStat->inc.Call_Rejected);
1617 			}
1618 			if (channel->pInterfaceStat->inc.Wrong_Number) {
1619 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1620 							  "Inc Wrong Nr                  =%lu", channel->pInterfaceStat->inc.Wrong_Number);
1621 			}
1622 			if (channel->pInterfaceStat->inc.Incompatible_Dst) {
1623 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1624 							  "Inc Incomp. Dest              =%lu", channel->pInterfaceStat->inc.Incompatible_Dst);
1625 			}
1626 			if (channel->pInterfaceStat->inc.Out_of_Order) {
1627 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1628 							  "Inc Out of Order              =%lu", channel->pInterfaceStat->inc.Out_of_Order);
1629 			}
1630 			if (channel->pInterfaceStat->inc.Ignored) {
1631 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1632 							  "Inc Ignored                   =%lu", channel->pInterfaceStat->inc.Ignored);
1633 			}
1634 
1635 			/*
1636 			  Outgoing Statistics
1637 			*/
1638 			if (channel->pInterfaceStat->outg.Calls) {
1639 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1640 							  "Outg Calls                    =%lu", channel->pInterfaceStat->outg.Calls);
1641 			}
1642 			if (channel->pInterfaceStat->outg.Connected) {
1643 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1644 							  "Outg Connected                =%lu", channel->pInterfaceStat->outg.Connected);
1645 			}
1646 			if (channel->pInterfaceStat->outg.User_Busy) {
1647 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1648 							  "Outg Busy                     =%lu", channel->pInterfaceStat->outg.User_Busy);
1649 			}
1650 			if (channel->pInterfaceStat->outg.No_Answer) {
1651 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1652 							  "Outg No Answer                =%lu", channel->pInterfaceStat->outg.No_Answer);
1653 			}
1654 			if (channel->pInterfaceStat->outg.Wrong_Number) {
1655 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1656 							  "Outg Wrong Nr                 =%lu", channel->pInterfaceStat->outg.Wrong_Number);
1657 			}
1658 			if (channel->pInterfaceStat->outg.Call_Rejected) {
1659 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1660 							  "Outg Rejected                 =%lu", channel->pInterfaceStat->outg.Call_Rejected);
1661 			}
1662 			if (channel->pInterfaceStat->outg.Other_Failures) {
1663 				diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1664 							  "Outg Other Failures           =%lu", channel->pInterfaceStat->outg.Other_Failures);
1665 			}
1666 		}
1667 		break;
1668 
1669 	case DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE:
1670 		if (channel->pInterfaceStat->mdm.Disc_Normal) {
1671 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1672 						  "MDM Disc Normal        = %lu", channel->pInterfaceStat->mdm.Disc_Normal);
1673 		}
1674 		if (channel->pInterfaceStat->mdm.Disc_Unspecified) {
1675 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1676 						  "MDM Disc Unsp.         = %lu", channel->pInterfaceStat->mdm.Disc_Unspecified);
1677 		}
1678 		if (channel->pInterfaceStat->mdm.Disc_Busy_Tone) {
1679 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1680 						  "MDM Disc Busy Tone     = %lu", channel->pInterfaceStat->mdm.Disc_Busy_Tone);
1681 		}
1682 		if (channel->pInterfaceStat->mdm.Disc_Congestion) {
1683 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1684 						  "MDM Disc Congestion    = %lu", channel->pInterfaceStat->mdm.Disc_Congestion);
1685 		}
1686 		if (channel->pInterfaceStat->mdm.Disc_Carr_Wait) {
1687 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1688 						  "MDM Disc Carrier Wait  = %lu", channel->pInterfaceStat->mdm.Disc_Carr_Wait);
1689 		}
1690 		if (channel->pInterfaceStat->mdm.Disc_Trn_Timeout) {
1691 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1692 						  "MDM Disc Trn. T.o.     = %lu", channel->pInterfaceStat->mdm.Disc_Trn_Timeout);
1693 		}
1694 		if (channel->pInterfaceStat->mdm.Disc_Incompat) {
1695 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1696 						  "MDM Disc Incompatible  = %lu", channel->pInterfaceStat->mdm.Disc_Incompat);
1697 		}
1698 		if (channel->pInterfaceStat->mdm.Disc_Frame_Rej) {
1699 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1700 						  "MDM Disc Frame Reject  = %lu", channel->pInterfaceStat->mdm.Disc_Frame_Rej);
1701 		}
1702 		if (channel->pInterfaceStat->mdm.Disc_V42bis) {
1703 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1704 						  "MDM Disc V.42bis       = %lu", channel->pInterfaceStat->mdm.Disc_V42bis);
1705 		}
1706 		break;
1707 
1708 	case DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE:
1709 		if (channel->pInterfaceStat->fax.Disc_Normal) {
1710 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1711 						  "FAX Disc Normal        = %lu", channel->pInterfaceStat->fax.Disc_Normal);
1712 		}
1713 		if (channel->pInterfaceStat->fax.Disc_Not_Ident) {
1714 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1715 						  "FAX Disc Not Ident.    = %lu", channel->pInterfaceStat->fax.Disc_Not_Ident);
1716 		}
1717 		if (channel->pInterfaceStat->fax.Disc_No_Response) {
1718 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1719 						  "FAX Disc No Response   = %lu", channel->pInterfaceStat->fax.Disc_No_Response);
1720 		}
1721 		if (channel->pInterfaceStat->fax.Disc_Retries) {
1722 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1723 						  "FAX Disc Max Retries   = %lu", channel->pInterfaceStat->fax.Disc_Retries);
1724 		}
1725 		if (channel->pInterfaceStat->fax.Disc_Unexp_Msg) {
1726 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1727 						  "FAX Unexp. Msg.        = %lu", channel->pInterfaceStat->fax.Disc_Unexp_Msg);
1728 		}
1729 		if (channel->pInterfaceStat->fax.Disc_No_Polling) {
1730 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1731 						  "FAX Disc No Polling    = %lu", channel->pInterfaceStat->fax.Disc_No_Polling);
1732 		}
1733 		if (channel->pInterfaceStat->fax.Disc_Training) {
1734 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1735 						  "FAX Disc Training      = %lu", channel->pInterfaceStat->fax.Disc_Training);
1736 		}
1737 		if (channel->pInterfaceStat->fax.Disc_Unexpected) {
1738 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1739 						  "FAX Disc Unexpected    = %lu", channel->pInterfaceStat->fax.Disc_Unexpected);
1740 		}
1741 		if (channel->pInterfaceStat->fax.Disc_Application) {
1742 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1743 						  "FAX Disc Application   = %lu", channel->pInterfaceStat->fax.Disc_Application);
1744 		}
1745 		if (channel->pInterfaceStat->fax.Disc_Incompat) {
1746 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1747 						  "FAX Disc Incompatible  = %lu", channel->pInterfaceStat->fax.Disc_Incompat);
1748 		}
1749 		if (channel->pInterfaceStat->fax.Disc_No_Command) {
1750 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1751 						  "FAX Disc No Command    = %lu", channel->pInterfaceStat->fax.Disc_No_Command);
1752 		}
1753 		if (channel->pInterfaceStat->fax.Disc_Long_Msg) {
1754 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1755 						  "FAX Disc Long Msg.     = %lu", channel->pInterfaceStat->fax.Disc_Long_Msg);
1756 		}
1757 		if (channel->pInterfaceStat->fax.Disc_Supervisor) {
1758 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1759 						  "FAX Disc Supervisor    = %lu", channel->pInterfaceStat->fax.Disc_Supervisor);
1760 		}
1761 		if (channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD) {
1762 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1763 						  "FAX Disc SUP SEP PWD   = %lu", channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD);
1764 		}
1765 		if (channel->pInterfaceStat->fax.Disc_Invalid_Msg) {
1766 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1767 						  "FAX Disc Invalid Msg.  = %lu", channel->pInterfaceStat->fax.Disc_Invalid_Msg);
1768 		}
1769 		if (channel->pInterfaceStat->fax.Disc_Page_Coding) {
1770 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1771 						  "FAX Disc Page Coding   = %lu", channel->pInterfaceStat->fax.Disc_Page_Coding);
1772 		}
1773 		if (channel->pInterfaceStat->fax.Disc_App_Timeout) {
1774 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1775 						  "FAX Disc Appl. T.o.    = %lu", channel->pInterfaceStat->fax.Disc_App_Timeout);
1776 		}
1777 		if (channel->pInterfaceStat->fax.Disc_Unspecified) {
1778 			diva_mnt_internal_dprintf(pC->hDbg->id, DLI_LOG,
1779 						  "FAX Disc Unspec.       = %lu", channel->pInterfaceStat->fax.Disc_Unspecified);
1780 		}
1781 		break;
1782 	}
1783 }
1784 
1785 /*
1786   Receive trace information from the Management Interface and store it in the
1787   internal trace buffer with MSG_TYPE_MLOG as is, without any filtering.
1788   Event Filtering and formatting is done in  Management Interface self.
1789 */
diva_maint_trace_notify(void * user_context,diva_strace_library_interface_t * hLib,int Adapter,void * xlog_buffer,int length)1790 static void diva_maint_trace_notify(void *user_context,
1791 				    diva_strace_library_interface_t *hLib,
1792 				    int Adapter,
1793 				    void *xlog_buffer,
1794 				    int length) {
1795 	diva_maint_client_t *pC = (diva_maint_client_t *)user_context;
1796 	diva_dbg_entry_head_t *pmsg;
1797 	word size;
1798 	dword sec, usec;
1799 	int ch = TraceFilterChannel;
1800 	int id = TraceFilterIdent;
1801 
1802 	/*
1803 	  Selective trace
1804 	*/
1805 	if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1806 	    (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1807 		const char *p = NULL;
1808 		int ch_value = -1;
1809 		MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer;
1810 
1811 		if (Adapter != clients[id].logical) {
1812 			return; /* Ignore all trace messages from other adapters */
1813 		}
1814 
1815 		if (TrcData->code == 24) {
1816 			p = (char *)&TrcData->code;
1817 			p += 2;
1818 		}
1819 
1820 		/*
1821 		  All L1 messages start as [dsp,ch], so we can filter this information
1822 		  and filter out all messages that use different channel
1823 		*/
1824 		if (p && p[0] == '[') {
1825 			if (p[2] == ',') {
1826 				p += 3;
1827 				ch_value = *p - '0';
1828 			} else if (p[3] == ',') {
1829 				p += 4;
1830 				ch_value = *p - '0';
1831 			}
1832 			if (ch_value >= 0) {
1833 				if (p[2] == ']') {
1834 					ch_value = ch_value * 10 + p[1] - '0';
1835 				}
1836 				if (ch_value != ch) {
1837 					return; /* Ignore other channels */
1838 				}
1839 			}
1840 		}
1841 
1842 	} else if (TraceFilter[0] != 0) {
1843 		return; /* Ignore trace if trace filter is activated, but idle */
1844 	}
1845 
1846 	diva_os_get_time(&sec, &usec);
1847 
1848 	while (!(pmsg = (diva_dbg_entry_head_t *)queueAllocMsg(dbg_queue,
1849 							       (word)length + sizeof(*pmsg)))) {
1850 		if ((pmsg = (diva_dbg_entry_head_t *)queuePeekMsg(dbg_queue, &size))) {
1851 			queueFreeMsg(dbg_queue);
1852 		} else {
1853 			break;
1854 		}
1855 	}
1856 	if (pmsg) {
1857 		memcpy(&pmsg[1], xlog_buffer, length);
1858 		pmsg->sequence    = dbg_sequence++;
1859 		pmsg->time_sec    = sec;
1860 		pmsg->time_usec   = usec;
1861 		pmsg->facility    = MSG_TYPE_MLOG;
1862 		pmsg->dli         = pC->logical;
1863 		pmsg->drv_id      = pC->hDbg->id;
1864 		pmsg->di_cpu      = 0;
1865 		pmsg->data_length = length;
1866 		queueCompleteMsg(pmsg);
1867 		if (queueCount(dbg_queue)) {
1868 			diva_maint_wakeup_read();
1869 		}
1870 	}
1871 }
1872 
1873 
1874 /*
1875   Convert MAINT trace mask to management interface trace mask/work/facility and
1876   issue command to management interface
1877 */
diva_change_management_debug_mask(diva_maint_client_t * pC,dword old_mask)1878 static void diva_change_management_debug_mask(diva_maint_client_t *pC, dword old_mask) {
1879 	if (pC->request && pC->hDbg && pC->pIdiLib) {
1880 		dword changed = pC->hDbg->dbgMask ^ old_mask;
1881 
1882 		if (changed & DIVA_MGT_DBG_TRACE) {
1883 			(*(pC->pIdiLib->DivaSTraceSetInfo))(pC->pIdiLib,
1884 							    (pC->hDbg->dbgMask & DIVA_MGT_DBG_TRACE) != 0);
1885 		}
1886 		if (changed & DIVA_MGT_DBG_DCHAN) {
1887 			(*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib,
1888 								(pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0);
1889 		}
1890 		if (!TraceFilter[0]) {
1891 			if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) {
1892 				int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
1893 
1894 				for (i = 0; i < pC->channels; i++) {
1895 					(*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i + 1, state);
1896 				}
1897 			}
1898 			if (changed & DIVA_MGT_DBG_IFC_AUDIO) {
1899 				int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
1900 
1901 				for (i = 0; i < pC->channels; i++) {
1902 					(*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i + 1, state);
1903 				}
1904 			}
1905 		}
1906 	}
1907 }
1908 
1909 
diva_mnt_internal_dprintf(dword drv_id,dword type,char * fmt,...)1910 void diva_mnt_internal_dprintf(dword drv_id, dword type, char *fmt, ...) {
1911 	va_list ap;
1912 
1913 	va_start(ap, fmt);
1914 	DI_format(0, (word)drv_id, (int)type, fmt, ap);
1915 	va_end(ap);
1916 }
1917 
1918 /*
1919   Shutdown all adapters before driver removal
1920 */
diva_mnt_shutdown_xdi_adapters(void)1921 int diva_mnt_shutdown_xdi_adapters(void) {
1922 	diva_os_spin_lock_magic_t old_irql, old_irql1;
1923 	int i, fret = 0;
1924 	byte *pmem;
1925 
1926 
1927 	for (i = 1; i < ARRAY_SIZE(clients); i++) {
1928 		pmem = NULL;
1929 
1930 		diva_os_enter_spin_lock(&dbg_adapter_lock, &old_irql1, "unload");
1931 		diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "unload");
1932 
1933 		if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
1934 			if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) {
1935 				/*
1936 				  Adapter removal complete
1937 				*/
1938 				if (clients[i].pIdiLib) {
1939 					(*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1940 					clients[i].pIdiLib = NULL;
1941 
1942 					pmem = clients[i].pmem;
1943 					clients[i].pmem = NULL;
1944 				}
1945 				clients[i].hDbg    = NULL;
1946 				clients[i].request_pending = 0;
1947 
1948 				if (clients[i].dma_handle >= 0) {
1949 					/*
1950 					  Free DMA handle
1951 					*/
1952 					diva_free_dma_descriptor(clients[i].request, clients[i].dma_handle);
1953 					clients[i].dma_handle = -1;
1954 				}
1955 				clients[i].request = NULL;
1956 			} else {
1957 				fret = -1;
1958 			}
1959 		}
1960 
1961 		diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "unload");
1962 		if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
1963 			clients[i].request_pending = 0;
1964 			(*(clients[i].request))((ENTITY *)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
1965 			if (clients[i].dma_handle >= 0) {
1966 				diva_free_dma_descriptor(clients[i].request, clients[i].dma_handle);
1967 				clients[i].dma_handle = -1;
1968 			}
1969 		}
1970 		diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "unload");
1971 
1972 		if (pmem) {
1973 			diva_os_free(0, pmem);
1974 		}
1975 	}
1976 
1977 	return (fret);
1978 }
1979 
1980 /*
1981   Set/Read the trace filter used for selective tracing.
1982   Affects B- and Audio Tap trace mask at run time
1983 */
diva_set_trace_filter(int filter_length,const char * filter)1984 int diva_set_trace_filter(int filter_length, const char *filter) {
1985 	diva_os_spin_lock_magic_t old_irql, old_irql1;
1986 	int i, ch, on, client_b_on, client_atap_on;
1987 
1988 	diva_os_enter_spin_lock(&dbg_adapter_lock, &old_irql1, "dbg mask");
1989 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "write_filter");
1990 
1991 	if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) {
1992 		memcpy(&TraceFilter[0], filter, filter_length);
1993 		if (TraceFilter[filter_length]) {
1994 			TraceFilter[filter_length] = 0;
1995 		}
1996 		if (TraceFilter[0] == '*') {
1997 			TraceFilter[0] = 0;
1998 		}
1999 	} else {
2000 		filter_length = -1;
2001 	}
2002 
2003 	TraceFilterIdent   = -1;
2004 	TraceFilterChannel = -1;
2005 
2006 	on = (TraceFilter[0] == 0);
2007 
2008 	for (i = 1; i < ARRAY_SIZE(clients); i++) {
2009 		if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
2010 			client_b_on    = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
2011 			client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO)    != 0);
2012 			for (ch = 0; ch < clients[i].channels; ch++) {
2013 				(*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch + 1, client_b_on);
2014 				(*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch + 1, client_atap_on);
2015 			}
2016 		}
2017 	}
2018 
2019 	for (i = 1; i < ARRAY_SIZE(clients); i++) {
2020 		if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
2021 			diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "write_filter");
2022 			clients[i].request_pending = 0;
2023 			(*(clients[i].request))((ENTITY *)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
2024 			diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "write_filter");
2025 		}
2026 	}
2027 
2028 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "write_filter");
2029 	diva_os_leave_spin_lock(&dbg_adapter_lock, &old_irql1, "dbg mask");
2030 
2031 	return (filter_length);
2032 }
2033 
diva_get_trace_filter(int max_length,char * filter)2034 int diva_get_trace_filter(int max_length, char *filter) {
2035 	diva_os_spin_lock_magic_t old_irql;
2036 	int len;
2037 
2038 	diva_os_enter_spin_lock(&dbg_q_lock, &old_irql, "read_filter");
2039 	len = strlen(&TraceFilter[0]) + 1;
2040 	if (max_length >= len) {
2041 		memcpy(filter, &TraceFilter[0], len);
2042 	}
2043 	diva_os_leave_spin_lock(&dbg_q_lock, &old_irql, "read_filter");
2044 
2045 	return (len);
2046 }
2047 
diva_dbg_cmp_key(const char * ref,const char * key)2048 static int diva_dbg_cmp_key(const char *ref, const char *key) {
2049 	while (*key && (*ref++ == *key++));
2050 	return (!*key && !*ref);
2051 }
2052 
2053 /*
2054   In case trace filter starts with "C" character then
2055   all following characters are interpreted as command.
2056   Followings commands are available:
2057   - single, trace single call at time, independent from CPN/CiPN
2058 */
diva_mnt_cmp_nmbr(const char * nmbr)2059 static int diva_mnt_cmp_nmbr(const char *nmbr) {
2060 	const char *ref = &TraceFilter[0];
2061 	int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr);
2062 
2063 	if (ref[0] == 'C') {
2064 		if (diva_dbg_cmp_key(&ref[1], "single")) {
2065 			return (0);
2066 		}
2067 		return (-1);
2068 	}
2069 
2070 	if (!ref_len || (ref_len > nmbr_len)) {
2071 		return (-1);
2072 	}
2073 
2074 	nmbr = nmbr + nmbr_len - 1;
2075 	ref  = ref  + ref_len  - 1;
2076 
2077 	while (ref_len--) {
2078 		if (*nmbr-- != *ref--) {
2079 			return (-1);
2080 		}
2081 	}
2082 
2083 	return (0);
2084 }
2085 
diva_get_dma_descriptor(IDI_CALL request,dword * dma_magic)2086 static int diva_get_dma_descriptor(IDI_CALL request, dword *dma_magic) {
2087 	ENTITY e;
2088 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
2089 
2090 	if (!request) {
2091 		return (-1);
2092 	}
2093 
2094 	pReq->xdi_dma_descriptor_operation.Req = 0;
2095 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2096 
2097 	pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
2098 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
2099 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2100 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
2101 
2102 	(*request)((ENTITY *)pReq);
2103 
2104 	if (!pReq->xdi_dma_descriptor_operation.info.operation &&
2105 	    (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
2106 	    pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
2107 		*dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
2108 		return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
2109 	} else {
2110 		return (-1);
2111 	}
2112 }
2113 
diva_free_dma_descriptor(IDI_CALL request,int nr)2114 static void diva_free_dma_descriptor(IDI_CALL request, int nr) {
2115 	ENTITY e;
2116 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
2117 
2118 	if (!request || (nr < 0)) {
2119 		return;
2120 	}
2121 
2122 	pReq->xdi_dma_descriptor_operation.Req = 0;
2123 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2124 
2125 	pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
2126 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
2127 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2128 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
2129 
2130 	(*request)((ENTITY *)pReq);
2131 }
2132