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