• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/src/linux/linux-2.6/drivers/isdn/hardware/eicon/
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
15static void DI_register (void *arg);
16static void DI_deregister (pDbgHandle hDbg);
17static void DI_format (int do_lock, word id, int type, char *format, va_list argument_list);
18static void DI_format_locked   (word id, int type, char *format, va_list argument_list);
19static void DI_format_old (word id, char *format, va_list ap) { }
20static void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap) { }
21static void single_p (byte * P, word * PLength, byte Id);
22static void diva_maint_xdi_cb (ENTITY* e);
23static word SuperTraceCreateReadReq (byte* P, const char* path);
24static int diva_mnt_cmp_nmbr (const char* nmbr);
25static void diva_free_dma_descriptor (IDI_CALL request, int nr);
26static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic);
27void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...);
28
29static dword MaxDumpSize = 256 ;
30static dword MaxXlogSize = 2 + 128 ;
31static char  TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH+1];
32static int TraceFilterIdent   = -1;
33static int TraceFilterChannel = -1;
34
35typedef 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;
53static diva_maint_client_t clients[MAX_DESCRIPTORS];
54
55static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask);
56
57static 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);
63static 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);
68static 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
76typedef 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
86typedef 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
96static 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
104static 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
138alloc:
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
151static 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
169static 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  */
188static MSG_QUEUE*          dbg_queue;
189static byte*               dbg_base;
190static int                 external_dbg_queue;
191static diva_os_spin_lock_t dbg_q_lock;
192static diva_os_spin_lock_t dbg_adapter_lock;
193static int                 dbg_q_busy;
194static volatile dword      dbg_sequence;
195static dword               start_sec;
196static 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  */
207int 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  */
273void* 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  */
303dword 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  */
312diva_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  */
335void 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  */
354void 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
374static 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
485static 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
565static 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
572static 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  */
733int 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
785int 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
807int 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
841static 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  */
861void 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, best_id = 0, free_id = -1;
865  char tmp[256];
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      best_id = 1;
910      break;
911    }
912  }
913
914  if (free_id < 0) {
915    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
916    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
917    diva_os_free (0, pmem);
918    return;
919  }
920
921  id = free_id;
922  clients[id].request  = d->request;
923  clients[id].request_pending = 0;
924  clients[id].hDbg     = &clients[id].Dbg;
925  clients[id].sec      = sec;
926  clients[id].usec     = usec;
927  strcpy (clients[id].drvName,     tmp);
928  strcpy (clients[id].Dbg.drvName, tmp);
929  clients[id].Dbg.drvTag[0] = 0;
930  clients[id].logical  = (int)logical;
931  clients[id].channels = (int)d->channels;
932  clients[id].dma_handle = -1;
933
934  clients[id].Dbg.dbgMask    = 0;
935  clients[id].dbgMask        = clients[id].Dbg.dbgMask;
936  if (id) {
937    clients[id].Dbg.dbgMask |= clients[free_id].last_dbgMask;
938  } else {
939    clients[id].last_dbgMask = 0;
940  }
941  clients[id].Dbg.Registered = DBG_HANDLE_REG_NEW;
942  clients[id].Dbg.id         = (byte)id;
943  clients[id].Dbg.dbg_end    = DI_deregister;
944  clients[id].Dbg.dbg_prt    = DI_format_locked;
945  clients[id].Dbg.dbg_ev     = DiProcessEventLog;
946  clients[id].Dbg.dbg_irq    = DI_format_locked;
947  clients[id].Dbg.next       = (pDbgHandle)DBG_MAGIC;
948
949  {
950    diva_trace_library_user_interface_t diva_maint_user_ifc = { &clients[id],
951																							 diva_maint_state_change_notify,
952																							 diva_maint_trace_notify,
953																							 diva_maint_error };
954
955    /*
956      Attach to adapter management interface
957      */
958    if ((clients[id].pIdiLib =
959               DivaSTraceLibraryCreateInstance ((int)logical, &diva_maint_user_ifc, pmem))) {
960      if (((*(clients[id].pIdiLib->DivaSTraceLibraryStart))(clients[id].pIdiLib->hLib))) {
961        diva_mnt_internal_dprintf (0, DLI_ERR, "Adapter(%d) Start failed", (int)logical);
962        (*(clients[id].pIdiLib->DivaSTraceLibraryFinit))(clients[id].pIdiLib->hLib);
963        clients[id].pIdiLib = NULL;
964      }
965    } else {
966      diva_mnt_internal_dprintf (0, DLI_ERR, "A(%d) management init failed", (int)logical);
967    }
968  }
969
970  if (!clients[id].pIdiLib) {
971    clients[id].request = NULL;
972    clients[id].request_pending = 0;
973    clients[id].hDbg    = NULL;
974    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
975    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
976    diva_os_free (0, pmem);
977    return;
978  }
979
980  /*
981    Log driver register, MAINT driver ID is '0'
982    */
983  len = sprintf (tmp, "DIMAINT - drv # %d = '%s' registered",
984                 id, clients[id].Dbg.drvName);
985
986  while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
987                                      (word)(len+1+sizeof(*pmsg))))) {
988    if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
989      queueFreeMsg (dbg_queue);
990    } else {
991      break;
992    }
993  }
994
995  if (pmsg) {
996    pmsg->sequence    = dbg_sequence++;
997    pmsg->time_sec    = sec;
998    pmsg->time_usec   = usec;
999    pmsg->facility    = MSG_TYPE_STRING;
1000    pmsg->dli         = DLI_REG;
1001    pmsg->drv_id      = 0; /* id 0 - DIMAINT */
1002    pmsg->di_cpu      = 0;
1003    pmsg->data_length = len+1;
1004
1005    memcpy (&pmsg[1], tmp, len+1);
1006    queueCompleteMsg (pmsg);
1007    diva_maint_wakeup_read();
1008  }
1009
1010  org_mask = clients[id].Dbg.dbgMask;
1011  clients[id].Dbg.dbgMask = 0;
1012
1013  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
1014
1015  if (clients[id].request_pending) {
1016    clients[id].request_pending = 0;
1017    (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
1018  }
1019
1020  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
1021
1022	diva_set_driver_dbg_mask (id, org_mask);
1023}
1024
1025/*
1026  De-Register XDI adapter
1027  */
1028void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) {
1029  diva_os_spin_lock_magic_t old_irql, old_irql1;
1030  dword sec, usec;
1031  int i;
1032  word size;
1033  byte* pmem = NULL;
1034
1035  diva_os_get_time (&sec, &usec);
1036
1037  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
1038  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
1039
1040  for (i = 1; i < ARRAY_SIZE(clients); i++) {
1041    if (clients[i].hDbg && (clients[i].request == d->request)) {
1042      diva_dbg_entry_head_t* pmsg;
1043      char tmp[256];
1044      int len;
1045
1046      if (clients[i].pIdiLib) {
1047        (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1048        clients[i].pIdiLib = NULL;
1049
1050        pmem = clients[i].pmem;
1051        clients[i].pmem = NULL;
1052      }
1053
1054      clients[i].hDbg    = NULL;
1055      clients[i].request_pending = 0;
1056      if (clients[i].dma_handle >= 0) {
1057        /*
1058          Free DMA handle
1059          */
1060        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1061        clients[i].dma_handle = -1;
1062      }
1063      clients[i].request = NULL;
1064
1065      /*
1066        Log driver register, MAINT driver ID is '0'
1067        */
1068      len = sprintf (tmp, "DIMAINT - drv # %d = '%s' de-registered",
1069                     i, clients[i].Dbg.drvName);
1070
1071      memset (&clients[i].Dbg, 0x00, sizeof(clients[i].Dbg));
1072
1073      while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
1074                                        (word)(len+1+sizeof(*pmsg))))) {
1075        if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
1076          queueFreeMsg (dbg_queue);
1077        } else {
1078          break;
1079        }
1080      }
1081
1082      if (pmsg) {
1083        pmsg->sequence    = dbg_sequence++;
1084        pmsg->time_sec    = sec;
1085        pmsg->time_usec   = usec;
1086        pmsg->facility    = MSG_TYPE_STRING;
1087        pmsg->dli         = DLI_REG;
1088        pmsg->drv_id      = 0; /* id 0 - DIMAINT */
1089        pmsg->di_cpu      = 0;
1090        pmsg->data_length = len+1;
1091
1092        memcpy (&pmsg[1], tmp, len+1);
1093  		  queueCompleteMsg (pmsg);
1094        diva_maint_wakeup_read();
1095      }
1096
1097      break;
1098    }
1099  }
1100
1101  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
1102  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
1103
1104  if (pmem) {
1105    diva_os_free (0, pmem);
1106  }
1107}
1108
1109/* ----------------------------------------------------------------
1110     Low level interface for management interface client
1111   ---------------------------------------------------------------- */
1112/*
1113  Return handle to client structure
1114  */
1115void* SuperTraceOpenAdapter   (int AdapterNumber) {
1116  int i;
1117
1118  for (i = 1; i < ARRAY_SIZE(clients); i++) {
1119    if (clients[i].hDbg && clients[i].request && (clients[i].logical == AdapterNumber)) {
1120      return (&clients[i]);
1121    }
1122  }
1123
1124  return NULL;
1125}
1126
1127int SuperTraceCloseAdapter  (void* AdapterHandle) {
1128  return (0);
1129}
1130
1131int SuperTraceReadRequest (void* AdapterHandle, const char* name, byte* data) {
1132  diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1133
1134  if (pC && pC->pIdiLib && pC->request) {
1135    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1136    byte* xdata = (byte*)&pC->xbuffer[0];
1137    char tmp = 0;
1138    word length;
1139
1140    if (!strcmp(name, "\\")) { /* Read ROOT */
1141      name = &tmp;
1142    }
1143    length = SuperTraceCreateReadReq (xdata, name);
1144    single_p (xdata, &length, 0); /* End Of Message */
1145
1146    e->Req        = MAN_READ;
1147    e->ReqCh      = 0;
1148    e->X->PLength = length;
1149    e->X->P			  = (byte*)xdata;
1150
1151    pC->request_pending = 1;
1152
1153    return (0);
1154  }
1155
1156  return (-1);
1157}
1158
1159int SuperTraceGetNumberOfChannels (void* AdapterHandle) {
1160  if (AdapterHandle) {
1161    diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1162
1163    return (pC->channels);
1164  }
1165
1166  return (0);
1167}
1168
1169int SuperTraceASSIGN (void* AdapterHandle, byte* data) {
1170  diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1171
1172  if (pC && pC->pIdiLib && pC->request) {
1173    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1174    IDI_SYNC_REQ* preq;
1175    char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
1176    char features[4];
1177    word assign_data_length = 1;
1178
1179    features[0] = 0;
1180    pC->xbuffer[0] = 0;
1181    preq = (IDI_SYNC_REQ*)&buffer[0];
1182    preq->xdi_extended_features.Req = 0;
1183    preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
1184    preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
1185    preq->xdi_extended_features.info.features = &features[0];
1186
1187    (*(pC->request))((ENTITY*)preq);
1188
1189    if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
1190        (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
1191      dword rx_dma_magic;
1192      if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) {
1193        pC->xbuffer[0] = LLI;
1194        pC->xbuffer[1] = 8;
1195        pC->xbuffer[2] = 0x40;
1196        pC->xbuffer[3] = (byte)pC->dma_handle;
1197        pC->xbuffer[4] = (byte)rx_dma_magic;
1198        pC->xbuffer[5] = (byte)(rx_dma_magic >>  8);
1199        pC->xbuffer[6] = (byte)(rx_dma_magic >> 16);
1200        pC->xbuffer[7] = (byte)(rx_dma_magic >> 24);
1201        pC->xbuffer[8] = (byte)DIVA_MAX_MANAGEMENT_TRANSFER_SIZE;
1202        pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8);
1203        pC->xbuffer[10] = 0;
1204
1205        assign_data_length = 11;
1206      }
1207    } else {
1208      pC->dma_handle = -1;
1209    }
1210
1211    e->Id          = MAN_ID;
1212    e->callback    = diva_maint_xdi_cb;
1213    e->XNum        = 1;
1214    e->X           = &pC->XData;
1215    e->Req         = ASSIGN;
1216    e->ReqCh       = 0;
1217    e->X->PLength  = assign_data_length;
1218    e->X->P        = (byte*)&pC->xbuffer[0];
1219
1220    pC->request_pending = 1;
1221
1222    return (0);
1223  }
1224
1225  return (-1);
1226}
1227
1228int SuperTraceREMOVE (void* AdapterHandle) {
1229  diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1230
1231  if (pC && pC->pIdiLib && pC->request) {
1232    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1233
1234    e->XNum        = 1;
1235    e->X           = &pC->XData;
1236    e->Req         = REMOVE;
1237    e->ReqCh       = 0;
1238    e->X->PLength  = 1;
1239    e->X->P        = (byte*)&pC->xbuffer[0];
1240    pC->xbuffer[0] = 0;
1241
1242    pC->request_pending = 1;
1243
1244    return (0);
1245  }
1246
1247  return (-1);
1248}
1249
1250int SuperTraceTraceOnRequest(void* hAdapter, const char* name, byte* data) {
1251  diva_maint_client_t* pC = (diva_maint_client_t*)hAdapter;
1252
1253  if (pC && pC->pIdiLib && pC->request) {
1254    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1255    byte* xdata = (byte*)&pC->xbuffer[0];
1256    char tmp = 0;
1257    word length;
1258
1259    if (!strcmp(name, "\\")) { /* Read ROOT */
1260      name = &tmp;
1261    }
1262    length = SuperTraceCreateReadReq (xdata, name);
1263    single_p (xdata, &length, 0); /* End Of Message */
1264    e->Req          = MAN_EVENT_ON;
1265    e->ReqCh        = 0;
1266    e->X->PLength   = length;
1267    e->X->P			    = (byte*)xdata;
1268
1269    pC->request_pending = 1;
1270
1271    return (0);
1272  }
1273
1274  return (-1);
1275}
1276
1277int SuperTraceWriteVar (void* AdapterHandle,
1278                        byte* data,
1279                        const char* name,
1280                        void* var,
1281                        byte type,
1282                        byte var_length) {
1283  diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1284
1285  if (pC && pC->pIdiLib && pC->request) {
1286    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1287    diva_man_var_header_t* pVar = (diva_man_var_header_t*)&pC->xbuffer[0];
1288    word length = SuperTraceCreateReadReq ((byte*)pVar, name);
1289
1290    memcpy (&pC->xbuffer[length], var, var_length);
1291    length += var_length;
1292    pVar->length += var_length;
1293    pVar->value_length = var_length;
1294    pVar->type = type;
1295    single_p ((byte*)pVar, &length, 0); /* End Of Message */
1296
1297    e->Req          = MAN_WRITE;
1298    e->ReqCh			  = 0;
1299    e->X->PLength   = length;
1300    e->X->P			    = (byte*)pVar;
1301
1302    pC->request_pending = 1;
1303
1304    return (0);
1305  }
1306
1307  return (-1);
1308}
1309
1310int SuperTraceExecuteRequest (void* AdapterHandle,
1311                              const char* name,
1312                              byte* data) {
1313  diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1314
1315  if (pC && pC->pIdiLib && pC->request) {
1316    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1317    byte* xdata = (byte*)&pC->xbuffer[0];
1318    word length;
1319
1320    length = SuperTraceCreateReadReq (xdata, name);
1321    single_p (xdata, &length, 0); /* End Of Message */
1322
1323    e->Req          = MAN_EXECUTE;
1324    e->ReqCh			  = 0;
1325    e->X->PLength   = length;
1326    e->X->P			    = (byte*)xdata;
1327
1328    pC->request_pending = 1;
1329
1330    return (0);
1331  }
1332
1333  return (-1);
1334}
1335
1336static word SuperTraceCreateReadReq (byte* P, const char* path) {
1337	byte var_length;
1338	byte* plen;
1339
1340	var_length = (byte)strlen (path);
1341
1342	*P++ = ESC;
1343	plen = P++;
1344	*P++ = 0x80; /* MAN_IE */
1345	*P++ = 0x00; /* Type */
1346	*P++ = 0x00; /* Attribute */
1347	*P++ = 0x00; /* Status */
1348	*P++ = 0x00; /* Variable Length */
1349	*P++ = var_length;
1350	memcpy (P, path, var_length);
1351	P += var_length;
1352	*plen = var_length + 0x06;
1353
1354	return ((word)(var_length + 0x08));
1355}
1356
1357static void single_p (byte * P, word * PLength, byte Id) {
1358  P[(*PLength)++] = Id;
1359}
1360
1361static void diva_maint_xdi_cb (ENTITY* e) {
1362  diva_strace_context_t* pLib = DIVAS_CONTAINING_RECORD(e,diva_strace_context_t,e);
1363  diva_maint_client_t* pC;
1364  diva_os_spin_lock_magic_t old_irql, old_irql1;
1365
1366
1367  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
1368  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
1369
1370  pC = (diva_maint_client_t*)pLib->hAdapter;
1371
1372  if ((e->complete == 255) || (pC->dma_handle < 0)) {
1373    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1374      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error");
1375    }
1376  } else {
1377    /*
1378      Process combined management interface indication
1379      */
1380    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1381      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)");
1382    }
1383  }
1384
1385  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
1386
1387
1388	if (pC->request_pending) {
1389    pC->request_pending = 0;
1390    (*(pC->request))(e);
1391	}
1392
1393  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
1394}
1395
1396
1397static void diva_maint_error (void* user_context,
1398                              diva_strace_library_interface_t* hLib,
1399                              int Adapter,
1400                              int error,
1401                              const char* file,
1402                              int line) {
1403	diva_mnt_internal_dprintf (0, DLI_ERR,
1404                             "Trace library error(%d) A(%d) %s %d", error, Adapter, file, line);
1405}
1406
1407static void print_ie (diva_trace_ie_t* ie, char* buffer, int length) {
1408	int i;
1409
1410  buffer[0] = 0;
1411
1412  if (length > 32) {
1413    for (i = 0; ((i < ie->length) && (length > 3)); i++) {
1414      sprintf (buffer, "%02x", ie->data[i]);
1415      buffer += 2;
1416      length -= 2;
1417      if (i < (ie->length-1)) {
1418        strcpy (buffer, " ");
1419        buffer++;
1420        length--;
1421      }
1422    }
1423  }
1424}
1425
1426static void diva_maint_state_change_notify (void* user_context,
1427                                            diva_strace_library_interface_t* hLib,
1428                                            int Adapter,
1429                                            diva_trace_line_state_t* channel,
1430                                            int notify_subject) {
1431  diva_maint_client_t*      pC    = (diva_maint_client_t*)user_context;
1432  diva_trace_fax_state_t*   fax   = &channel->fax;
1433  diva_trace_modem_state_t* modem = &channel->modem;
1434  char tmp[256];
1435
1436  if (!pC->hDbg) {
1437    return;
1438  }
1439
1440  switch (notify_subject) {
1441    case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: {
1442      int view = (TraceFilter[0] == 0);
1443      /*
1444        Process selective Trace
1445        */
1446      if (channel->Line[0] == 'I' && channel->Line[1] == 'd' &&
1447          channel->Line[2] == 'l' && channel->Line[3] == 'e') {
1448        if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) {
1449          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0);
1450          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0);
1451          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d",
1452                                     (int)channel->ChannelNumber);
1453          TraceFilterIdent   = -1;
1454          TraceFilterChannel = -1;
1455          view = 1;
1456        }
1457      } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) &&
1458                                                               diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) {
1459
1460        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */
1461          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1);
1462        }
1463        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */
1464          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1);
1465        }
1466
1467        TraceFilterIdent   = pC->hDbg->id;
1468        TraceFilterChannel = (int)channel->ChannelNumber;
1469
1470        if (TraceFilterIdent >= 0) {
1471          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d",
1472                                     (int)channel->ChannelNumber);
1473          view = 1;
1474        }
1475      }
1476      if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) {
1477        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch     = %d",
1478                                                                     (int)channel->ChannelNumber);
1479        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]);
1480        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer1 = <%s>", &channel->Framing[0]);
1481        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer2 = <%s>", &channel->Layer2[0]);
1482        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer3 = <%s>", &channel->Layer3[0]);
1483        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RAddr  = <%s>",
1484                                                                     &channel->RemoteAddress[0]);
1485        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RSAddr = <%s>",
1486                                                                     &channel->RemoteSubAddress[0]);
1487        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LAddr  = <%s>",
1488                                                                     &channel->LocalAddress[0]);
1489        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LSAddr = <%s>",
1490                                                                     &channel->LocalSubAddress[0]);
1491        print_ie(&channel->call_BC, tmp, sizeof(tmp));
1492        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L BC     = <%s>", tmp);
1493        print_ie(&channel->call_HLC, tmp, sizeof(tmp));
1494        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L HLC    = <%s>", tmp);
1495        print_ie(&channel->call_LLC, tmp, sizeof(tmp));
1496        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LLC    = <%s>", tmp);
1497        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L CR     = 0x%x", channel->CallReference);
1498        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Disc   = 0x%x",
1499                                                                    channel->LastDisconnecCause);
1500        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner  = <%s>", &channel->UserID[0]);
1501      }
1502
1503		} break;
1504
1505    case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE:
1506      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) {
1507				{
1508					int ch = TraceFilterChannel;
1509					int id = TraceFilterIdent;
1510
1511					if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1512						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1513						if (ch != (int)modem->ChannelNumber) {
1514							break;
1515						}
1516					} else if (TraceFilter[0] != 0) {
1517						break;
1518					}
1519				}
1520
1521
1522        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch    = %lu",
1523                                                                     (int)modem->ChannelNumber);
1524        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu",     modem->Event);
1525        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Norm  = %lu",     modem->Norm);
1526        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Opts. = 0x%08x",  modem->Options);
1527        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Tx    = %lu Bps", modem->TxSpeed);
1528        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rx    = %lu Bps", modem->RxSpeed);
1529        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RT    = %lu mSec",
1530                                                                     modem->RoundtripMsec);
1531        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Sr    = %lu",     modem->SymbolRate);
1532        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rxl   = %d dBm",  modem->RxLeveldBm);
1533        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM El    = %d dBm",  modem->EchoLeveldBm);
1534        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM SNR   = %lu dB",  modem->SNRdb);
1535        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM MAE   = %lu",     modem->MAE);
1536        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRet  = %lu",
1537                                                                     modem->LocalRetrains);
1538        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRet  = %lu",
1539                                                                     modem->RemoteRetrains);
1540        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRes  = %lu",     modem->LocalResyncs);
1541        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRes  = %lu",
1542                                                                     modem->RemoteResyncs);
1543        if (modem->Event == 3) {
1544          diva_mnt_internal_dprintf(pC->hDbg->id,DLI_STAT,"MDM Disc  =  %lu",    modem->DiscReason);
1545        }
1546      }
1547      if ((modem->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_STATISTICS)) {
1548        (*(pC->pIdiLib->DivaSTraceGetModemStatistics))(pC->pIdiLib);
1549      }
1550      break;
1551
1552    case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE:
1553      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) {
1554				{
1555					int ch = TraceFilterChannel;
1556					int id = TraceFilterIdent;
1557
1558					if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1559						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1560						if (ch != (int)fax->ChannelNumber) {
1561							break;
1562						}
1563					} else if (TraceFilter[0] != 0) {
1564						break;
1565					}
1566				}
1567
1568        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch    = %lu",(int)fax->ChannelNumber);
1569        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu",     fax->Event);
1570        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu",     fax->Page_Counter);
1571        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Feat. = 0x%08x",  fax->Features);
1572        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX ID    = <%s>",    &fax->Station_ID[0]);
1573        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Saddr = <%s>",    &fax->Subaddress[0]);
1574        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pwd   = <%s>",    &fax->Password[0]);
1575        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Speed = %lu",     fax->Speed);
1576        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Res.  = 0x%08x",  fax->Resolution);
1577        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Width = %lu",     fax->Paper_Width);
1578        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Length= %lu",     fax->Paper_Length);
1579        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX SLT   = %lu",     fax->Scanline_Time);
1580        if (fax->Event == 3) {
1581          diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Disc  = %lu",     fax->Disc_Reason);
1582        }
1583      }
1584      if ((fax->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_STATISTICS)) {
1585        (*(pC->pIdiLib->DivaSTraceGetFaxStatistics))(pC->pIdiLib);
1586      }
1587      break;
1588
1589    case DIVA_SUPER_TRACE_INTERFACE_CHANGE:
1590      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_EVENTS) {
1591        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT,
1592                                 "Layer 1 -> [%s]", channel->pInterface->Layer1);
1593        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT,
1594                                 "Layer 2 -> [%s]", channel->pInterface->Layer2);
1595      }
1596      break;
1597
1598    case DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE:
1599      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_STATISTICS) {
1600        /*
1601          Incoming Statistics
1602          */
1603        if (channel->pInterfaceStat->inc.Calls) {
1604          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1605          "Inc Calls                     =%lu", channel->pInterfaceStat->inc.Calls);
1606        }
1607        if (channel->pInterfaceStat->inc.Connected) {
1608          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1609          "Inc Connected                 =%lu", channel->pInterfaceStat->inc.Connected);
1610        }
1611        if (channel->pInterfaceStat->inc.User_Busy) {
1612          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1613          "Inc Busy                      =%lu", channel->pInterfaceStat->inc.User_Busy);
1614        }
1615        if (channel->pInterfaceStat->inc.Call_Rejected) {
1616          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1617          "Inc Rejected                  =%lu", channel->pInterfaceStat->inc.Call_Rejected);
1618        }
1619        if (channel->pInterfaceStat->inc.Wrong_Number) {
1620          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1621          "Inc Wrong Nr                  =%lu", channel->pInterfaceStat->inc.Wrong_Number);
1622        }
1623        if (channel->pInterfaceStat->inc.Incompatible_Dst) {
1624          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1625          "Inc Incomp. Dest              =%lu", channel->pInterfaceStat->inc.Incompatible_Dst);
1626        }
1627        if (channel->pInterfaceStat->inc.Out_of_Order) {
1628          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1629          "Inc Out of Order              =%lu", channel->pInterfaceStat->inc.Out_of_Order);
1630        }
1631        if (channel->pInterfaceStat->inc.Ignored) {
1632          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1633          "Inc Ignored                   =%lu", channel->pInterfaceStat->inc.Ignored);
1634        }
1635
1636        /*
1637          Outgoing Statistics
1638          */
1639        if (channel->pInterfaceStat->outg.Calls) {
1640          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1641          "Outg Calls                    =%lu", channel->pInterfaceStat->outg.Calls);
1642        }
1643        if (channel->pInterfaceStat->outg.Connected) {
1644          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1645          "Outg Connected                =%lu", channel->pInterfaceStat->outg.Connected);
1646        }
1647        if (channel->pInterfaceStat->outg.User_Busy) {
1648          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1649          "Outg Busy                     =%lu", channel->pInterfaceStat->outg.User_Busy);
1650        }
1651        if (channel->pInterfaceStat->outg.No_Answer) {
1652          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1653          "Outg No Answer                =%lu", channel->pInterfaceStat->outg.No_Answer);
1654        }
1655        if (channel->pInterfaceStat->outg.Wrong_Number) {
1656          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1657          "Outg Wrong Nr                 =%lu", channel->pInterfaceStat->outg.Wrong_Number);
1658        }
1659        if (channel->pInterfaceStat->outg.Call_Rejected) {
1660          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1661          "Outg Rejected                 =%lu", channel->pInterfaceStat->outg.Call_Rejected);
1662        }
1663        if (channel->pInterfaceStat->outg.Other_Failures) {
1664          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1665          "Outg Other Failures           =%lu", channel->pInterfaceStat->outg.Other_Failures);
1666        }
1667      }
1668      break;
1669
1670    case DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE:
1671      if (channel->pInterfaceStat->mdm.Disc_Normal) {
1672        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1673        "MDM Disc Normal        = %lu", channel->pInterfaceStat->mdm.Disc_Normal);
1674      }
1675      if (channel->pInterfaceStat->mdm.Disc_Unspecified) {
1676        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1677        "MDM Disc Unsp.         = %lu", channel->pInterfaceStat->mdm.Disc_Unspecified);
1678      }
1679      if (channel->pInterfaceStat->mdm.Disc_Busy_Tone) {
1680        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1681        "MDM Disc Busy Tone     = %lu", channel->pInterfaceStat->mdm.Disc_Busy_Tone);
1682      }
1683      if (channel->pInterfaceStat->mdm.Disc_Congestion) {
1684        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1685        "MDM Disc Congestion    = %lu", channel->pInterfaceStat->mdm.Disc_Congestion);
1686      }
1687      if (channel->pInterfaceStat->mdm.Disc_Carr_Wait) {
1688        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1689        "MDM Disc Carrier Wait  = %lu", channel->pInterfaceStat->mdm.Disc_Carr_Wait);
1690      }
1691      if (channel->pInterfaceStat->mdm.Disc_Trn_Timeout) {
1692        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1693        "MDM Disc Trn. T.o.     = %lu", channel->pInterfaceStat->mdm.Disc_Trn_Timeout);
1694      }
1695      if (channel->pInterfaceStat->mdm.Disc_Incompat) {
1696        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1697        "MDM Disc Incompatible  = %lu", channel->pInterfaceStat->mdm.Disc_Incompat);
1698      }
1699      if (channel->pInterfaceStat->mdm.Disc_Frame_Rej) {
1700        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1701        "MDM Disc Frame Reject  = %lu", channel->pInterfaceStat->mdm.Disc_Frame_Rej);
1702      }
1703      if (channel->pInterfaceStat->mdm.Disc_V42bis) {
1704        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1705        "MDM Disc V.42bis       = %lu", channel->pInterfaceStat->mdm.Disc_V42bis);
1706      }
1707      break;
1708
1709    case DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE:
1710      if (channel->pInterfaceStat->fax.Disc_Normal) {
1711        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1712        "FAX Disc Normal        = %lu", channel->pInterfaceStat->fax.Disc_Normal);
1713      }
1714      if (channel->pInterfaceStat->fax.Disc_Not_Ident) {
1715        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1716        "FAX Disc Not Ident.    = %lu", channel->pInterfaceStat->fax.Disc_Not_Ident);
1717      }
1718      if (channel->pInterfaceStat->fax.Disc_No_Response) {
1719        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1720        "FAX Disc No Response   = %lu", channel->pInterfaceStat->fax.Disc_No_Response);
1721      }
1722      if (channel->pInterfaceStat->fax.Disc_Retries) {
1723        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1724        "FAX Disc Max Retries   = %lu", channel->pInterfaceStat->fax.Disc_Retries);
1725      }
1726      if (channel->pInterfaceStat->fax.Disc_Unexp_Msg) {
1727        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1728        "FAX Unexp. Msg.        = %lu", channel->pInterfaceStat->fax.Disc_Unexp_Msg);
1729      }
1730      if (channel->pInterfaceStat->fax.Disc_No_Polling) {
1731        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1732        "FAX Disc No Polling    = %lu", channel->pInterfaceStat->fax.Disc_No_Polling);
1733      }
1734      if (channel->pInterfaceStat->fax.Disc_Training) {
1735        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1736        "FAX Disc Training      = %lu", channel->pInterfaceStat->fax.Disc_Training);
1737      }
1738      if (channel->pInterfaceStat->fax.Disc_Unexpected) {
1739        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1740        "FAX Disc Unexpected    = %lu", channel->pInterfaceStat->fax.Disc_Unexpected);
1741      }
1742      if (channel->pInterfaceStat->fax.Disc_Application) {
1743        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1744        "FAX Disc Application   = %lu", channel->pInterfaceStat->fax.Disc_Application);
1745      }
1746      if (channel->pInterfaceStat->fax.Disc_Incompat) {
1747        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1748        "FAX Disc Incompatible  = %lu", channel->pInterfaceStat->fax.Disc_Incompat);
1749      }
1750      if (channel->pInterfaceStat->fax.Disc_No_Command) {
1751        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1752        "FAX Disc No Command    = %lu", channel->pInterfaceStat->fax.Disc_No_Command);
1753      }
1754      if (channel->pInterfaceStat->fax.Disc_Long_Msg) {
1755        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1756        "FAX Disc Long Msg.     = %lu", channel->pInterfaceStat->fax.Disc_Long_Msg);
1757      }
1758      if (channel->pInterfaceStat->fax.Disc_Supervisor) {
1759        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1760        "FAX Disc Supervisor    = %lu", channel->pInterfaceStat->fax.Disc_Supervisor);
1761      }
1762      if (channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD) {
1763        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1764        "FAX Disc SUP SEP PWD   = %lu", channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD);
1765      }
1766      if (channel->pInterfaceStat->fax.Disc_Invalid_Msg) {
1767        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1768        "FAX Disc Invalid Msg.  = %lu", channel->pInterfaceStat->fax.Disc_Invalid_Msg);
1769      }
1770      if (channel->pInterfaceStat->fax.Disc_Page_Coding) {
1771        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1772        "FAX Disc Page Coding   = %lu", channel->pInterfaceStat->fax.Disc_Page_Coding);
1773      }
1774      if (channel->pInterfaceStat->fax.Disc_App_Timeout) {
1775        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1776        "FAX Disc Appl. T.o.    = %lu", channel->pInterfaceStat->fax.Disc_App_Timeout);
1777      }
1778      if (channel->pInterfaceStat->fax.Disc_Unspecified) {
1779        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1780        "FAX Disc Unspec.       = %lu", channel->pInterfaceStat->fax.Disc_Unspecified);
1781      }
1782      break;
1783  }
1784}
1785
1786/*
1787  Receive trace information from the Management Interface and store it in the
1788  internal trace buffer with MSG_TYPE_MLOG as is, without any filtering.
1789  Event Filtering and formatting is done in  Management Interface self.
1790  */
1791static void diva_maint_trace_notify (void* user_context,
1792                                     diva_strace_library_interface_t* hLib,
1793                                     int Adapter,
1794                                     void* xlog_buffer,
1795                                     int length) {
1796  diva_maint_client_t* pC = (diva_maint_client_t*)user_context;
1797  diva_dbg_entry_head_t* pmsg;
1798  word size;
1799  dword sec, usec;
1800  int ch = TraceFilterChannel;
1801  int id = TraceFilterIdent;
1802
1803  /*
1804    Selective trace
1805    */
1806  if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1807      (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1808    const char* p = NULL;
1809    int ch_value = -1;
1810    MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer;
1811
1812    if (Adapter != clients[id].logical) {
1813      return; /* Ignore all trace messages from other adapters */
1814    }
1815
1816    if (TrcData->code == 24) {
1817      p = (char*)&TrcData->code;
1818      p += 2;
1819    }
1820
1821    /*
1822      All L1 messages start as [dsp,ch], so we can filter this information
1823      and filter out all messages that use different channel
1824      */
1825    if (p && p[0] == '[') {
1826      if (p[2] == ',') {
1827        p += 3;
1828        ch_value = *p - '0';
1829      } else if (p[3] == ',') {
1830        p += 4;
1831        ch_value = *p - '0';
1832      }
1833      if (ch_value >= 0) {
1834        if (p[2] == ']') {
1835          ch_value = ch_value * 10 + p[1] - '0';
1836        }
1837        if (ch_value != ch) {
1838          return; /* Ignore other channels */
1839        }
1840      }
1841    }
1842
1843	} else if (TraceFilter[0] != 0) {
1844    return; /* Ignore trace if trace filter is activated, but idle */
1845  }
1846
1847  diva_os_get_time (&sec, &usec);
1848
1849  while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
1850                              (word)length+sizeof(*pmsg)))) {
1851    if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
1852      queueFreeMsg (dbg_queue);
1853    } else {
1854      break;
1855    }
1856  }
1857  if (pmsg) {
1858    memcpy (&pmsg[1], xlog_buffer, length);
1859    pmsg->sequence    = dbg_sequence++;
1860    pmsg->time_sec    = sec;
1861    pmsg->time_usec   = usec;
1862    pmsg->facility    = MSG_TYPE_MLOG;
1863    pmsg->dli         = pC->logical;
1864    pmsg->drv_id      = pC->hDbg->id;
1865    pmsg->di_cpu      = 0;
1866    pmsg->data_length = length;
1867    queueCompleteMsg (pmsg);
1868    if (queueCount(dbg_queue)) {
1869      diva_maint_wakeup_read();
1870    }
1871  }
1872}
1873
1874
1875/*
1876  Convert MAINT trace mask to management interface trace mask/work/facility and
1877  issue command to management interface
1878  */
1879static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask) {
1880  if (pC->request && pC->hDbg && pC->pIdiLib) {
1881    dword changed = pC->hDbg->dbgMask ^ old_mask;
1882
1883    if (changed & DIVA_MGT_DBG_TRACE) {
1884      (*(pC->pIdiLib->DivaSTraceSetInfo))(pC->pIdiLib,
1885                                          (pC->hDbg->dbgMask & DIVA_MGT_DBG_TRACE) != 0);
1886    }
1887    if (changed & DIVA_MGT_DBG_DCHAN) {
1888      (*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib,
1889                                              (pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0);
1890    }
1891    if (!TraceFilter[0]) {
1892      if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) {
1893        int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
1894
1895        for (i = 0; i < pC->channels; i++) {
1896          (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state);
1897        }
1898      }
1899      if (changed & DIVA_MGT_DBG_IFC_AUDIO) {
1900        int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
1901
1902        for (i = 0; i < pC->channels; i++) {
1903          (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state);
1904        }
1905      }
1906    }
1907  }
1908}
1909
1910
1911void diva_mnt_internal_dprintf (dword drv_id, dword type, char* fmt, ...) {
1912  va_list ap;
1913
1914	va_start(ap, fmt);
1915  DI_format (0, (word)drv_id, (int)type, fmt, ap);
1916	va_end(ap);
1917}
1918
1919/*
1920  Shutdown all adapters before driver removal
1921  */
1922int diva_mnt_shutdown_xdi_adapters (void) {
1923  diva_os_spin_lock_magic_t old_irql, old_irql1;
1924  int i, fret = 0;
1925  byte * pmem;
1926
1927
1928  for (i = 1; i < ARRAY_SIZE(clients); i++) {
1929    pmem = NULL;
1930
1931    diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
1932    diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload");
1933
1934    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
1935      if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) {
1936        /*
1937          Adapter removal complete
1938          */
1939        if (clients[i].pIdiLib) {
1940          (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1941          clients[i].pIdiLib = NULL;
1942
1943          pmem = clients[i].pmem;
1944          clients[i].pmem = NULL;
1945        }
1946        clients[i].hDbg    = NULL;
1947        clients[i].request_pending = 0;
1948
1949        if (clients[i].dma_handle >= 0) {
1950          /*
1951            Free DMA handle
1952            */
1953          diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1954          clients[i].dma_handle = -1;
1955				}
1956        clients[i].request = NULL;
1957      } else {
1958        fret = -1;
1959      }
1960    }
1961
1962    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload");
1963    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
1964      clients[i].request_pending = 0;
1965      (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
1966      if (clients[i].dma_handle >= 0) {
1967        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1968        clients[i].dma_handle = -1;
1969      }
1970    }
1971    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
1972
1973    if (pmem) {
1974      diva_os_free (0, pmem);
1975    }
1976  }
1977
1978  return (fret);
1979}
1980
1981/*
1982  Set/Read the trace filter used for selective tracing.
1983  Affects B- and Audio Tap trace mask at run time
1984  */
1985int diva_set_trace_filter (int filter_length, const char* filter) {
1986  diva_os_spin_lock_magic_t old_irql, old_irql1;
1987  int i, ch, on, client_b_on, client_atap_on;
1988
1989  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
1990  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
1991
1992  if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) {
1993    memcpy (&TraceFilter[0], filter, filter_length);
1994    if (TraceFilter[filter_length]) {
1995      TraceFilter[filter_length] = 0;
1996    }
1997    if (TraceFilter[0] == '*') {
1998      TraceFilter[0] = 0;
1999    }
2000  } else {
2001    filter_length = -1;
2002  }
2003
2004  TraceFilterIdent   = -1;
2005  TraceFilterChannel = -1;
2006
2007  on = (TraceFilter[0] == 0);
2008
2009  for (i = 1; i < ARRAY_SIZE(clients); i++) {
2010    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
2011      client_b_on    = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
2012      client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO)    != 0);
2013      for (ch = 0; ch < clients[i].channels; ch++) {
2014        (*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch+1, client_b_on);
2015        (*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch+1, client_atap_on);
2016      }
2017    }
2018  }
2019
2020  for (i = 1; i < ARRAY_SIZE(clients); i++) {
2021    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
2022      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
2023      clients[i].request_pending = 0;
2024      (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
2025      diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
2026    }
2027  }
2028
2029  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
2030  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
2031
2032  return (filter_length);
2033}
2034
2035int diva_get_trace_filter (int max_length, char* filter) {
2036  diva_os_spin_lock_magic_t old_irql;
2037  int len;
2038
2039  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
2040  len = strlen (&TraceFilter[0]) + 1;
2041  if (max_length >= len) {
2042    memcpy (filter, &TraceFilter[0], len);
2043  }
2044  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
2045
2046  return (len);
2047}
2048
2049static int diva_dbg_cmp_key (const char* ref, const char* key) {
2050	while (*key && (*ref++ == *key++));
2051  return (!*key && !*ref);
2052}
2053
2054/*
2055  In case trace filter starts with "C" character then
2056  all following characters are interpreted as command.
2057  Followings commands are available:
2058  - single, trace single call at time, independent from CPN/CiPN
2059  */
2060static int diva_mnt_cmp_nmbr (const char* nmbr) {
2061  const char* ref = &TraceFilter[0];
2062  int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr);
2063
2064  if (ref[0] == 'C') {
2065    if (diva_dbg_cmp_key (&ref[1], "single")) {
2066      return (0);
2067    }
2068    return (-1);
2069  }
2070
2071  if (!ref_len || (ref_len > nmbr_len)) {
2072    return (-1);
2073  }
2074
2075  nmbr = nmbr + nmbr_len - 1;
2076  ref  = ref  + ref_len  - 1;
2077
2078  while (ref_len--) {
2079    if (*nmbr-- != *ref--) {
2080      return (-1);
2081    }
2082  }
2083
2084  return (0);
2085}
2086
2087static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) {
2088  ENTITY e;
2089  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
2090
2091  if (!request) {
2092    return (-1);
2093  }
2094
2095  pReq->xdi_dma_descriptor_operation.Req = 0;
2096  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2097
2098  pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
2099  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
2100  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2101  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
2102
2103  (*request)((ENTITY*)pReq);
2104
2105  if (!pReq->xdi_dma_descriptor_operation.info.operation &&
2106      (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
2107      pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
2108    *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
2109    return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
2110  } else {
2111    return (-1);
2112  }
2113}
2114
2115static void diva_free_dma_descriptor (IDI_CALL request, int nr) {
2116  ENTITY e;
2117  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
2118
2119  if (!request || (nr < 0)) {
2120    return;
2121  }
2122
2123  pReq->xdi_dma_descriptor_operation.Req = 0;
2124  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2125
2126  pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
2127  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
2128  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2129  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
2130
2131  (*request)((ENTITY*)pReq);
2132}
2133