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