diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hardware/eicon/debug.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hardware/eicon/debug.c')
-rw-r--r-- | drivers/isdn/hardware/eicon/debug.c | 2133 |
1 files changed, 2133 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c new file mode 100644 index 000000000000..6851c6270ce8 --- /dev/null +++ b/drivers/isdn/hardware/eicon/debug.c | |||
@@ -0,0 +1,2133 @@ | |||
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 < (sizeof(clients)/sizeof(clients[0])); 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 < (sizeof(clients)/sizeof(clients[0])); 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 < (sizeof(clients)/sizeof(clients[0])); 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 >= (sizeof(clients)/sizeof(clients[0])))) { | ||
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), 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), 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 >= (sizeof(clients)/sizeof(clients[0])))) { | ||
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 >= (sizeof(clients)/sizeof(clients[0])))) { | ||
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, best_id = 0, free_id = -1; | ||
865 | char tmp[256]; | ||
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 < (sizeof(clients)/sizeof(clients[0])); 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 | best_id = 1; | ||
910 | break; | ||
911 | } | ||
912 | } | ||
913 | |||
914 | if (free_id < 0) { | ||
915 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); | ||
916 | diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); | ||
917 | diva_os_free (0, pmem); | ||
918 | return; | ||
919 | } | ||
920 | |||
921 | id = free_id; | ||
922 | clients[id].request = d->request; | ||
923 | clients[id].request_pending = 0; | ||
924 | clients[id].hDbg = &clients[id].Dbg; | ||
925 | clients[id].sec = sec; | ||
926 | clients[id].usec = usec; | ||
927 | strcpy (clients[id].drvName, tmp); | ||
928 | strcpy (clients[id].Dbg.drvName, tmp); | ||
929 | clients[id].Dbg.drvTag[0] = 0; | ||
930 | clients[id].logical = (int)logical; | ||
931 | clients[id].channels = (int)d->channels; | ||
932 | clients[id].dma_handle = -1; | ||
933 | |||
934 | clients[id].Dbg.dbgMask = 0; | ||
935 | clients[id].dbgMask = clients[id].Dbg.dbgMask; | ||
936 | if (id) { | ||
937 | clients[id].Dbg.dbgMask |= clients[free_id].last_dbgMask; | ||
938 | } else { | ||
939 | clients[id].last_dbgMask = 0; | ||
940 | } | ||
941 | clients[id].Dbg.Registered = DBG_HANDLE_REG_NEW; | ||
942 | clients[id].Dbg.id = (byte)id; | ||
943 | clients[id].Dbg.dbg_end = DI_deregister; | ||
944 | clients[id].Dbg.dbg_prt = DI_format_locked; | ||
945 | clients[id].Dbg.dbg_ev = DiProcessEventLog; | ||
946 | clients[id].Dbg.dbg_irq = DI_format_locked; | ||
947 | clients[id].Dbg.next = (pDbgHandle)DBG_MAGIC; | ||
948 | |||
949 | { | ||
950 | diva_trace_library_user_interface_t diva_maint_user_ifc = { &clients[id], | ||
951 | diva_maint_state_change_notify, | ||
952 | diva_maint_trace_notify, | ||
953 | diva_maint_error }; | ||
954 | |||
955 | /* | ||
956 | Attach to adapter management interface | ||
957 | */ | ||
958 | if ((clients[id].pIdiLib = | ||
959 | DivaSTraceLibraryCreateInstance ((int)logical, &diva_maint_user_ifc, pmem))) { | ||
960 | if (((*(clients[id].pIdiLib->DivaSTraceLibraryStart))(clients[id].pIdiLib->hLib))) { | ||
961 | diva_mnt_internal_dprintf (0, DLI_ERR, "Adapter(%d) Start failed", (int)logical); | ||
962 | (*(clients[id].pIdiLib->DivaSTraceLibraryFinit))(clients[id].pIdiLib->hLib); | ||
963 | clients[id].pIdiLib = NULL; | ||
964 | } | ||
965 | } else { | ||
966 | diva_mnt_internal_dprintf (0, DLI_ERR, "A(%d) management init failed", (int)logical); | ||
967 | } | ||
968 | } | ||
969 | |||
970 | if (!clients[id].pIdiLib) { | ||
971 | clients[id].request = NULL; | ||
972 | clients[id].request_pending = 0; | ||
973 | clients[id].hDbg = NULL; | ||
974 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); | ||
975 | diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); | ||
976 | diva_os_free (0, pmem); | ||
977 | return; | ||
978 | } | ||
979 | |||
980 | /* | ||
981 | Log driver register, MAINT driver ID is '0' | ||
982 | */ | ||
983 | len = sprintf (tmp, "DIMAINT - drv # %d = '%s' registered", | ||
984 | id, clients[id].Dbg.drvName); | ||
985 | |||
986 | while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue, | ||
987 | (word)(len+1+sizeof(*pmsg))))) { | ||
988 | if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) { | ||
989 | queueFreeMsg (dbg_queue); | ||
990 | } else { | ||
991 | break; | ||
992 | } | ||
993 | } | ||
994 | |||
995 | if (pmsg) { | ||
996 | pmsg->sequence = dbg_sequence++; | ||
997 | pmsg->time_sec = sec; | ||
998 | pmsg->time_usec = usec; | ||
999 | pmsg->facility = MSG_TYPE_STRING; | ||
1000 | pmsg->dli = DLI_REG; | ||
1001 | pmsg->drv_id = 0; /* id 0 - DIMAINT */ | ||
1002 | pmsg->di_cpu = 0; | ||
1003 | pmsg->data_length = len+1; | ||
1004 | |||
1005 | memcpy (&pmsg[1], tmp, len+1); | ||
1006 | queueCompleteMsg (pmsg); | ||
1007 | diva_maint_wakeup_read(); | ||
1008 | } | ||
1009 | |||
1010 | org_mask = clients[id].Dbg.dbgMask; | ||
1011 | clients[id].Dbg.dbgMask = 0; | ||
1012 | |||
1013 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); | ||
1014 | |||
1015 | if (clients[id].request_pending) { | ||
1016 | clients[id].request_pending = 0; | ||
1017 | (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib)); | ||
1018 | } | ||
1019 | |||
1020 | diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); | ||
1021 | |||
1022 | diva_set_driver_dbg_mask (id, org_mask); | ||
1023 | } | ||
1024 | |||
1025 | /* | ||
1026 | De-Register XDI adapter | ||
1027 | */ | ||
1028 | void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) { | ||
1029 | diva_os_spin_lock_magic_t old_irql, old_irql1; | ||
1030 | dword sec, usec; | ||
1031 | int i; | ||
1032 | word size; | ||
1033 | byte* pmem = NULL; | ||
1034 | |||
1035 | diva_os_get_time (&sec, &usec); | ||
1036 | |||
1037 | diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read"); | ||
1038 | diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read"); | ||
1039 | |||
1040 | for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { | ||
1041 | if (clients[i].hDbg && (clients[i].request == d->request)) { | ||
1042 | diva_dbg_entry_head_t* pmsg; | ||
1043 | char tmp[256]; | ||
1044 | int len; | ||
1045 | |||
1046 | if (clients[i].pIdiLib) { | ||
1047 | (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib); | ||
1048 | clients[i].pIdiLib = NULL; | ||
1049 | |||
1050 | pmem = clients[i].pmem; | ||
1051 | clients[i].pmem = NULL; | ||
1052 | } | ||
1053 | |||
1054 | clients[i].hDbg = NULL; | ||
1055 | clients[i].request_pending = 0; | ||
1056 | if (clients[i].dma_handle >= 0) { | ||
1057 | /* | ||
1058 | Free DMA handle | ||
1059 | */ | ||
1060 | diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); | ||
1061 | clients[i].dma_handle = -1; | ||
1062 | } | ||
1063 | clients[i].request = NULL; | ||
1064 | |||
1065 | /* | ||
1066 | Log driver register, MAINT driver ID is '0' | ||
1067 | */ | ||
1068 | len = sprintf (tmp, "DIMAINT - drv # %d = '%s' de-registered", | ||
1069 | i, clients[i].Dbg.drvName); | ||
1070 | |||
1071 | memset (&clients[i].Dbg, 0x00, sizeof(clients[i].Dbg)); | ||
1072 | |||
1073 | while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue, | ||
1074 | (word)(len+1+sizeof(*pmsg))))) { | ||
1075 | if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) { | ||
1076 | queueFreeMsg (dbg_queue); | ||
1077 | } else { | ||
1078 | break; | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | if (pmsg) { | ||
1083 | pmsg->sequence = dbg_sequence++; | ||
1084 | pmsg->time_sec = sec; | ||
1085 | pmsg->time_usec = usec; | ||
1086 | pmsg->facility = MSG_TYPE_STRING; | ||
1087 | pmsg->dli = DLI_REG; | ||
1088 | pmsg->drv_id = 0; /* id 0 - DIMAINT */ | ||
1089 | pmsg->di_cpu = 0; | ||
1090 | pmsg->data_length = len+1; | ||
1091 | |||
1092 | memcpy (&pmsg[1], tmp, len+1); | ||
1093 | queueCompleteMsg (pmsg); | ||
1094 | diva_maint_wakeup_read(); | ||
1095 | } | ||
1096 | |||
1097 | break; | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack"); | ||
1102 | diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack"); | ||
1103 | |||
1104 | if (pmem) { | ||
1105 | diva_os_free (0, pmem); | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | /* ---------------------------------------------------------------- | ||
1110 | Low level interface for management interface client | ||
1111 | ---------------------------------------------------------------- */ | ||
1112 | /* | ||
1113 | Return handle to client structure | ||
1114 | */ | ||
1115 | void* SuperTraceOpenAdapter (int AdapterNumber) { | ||
1116 | int i; | ||
1117 | |||
1118 | for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { | ||
1119 | if (clients[i].hDbg && clients[i].request && (clients[i].logical == AdapterNumber)) { | ||
1120 | return (&clients[i]); | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | return NULL; | ||
1125 | } | ||
1126 | |||
1127 | int SuperTraceCloseAdapter (void* AdapterHandle) { | ||
1128 | return (0); | ||
1129 | } | ||
1130 | |||
1131 | int SuperTraceReadRequest (void* AdapterHandle, const char* name, byte* data) { | ||
1132 | diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle; | ||
1133 | |||
1134 | if (pC && pC->pIdiLib && pC->request) { | ||
1135 | ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); | ||
1136 | byte* xdata = (byte*)&pC->xbuffer[0]; | ||
1137 | char tmp = 0; | ||
1138 | word length; | ||
1139 | |||
1140 | if (!strcmp(name, "\\")) { /* Read ROOT */ | ||
1141 | name = &tmp; | ||
1142 | } | ||
1143 | length = SuperTraceCreateReadReq (xdata, name); | ||
1144 | single_p (xdata, &length, 0); /* End Of Message */ | ||
1145 | |||
1146 | e->Req = MAN_READ; | ||
1147 | e->ReqCh = 0; | ||
1148 | e->X->PLength = length; | ||
1149 | e->X->P = (byte*)xdata; | ||
1150 | |||
1151 | pC->request_pending = 1; | ||
1152 | |||
1153 | return (0); | ||
1154 | } | ||
1155 | |||
1156 | return (-1); | ||
1157 | } | ||
1158 | |||
1159 | int SuperTraceGetNumberOfChannels (void* AdapterHandle) { | ||
1160 | if (AdapterHandle) { | ||
1161 | diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle; | ||
1162 | |||
1163 | return (pC->channels); | ||
1164 | } | ||
1165 | |||
1166 | return (0); | ||
1167 | } | ||
1168 | |||
1169 | int SuperTraceASSIGN (void* AdapterHandle, byte* data) { | ||
1170 | diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle; | ||
1171 | |||
1172 | if (pC && pC->pIdiLib && pC->request) { | ||
1173 | ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); | ||
1174 | IDI_SYNC_REQ* preq; | ||
1175 | char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)]; | ||
1176 | char features[4]; | ||
1177 | word assign_data_length = 1; | ||
1178 | |||
1179 | features[0] = 0; | ||
1180 | pC->xbuffer[0] = 0; | ||
1181 | preq = (IDI_SYNC_REQ*)&buffer[0]; | ||
1182 | preq->xdi_extended_features.Req = 0; | ||
1183 | preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES; | ||
1184 | preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features); | ||
1185 | preq->xdi_extended_features.info.features = &features[0]; | ||
1186 | |||
1187 | (*(pC->request))((ENTITY*)preq); | ||
1188 | |||
1189 | if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && | ||
1190 | (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { | ||
1191 | dword rx_dma_magic; | ||
1192 | if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { | ||
1193 | pC->xbuffer[0] = LLI; | ||
1194 | pC->xbuffer[1] = 8; | ||
1195 | pC->xbuffer[2] = 0x40; | ||
1196 | pC->xbuffer[3] = (byte)pC->dma_handle; | ||
1197 | pC->xbuffer[4] = (byte)rx_dma_magic; | ||
1198 | pC->xbuffer[5] = (byte)(rx_dma_magic >> 8); | ||
1199 | pC->xbuffer[6] = (byte)(rx_dma_magic >> 16); | ||
1200 | pC->xbuffer[7] = (byte)(rx_dma_magic >> 24); | ||
1201 | pC->xbuffer[8] = (byte)DIVA_MAX_MANAGEMENT_TRANSFER_SIZE; | ||
1202 | pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8); | ||
1203 | pC->xbuffer[10] = 0; | ||
1204 | |||
1205 | assign_data_length = 11; | ||
1206 | } | ||
1207 | } else { | ||
1208 | pC->dma_handle = -1; | ||
1209 | } | ||
1210 | |||
1211 | e->Id = MAN_ID; | ||
1212 | e->callback = diva_maint_xdi_cb; | ||
1213 | e->XNum = 1; | ||
1214 | e->X = &pC->XData; | ||
1215 | e->Req = ASSIGN; | ||
1216 | e->ReqCh = 0; | ||
1217 | e->X->PLength = assign_data_length; | ||
1218 | e->X->P = (byte*)&pC->xbuffer[0]; | ||
1219 | |||
1220 | pC->request_pending = 1; | ||
1221 | |||
1222 | return (0); | ||
1223 | } | ||
1224 | |||
1225 | return (-1); | ||
1226 | } | ||
1227 | |||
1228 | int SuperTraceREMOVE (void* AdapterHandle) { | ||
1229 | diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle; | ||
1230 | |||
1231 | if (pC && pC->pIdiLib && pC->request) { | ||
1232 | ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); | ||
1233 | |||
1234 | e->XNum = 1; | ||
1235 | e->X = &pC->XData; | ||
1236 | e->Req = REMOVE; | ||
1237 | e->ReqCh = 0; | ||
1238 | e->X->PLength = 1; | ||
1239 | e->X->P = (byte*)&pC->xbuffer[0]; | ||
1240 | pC->xbuffer[0] = 0; | ||
1241 | |||
1242 | pC->request_pending = 1; | ||
1243 | |||
1244 | return (0); | ||
1245 | } | ||
1246 | |||
1247 | return (-1); | ||
1248 | } | ||
1249 | |||
1250 | int SuperTraceTraceOnRequest(void* hAdapter, const char* name, byte* data) { | ||
1251 | diva_maint_client_t* pC = (diva_maint_client_t*)hAdapter; | ||
1252 | |||
1253 | if (pC && pC->pIdiLib && pC->request) { | ||
1254 | ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); | ||
1255 | byte* xdata = (byte*)&pC->xbuffer[0]; | ||
1256 | char tmp = 0; | ||
1257 | word length; | ||
1258 | |||
1259 | if (!strcmp(name, "\\")) { /* Read ROOT */ | ||
1260 | name = &tmp; | ||
1261 | } | ||
1262 | length = SuperTraceCreateReadReq (xdata, name); | ||
1263 | single_p (xdata, &length, 0); /* End Of Message */ | ||
1264 | e->Req = MAN_EVENT_ON; | ||
1265 | e->ReqCh = 0; | ||
1266 | e->X->PLength = length; | ||
1267 | e->X->P = (byte*)xdata; | ||
1268 | |||
1269 | pC->request_pending = 1; | ||
1270 | |||
1271 | return (0); | ||
1272 | } | ||
1273 | |||
1274 | return (-1); | ||
1275 | } | ||
1276 | |||
1277 | int SuperTraceWriteVar (void* AdapterHandle, | ||
1278 | byte* data, | ||
1279 | const char* name, | ||
1280 | void* var, | ||
1281 | byte type, | ||
1282 | byte var_length) { | ||
1283 | diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle; | ||
1284 | |||
1285 | if (pC && pC->pIdiLib && pC->request) { | ||
1286 | ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); | ||
1287 | diva_man_var_header_t* pVar = (diva_man_var_header_t*)&pC->xbuffer[0]; | ||
1288 | word length = SuperTraceCreateReadReq ((byte*)pVar, name); | ||
1289 | |||
1290 | memcpy (&pC->xbuffer[length], var, var_length); | ||
1291 | length += var_length; | ||
1292 | pVar->length += var_length; | ||
1293 | pVar->value_length = var_length; | ||
1294 | pVar->type = type; | ||
1295 | single_p ((byte*)pVar, &length, 0); /* End Of Message */ | ||
1296 | |||
1297 | e->Req = MAN_WRITE; | ||
1298 | e->ReqCh = 0; | ||
1299 | e->X->PLength = length; | ||
1300 | e->X->P = (byte*)pVar; | ||
1301 | |||
1302 | pC->request_pending = 1; | ||
1303 | |||
1304 | return (0); | ||
1305 | } | ||
1306 | |||
1307 | return (-1); | ||
1308 | } | ||
1309 | |||
1310 | int SuperTraceExecuteRequest (void* AdapterHandle, | ||
1311 | const char* name, | ||
1312 | byte* data) { | ||
1313 | diva_maint_client_t* pC = (diva_maint_client_t*)AdapterHandle; | ||
1314 | |||
1315 | if (pC && pC->pIdiLib && pC->request) { | ||
1316 | ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); | ||
1317 | byte* xdata = (byte*)&pC->xbuffer[0]; | ||
1318 | word length; | ||
1319 | |||
1320 | length = SuperTraceCreateReadReq (xdata, name); | ||
1321 | single_p (xdata, &length, 0); /* End Of Message */ | ||
1322 | |||
1323 | e->Req = MAN_EXECUTE; | ||
1324 | e->ReqCh = 0; | ||
1325 | e->X->PLength = length; | ||
1326 | e->X->P = (byte*)xdata; | ||
1327 | |||
1328 | pC->request_pending = 1; | ||
1329 | |||
1330 | return (0); | ||
1331 | } | ||
1332 | |||
1333 | return (-1); | ||
1334 | } | ||
1335 | |||
1336 | static word SuperTraceCreateReadReq (byte* P, const char* path) { | ||
1337 | byte var_length; | ||
1338 | byte* plen; | ||
1339 | |||
1340 | var_length = (byte)strlen (path); | ||
1341 | |||
1342 | *P++ = ESC; | ||
1343 | plen = P++; | ||
1344 | *P++ = 0x80; /* MAN_IE */ | ||
1345 | *P++ = 0x00; /* Type */ | ||
1346 | *P++ = 0x00; /* Attribute */ | ||
1347 | *P++ = 0x00; /* Status */ | ||
1348 | *P++ = 0x00; /* Variable Length */ | ||
1349 | *P++ = var_length; | ||
1350 | memcpy (P, path, var_length); | ||
1351 | P += var_length; | ||
1352 | *plen = var_length + 0x06; | ||
1353 | |||
1354 | return ((word)(var_length + 0x08)); | ||
1355 | } | ||
1356 | |||
1357 | static void single_p (byte * P, word * PLength, byte Id) { | ||
1358 | P[(*PLength)++] = Id; | ||
1359 | } | ||
1360 | |||
1361 | static void diva_maint_xdi_cb (ENTITY* e) { | ||
1362 | diva_strace_context_t* pLib = DIVAS_CONTAINING_RECORD(e,diva_strace_context_t,e); | ||
1363 | diva_maint_client_t* pC; | ||
1364 | diva_os_spin_lock_magic_t old_irql, old_irql1; | ||
1365 | |||
1366 | |||
1367 | diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb"); | ||
1368 | diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb"); | ||
1369 | |||
1370 | pC = (diva_maint_client_t*)pLib->hAdapter; | ||
1371 | |||
1372 | if ((e->complete == 255) || (pC->dma_handle < 0)) { | ||
1373 | if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { | ||
1374 | diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error"); | ||
1375 | } | ||
1376 | } else { | ||
1377 | /* | ||
1378 | Process combined management interface indication | ||
1379 | */ | ||
1380 | if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { | ||
1381 | diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)"); | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb"); | ||
1386 | |||
1387 | |||
1388 | if (pC->request_pending) { | ||
1389 | pC->request_pending = 0; | ||
1390 | (*(pC->request))(e); | ||
1391 | } | ||
1392 | |||
1393 | diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb"); | ||
1394 | } | ||
1395 | |||
1396 | |||
1397 | static void diva_maint_error (void* user_context, | ||
1398 | diva_strace_library_interface_t* hLib, | ||
1399 | int Adapter, | ||
1400 | int error, | ||
1401 | const char* file, | ||
1402 | int line) { | ||
1403 | diva_mnt_internal_dprintf (0, DLI_ERR, | ||
1404 | "Trace library error(%d) A(%d) %s %d", error, Adapter, file, line); | ||
1405 | } | ||
1406 | |||
1407 | static void print_ie (diva_trace_ie_t* ie, char* buffer, int length) { | ||
1408 | int i; | ||
1409 | |||
1410 | buffer[0] = 0; | ||
1411 | |||
1412 | if (length > 32) { | ||
1413 | for (i = 0; ((i < ie->length) && (length > 3)); i++) { | ||
1414 | sprintf (buffer, "%02x", ie->data[i]); | ||
1415 | buffer += 2; | ||
1416 | length -= 2; | ||
1417 | if (i < (ie->length-1)) { | ||
1418 | strcpy (buffer, " "); | ||
1419 | buffer++; | ||
1420 | length--; | ||
1421 | } | ||
1422 | } | ||
1423 | } | ||
1424 | } | ||
1425 | |||
1426 | static void diva_maint_state_change_notify (void* user_context, | ||
1427 | diva_strace_library_interface_t* hLib, | ||
1428 | int Adapter, | ||
1429 | diva_trace_line_state_t* channel, | ||
1430 | int notify_subject) { | ||
1431 | diva_maint_client_t* pC = (diva_maint_client_t*)user_context; | ||
1432 | diva_trace_fax_state_t* fax = &channel->fax; | ||
1433 | diva_trace_modem_state_t* modem = &channel->modem; | ||
1434 | char tmp[256]; | ||
1435 | |||
1436 | if (!pC->hDbg) { | ||
1437 | return; | ||
1438 | } | ||
1439 | |||
1440 | switch (notify_subject) { | ||
1441 | case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: { | ||
1442 | int view = (TraceFilter[0] == 0); | ||
1443 | /* | ||
1444 | Process selective Trace | ||
1445 | */ | ||
1446 | if (channel->Line[0] == 'I' && channel->Line[1] == 'd' && | ||
1447 | channel->Line[2] == 'l' && channel->Line[3] == 'e') { | ||
1448 | if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) { | ||
1449 | (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0); | ||
1450 | (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0); | ||
1451 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d", | ||
1452 | (int)channel->ChannelNumber); | ||
1453 | TraceFilterIdent = -1; | ||
1454 | TraceFilterChannel = -1; | ||
1455 | view = 1; | ||
1456 | } | ||
1457 | } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) && | ||
1458 | diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) { | ||
1459 | |||
1460 | if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */ | ||
1461 | (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1); | ||
1462 | } | ||
1463 | if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */ | ||
1464 | (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1); | ||
1465 | } | ||
1466 | |||
1467 | TraceFilterIdent = pC->hDbg->id; | ||
1468 | TraceFilterChannel = (int)channel->ChannelNumber; | ||
1469 | |||
1470 | if (TraceFilterIdent >= 0) { | ||
1471 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d", | ||
1472 | (int)channel->ChannelNumber); | ||
1473 | view = 1; | ||
1474 | } | ||
1475 | } | ||
1476 | if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) { | ||
1477 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch = %d", | ||
1478 | (int)channel->ChannelNumber); | ||
1479 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]); | ||
1480 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer1 = <%s>", &channel->Framing[0]); | ||
1481 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer2 = <%s>", &channel->Layer2[0]); | ||
1482 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Layer3 = <%s>", &channel->Layer3[0]); | ||
1483 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RAddr = <%s>", | ||
1484 | &channel->RemoteAddress[0]); | ||
1485 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L RSAddr = <%s>", | ||
1486 | &channel->RemoteSubAddress[0]); | ||
1487 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LAddr = <%s>", | ||
1488 | &channel->LocalAddress[0]); | ||
1489 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LSAddr = <%s>", | ||
1490 | &channel->LocalSubAddress[0]); | ||
1491 | print_ie(&channel->call_BC, tmp, sizeof(tmp)); | ||
1492 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L BC = <%s>", tmp); | ||
1493 | print_ie(&channel->call_HLC, tmp, sizeof(tmp)); | ||
1494 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L HLC = <%s>", tmp); | ||
1495 | print_ie(&channel->call_LLC, tmp, sizeof(tmp)); | ||
1496 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L LLC = <%s>", tmp); | ||
1497 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L CR = 0x%x", channel->CallReference); | ||
1498 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Disc = 0x%x", | ||
1499 | channel->LastDisconnecCause); | ||
1500 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner = <%s>", &channel->UserID[0]); | ||
1501 | } | ||
1502 | |||
1503 | } break; | ||
1504 | |||
1505 | case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE: | ||
1506 | if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) { | ||
1507 | { | ||
1508 | int ch = TraceFilterChannel; | ||
1509 | int id = TraceFilterIdent; | ||
1510 | |||
1511 | if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && | ||
1512 | (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { | ||
1513 | if (ch != (int)modem->ChannelNumber) { | ||
1514 | break; | ||
1515 | } | ||
1516 | } else if (TraceFilter[0] != 0) { | ||
1517 | break; | ||
1518 | } | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch = %lu", | ||
1523 | (int)modem->ChannelNumber); | ||
1524 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu", modem->Event); | ||
1525 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Norm = %lu", modem->Norm); | ||
1526 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Opts. = 0x%08x", modem->Options); | ||
1527 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Tx = %lu Bps", modem->TxSpeed); | ||
1528 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rx = %lu Bps", modem->RxSpeed); | ||
1529 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RT = %lu mSec", | ||
1530 | modem->RoundtripMsec); | ||
1531 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Sr = %lu", modem->SymbolRate); | ||
1532 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Rxl = %d dBm", modem->RxLeveldBm); | ||
1533 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM El = %d dBm", modem->EchoLeveldBm); | ||
1534 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM SNR = %lu dB", modem->SNRdb); | ||
1535 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM MAE = %lu", modem->MAE); | ||
1536 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRet = %lu", | ||
1537 | modem->LocalRetrains); | ||
1538 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRet = %lu", | ||
1539 | modem->RemoteRetrains); | ||
1540 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM LRes = %lu", modem->LocalResyncs); | ||
1541 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM RRes = %lu", | ||
1542 | modem->RemoteResyncs); | ||
1543 | if (modem->Event == 3) { | ||
1544 | diva_mnt_internal_dprintf(pC->hDbg->id,DLI_STAT,"MDM Disc = %lu", modem->DiscReason); | ||
1545 | } | ||
1546 | } | ||
1547 | if ((modem->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_STATISTICS)) { | ||
1548 | (*(pC->pIdiLib->DivaSTraceGetModemStatistics))(pC->pIdiLib); | ||
1549 | } | ||
1550 | break; | ||
1551 | |||
1552 | case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE: | ||
1553 | if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) { | ||
1554 | { | ||
1555 | int ch = TraceFilterChannel; | ||
1556 | int id = TraceFilterIdent; | ||
1557 | |||
1558 | if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && | ||
1559 | (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { | ||
1560 | if (ch != (int)fax->ChannelNumber) { | ||
1561 | break; | ||
1562 | } | ||
1563 | } else if (TraceFilter[0] != 0) { | ||
1564 | break; | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1568 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch = %lu",(int)fax->ChannelNumber); | ||
1569 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu", fax->Event); | ||
1570 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu", fax->Page_Counter); | ||
1571 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Feat. = 0x%08x", fax->Features); | ||
1572 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX ID = <%s>", &fax->Station_ID[0]); | ||
1573 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Saddr = <%s>", &fax->Subaddress[0]); | ||
1574 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pwd = <%s>", &fax->Password[0]); | ||
1575 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Speed = %lu", fax->Speed); | ||
1576 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Res. = 0x%08x", fax->Resolution); | ||
1577 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Width = %lu", fax->Paper_Width); | ||
1578 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Length= %lu", fax->Paper_Length); | ||
1579 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX SLT = %lu", fax->Scanline_Time); | ||
1580 | if (fax->Event == 3) { | ||
1581 | diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Disc = %lu", fax->Disc_Reason); | ||
1582 | } | ||
1583 | } | ||
1584 | if ((fax->Event == 3) && (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_STATISTICS)) { | ||
1585 | (*(pC->pIdiLib->DivaSTraceGetFaxStatistics))(pC->pIdiLib); | ||
1586 | } | ||
1587 | break; | ||
1588 | |||
1589 | case DIVA_SUPER_TRACE_INTERFACE_CHANGE: | ||
1590 | if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_EVENTS) { | ||
1591 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, | ||
1592 | "Layer 1 -> [%s]", channel->pInterface->Layer1); | ||
1593 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, | ||
1594 | "Layer 2 -> [%s]", channel->pInterface->Layer2); | ||
1595 | } | ||
1596 | break; | ||
1597 | |||
1598 | case DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE: | ||
1599 | if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_STATISTICS) { | ||
1600 | /* | ||
1601 | Incoming Statistics | ||
1602 | */ | ||
1603 | if (channel->pInterfaceStat->inc.Calls) { | ||
1604 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1605 | "Inc Calls =%lu", channel->pInterfaceStat->inc.Calls); | ||
1606 | } | ||
1607 | if (channel->pInterfaceStat->inc.Connected) { | ||
1608 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1609 | "Inc Connected =%lu", channel->pInterfaceStat->inc.Connected); | ||
1610 | } | ||
1611 | if (channel->pInterfaceStat->inc.User_Busy) { | ||
1612 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1613 | "Inc Busy =%lu", channel->pInterfaceStat->inc.User_Busy); | ||
1614 | } | ||
1615 | if (channel->pInterfaceStat->inc.Call_Rejected) { | ||
1616 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1617 | "Inc Rejected =%lu", channel->pInterfaceStat->inc.Call_Rejected); | ||
1618 | } | ||
1619 | if (channel->pInterfaceStat->inc.Wrong_Number) { | ||
1620 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1621 | "Inc Wrong Nr =%lu", channel->pInterfaceStat->inc.Wrong_Number); | ||
1622 | } | ||
1623 | if (channel->pInterfaceStat->inc.Incompatible_Dst) { | ||
1624 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1625 | "Inc Incomp. Dest =%lu", channel->pInterfaceStat->inc.Incompatible_Dst); | ||
1626 | } | ||
1627 | if (channel->pInterfaceStat->inc.Out_of_Order) { | ||
1628 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1629 | "Inc Out of Order =%lu", channel->pInterfaceStat->inc.Out_of_Order); | ||
1630 | } | ||
1631 | if (channel->pInterfaceStat->inc.Ignored) { | ||
1632 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1633 | "Inc Ignored =%lu", channel->pInterfaceStat->inc.Ignored); | ||
1634 | } | ||
1635 | |||
1636 | /* | ||
1637 | Outgoing Statistics | ||
1638 | */ | ||
1639 | if (channel->pInterfaceStat->outg.Calls) { | ||
1640 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1641 | "Outg Calls =%lu", channel->pInterfaceStat->outg.Calls); | ||
1642 | } | ||
1643 | if (channel->pInterfaceStat->outg.Connected) { | ||
1644 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1645 | "Outg Connected =%lu", channel->pInterfaceStat->outg.Connected); | ||
1646 | } | ||
1647 | if (channel->pInterfaceStat->outg.User_Busy) { | ||
1648 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1649 | "Outg Busy =%lu", channel->pInterfaceStat->outg.User_Busy); | ||
1650 | } | ||
1651 | if (channel->pInterfaceStat->outg.No_Answer) { | ||
1652 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1653 | "Outg No Answer =%lu", channel->pInterfaceStat->outg.No_Answer); | ||
1654 | } | ||
1655 | if (channel->pInterfaceStat->outg.Wrong_Number) { | ||
1656 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1657 | "Outg Wrong Nr =%lu", channel->pInterfaceStat->outg.Wrong_Number); | ||
1658 | } | ||
1659 | if (channel->pInterfaceStat->outg.Call_Rejected) { | ||
1660 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1661 | "Outg Rejected =%lu", channel->pInterfaceStat->outg.Call_Rejected); | ||
1662 | } | ||
1663 | if (channel->pInterfaceStat->outg.Other_Failures) { | ||
1664 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1665 | "Outg Other Failures =%lu", channel->pInterfaceStat->outg.Other_Failures); | ||
1666 | } | ||
1667 | } | ||
1668 | break; | ||
1669 | |||
1670 | case DIVA_SUPER_TRACE_NOTIFY_MDM_STAT_CHANGE: | ||
1671 | if (channel->pInterfaceStat->mdm.Disc_Normal) { | ||
1672 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1673 | "MDM Disc Normal = %lu", channel->pInterfaceStat->mdm.Disc_Normal); | ||
1674 | } | ||
1675 | if (channel->pInterfaceStat->mdm.Disc_Unspecified) { | ||
1676 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1677 | "MDM Disc Unsp. = %lu", channel->pInterfaceStat->mdm.Disc_Unspecified); | ||
1678 | } | ||
1679 | if (channel->pInterfaceStat->mdm.Disc_Busy_Tone) { | ||
1680 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1681 | "MDM Disc Busy Tone = %lu", channel->pInterfaceStat->mdm.Disc_Busy_Tone); | ||
1682 | } | ||
1683 | if (channel->pInterfaceStat->mdm.Disc_Congestion) { | ||
1684 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1685 | "MDM Disc Congestion = %lu", channel->pInterfaceStat->mdm.Disc_Congestion); | ||
1686 | } | ||
1687 | if (channel->pInterfaceStat->mdm.Disc_Carr_Wait) { | ||
1688 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1689 | "MDM Disc Carrier Wait = %lu", channel->pInterfaceStat->mdm.Disc_Carr_Wait); | ||
1690 | } | ||
1691 | if (channel->pInterfaceStat->mdm.Disc_Trn_Timeout) { | ||
1692 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1693 | "MDM Disc Trn. T.o. = %lu", channel->pInterfaceStat->mdm.Disc_Trn_Timeout); | ||
1694 | } | ||
1695 | if (channel->pInterfaceStat->mdm.Disc_Incompat) { | ||
1696 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1697 | "MDM Disc Incompatible = %lu", channel->pInterfaceStat->mdm.Disc_Incompat); | ||
1698 | } | ||
1699 | if (channel->pInterfaceStat->mdm.Disc_Frame_Rej) { | ||
1700 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1701 | "MDM Disc Frame Reject = %lu", channel->pInterfaceStat->mdm.Disc_Frame_Rej); | ||
1702 | } | ||
1703 | if (channel->pInterfaceStat->mdm.Disc_V42bis) { | ||
1704 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1705 | "MDM Disc V.42bis = %lu", channel->pInterfaceStat->mdm.Disc_V42bis); | ||
1706 | } | ||
1707 | break; | ||
1708 | |||
1709 | case DIVA_SUPER_TRACE_NOTIFY_FAX_STAT_CHANGE: | ||
1710 | if (channel->pInterfaceStat->fax.Disc_Normal) { | ||
1711 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1712 | "FAX Disc Normal = %lu", channel->pInterfaceStat->fax.Disc_Normal); | ||
1713 | } | ||
1714 | if (channel->pInterfaceStat->fax.Disc_Not_Ident) { | ||
1715 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1716 | "FAX Disc Not Ident. = %lu", channel->pInterfaceStat->fax.Disc_Not_Ident); | ||
1717 | } | ||
1718 | if (channel->pInterfaceStat->fax.Disc_No_Response) { | ||
1719 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1720 | "FAX Disc No Response = %lu", channel->pInterfaceStat->fax.Disc_No_Response); | ||
1721 | } | ||
1722 | if (channel->pInterfaceStat->fax.Disc_Retries) { | ||
1723 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1724 | "FAX Disc Max Retries = %lu", channel->pInterfaceStat->fax.Disc_Retries); | ||
1725 | } | ||
1726 | if (channel->pInterfaceStat->fax.Disc_Unexp_Msg) { | ||
1727 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1728 | "FAX Unexp. Msg. = %lu", channel->pInterfaceStat->fax.Disc_Unexp_Msg); | ||
1729 | } | ||
1730 | if (channel->pInterfaceStat->fax.Disc_No_Polling) { | ||
1731 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1732 | "FAX Disc No Polling = %lu", channel->pInterfaceStat->fax.Disc_No_Polling); | ||
1733 | } | ||
1734 | if (channel->pInterfaceStat->fax.Disc_Training) { | ||
1735 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1736 | "FAX Disc Training = %lu", channel->pInterfaceStat->fax.Disc_Training); | ||
1737 | } | ||
1738 | if (channel->pInterfaceStat->fax.Disc_Unexpected) { | ||
1739 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1740 | "FAX Disc Unexpected = %lu", channel->pInterfaceStat->fax.Disc_Unexpected); | ||
1741 | } | ||
1742 | if (channel->pInterfaceStat->fax.Disc_Application) { | ||
1743 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1744 | "FAX Disc Application = %lu", channel->pInterfaceStat->fax.Disc_Application); | ||
1745 | } | ||
1746 | if (channel->pInterfaceStat->fax.Disc_Incompat) { | ||
1747 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1748 | "FAX Disc Incompatible = %lu", channel->pInterfaceStat->fax.Disc_Incompat); | ||
1749 | } | ||
1750 | if (channel->pInterfaceStat->fax.Disc_No_Command) { | ||
1751 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1752 | "FAX Disc No Command = %lu", channel->pInterfaceStat->fax.Disc_No_Command); | ||
1753 | } | ||
1754 | if (channel->pInterfaceStat->fax.Disc_Long_Msg) { | ||
1755 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1756 | "FAX Disc Long Msg. = %lu", channel->pInterfaceStat->fax.Disc_Long_Msg); | ||
1757 | } | ||
1758 | if (channel->pInterfaceStat->fax.Disc_Supervisor) { | ||
1759 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1760 | "FAX Disc Supervisor = %lu", channel->pInterfaceStat->fax.Disc_Supervisor); | ||
1761 | } | ||
1762 | if (channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD) { | ||
1763 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1764 | "FAX Disc SUP SEP PWD = %lu", channel->pInterfaceStat->fax.Disc_SUB_SEP_PWD); | ||
1765 | } | ||
1766 | if (channel->pInterfaceStat->fax.Disc_Invalid_Msg) { | ||
1767 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1768 | "FAX Disc Invalid Msg. = %lu", channel->pInterfaceStat->fax.Disc_Invalid_Msg); | ||
1769 | } | ||
1770 | if (channel->pInterfaceStat->fax.Disc_Page_Coding) { | ||
1771 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1772 | "FAX Disc Page Coding = %lu", channel->pInterfaceStat->fax.Disc_Page_Coding); | ||
1773 | } | ||
1774 | if (channel->pInterfaceStat->fax.Disc_App_Timeout) { | ||
1775 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1776 | "FAX Disc Appl. T.o. = %lu", channel->pInterfaceStat->fax.Disc_App_Timeout); | ||
1777 | } | ||
1778 | if (channel->pInterfaceStat->fax.Disc_Unspecified) { | ||
1779 | diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, | ||
1780 | "FAX Disc Unspec. = %lu", channel->pInterfaceStat->fax.Disc_Unspecified); | ||
1781 | } | ||
1782 | break; | ||
1783 | } | ||
1784 | } | ||
1785 | |||
1786 | /* | ||
1787 | Receive trace information from the Management Interface and store it in the | ||
1788 | internal trace buffer with MSG_TYPE_MLOG as is, without any filtering. | ||
1789 | Event Filtering and formatting is done in Management Interface self. | ||
1790 | */ | ||
1791 | static void diva_maint_trace_notify (void* user_context, | ||
1792 | diva_strace_library_interface_t* hLib, | ||
1793 | int Adapter, | ||
1794 | void* xlog_buffer, | ||
1795 | int length) { | ||
1796 | diva_maint_client_t* pC = (diva_maint_client_t*)user_context; | ||
1797 | diva_dbg_entry_head_t* pmsg; | ||
1798 | word size; | ||
1799 | dword sec, usec; | ||
1800 | int ch = TraceFilterChannel; | ||
1801 | int id = TraceFilterIdent; | ||
1802 | |||
1803 | /* | ||
1804 | Selective trace | ||
1805 | */ | ||
1806 | if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && | ||
1807 | (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { | ||
1808 | const char* p = NULL; | ||
1809 | int ch_value = -1; | ||
1810 | MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer; | ||
1811 | |||
1812 | if (Adapter != clients[id].logical) { | ||
1813 | return; /* Ignore all trace messages from other adapters */ | ||
1814 | } | ||
1815 | |||
1816 | if (TrcData->code == 24) { | ||
1817 | p = (char*)&TrcData->code; | ||
1818 | p += 2; | ||
1819 | } | ||
1820 | |||
1821 | /* | ||
1822 | All L1 messages start as [dsp,ch], so we can filter this information | ||
1823 | and filter out all messages that use different channel | ||
1824 | */ | ||
1825 | if (p && p[0] == '[') { | ||
1826 | if (p[2] == ',') { | ||
1827 | p += 3; | ||
1828 | ch_value = *p - '0'; | ||
1829 | } else if (p[3] == ',') { | ||
1830 | p += 4; | ||
1831 | ch_value = *p - '0'; | ||
1832 | } | ||
1833 | if (ch_value >= 0) { | ||
1834 | if (p[2] == ']') { | ||
1835 | ch_value = ch_value * 10 + p[1] - '0'; | ||
1836 | } | ||
1837 | if (ch_value != ch) { | ||
1838 | return; /* Ignore other channels */ | ||
1839 | } | ||
1840 | } | ||
1841 | } | ||
1842 | |||
1843 | } else if (TraceFilter[0] != 0) { | ||
1844 | return; /* Ignore trace if trace filter is activated, but idle */ | ||
1845 | } | ||
1846 | |||
1847 | diva_os_get_time (&sec, &usec); | ||
1848 | |||
1849 | while (!(pmsg = (diva_dbg_entry_head_t*)queueAllocMsg (dbg_queue, | ||
1850 | (word)length+sizeof(*pmsg)))) { | ||
1851 | if ((pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, &size))) { | ||
1852 | queueFreeMsg (dbg_queue); | ||
1853 | } else { | ||
1854 | break; | ||
1855 | } | ||
1856 | } | ||
1857 | if (pmsg) { | ||
1858 | memcpy (&pmsg[1], xlog_buffer, length); | ||
1859 | pmsg->sequence = dbg_sequence++; | ||
1860 | pmsg->time_sec = sec; | ||
1861 | pmsg->time_usec = usec; | ||
1862 | pmsg->facility = MSG_TYPE_MLOG; | ||
1863 | pmsg->dli = pC->logical; | ||
1864 | pmsg->drv_id = pC->hDbg->id; | ||
1865 | pmsg->di_cpu = 0; | ||
1866 | pmsg->data_length = length; | ||
1867 | queueCompleteMsg (pmsg); | ||
1868 | if (queueCount(dbg_queue)) { | ||
1869 | diva_maint_wakeup_read(); | ||
1870 | } | ||
1871 | } | ||
1872 | } | ||
1873 | |||
1874 | |||
1875 | /* | ||
1876 | Convert MAINT trace mask to management interface trace mask/work/facility and | ||
1877 | issue command to management interface | ||
1878 | */ | ||
1879 | static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask) { | ||
1880 | if (pC->request && pC->hDbg && pC->pIdiLib) { | ||
1881 | dword changed = pC->hDbg->dbgMask ^ old_mask; | ||
1882 | |||
1883 | if (changed & DIVA_MGT_DBG_TRACE) { | ||
1884 | (*(pC->pIdiLib->DivaSTraceSetInfo))(pC->pIdiLib, | ||
1885 | (pC->hDbg->dbgMask & DIVA_MGT_DBG_TRACE) != 0); | ||
1886 | } | ||
1887 | if (changed & DIVA_MGT_DBG_DCHAN) { | ||
1888 | (*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib, | ||
1889 | (pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0); | ||
1890 | } | ||
1891 | if (!TraceFilter[0]) { | ||
1892 | if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) { | ||
1893 | int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0); | ||
1894 | |||
1895 | for (i = 0; i < pC->channels; i++) { | ||
1896 | (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state); | ||
1897 | } | ||
1898 | } | ||
1899 | if (changed & DIVA_MGT_DBG_IFC_AUDIO) { | ||
1900 | int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0); | ||
1901 | |||
1902 | for (i = 0; i < pC->channels; i++) { | ||
1903 | (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state); | ||
1904 | } | ||
1905 | } | ||
1906 | } | ||
1907 | } | ||
1908 | } | ||
1909 | |||
1910 | |||
1911 | void diva_mnt_internal_dprintf (dword drv_id, dword type, char* fmt, ...) { | ||
1912 | va_list ap; | ||
1913 | |||
1914 | va_start(ap, fmt); | ||
1915 | DI_format (0, (word)drv_id, (int)type, fmt, ap); | ||
1916 | va_end(ap); | ||
1917 | } | ||
1918 | |||
1919 | /* | ||
1920 | Shutdown all adapters before driver removal | ||
1921 | */ | ||
1922 | int diva_mnt_shutdown_xdi_adapters (void) { | ||
1923 | diva_os_spin_lock_magic_t old_irql, old_irql1; | ||
1924 | int i, fret = 0; | ||
1925 | byte * pmem; | ||
1926 | |||
1927 | |||
1928 | for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { | ||
1929 | pmem = NULL; | ||
1930 | |||
1931 | diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload"); | ||
1932 | diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload"); | ||
1933 | |||
1934 | if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) { | ||
1935 | if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) { | ||
1936 | /* | ||
1937 | Adapter removal complete | ||
1938 | */ | ||
1939 | if (clients[i].pIdiLib) { | ||
1940 | (*(clients[i].pIdiLib->DivaSTraceLibraryFinit))(clients[i].pIdiLib->hLib); | ||
1941 | clients[i].pIdiLib = NULL; | ||
1942 | |||
1943 | pmem = clients[i].pmem; | ||
1944 | clients[i].pmem = NULL; | ||
1945 | } | ||
1946 | clients[i].hDbg = NULL; | ||
1947 | clients[i].request_pending = 0; | ||
1948 | |||
1949 | if (clients[i].dma_handle >= 0) { | ||
1950 | /* | ||
1951 | Free DMA handle | ||
1952 | */ | ||
1953 | diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); | ||
1954 | clients[i].dma_handle = -1; | ||
1955 | } | ||
1956 | clients[i].request = NULL; | ||
1957 | } else { | ||
1958 | fret = -1; | ||
1959 | } | ||
1960 | } | ||
1961 | |||
1962 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload"); | ||
1963 | if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) { | ||
1964 | clients[i].request_pending = 0; | ||
1965 | (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib)); | ||
1966 | if (clients[i].dma_handle >= 0) { | ||
1967 | diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); | ||
1968 | clients[i].dma_handle = -1; | ||
1969 | } | ||
1970 | } | ||
1971 | diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload"); | ||
1972 | |||
1973 | if (pmem) { | ||
1974 | diva_os_free (0, pmem); | ||
1975 | } | ||
1976 | } | ||
1977 | |||
1978 | return (fret); | ||
1979 | } | ||
1980 | |||
1981 | /* | ||
1982 | Set/Read the trace filter used for selective tracing. | ||
1983 | Affects B- and Audio Tap trace mask at run time | ||
1984 | */ | ||
1985 | int diva_set_trace_filter (int filter_length, const char* filter) { | ||
1986 | diva_os_spin_lock_magic_t old_irql, old_irql1; | ||
1987 | int i, ch, on, client_b_on, client_atap_on; | ||
1988 | |||
1989 | diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); | ||
1990 | diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); | ||
1991 | |||
1992 | if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) { | ||
1993 | memcpy (&TraceFilter[0], filter, filter_length); | ||
1994 | if (TraceFilter[filter_length]) { | ||
1995 | TraceFilter[filter_length] = 0; | ||
1996 | } | ||
1997 | if (TraceFilter[0] == '*') { | ||
1998 | TraceFilter[0] = 0; | ||
1999 | } | ||
2000 | } else { | ||
2001 | filter_length = -1; | ||
2002 | } | ||
2003 | |||
2004 | TraceFilterIdent = -1; | ||
2005 | TraceFilterChannel = -1; | ||
2006 | |||
2007 | on = (TraceFilter[0] == 0); | ||
2008 | |||
2009 | for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { | ||
2010 | if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) { | ||
2011 | client_b_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0); | ||
2012 | client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0); | ||
2013 | for (ch = 0; ch < clients[i].channels; ch++) { | ||
2014 | (*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch+1, client_b_on); | ||
2015 | (*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch+1, client_atap_on); | ||
2016 | } | ||
2017 | } | ||
2018 | } | ||
2019 | |||
2020 | for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { | ||
2021 | if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) { | ||
2022 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); | ||
2023 | clients[i].request_pending = 0; | ||
2024 | (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib)); | ||
2025 | diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); | ||
2026 | } | ||
2027 | } | ||
2028 | |||
2029 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter"); | ||
2030 | diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); | ||
2031 | |||
2032 | return (filter_length); | ||
2033 | } | ||
2034 | |||
2035 | int diva_get_trace_filter (int max_length, char* filter) { | ||
2036 | diva_os_spin_lock_magic_t old_irql; | ||
2037 | int len; | ||
2038 | |||
2039 | diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read_filter"); | ||
2040 | len = strlen (&TraceFilter[0]) + 1; | ||
2041 | if (max_length >= len) { | ||
2042 | memcpy (filter, &TraceFilter[0], len); | ||
2043 | } | ||
2044 | diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_filter"); | ||
2045 | |||
2046 | return (len); | ||
2047 | } | ||
2048 | |||
2049 | static int diva_dbg_cmp_key (const char* ref, const char* key) { | ||
2050 | while (*key && (*ref++ == *key++)); | ||
2051 | return (!*key && !*ref); | ||
2052 | } | ||
2053 | |||
2054 | /* | ||
2055 | In case trace filter starts with "C" character then | ||
2056 | all following characters are interpreted as command. | ||
2057 | Followings commands are available: | ||
2058 | - single, trace single call at time, independent from CPN/CiPN | ||
2059 | */ | ||
2060 | static int diva_mnt_cmp_nmbr (const char* nmbr) { | ||
2061 | const char* ref = &TraceFilter[0]; | ||
2062 | int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr); | ||
2063 | |||
2064 | if (ref[0] == 'C') { | ||
2065 | if (diva_dbg_cmp_key (&ref[1], "single")) { | ||
2066 | return (0); | ||
2067 | } | ||
2068 | return (-1); | ||
2069 | } | ||
2070 | |||
2071 | if (!ref_len || (ref_len > nmbr_len)) { | ||
2072 | return (-1); | ||
2073 | } | ||
2074 | |||
2075 | nmbr = nmbr + nmbr_len - 1; | ||
2076 | ref = ref + ref_len - 1; | ||
2077 | |||
2078 | while (ref_len--) { | ||
2079 | if (*nmbr-- != *ref--) { | ||
2080 | return (-1); | ||
2081 | } | ||
2082 | } | ||
2083 | |||
2084 | return (0); | ||
2085 | } | ||
2086 | |||
2087 | static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) { | ||
2088 | ENTITY e; | ||
2089 | IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; | ||
2090 | |||
2091 | if (!request) { | ||
2092 | return (-1); | ||
2093 | } | ||
2094 | |||
2095 | pReq->xdi_dma_descriptor_operation.Req = 0; | ||
2096 | pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; | ||
2097 | |||
2098 | pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC; | ||
2099 | pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1; | ||
2100 | pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; | ||
2101 | pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0; | ||
2102 | |||
2103 | (*request)((ENTITY*)pReq); | ||
2104 | |||
2105 | if (!pReq->xdi_dma_descriptor_operation.info.operation && | ||
2106 | (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) && | ||
2107 | pReq->xdi_dma_descriptor_operation.info.descriptor_magic) { | ||
2108 | *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic; | ||
2109 | return (pReq->xdi_dma_descriptor_operation.info.descriptor_number); | ||
2110 | } else { | ||
2111 | return (-1); | ||
2112 | } | ||
2113 | } | ||
2114 | |||
2115 | static void diva_free_dma_descriptor (IDI_CALL request, int nr) { | ||
2116 | ENTITY e; | ||
2117 | IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e; | ||
2118 | |||
2119 | if (!request || (nr < 0)) { | ||
2120 | return; | ||
2121 | } | ||
2122 | |||
2123 | pReq->xdi_dma_descriptor_operation.Req = 0; | ||
2124 | pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION; | ||
2125 | |||
2126 | pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE; | ||
2127 | pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr; | ||
2128 | pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL; | ||
2129 | pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0; | ||
2130 | |||
2131 | (*request)((ENTITY*)pReq); | ||
2132 | } | ||
2133 | |||