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