linux/drivers/isdn/hardware/eicon/debug.c
<<
>>
Prefs
   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, free_id = -1;
 865  char tmp[128];
 866  diva_dbg_entry_head_t* pmsg = NULL;
 867  int len;
 868  word size;
 869  byte* pmem;
 870
 871  diva_os_get_time (&sec, &usec);
 872  diva_get_idi_adapter_info (d->request, &serial, &logical);
 873  if (serial & 0xff000000) {
 874    sprintf (tmp, "ADAPTER:%d SN:%u-%d",
 875             (int)logical,
 876             serial & 0x00ffffff,
 877             (byte)(((serial & 0xff000000) >> 24) + 1));
 878  } else {
 879    sprintf (tmp, "ADAPTER:%d SN:%u", (int)logical, serial);
 880  }
 881
 882  if (!(pmem = diva_os_malloc (0, DivaSTraceGetMemotyRequirement (d->channels)))) {
 883    return;
 884  }
 885  memset (pmem, 0x00, DivaSTraceGetMemotyRequirement (d->channels));
 886
 887  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
 888  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 889
 890  for (id = 1; id < ARRAY_SIZE(clients); id++) {
 891    if (clients[id].hDbg && (clients[id].request == d->request)) {
 892      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
 893      diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
 894      diva_os_free(0, pmem);
 895      return;
 896    }
 897    if (clients[id].hDbg) { /* slot is busy */
 898      continue;
 899    }
 900    if (free_id < 0) {
 901      free_id = id;
 902    }
 903    if (!strcmp (clients[id].drvName, tmp)) {
 904      /*
 905        This driver was already registered with this name
 906        and slot is still free - reuse it
 907        */
 908      free_id = id;
 909      break;
 910    }
 911  }
 912
 913  if (free_id < 0) {
 914    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
 915    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
 916    diva_os_free (0, pmem);
 917    return;
 918  }
 919
 920  id = free_id;
 921  clients[id].request  = d->request;
 922  clients[id].request_pending = 0;
 923  clients[id].hDbg     = &clients[id].Dbg;
 924  clients[id].sec      = sec;
 925  clients[id].usec     = usec;
 926  strcpy (clients[id].drvName,     tmp);
 927  strcpy (clients[id].Dbg.drvName, tmp);
 928  clients[id].Dbg.drvTag[0] = 0;
 929  clients[id].logical  = (int)logical;
 930  clients[id].channels = (int)d->channels;
 931  clients[id].dma_handle = -1;
 932
 933  clients[id].Dbg.dbgMask    = 0;
 934  clients[id].dbgMask        = clients[id].Dbg.dbgMask;
 935  if (id) {
 936    clients[id].Dbg.dbgMask |= clients[free_id].last_dbgMask;
 937  } else {
 938    clients[id].last_dbgMask = 0;
 939  }
 940  clients[id].Dbg.Registered = DBG_HANDLE_REG_NEW;
 941  clients[id].Dbg.id         = (byte)id;
 942  clients[id].Dbg.dbg_end    = DI_deregister;
 943  clients[id].Dbg.dbg_prt    = DI_format_locked;
 944  clients[id].Dbg.dbg_ev     = DiProcessEventLog;
 945  clients[id].Dbg.dbg_irq    = DI_format_locked;
 946  clients[id].Dbg.next       = (pDbgHandle)DBG_MAGIC;
 947
 948  {
 949    diva_trace_library_user_interface_t diva_maint_user_ifc = { &clients[id],
 950                                                                                                                                                                                         diva_maint_state_change_notify,
 951                                                                                                                                                                                         diva_maint_trace_notify,
 952                                                                                                                                                                                         diva_maint_error };
 953
 954    /*
 955      Attach to adapter management interface
 956      */
 957    if ((clients[id].pIdiLib =
 958               DivaSTraceLibraryCreateInstance ((int)logical, &diva_maint_user_ifc, pmem))) {
 959      if (((*(clients[id].pIdiLib->DivaSTraceLibraryStart))(clients[id].pIdiLib->hLib))) {
 960        diva_mnt_internal_dprintf (0, DLI_ERR, "Adapter(%d) Start failed", (int)logical);
 961        (*(clients[id].pIdiLib->DivaSTraceLibraryFinit))(clients[id].pIdiLib->hLib);
 962        clients[id].pIdiLib = NULL;
 963      }
 964    } else {
 965      diva_mnt_internal_dprintf (0, DLI_ERR, "A(%d) management init failed", (int)logical);
 966    }
 967  }
 968
 969  if (!clients[id].pIdiLib) {
 970    clients[id].request = NULL;
 971    clients[id].request_pending = 0;
 972    clients[id].hDbg    = NULL;
 973    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
 974    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
 975    diva_os_free (0, pmem);
 976    return;
 977  }
 978
 979  /*
 980    Log driver register, MAINT driver ID is '0'
 981    */
 982  len = sprintf (tmp, "DIMAINT - drv # %d = '%s' registered",
 983                 id, clients[id].Dbg.drvName);
 984
 985  while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
 986                                      (word)(len+1+sizeof(*pmsg))))) {
 987    if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
 988      queueFreeMsg (dbg_queue);
 989    } else {
 990      break;
 991    }
 992  }
 993
 994  if (pmsg) {
 995    pmsg->sequence    = dbg_sequence++;
 996    pmsg->time_sec    = sec;
 997    pmsg->time_usec   = usec;
 998    pmsg->facility    = MSG_TYPE_STRING;
 999    pmsg->dli         = DLI_REG;
1000    pmsg->drv_id      = 0; /* id 0 - DIMAINT */
1001    pmsg->di_cpu      = 0;
1002    pmsg->data_length = len+1;
1003
1004    memcpy (&pmsg[1], tmp, len+1);
1005    queueCompleteMsg (pmsg);
1006    diva_maint_wakeup_read();
1007  }
1008
1009  org_mask = clients[id].Dbg.dbgMask;
1010  clients[id].Dbg.dbgMask = 0;
1011
1012  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
1013
1014  if (clients[id].request_pending) {
1015    clients[id].request_pending = 0;
1016    (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
1017  }
1018
1019  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
1020
1021        diva_set_driver_dbg_mask (id, org_mask);
1022}
1023
1024/*
1025  De-Register XDI adapter
1026  */
1027void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) {
1028  diva_os_spin_lock_magic_t old_irql, old_irql1;
1029  dword sec, usec;
1030  int i;
1031  word size;
1032  byte* pmem = NULL;
1033
1034  diva_os_get_time (&sec, &usec);
1035
1036  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
1037  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
1038
1039  for (i = 1; i < ARRAY_SIZE(clients); i++) {
1040    if (clients[i].hDbg && (clients[i].request == d->request)) {
1041      diva_dbg_entry_head_t* pmsg;
1042      char tmp[256];
1043      int len;
1044
1045      if (clients[i].pIdiLib) {
1046        (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1047        clients[i].pIdiLib = NULL;
1048
1049        pmem = clients[i].pmem;
1050        clients[i].pmem = NULL;
1051      }
1052
1053      clients[i].hDbg    = NULL;
1054      clients[i].request_pending = 0;
1055      if (clients[i].dma_handle >= 0) {
1056        /*
1057          Free DMA handle
1058          */
1059        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1060        clients[i].dma_handle = -1;
1061      }
1062      clients[i].request = NULL;
1063
1064      /*
1065        Log driver register, MAINT driver ID is '0'
1066        */
1067      len = sprintf (tmp, "DIMAINT - drv # %d = '%s' de-registered",
1068                     i, clients[i].Dbg.drvName);
1069
1070      memset (&clients[i].Dbg, 0x00, sizeof(clients[i].Dbg));
1071
1072      while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
1073                                        (word)(len+1+sizeof(*pmsg))))) {
1074        if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
1075          queueFreeMsg (dbg_queue);
1076        } else {
1077          break;
1078        }
1079      }
1080
1081      if (pmsg) {
1082        pmsg->sequence    = dbg_sequence++;
1083        pmsg->time_sec    = sec;
1084        pmsg->time_usec   = usec;
1085        pmsg->facility    = MSG_TYPE_STRING;
1086        pmsg->dli         = DLI_REG;
1087        pmsg->drv_id      = 0; /* id 0 - DIMAINT */
1088        pmsg->di_cpu      = 0;
1089        pmsg->data_length = len+1;
1090
1091        memcpy (&pmsg[1], tmp, len+1);
1092                  queueCompleteMsg (pmsg);
1093        diva_maint_wakeup_read();
1094      }
1095
1096      break;
1097    }
1098  }
1099
1100  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
1101  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
1102
1103  if (pmem) {
1104    diva_os_free (0, pmem);
1105  }
1106}
1107
1108/* ----------------------------------------------------------------
1109     Low level interface for management interface client
1110   ---------------------------------------------------------------- */
1111/*
1112  Return handle to client structure
1113  */
1114void* 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
1126int SuperTraceCloseAdapter  (void* AdapterHandle) {
1127  return (0);
1128}
1129
1130int 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
1158int 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
1168int SuperTraceASSIGN (void* AdapterHandle, byte* data) {
1169  diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1170
1171  if (pC && pC->pIdiLib && pC->request) {
1172    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1173    IDI_SYNC_REQ* preq;
1174    char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
1175    char features[4];
1176    word assign_data_length = 1;
1177
1178    features[0] = 0;
1179    pC->xbuffer[0] = 0;
1180    preq = (IDI_SYNC_REQ*)&buffer[0];
1181    preq->xdi_extended_features.Req = 0;
1182    preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
1183    preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
1184    preq->xdi_extended_features.info.features = &features[0];
1185
1186    (*(pC->request))((ENTITY*)preq);
1187
1188    if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
1189        (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
1190      dword uninitialized_var(rx_dma_magic);
1191      if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) {
1192        pC->xbuffer[0] = LLI;
1193        pC->xbuffer[1] = 8;
1194        pC->xbuffer[2] = 0x40;
1195        pC->xbuffer[3] = (byte)pC->dma_handle;
1196        pC->xbuffer[4] = (byte)rx_dma_magic;
1197        pC->xbuffer[5] = (byte)(rx_dma_magic >>  8);
1198        pC->xbuffer[6] = (byte)(rx_dma_magic >> 16);
1199        pC->xbuffer[7] = (byte)(rx_dma_magic >> 24);
1200        pC->xbuffer[8] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE & 0xFF);
1201        pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8);
1202        pC->xbuffer[10] = 0;
1203
1204        assign_data_length = 11;
1205      }
1206    } else {
1207      pC->dma_handle = -1;
1208    }
1209
1210    e->Id          = MAN_ID;
1211    e->callback    = diva_maint_xdi_cb;
1212    e->XNum        = 1;
1213    e->X           = &pC->XData;
1214    e->Req         = ASSIGN;
1215    e->ReqCh       = 0;
1216    e->X->PLength  = assign_data_length;
1217    e->X->P        = (byte*)&pC->xbuffer[0];
1218
1219    pC->request_pending = 1;
1220
1221    return (0);
1222  }
1223
1224  return (-1);
1225}
1226
1227int 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
1249int 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
1276int SuperTraceWriteVar (void* AdapterHandle,
1277                        byte* data,
1278                        const char* name,
1279                        void* var,
1280                        byte type,
1281                        byte var_length) {
1282  diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle;
1283
1284  if (pC && pC->pIdiLib && pC->request) {
1285    ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
1286    diva_man_var_header_t* pVar = (diva_man_var_header_t*)&pC->xbuffer[0];
1287    word length = SuperTraceCreateReadReq ((byte*)pVar, name);
1288
1289    memcpy (&pC->xbuffer[length], var, var_length);
1290    length += var_length;
1291    pVar->length += var_length;
1292    pVar->value_length = var_length;
1293    pVar->type = type;
1294    single_p ((byte*)pVar, &length, 0); /* End Of Message */
1295
1296    e->Req          = MAN_WRITE;
1297    e->ReqCh                      = 0;
1298    e->X->PLength   = length;
1299    e->X->P                         = (byte*)pVar;
1300
1301    pC->request_pending = 1;
1302
1303    return (0);
1304  }
1305
1306  return (-1);
1307}
1308
1309int 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
1335static 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
1356static void single_p (byte * P, word * PLength, byte Id) {
1357  P[(*PLength)++] = Id;
1358}
1359
1360static void diva_maint_xdi_cb (ENTITY* e) {
1361  diva_strace_context_t* pLib = DIVAS_CONTAINING_RECORD(e,diva_strace_context_t,e);
1362  diva_maint_client_t* pC;
1363  diva_os_spin_lock_magic_t old_irql, old_irql1;
1364
1365
1366  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
1367  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
1368
1369  pC = (diva_maint_client_t*)pLib->hAdapter;
1370
1371  if ((e->complete == 255) || (pC->dma_handle < 0)) {
1372    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1373      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error");
1374    }
1375  } else {
1376    /*
1377      Process combined management interface indication
1378      */
1379    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
1380      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)");
1381    }
1382  }
1383
1384  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
1385
1386
1387        if (pC->request_pending) {
1388    pC->request_pending = 0;
1389    (*(pC->request))(e);
1390        }
1391
1392  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
1393}
1394
1395
1396static void diva_maint_error (void* user_context,
1397                              diva_strace_library_interface_t* hLib,
1398                              int Adapter,
1399                              int error,
1400                              const char* file,
1401                              int line) {
1402        diva_mnt_internal_dprintf (0, DLI_ERR,
1403                             "Trace library error(%d) A(%d) %s %d", error, Adapter, file, line);
1404}
1405
1406static 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
1425static void diva_maint_state_change_notify (void* user_context,
1426                                            diva_strace_library_interface_t* hLib,
1427                                            int Adapter,
1428                                            diva_trace_line_state_t* channel,
1429                                            int notify_subject) {
1430  diva_maint_client_t*      pC    = (diva_maint_client_t*)user_context;
1431  diva_trace_fax_state_t*   fax   = &channel->fax;
1432  diva_trace_modem_state_t* modem = &channel->modem;
1433  char tmp[256];
1434
1435  if (!pC->hDbg) {
1436    return;
1437  }
1438
1439  switch (notify_subject) {
1440    case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: {
1441      int view = (TraceFilter[0] == 0);
1442      /*
1443        Process selective Trace
1444        */
1445      if (channel->Line[0] == 'I' && channel->Line[1] == 'd' &&
1446          channel->Line[2] == 'l' && channel->Line[3] == 'e') {
1447        if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) {
1448          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0);
1449          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0);
1450          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d",
1451                                     (int)channel->ChannelNumber);
1452          TraceFilterIdent   = -1;
1453          TraceFilterChannel = -1;
1454          view = 1;
1455        }
1456      } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) &&
1457                                                               diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) {
1458
1459        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */
1460          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1);
1461        }
1462        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */
1463          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1);
1464        }
1465
1466        TraceFilterIdent   = pC->hDbg->id;
1467        TraceFilterChannel = (int)channel->ChannelNumber;
1468
1469        if (TraceFilterIdent >= 0) {
1470          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d",
1471                                     (int)channel->ChannelNumber);
1472          view = 1;
1473        }
1474      }
1475      if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) {
1476        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch     = %d",
1477                                                                     (int)channel->ChannelNumber);
1478        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]);
1479        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer1 = <%s>", &channel->Framing[0]);
1480        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer2 = <%s>", &channel->Layer2[0]);
1481        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer3 = <%s>", &channel->Layer3[0]);
1482        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RAddr  = <%s>",
1483                                                                     &channel->RemoteAddress[0]);
1484        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RSAddr = <%s>",
1485                                                                     &channel->RemoteSubAddress[0]);
1486        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LAddr  = <%s>",
1487                                                                     &channel->LocalAddress[0]);
1488        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LSAddr = <%s>",
1489                                                                     &channel->LocalSubAddress[0]);
1490        print_ie(&channel->call_BC, tmp, sizeof(tmp));
1491        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L BC     = <%s>", tmp);
1492        print_ie(&channel->call_HLC, tmp, sizeof(tmp));
1493        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L HLC    = <%s>", tmp);
1494        print_ie(&channel->call_LLC, tmp, sizeof(tmp));
1495        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LLC    = <%s>", tmp);
1496        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L CR     = 0x%x", channel->CallReference);
1497        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Disc   = 0x%x",
1498                                                                    channel->LastDisconnecCause);
1499        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner  = <%s>", &channel->UserID[0]);
1500      }
1501
1502                } break;
1503
1504    case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE:
1505      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) {
1506                                {
1507                                        int ch = TraceFilterChannel;
1508                                        int id = TraceFilterIdent;
1509
1510                                        if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1511                                                (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1512                                                if (ch != (int)modem->ChannelNumber) {
1513                                                        break;
1514                                                }
1515                                        } else if (TraceFilter[0] != 0) {
1516                                                break;
1517                                        }
1518                                }
1519
1520
1521        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch    = %lu",
1522                                                                     (int)modem->ChannelNumber);
1523        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu",     modem->Event);
1524        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Norm  = %lu",     modem->Norm);
1525        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Opts. = 0x%08x",  modem->Options);
1526        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Tx    = %lu Bps", modem->TxSpeed);
1527        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rx    = %lu Bps", modem->RxSpeed);
1528        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RT    = %lu mSec",
1529                                                                     modem->RoundtripMsec);
1530        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Sr    = %lu",     modem->SymbolRate);
1531        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rxl   = %d dBm",  modem->RxLeveldBm);
1532        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM El    = %d dBm",  modem->EchoLeveldBm);
1533        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM SNR   = %lu dB",  modem->SNRdb);
1534        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM MAE   = %lu",     modem->MAE);
1535        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRet  = %lu",
1536                                                                     modem->LocalRetrains);
1537        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRet  = %lu",
1538                                                                     modem->RemoteRetrains);
1539        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRes  = %lu",     modem->LocalResyncs);
1540        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRes  = %lu",
1541                                                                     modem->RemoteResyncs);
1542        if (modem->Event == 3) {
1543          diva_mnt_internal_dprintf(pC->hDbg->id,DLI_STAT,"MDM Disc  =  %lu",    modem->DiscReason);
1544        }
1545      }
1546      if ((modem->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_STATISTICS)) {
1547        (*(pC->pIdiLib->DivaSTraceGetModemStatistics))(pC->pIdiLib);
1548      }
1549      break;
1550
1551    case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE:
1552      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) {
1553                                {
1554                                        int ch = TraceFilterChannel;
1555                                        int id = TraceFilterIdent;
1556
1557                                        if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1558                                                (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1559                                                if (ch != (int)fax->ChannelNumber) {
1560                                                        break;
1561                                                }
1562                                        } else if (TraceFilter[0] != 0) {
1563                                                break;
1564                                        }
1565                                }
1566
1567        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch    = %lu",(int)fax->ChannelNumber);
1568        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu",     fax->Event);
1569        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu",     fax->Page_Counter);
1570        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Feat. = 0x%08x",  fax->Features);
1571        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX ID    = <%s>",    &fax->Station_ID[0]);
1572        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Saddr = <%s>",    &fax->Subaddress[0]);
1573        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pwd   = <%s>",    &fax->Password[0]);
1574        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Speed = %lu",     fax->Speed);
1575        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Res.  = 0x%08x",  fax->Resolution);
1576        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Width = %lu",     fax->Paper_Width);
1577        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Length= %lu",     fax->Paper_Length);
1578        diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX SLT   = %lu",     fax->Scanline_Time);
1579        if (fax->Event == 3) {
1580          diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Disc  = %lu",     fax->Disc_Reason);
1581        }
1582      }
1583      if ((fax->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_STATISTICS)) {
1584        (*(pC->pIdiLib->DivaSTraceGetFaxStatistics))(pC->pIdiLib);
1585      }
1586      break;
1587
1588    case DIVA_SUPER_TRACE_INTERFACE_CHANGE:
1589      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_EVENTS) {
1590        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT,
1591                                 "Layer 1 -> [%s]", channel->pInterface->Layer1);
1592        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT,
1593                                 "Layer 2 -> [%s]", channel->pInterface->Layer2);
1594      }
1595      break;
1596
1597    case DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE:
1598      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_STATISTICS) {
1599        /*
1600          Incoming Statistics
1601          */
1602        if (channel->pInterfaceStat->inc.Calls) {
1603          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1604          "Inc Calls                     =%lu", channel->pInterfaceStat->inc.Calls);
1605        }
1606        if (channel->pInterfaceStat->inc.Connected) {
1607          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1608          "Inc Connected                 =%lu", channel->pInterfaceStat->inc.Connected);
1609        }
1610        if (channel->pInterfaceStat->inc.User_Busy) {
1611          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1612          "Inc Busy                      =%lu", channel->pInterfaceStat->inc.User_Busy);
1613        }
1614        if (channel->pInterfaceStat->inc.Call_Rejected) {
1615          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1616          "Inc Rejected                  =%lu", channel->pInterfaceStat->inc.Call_Rejected);
1617        }
1618        if (channel->pInterfaceStat->inc.Wrong_Number) {
1619          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1620          "Inc Wrong Nr                  =%lu", channel->pInterfaceStat->inc.Wrong_Number);
1621        }
1622        if (channel->pInterfaceStat->inc.Incompatible_Dst) {
1623          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1624          "Inc Incomp. Dest              =%lu", channel->pInterfaceStat->inc.Incompatible_Dst);
1625        }
1626        if (channel->pInterfaceStat->inc.Out_of_Order) {
1627          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1628          "Inc Out of Order              =%lu", channel->pInterfaceStat->inc.Out_of_Order);
1629        }
1630        if (channel->pInterfaceStat->inc.Ignored) {
1631          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1632          "Inc Ignored                   =%lu", channel->pInterfaceStat->inc.Ignored);
1633        }
1634        
1635        /*
1636          Outgoing Statistics
1637          */
1638        if (channel->pInterfaceStat->outg.Calls) {
1639          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1640          "Outg Calls                    =%lu", channel->pInterfaceStat->outg.Calls);
1641        }
1642        if (channel->pInterfaceStat->outg.Connected) {
1643          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1644          "Outg Connected                =%lu", channel->pInterfaceStat->outg.Connected);
1645        }
1646        if (channel->pInterfaceStat->outg.User_Busy) {
1647          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1648          "Outg Busy                     =%lu", channel->pInterfaceStat->outg.User_Busy);
1649        }
1650        if (channel->pInterfaceStat->outg.No_Answer) {
1651          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1652          "Outg No Answer                =%lu", channel->pInterfaceStat->outg.No_Answer);
1653        }
1654        if (channel->pInterfaceStat->outg.Wrong_Number) {
1655          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1656          "Outg Wrong Nr                 =%lu", channel->pInterfaceStat->outg.Wrong_Number);
1657        }
1658        if (channel->pInterfaceStat->outg.Call_Rejected) {
1659          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1660          "Outg Rejected                 =%lu", channel->pInterfaceStat->outg.Call_Rejected);
1661        }
1662        if (channel->pInterfaceStat->outg.Other_Failures) {
1663          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1664          "Outg Other Failures           =%lu", channel->pInterfaceStat->outg.Other_Failures);
1665        }
1666      }
1667      break;
1668
1669    case DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE:
1670      if (channel->pInterfaceStat->mdm.Disc_Normal) {
1671        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1672        "MDM Disc Normal        = %lu", channel->pInterfaceStat->mdm.Disc_Normal);
1673      }
1674      if (channel->pInterfaceStat->mdm.Disc_Unspecified) {
1675        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1676        "MDM Disc Unsp.         = %lu", channel->pInterfaceStat->mdm.Disc_Unspecified);
1677      }
1678      if (channel->pInterfaceStat->mdm.Disc_Busy_Tone) {
1679        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1680        "MDM Disc Busy Tone     = %lu", channel->pInterfaceStat->mdm.Disc_Busy_Tone);
1681      }
1682      if (channel->pInterfaceStat->mdm.Disc_Congestion) {
1683        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1684        "MDM Disc Congestion    = %lu", channel->pInterfaceStat->mdm.Disc_Congestion);
1685      }
1686      if (channel->pInterfaceStat->mdm.Disc_Carr_Wait) {
1687        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1688        "MDM Disc Carrier Wait  = %lu", channel->pInterfaceStat->mdm.Disc_Carr_Wait);
1689      }
1690      if (channel->pInterfaceStat->mdm.Disc_Trn_Timeout) {
1691        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1692        "MDM Disc Trn. T.o.     = %lu", channel->pInterfaceStat->mdm.Disc_Trn_Timeout);
1693      }
1694      if (channel->pInterfaceStat->mdm.Disc_Incompat) {
1695        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1696        "MDM Disc Incompatible  = %lu", channel->pInterfaceStat->mdm.Disc_Incompat);
1697      }
1698      if (channel->pInterfaceStat->mdm.Disc_Frame_Rej) {
1699        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1700        "MDM Disc Frame Reject  = %lu", channel->pInterfaceStat->mdm.Disc_Frame_Rej);
1701      }
1702      if (channel->pInterfaceStat->mdm.Disc_V42bis) {
1703        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1704        "MDM Disc V.42bis       = %lu", channel->pInterfaceStat->mdm.Disc_V42bis);
1705      }
1706      break;
1707
1708    case DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE:
1709      if (channel->pInterfaceStat->fax.Disc_Normal) {
1710        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1711        "FAX Disc Normal        = %lu", channel->pInterfaceStat->fax.Disc_Normal);
1712      }
1713      if (channel->pInterfaceStat->fax.Disc_Not_Ident) {
1714        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1715        "FAX Disc Not Ident.    = %lu", channel->pInterfaceStat->fax.Disc_Not_Ident);
1716      }
1717      if (channel->pInterfaceStat->fax.Disc_No_Response) {
1718        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1719        "FAX Disc No Response   = %lu", channel->pInterfaceStat->fax.Disc_No_Response);
1720      }
1721      if (channel->pInterfaceStat->fax.Disc_Retries) {
1722        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1723        "FAX Disc Max Retries   = %lu", channel->pInterfaceStat->fax.Disc_Retries);
1724      }
1725      if (channel->pInterfaceStat->fax.Disc_Unexp_Msg) {
1726        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1727        "FAX Unexp. Msg.        = %lu", channel->pInterfaceStat->fax.Disc_Unexp_Msg);
1728      }
1729      if (channel->pInterfaceStat->fax.Disc_No_Polling) {
1730        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1731        "FAX Disc No Polling    = %lu", channel->pInterfaceStat->fax.Disc_No_Polling);
1732      }
1733      if (channel->pInterfaceStat->fax.Disc_Training) {
1734        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1735        "FAX Disc Training      = %lu", channel->pInterfaceStat->fax.Disc_Training);
1736      }
1737      if (channel->pInterfaceStat->fax.Disc_Unexpected) {
1738        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1739        "FAX Disc Unexpected    = %lu", channel->pInterfaceStat->fax.Disc_Unexpected);
1740      }
1741      if (channel->pInterfaceStat->fax.Disc_Application) {
1742        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1743        "FAX Disc Application   = %lu", channel->pInterfaceStat->fax.Disc_Application);
1744      }
1745      if (channel->pInterfaceStat->fax.Disc_Incompat) {
1746        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1747        "FAX Disc Incompatible  = %lu", channel->pInterfaceStat->fax.Disc_Incompat);
1748      }
1749      if (channel->pInterfaceStat->fax.Disc_No_Command) {
1750        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1751        "FAX Disc No Command    = %lu", channel->pInterfaceStat->fax.Disc_No_Command);
1752      }
1753      if (channel->pInterfaceStat->fax.Disc_Long_Msg) {
1754        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1755        "FAX Disc Long Msg.     = %lu", channel->pInterfaceStat->fax.Disc_Long_Msg);
1756      }
1757      if (channel->pInterfaceStat->fax.Disc_Supervisor) {
1758        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1759        "FAX Disc Supervisor    = %lu", channel->pInterfaceStat->fax.Disc_Supervisor);
1760      }
1761      if (channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD) {
1762        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1763        "FAX Disc SUP SEP PWD   = %lu", channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD);
1764      }
1765      if (channel->pInterfaceStat->fax.Disc_Invalid_Msg) {
1766        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1767        "FAX Disc Invalid Msg.  = %lu", channel->pInterfaceStat->fax.Disc_Invalid_Msg);
1768      }
1769      if (channel->pInterfaceStat->fax.Disc_Page_Coding) {
1770        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1771        "FAX Disc Page Coding   = %lu", channel->pInterfaceStat->fax.Disc_Page_Coding);
1772      }
1773      if (channel->pInterfaceStat->fax.Disc_App_Timeout) {
1774        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1775        "FAX Disc Appl. T.o.    = %lu", channel->pInterfaceStat->fax.Disc_App_Timeout);
1776      }
1777      if (channel->pInterfaceStat->fax.Disc_Unspecified) {
1778        diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG,
1779        "FAX Disc Unspec.       = %lu", channel->pInterfaceStat->fax.Disc_Unspecified);
1780      }
1781      break;
1782  }
1783}
1784
1785/*
1786  Receive trace information from the Management Interface and store it in the
1787  internal trace buffer with MSG_TYPE_MLOG as is, without any filtering.
1788  Event Filtering and formatting is done in  Management Interface self.
1789  */
1790static void diva_maint_trace_notify (void* user_context,
1791                                     diva_strace_library_interface_t* hLib,
1792                                     int Adapter,
1793                                     void* xlog_buffer,
1794                                     int length) {
1795  diva_maint_client_t* pC = (diva_maint_client_t*)user_context;
1796  diva_dbg_entry_head_t* pmsg;
1797  word size;
1798  dword sec, usec;
1799  int ch = TraceFilterChannel;
1800  int id = TraceFilterIdent;
1801
1802  /*
1803    Selective trace
1804    */
1805  if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
1806      (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
1807    const char* p = NULL;
1808    int ch_value = -1;
1809    MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer;
1810
1811    if (Adapter != clients[id].logical) {
1812      return; /* Ignore all trace messages from other adapters */
1813    }
1814
1815    if (TrcData->code == 24) {
1816      p = (char*)&TrcData->code;
1817      p += 2;
1818    }
1819
1820    /*
1821      All L1 messages start as [dsp,ch], so we can filter this information
1822      and filter out all messages that use different channel
1823      */
1824    if (p && p[0] == '[') {
1825      if (p[2] == ',') {
1826        p += 3;
1827        ch_value = *p - '0';
1828      } else if (p[3] == ',') {
1829        p += 4;
1830        ch_value = *p - '0';
1831      }
1832      if (ch_value >= 0) {
1833        if (p[2] == ']') {
1834          ch_value = ch_value * 10 + p[1] - '0';
1835        }
1836        if (ch_value != ch) {
1837          return; /* Ignore other channels */
1838        }
1839      }
1840    }
1841
1842        } else if (TraceFilter[0] != 0) {
1843    return; /* Ignore trace if trace filter is activated, but idle */
1844  }
1845
1846  diva_os_get_time (&sec, &usec);
1847
1848  while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue,
1849                              (word)length+sizeof(*pmsg)))) {
1850    if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) {
1851      queueFreeMsg (dbg_queue);
1852    } else {
1853      break;
1854    }
1855  }
1856  if (pmsg) {
1857    memcpy (&pmsg[1], xlog_buffer, length);
1858    pmsg->sequence    = dbg_sequence++;
1859    pmsg->time_sec    = sec;
1860    pmsg->time_usec   = usec;
1861    pmsg->facility    = MSG_TYPE_MLOG;
1862    pmsg->dli         = pC->logical;
1863    pmsg->drv_id      = pC->hDbg->id;
1864    pmsg->di_cpu      = 0;
1865    pmsg->data_length = length;
1866    queueCompleteMsg (pmsg);
1867    if (queueCount(dbg_queue)) {
1868      diva_maint_wakeup_read();
1869    }
1870  }
1871}
1872
1873
1874/*
1875  Convert MAINT trace mask to management interface trace mask/work/facility and
1876  issue command to management interface
1877  */
1878static 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
1910void 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  */
1921int diva_mnt_shutdown_xdi_adapters (void) {
1922  diva_os_spin_lock_magic_t old_irql, old_irql1;
1923  int i, fret = 0;
1924  byte * pmem;
1925
1926
1927  for (i = 1; i < ARRAY_SIZE(clients); i++) {
1928    pmem = NULL;
1929
1930    diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
1931    diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload");
1932
1933    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
1934      if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) {
1935        /*
1936          Adapter removal complete
1937          */
1938        if (clients[i].pIdiLib) {
1939          (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib);
1940          clients[i].pIdiLib = NULL;
1941
1942          pmem = clients[i].pmem;
1943          clients[i].pmem = NULL;
1944        }
1945        clients[i].hDbg    = NULL;
1946        clients[i].request_pending = 0;
1947
1948        if (clients[i].dma_handle >= 0) {
1949          /*
1950            Free DMA handle
1951            */
1952          diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1953          clients[i].dma_handle = -1;
1954                                }
1955        clients[i].request = NULL;
1956      } else {
1957        fret = -1;
1958      }
1959    }
1960
1961    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload");
1962    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
1963      clients[i].request_pending = 0;
1964      (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
1965      if (clients[i].dma_handle >= 0) {
1966        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
1967        clients[i].dma_handle = -1;
1968      }
1969    }
1970    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
1971
1972    if (pmem) {
1973      diva_os_free (0, pmem);
1974    }
1975  }
1976
1977  return (fret);
1978}
1979
1980/*
1981  Set/Read the trace filter used for selective tracing.
1982  Affects B- and Audio Tap trace mask at run time
1983  */
1984int 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
2034int 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
2048static 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  */
2059static 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
2086static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) {
2087  ENTITY e;
2088  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
2089
2090  if (!request) {
2091    return (-1);
2092  }
2093
2094  pReq->xdi_dma_descriptor_operation.Req = 0;
2095  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2096
2097  pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
2098  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
2099  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2100  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
2101
2102  (*request)((ENTITY*)pReq);
2103
2104  if (!pReq->xdi_dma_descriptor_operation.info.operation &&
2105      (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
2106      pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
2107    *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
2108    return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
2109  } else {
2110    return (-1);
2111  }
2112}
2113
2114static void diva_free_dma_descriptor (IDI_CALL request, int nr) {
2115  ENTITY e;
2116  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
2117
2118  if (!request || (nr < 0)) {
2119    return;
2120  }
2121
2122  pReq->xdi_dma_descriptor_operation.Req = 0;
2123  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
2124
2125  pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
2126  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
2127  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
2128  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
2129
2130  (*request)((ENTITY*)pReq);
2131}
2132
2133
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.