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