]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/isdn/hardware/eicon/debug.c
576b7b4a32787017e44ed3f3ebf6f40dcc6a965c
[mirror_ubuntu-artful-kernel.git] / drivers / isdn / hardware / eicon / debug.c
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
15 static void DI_register(void *arg);
16 static void DI_deregister(pDbgHandle hDbg);
17 static void DI_format(int do_lock, word id, int type, char *format, va_list argument_list);
18 static void DI_format_locked(word id, int type, char *format, va_list argument_list);
19 static void DI_format_old(word id, char *format, va_list ap) { }
20 static void DiProcessEventLog(unsigned short id, unsigned long msgID, va_list ap) { }
21 static void single_p(byte *P, word *PLength, byte Id);
22 static void diva_maint_xdi_cb(ENTITY *e);
23 static word SuperTraceCreateReadReq(byte *P, const char *path);
24 static int diva_mnt_cmp_nmbr(const char *nmbr);
25 static void diva_free_dma_descriptor(IDI_CALL request, int nr);
26 static int diva_get_dma_descriptor(IDI_CALL request, dword *dma_magic);
27 void diva_mnt_internal_dprintf(dword drv_id, dword type, char *p, ...);
28
29 static dword MaxDumpSize = 256;
30 static dword MaxXlogSize = 2 + 128;
31 static char TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH + 1];
32 static int TraceFilterIdent = -1;
33 static int TraceFilterChannel = -1;
34
35 typedef 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;
53 static diva_maint_client_t clients[MAX_DESCRIPTORS];
54
55 static void diva_change_management_debug_mask(diva_maint_client_t *pC, dword old_mask);
56
57 static 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);
63 static 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);
68 static 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
76 typedef 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
86 typedef 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
96 static 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
104 static 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
138 alloc:
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
151 static 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
169 static 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 */
188 static MSG_QUEUE *dbg_queue;
189 static byte *dbg_base;
190 static int external_dbg_queue;
191 static diva_os_spin_lock_t dbg_q_lock;
192 static diva_os_spin_lock_t dbg_adapter_lock;
193 static int dbg_q_busy;
194 static 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 */
205 int 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 */
269 void *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 */
299 dword 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 */
308 diva_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 */
331 void 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 */
350 void 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
370 static 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
481 static 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
561 static 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
568 static 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 */
729 int 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
781 int 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
803 int 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
837 static 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 */
857 void 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 */
1023 void 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 */
1110 void *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
1122 int SuperTraceCloseAdapter(void *AdapterHandle) {
1123 return (0);
1124 }
1125
1126 int 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
1154 int 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
1164 int 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
1223 int 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
1245 int 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
1272 int 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
1305 int 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
1331 static 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
1352 static void single_p(byte *P, word *PLength, byte Id) {
1353 P[(*PLength)++] = Id;
1354 }
1355
1356 static 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
1392 static 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
1402 static 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
1421 static 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 */
1786 static 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 */
1874 static 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
1906 void 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 */
1917 int 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 */
1980 int 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
2030 int 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
2044 static 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 Followings commands are available:
2053 - single, trace single call at time, independent from CPN/CiPN
2054 */
2055 static 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
2082 static 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
2110 static 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 }