+/*
+ Set/Read the trace filter used for selective tracing.
+ Affects B- and Audio Tap trace mask at run time
+ */
+int diva_set_trace_filter (int filter_length, const char* filter) {
+ diva_os_spin_lock_magic_t old_irql, old_irql1;
+ int i, ch, on, client_b_on, client_atap_on;
+
+ diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+ diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+
+ if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) {
+ memcpy (&TraceFilter[0], filter, filter_length);
+ if (TraceFilter[filter_length]) {
+ TraceFilter[filter_length] = 0;
+ }
+ if (TraceFilter[0] == '*') {
+ TraceFilter[0] = 0;
+ }
+ } else {
+ filter_length = -1;
+ }
+
+ TraceFilterIdent = -1;
+ TraceFilterChannel = -1;
+
+ on = (TraceFilter[0] == 0);
+
+ for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+ if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
+ client_b_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
+ client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
+ for (ch = 0; ch < clients[i].channels; ch++) {
+ (*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch+1, client_b_on);
+ (*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch+1, client_atap_on);
+ }
+ }
+ }
+
+ for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+ if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
+ diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+ clients[i].request_pending = 0;
+ (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
+ diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+ }
+ }
+
+ diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+ diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+
+ return (filter_length);
+}
+
+int diva_get_trace_filter (int max_length, char* filter) {
+ diva_os_spin_lock_magic_t old_irql;
+ int len;
+
+ diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
+ len = strlen (&TraceFilter[0]) + 1;
+ if (max_length >= len) {
+ memcpy (filter, &TraceFilter[0], len);
+ }
+ diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
+
+ return (len);
+}
+
+static int diva_dbg_cmp_key (const char* ref, const char* key) {
+ while (*key && (*ref++ == *key++));
+ return (!*key && !*ref);
+}
+
+/*
+ In case trace filter starts with "C" character then
+ all following characters are interpreted as command.
+ Followings commands are available:
+ - single, trace single call at time, independent from CPN/CiPN
+ */
+static int diva_mnt_cmp_nmbr (const char* nmbr) {
+ const char* ref = &TraceFilter[0];
+ int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr);
+
+ if (ref[0] == 'C') {
+ if (diva_dbg_cmp_key (&ref[1], "single")) {
+ return (0);
+ }
+ return (-1);
+ }
+
+ if (!ref_len || (ref_len > nmbr_len)) {
+ return (-1);
+ }
+
+ nmbr = nmbr + nmbr_len - 1;
+ ref = ref + ref_len - 1;
+
+ while (ref_len--) {
+ if (*nmbr-- != *ref--) {
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) {
+ ENTITY e;
+ IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
+
+ if (!request) {
+ return (-1);
+ }
+
+ pReq->xdi_dma_descriptor_operation.Req = 0;
+ pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
+
+ pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
+ pReq->xdi_dma_descriptor_operation.info.descriptor_number = -1;
+ pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
+ pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
+
+ (*request)((ENTITY*)pReq);
+
+ if (!pReq->xdi_dma_descriptor_operation.info.operation &&
+ (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
+ pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
+ *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
+ return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
+ } else {
+ return (-1);
+ }
+}
+
+static void diva_free_dma_descriptor (IDI_CALL request, int nr) {
+ ENTITY e;
+ IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
+
+ if (!request || (nr < 0)) {
+ return;
+ }
+
+ pReq->xdi_dma_descriptor_operation.Req = 0;
+ pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
+
+ pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
+ pReq->xdi_dma_descriptor_operation.info.descriptor_number = nr;
+ pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
+ pReq->xdi_dma_descriptor_operation.info.descriptor_magic = 0;
+
+ (*request)((ENTITY*)pReq);
+}
+