📄 debug.c
字号:
#include "platform.h"#include "pc.h"#include "di_defs.h"#include "debug_if.h"#include "divasync.h"#include "kst_ifc.h"#include "maintidi.h"#include "man_defs.h"/* LOCALS */#define DBG_MAGIC (0x47114711L)static void DI_register (void *arg);static void DI_deregister (pDbgHandle hDbg);static void DI_format (int do_lock, word id, int type, char *format, va_list argument_list);static void DI_format_locked (word id, int type, char *format, va_list argument_list);static void DI_format_old (word id, char *format, va_list ap) { }static void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap) { }static void single_p (byte * P, word * PLength, byte Id);static void diva_maint_xdi_cb (ENTITY* e);static word SuperTraceCreateReadReq (byte* P, const char* path);static int diva_mnt_cmp_nmbr (const char* nmbr);static void diva_free_dma_descriptor (IDI_CALL request, int nr);static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic);void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...);static dword MaxDumpSize = 256 ;static dword MaxXlogSize = 2 + 128 ;static char TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH+1];static int TraceFilterIdent = -1;static int TraceFilterChannel = -1;typedef struct _diva_maint_client { dword sec; dword usec; pDbgHandle hDbg; char drvName[128]; dword dbgMask; dword last_dbgMask; IDI_CALL request; _DbgHandle_ Dbg; int logical; int channels; diva_strace_library_interface_t* pIdiLib; BUFFERS XData; char xbuffer[2048+512]; byte* pmem; int request_pending; int dma_handle;} diva_maint_client_t;static diva_maint_client_t clients[MAX_DESCRIPTORS];static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask);static void diva_maint_error (void* user_context, diva_strace_library_interface_t* hLib, int Adapter, int error, const char* file, int line);static void diva_maint_state_change_notify (void* user_context, diva_strace_library_interface_t* hLib, int Adapter, diva_trace_line_state_t* channel, int notify_subject);static void diva_maint_trace_notify (void* user_context, diva_strace_library_interface_t* hLib, int Adapter, void* xlog_buffer, int length);typedef struct MSG_QUEUE { dword Size; /* total size of queue (constant) */ byte *Base; /* lowest address (constant) */ byte *High; /* Base + Size (constant) */ byte *Head; /* first message in queue (if any) */ byte *Tail; /* first free position */ byte *Wrap; /* current wraparound position */ dword Count; /* current no of bytes in queue */} MSG_QUEUE;typedef struct MSG_HEAD { volatile dword Size; /* size of data following MSG_HEAD */#define MSG_INCOMPLETE 0x8000 /* ored to Size until queueCompleteMsg */} MSG_HEAD;#define queueCompleteMsg(p) do{ ((MSG_HEAD *)p - 1)->Size &= ~MSG_INCOMPLETE; }while(0)#define queueCount(q) ((q)->Count)#define MSG_NEED(size) \ ( (sizeof(MSG_HEAD) + size + sizeof(dword) - 1) & ~(sizeof(dword) - 1) )static void queueInit (MSG_QUEUE *Q, byte *Buffer, dword sizeBuffer) { Q->Size = sizeBuffer; Q->Base = Q->Head = Q->Tail = Buffer; Q->High = Buffer + sizeBuffer; Q->Wrap = NULL; Q->Count= 0;}static byte *queueAllocMsg (MSG_QUEUE *Q, word size) { /* Allocate 'size' bytes at tail of queue which will be filled later * directly with callers own message header info and/or message. * An 'alloced' message is marked incomplete by oring the 'Size' field * with MSG_INCOMPLETE. * This must be reset via queueCompleteMsg() after the message is filled. * As long as a message is marked incomplete queuePeekMsg() will return * a 'queue empty' condition when it reaches such a message. */ MSG_HEAD *Msg; word need = MSG_NEED(size); if (Q->Tail == Q->Head) { if (Q->Wrap || need > Q->Size) { return NULL; /* full */ } goto alloc; /* empty */ } if (Q->Tail > Q->Head) { if (Q->Tail + need <= Q->High) goto alloc; /* append */ if (Q->Base + need > Q->Head) { return NULL; /* too much */ } /* wraparound the queue (but not the message) */ Q->Wrap = Q->Tail; Q->Tail = Q->Base; goto alloc; } if (Q->Tail + need > Q->Head) { return NULL; /* too much */ }alloc: Msg = (MSG_HEAD *)Q->Tail; Msg->Size = size | MSG_INCOMPLETE; Q->Tail += need; Q->Count += size; return ((byte*)(Msg + 1));}static void queueFreeMsg (MSG_QUEUE *Q) {/* Free the message at head of queue */ word size = ((MSG_HEAD *)Q->Head)->Size & ~MSG_INCOMPLETE; Q->Head += MSG_NEED(size); Q->Count -= size; if (Q->Wrap) { if (Q->Head >= Q->Wrap) { Q->Head = Q->Base; Q->Wrap = NULL; } } else if (Q->Head >= Q->Tail) { Q->Head = Q->Tail = Q->Base; }}static byte *queuePeekMsg (MSG_QUEUE *Q, word *size) { /* Show the first valid message in queue BUT DON'T free the message. * After looking on the message contents it can be freed queueFreeMsg() * or simply remain in message queue. */ MSG_HEAD *Msg = (MSG_HEAD *)Q->Head; if (((byte *)Msg == Q->Tail && !Q->Wrap) || (Msg->Size & MSG_INCOMPLETE)) { return NULL; } else { *size = Msg->Size; return ((byte *)(Msg + 1)); }}/* Message queue header */static MSG_QUEUE* dbg_queue;static byte* dbg_base;static int external_dbg_queue;static diva_os_spin_lock_t dbg_q_lock;static diva_os_spin_lock_t dbg_adapter_lock;static int dbg_q_busy;static volatile dword dbg_sequence;static dword start_sec;static dword start_usec;/* INTERFACE: Initialize run time queue structures. base: base of the message queue length: length of the message queue do_init: perfor queue reset return: zero on success, -1 on error */int diva_maint_init (byte* base, unsigned long length, int do_init) { if (dbg_queue || (!base) || (length < (4096*4))) { return (-1); } TraceFilter[0] = 0; TraceFilterIdent = -1; TraceFilterChannel = -1; dbg_base = base; diva_os_get_time (&start_sec, &start_usec); *(dword*)base = (dword)DBG_MAGIC; /* Store Magic */ base += sizeof(dword); length -= sizeof(dword); *(dword*)base = 2048; /* Extension Field Length */ base += sizeof(dword); length -= sizeof(dword); strcpy (base, "KERNEL MODE BUFFER\n"); base += 2048; length -= 2048; *(dword*)base = 0; /* Terminate extension */ base += sizeof(dword); length -= sizeof(dword); *(void**)base = (void*)(base+sizeof(void*)); /* Store Base */ base += sizeof(void*); length -= sizeof(void*); dbg_queue = (MSG_QUEUE*)base; queueInit (dbg_queue, base + sizeof(MSG_QUEUE), length - sizeof(MSG_QUEUE) - 512); external_dbg_queue = 0; if (!do_init) { external_dbg_queue = 1; /* memory was located on the external device */ } if (diva_os_initialize_spin_lock (&dbg_q_lock, "dbg_init")) { dbg_queue = NULL; dbg_base = NULL; external_dbg_queue = 0; return (-1); } if (diva_os_initialize_spin_lock (&dbg_adapter_lock, "dbg_init")) { diva_os_destroy_spin_lock(&dbg_q_lock, "dbg_init"); dbg_queue = NULL; dbg_base = NULL; external_dbg_queue = 0; return (-1); } return (0);}/* INTERFACE: Finit at unload time return address of internal queue or zero if queue was external */void* diva_maint_finit (void) { void* ret = (void*)dbg_base; int i; dbg_queue = NULL; dbg_base = NULL; if (ret) { diva_os_destroy_spin_lock(&dbg_q_lock, "dbg_finit"); diva_os_destroy_spin_lock(&dbg_adapter_lock, "dbg_finit"); } if (external_dbg_queue) { ret = NULL; } external_dbg_queue = 0; for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { if (clients[i].pmem) { diva_os_free (0, clients[i].pmem); } } return (ret);}/* INTERFACE: Return amount of messages in debug queue */dword diva_dbg_q_length (void) { return (dbg_queue ? queueCount(dbg_queue) : 0);}/* INTERFACE: Lock message queue and return the pointer to the first entry. */diva_dbg_entry_head_t* diva_maint_get_message (word* size, diva_os_spin_lock_magic_t* old_irql) { diva_dbg_entry_head_t* pmsg = NULL; diva_os_enter_spin_lock (&dbg_q_lock, old_irql, "read"); if (dbg_q_busy) { diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_busy"); return NULL; } dbg_q_busy = 1; if (!(pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, size))) { dbg_q_busy = 0; diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_empty"); } return (pmsg);}/* INTERFACE: acknowledge last message and unlock queue */void diva_maint_ack_message (int do_release, diva_os_spin_lock_magic_t* old_irql) { if (!dbg_q_busy) { return; } if (do_release) { queueFreeMsg (dbg_queue); } dbg_q_busy = 0; diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_ack");}/* INTERFACE: PRT COMP function used to register with MAINT adapter or log in compatibility mode in case older driver version is connected too */void diva_maint_prtComp (char *format, ...) { void *hDbg; va_list ap; if (!format) return; va_start(ap, format); /* register to new log driver functions */ if ((format[0] == 0) && ((unsigned char)format[1] == 255)) { hDbg = va_arg(ap, void *); /* ptr to DbgHandle */ DI_register (hDbg); } va_end (ap);}static void DI_register (void *arg) { diva_os_spin_lock_magic_t old_irql; dword sec, usec; pDbgHandle hDbg ; int id, free_id = -1, best_id = 0; diva_os_get_time (&sec, &usec); hDbg = (pDbgHandle)arg ; /* Check for bad args, specially for the old obsolete debug handle */ if ((hDbg == NULL) || ((hDbg->id == 0) && (((_OldDbgHandle_ *)hDbg)->id == -1)) || (hDbg->Registered != 0)) { return ; } diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register"); for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) { if (clients[id].hDbg == hDbg) { /* driver already registered */ diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); return; } if (clients[id].hDbg) { /* slot is busy */ continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -