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