Showing error 1801

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/isdn/hardware/eicon/debug.c
Line in file: 704
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-11 08:47:26 UTC


Source:

   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 uninitialized_var(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