| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 290 | for (i = 1; i < ARRAY_SIZE(clients); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 394 | for (id = 1; id < ARRAY_SIZE(clients); id++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 497 | for (i = 1; i < ARRAY_SIZE(clients); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) || | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 739 | (id >= ARRAY_SIZE(clients))) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Amol Lad | e2de257 | 2006-12-08 02:39:32 -0800 | [diff] [blame] | 759 | if ((to_copy = min(strlen(clients[id].drvName), (size_t)(data_length-1)))) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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; | 
| Amol Lad | e2de257 | 2006-12-08 02:39:32 -0800 | [diff] [blame] | 766 | if ((to_copy = min(strlen(clients[id].hDbg->drvTag), (size_t)(data_length-2)))) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 789 | if (!data || !id || (id >= ARRAY_SIZE(clients))) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 812 | if (!id || (id >= ARRAY_SIZE(clients))) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 890 | for (id = 1; id < ARRAY_SIZE(clients); id++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 1040 | for (i = 1; i < ARRAY_SIZE(clients); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 1118 | for (i = 1; i < ARRAY_SIZE(clients); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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)) { | 
| Andrew Morton | 162c0d9 | 2008-02-06 01:38:31 -0800 | [diff] [blame] | 1191 | dword uninitialized_var(rx_dma_magic); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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); | 
| Hannes Eder | 215a9c7 | 2009-02-25 13:11:23 +0000 | [diff] [blame] | 1201 | pC->xbuffer[8] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE & 0xFF); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 1511 | if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) && | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 1558 | if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) && | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | */ | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 1806 | if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) && | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 1928 | for (i = 1; i < ARRAY_SIZE(clients); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 2009 | for (i = 1; i < ARRAY_SIZE(clients); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Ahmed S. Darwish | f85aaeb | 2007-02-12 00:53:27 -0800 | [diff] [blame] | 2020 | for (i = 1; i < ARRAY_SIZE(clients); i++) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  |