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