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