X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fisdn%2Fhardware%2Feicon%2Fdebug.c;h=6851c6270ce87870132af4c8b46f277c6eae0a6f;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=e8e99ad354fbc2d65e273bc57e576a7793a801f3;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index e8e99ad35..6851c6270 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c @@ -5,6 +5,7 @@ #include "divasync.h" #include "kst_ifc.h" #include "maintidi.h" +#include "man_defs.h" /* LOCALS @@ -13,17 +14,23 @@ 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 ap); +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 (word id, dword msgID, 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; @@ -40,9 +47,10 @@ typedef struct _diva_maint_client { BUFFERS XData; char xbuffer[2048+512]; byte* pmem; - int request_pending; + int request_pending; + int dma_handle; } diva_maint_client_t; -static diva_maint_client_t clients[64]; +static diva_maint_client_t clients[MAX_DESCRIPTORS]; static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask); @@ -201,6 +209,10 @@ int diva_maint_init (byte* base, unsigned long length, int do_init) { return (-1); } + TraceFilter[0] = 0; + TraceFilterIdent = -1; + TraceFilterChannel = -1; + dbg_base = base; diva_os_get_time (&start_sec, &start_usec); @@ -249,7 +261,6 @@ int diva_maint_init (byte* base, unsigned long length, int do_init) { return (-1); } - return (0); } @@ -302,16 +313,16 @@ 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_hard (&dbg_q_lock, old_irql, "read"); + diva_os_enter_spin_lock (&dbg_q_lock, old_irql, "read"); if (dbg_q_busy) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_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_hard (&dbg_q_lock, old_irql, "read_empty"); + diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_empty"); } return (pmsg); @@ -330,7 +341,7 @@ void diva_maint_ack_message (int do_release, queueFreeMsg (dbg_queue); } dbg_q_busy = 0; - diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_ack"); + diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_ack"); } @@ -378,14 +389,14 @@ static void DI_register (void *arg) { return ; } - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + 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_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); return; } if (clients[id].hDbg) { /* slot is busy */ @@ -468,7 +479,7 @@ static void DI_register (void *arg) { } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); } static void DI_deregister (pDbgHandle hDbg) { @@ -480,8 +491,8 @@ static void DI_deregister (pDbgHandle hDbg) { diva_os_get_time (&sec, &usec); - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read"); for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { if (clients[i].hDbg == hDbg) { @@ -543,8 +554,8 @@ static void DI_deregister (pDbgHandle hDbg) { } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack"); if (pmem) { diva_os_free (0, pmem); @@ -572,13 +583,22 @@ static void DI_format (int do_lock, char *data; unsigned short code; - if (!format) + if (diva_os_in_irq()) { + dbg_sequence++; return; + } + + if ((!format) || + ((TraceFilter[0] != 0) && ((TraceFilterIdent < 0) || (TraceFilterChannel < 0)))) { + return; + } + + diva_os_get_time (&sec, &usec); if (do_lock) { - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "format"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "format"); } switch (type) { @@ -703,7 +723,7 @@ static void DI_format (int do_lock, } if (do_lock) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "format"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "format"); } } @@ -720,7 +740,7 @@ int diva_get_driver_info (dword id, byte* data, int data_length) { return (-1); } - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info"); if (clients[id].hDbg) { *p++ = 1; @@ -757,7 +777,7 @@ int diva_get_driver_info (dword id, byte* data, int data_length) { } *p++ = 0; - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info"); return (p - data); } @@ -769,7 +789,7 @@ int diva_get_driver_dbg_mask (dword id, byte* data) { if (!data || !id || (id >= (sizeof(clients)/sizeof(clients[0])))) { return (-1); } - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info"); if (clients[id].hDbg) { ret = 4; @@ -779,7 +799,7 @@ int diva_get_driver_dbg_mask (dword id, byte* data) { *data++= (byte)(clients[id].hDbg->dbgMask >> 24); } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info"); return (ret); } @@ -793,8 +813,8 @@ int diva_set_driver_dbg_mask (dword id, dword mask) { return (-1); } - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "dbg mask"); if (clients[id].hDbg) { dword old_mask = clients[id].hDbg->dbgMask; @@ -806,14 +826,14 @@ int diva_set_driver_dbg_mask (dword id, dword mask) { } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "dbg mask"); if (clients[id].request_pending) { clients[id].request_pending = 0; (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib)); } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask"); return (ret); } @@ -851,12 +871,12 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { diva_os_get_time (&sec, &usec); diva_get_idi_adapter_info (d->request, &serial, &logical); if (serial & 0xff000000) { - sprintf (tmp, "ADAPTER:%d SN:%d-%d", + sprintf (tmp, "ADAPTER:%d SN:%u-%d", (int)logical, serial & 0x00ffffff, (byte)(((serial & 0xff000000) >> 24) + 1)); } else { - sprintf (tmp, "ADAPTER:%d SN:%d", (int)logical, serial); + sprintf (tmp, "ADAPTER:%d SN:%u", (int)logical, serial); } if (!(pmem = diva_os_malloc (0, DivaSTraceGetMemotyRequirement (d->channels)))) { @@ -864,13 +884,14 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { } memset (pmem, 0x00, DivaSTraceGetMemotyRequirement (d->channels)); - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); + 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 && (clients[id].request == d->request)) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_free(0, pmem); return; } if (clients[id].hDbg) { /* slot is busy */ @@ -891,8 +912,8 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { } if (free_id < 0) { - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); diva_os_free (0, pmem); return; } @@ -908,6 +929,7 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { clients[id].Dbg.drvTag[0] = 0; clients[id].logical = (int)logical; clients[id].channels = (int)d->channels; + clients[id].dma_handle = -1; clients[id].Dbg.dbgMask = 0; clients[id].dbgMask = clients[id].Dbg.dbgMask; @@ -949,8 +971,8 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { clients[id].request = NULL; clients[id].request_pending = 0; clients[id].hDbg = NULL; - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); diva_os_free (0, pmem); return; } @@ -988,14 +1010,14 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) { org_mask = clients[id].Dbg.dbgMask; clients[id].Dbg.dbgMask = 0; - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register"); if (clients[id].request_pending) { clients[id].request_pending = 0; (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib)); } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register"); diva_set_driver_dbg_mask (id, org_mask); } @@ -1012,8 +1034,8 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) { diva_os_get_time (&sec, &usec); - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read"); for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { if (clients[i].hDbg && (clients[i].request == d->request)) { @@ -1030,8 +1052,15 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) { } clients[i].hDbg = NULL; - clients[i].request = NULL; clients[i].request_pending = 0; + if (clients[i].dma_handle >= 0) { + /* + Free DMA handle + */ + diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); + clients[i].dma_handle = -1; + } + clients[i].request = NULL; /* Log driver register, MAINT driver ID is '0' @@ -1069,8 +1098,8 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) { } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack"); - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack"); if (pmem) { diva_os_free (0, pmem); @@ -1142,6 +1171,42 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) { if (pC && pC->pIdiLib && pC->request) { ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib); + IDI_SYNC_REQ* preq; + char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)]; + char features[4]; + word assign_data_length = 1; + + features[0] = 0; + pC->xbuffer[0] = 0; + preq = (IDI_SYNC_REQ*)&buffer[0]; + preq->xdi_extended_features.Req = 0; + preq->xdi_extended_features.Rc = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES; + preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features); + preq->xdi_extended_features.info.features = &features[0]; + + (*(pC->request))((ENTITY*)preq); + + if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && + (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { + dword rx_dma_magic; + if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { + pC->xbuffer[0] = LLI; + pC->xbuffer[1] = 8; + pC->xbuffer[2] = 0x40; + pC->xbuffer[3] = (byte)pC->dma_handle; + pC->xbuffer[4] = (byte)rx_dma_magic; + pC->xbuffer[5] = (byte)(rx_dma_magic >> 8); + pC->xbuffer[6] = (byte)(rx_dma_magic >> 16); + pC->xbuffer[7] = (byte)(rx_dma_magic >> 24); + pC->xbuffer[8] = (byte)DIVA_MAX_MANAGEMENT_TRANSFER_SIZE; + pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8); + pC->xbuffer[10] = 0; + + assign_data_length = 11; + } + } else { + pC->dma_handle = -1; + } e->Id = MAN_ID; e->callback = diva_maint_xdi_cb; @@ -1149,9 +1214,8 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) { e->X = &pC->XData; e->Req = ASSIGN; e->ReqCh = 0; - e->X->PLength = 1; + e->X->PLength = assign_data_length; e->X->P = (byte*)&pC->xbuffer[0]; - pC->xbuffer[0] = 0; pC->request_pending = 1; @@ -1300,16 +1364,25 @@ static void diva_maint_xdi_cb (ENTITY* e) { diva_os_spin_lock_magic_t old_irql, old_irql1; - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb"); pC = (diva_maint_client_t*)pLib->hAdapter; - if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { - diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error"); + if ((e->complete == 255) || (pC->dma_handle < 0)) { + if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { + diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error"); + } + } else { + /* + Process combined management interface indication + */ + if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) { + diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)"); + } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb"); if (pC->request_pending) { @@ -1317,7 +1390,7 @@ static void diva_maint_xdi_cb (ENTITY* e) { (*(pC->request))(e); } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb"); } @@ -1365,8 +1438,42 @@ static void diva_maint_state_change_notify (void* user_context, } switch (notify_subject) { - case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: - if (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS) { + case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: { + int view = (TraceFilter[0] == 0); + /* + Process selective Trace + */ + if (channel->Line[0] == 'I' && channel->Line[1] == 'd' && + channel->Line[2] == 'l' && channel->Line[3] == 'e') { + if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) { + (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0); + (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0); + diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d", + (int)channel->ChannelNumber); + TraceFilterIdent = -1; + TraceFilterChannel = -1; + view = 1; + } + } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) && + diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) { + + if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */ + (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1); + } + if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */ + (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1); + } + + TraceFilterIdent = pC->hDbg->id; + TraceFilterChannel = (int)channel->ChannelNumber; + + if (TraceFilterIdent >= 0) { + diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d", + (int)channel->ChannelNumber); + view = 1; + } + } + if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) { diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch = %d", (int)channel->ChannelNumber); diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]); @@ -1392,10 +1499,26 @@ static void diva_maint_state_change_notify (void* user_context, channel->LastDisconnecCause); diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner = <%s>", &channel->UserID[0]); } - break; + + } break; case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE: if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) { + { + int ch = TraceFilterChannel; + int id = TraceFilterIdent; + + if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && + (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { + if (ch != (int)modem->ChannelNumber) { + break; + } + } else if (TraceFilter[0] != 0) { + break; + } + } + + diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch = %lu", (int)modem->ChannelNumber); diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu", modem->Event); @@ -1428,6 +1551,20 @@ static void diva_maint_state_change_notify (void* user_context, case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE: if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) { + { + int ch = TraceFilterChannel; + int id = TraceFilterIdent; + + if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && + (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { + if (ch != (int)fax->ChannelNumber) { + break; + } + } else if (TraceFilter[0] != 0) { + break; + } + } + diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch = %lu",(int)fax->ChannelNumber); diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu", fax->Event); diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu", fax->Page_Counter); @@ -1660,6 +1797,52 @@ static void diva_maint_trace_notify (void* user_context, diva_dbg_entry_head_t* pmsg; word size; dword sec, usec; + int ch = TraceFilterChannel; + int id = TraceFilterIdent; + + /* + Selective trace + */ + if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) && + (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) { + const char* p = NULL; + int ch_value = -1; + MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer; + + if (Adapter != clients[id].logical) { + return; /* Ignore all trace messages from other adapters */ + } + + if (TrcData->code == 24) { + p = (char*)&TrcData->code; + p += 2; + } + + /* + All L1 messages start as [dsp,ch], so we can filter this information + and filter out all messages that use different channel + */ + if (p && p[0] == '[') { + if (p[2] == ',') { + p += 3; + ch_value = *p - '0'; + } else if (p[3] == ',') { + p += 4; + ch_value = *p - '0'; + } + if (ch_value >= 0) { + if (p[2] == ']') { + ch_value = ch_value * 10 + p[1] - '0'; + } + if (ch_value != ch) { + return; /* Ignore other channels */ + } + } + } + + } else if (TraceFilter[0] != 0) { + return; /* Ignore trace if trace filter is activated, but idle */ + } diva_os_get_time (&sec, &usec); @@ -1705,18 +1888,20 @@ static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword ol (*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib, (pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0); } - if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) { - int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0); + if (!TraceFilter[0]) { + if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) { + int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0); - for (i = 0; i < pC->channels; i++) { - (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state); + for (i = 0; i < pC->channels; i++) { + (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state); + } } - } - if (changed & DIVA_MGT_DBG_IFC_AUDIO) { - int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0); + if (changed & DIVA_MGT_DBG_IFC_AUDIO) { + int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0); - for (i = 0; i < pC->channels; i++) { - (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state); + for (i = 0; i < pC->channels; i++) { + (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state); + } } } } @@ -1743,8 +1928,8 @@ int diva_mnt_shutdown_xdi_adapters (void) { for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) { pmem = NULL; - diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload"); - diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "unload"); + diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload"); + diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload"); if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) { if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) { @@ -1759,19 +1944,31 @@ int diva_mnt_shutdown_xdi_adapters (void) { clients[i].pmem = NULL; } clients[i].hDbg = NULL; - clients[i].request = NULL; clients[i].request_pending = 0; + + if (clients[i].dma_handle >= 0) { + /* + Free DMA handle + */ + diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); + clients[i].dma_handle = -1; + } + clients[i].request = NULL; } else { fret = -1; } } - diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "unload"); + diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload"); if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) { clients[i].request_pending = 0; (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib)); + if (clients[i].dma_handle >= 0) { + diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle); + clients[i].dma_handle = -1; + } } - diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload"); + diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload"); if (pmem) { diva_os_free (0, pmem); @@ -1781,3 +1978,156 @@ int diva_mnt_shutdown_xdi_adapters (void) { return (fret); } +/* + 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); +} +