Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/hardware/eicon/debug.c
15115 views
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
}
2132
2133
2134