/* * TRC_CORE.C - trace core module */ #include #include #include #include #include #include #include #include #include #include #include #include /* local trace context table (NULL=free) */ #define CheckNULLTrace(Trace) \ { \ if (Trace == NULL) \ break; \ } /* register an available idd */ INT trc_register_idd(VOID *idd) { IDD_MSG msg; D_LOG(D_ENTRY, ("trc_register_idd: entry, idd: 0x%lx", idd)); /* add handle to idd command receiver */ if ( idd_attach(idd, IDD_PORT_CMD_RX, (VOID*)trc__cmd_handler, idd) != IDD_E_SUCC ) return(TRC_E_IDD); /* issue idd command to stop trace */ NdisZeroMemory(&msg, sizeof(msg)); msg.opcode = CMD_TRC_OFF; if ( idd_send_msg(idd, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) return(TRC_E_IDD); return(TRC_E_SUCC); } /* deregister an available idd */ INT trc_deregister_idd(VOID *idd) { IDD_MSG msg; D_LOG(D_ENTRY, ("trc_deregister_idd: entry, idd: 0x%lx", idd)); /* issue idd command to stop trace */ NdisZeroMemory(&msg, sizeof(msg)); msg.opcode = CMD_TRC_OFF; if ( idd_send_msg(idd, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) return(TRC_E_IDD); /* remove handle from idd command receiver */ if ( idd_detach(idd, IDD_PORT_CMD_RX, (VOID*)trc__cmd_handler, idd) != IDD_E_SUCC ) return(TRC_E_IDD); else return(TRC_E_SUCC); } /* create a trace object */ INT trc_create(VOID **trc_1, ULONG depth) { TRC **ret_trc = (TRC**)trc_1; NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(0xffffffff, 0xffffffff); TRC *trc; D_LOG(D_ENTRY, ("trc_create: entry, ret_trc: 0x%lx, depth: %ld", ret_trc, depth)); /* allocate memory object */ NdisAllocateMemory((PVOID*)&trc, sizeof(*trc), 0, pa); if ( !trc ) { mem_alloc_failed: D_LOG(D_ALWAYS, ("trc_create: memory allocate failed!")); return(TRC_E_NOMEM); } D_LOG(D_ALWAYS, ("trc_create: trc: 0x%lx", trc)); NdisZeroMemory(trc, sizeof(*trc)); /* allocate buffer memory */ NdisAllocateMemory((PVOID*)&trc->ent_tbl, sizeof(TRC_ENTRY) * depth, 0, pa); if ( !trc->ent_tbl ) goto mem_alloc_failed; D_LOG(D_ALWAYS, ("trc_create: trc->ent_tbl: 0x%lx", trc->ent_tbl)); NdisZeroMemory(trc->ent_tbl, sizeof(TRC_ENTRY) * depth); /* setup initial field values */ trc->stat.state = TRC_ST_STOP; trc->stat.filter = TRC_FT_NONE; trc->stat.depth = depth; /* return succ */ *ret_trc = trc; return(TRC_E_SUCC); } /* delte a trace object */ INT trc_destroy(VOID *trc_1) { TRC *trc = (TRC*)trc_1; D_LOG(D_ENTRY, ("trc_destroy: entry, trc: 0x%lx", trc)); /* free memory */ NdisFreeMemory(trc->ent_tbl, sizeof(TRC_ENTRY) * trc->stat.depth, 0); NdisFreeMemory(trc, sizeof(*trc), 0); return(TRC_E_SUCC); } /* perform a trace control function */ INT trc_control(VOID *idd, ULONG op, ULONG arg) { IDD_MSG msg; TRC *trc; INT ret; trc = idd_get_trc(idd); D_LOG(D_ENTRY, ("trc_control: idd: 0x%lx trc: 0x%lx, op: 0x%x, arg: 0x%x", idd, trc, op, arg)); /* branch on opcode */ switch ( op ) { case TRC_OP_CREATE: D_LOG(D_ENTRY, ("trc_control: CreateTrace")); // if no trace object for this idd yet if (trc == NULL) { //create trace object if ((ret = trc_create(&trc, arg)) != TRC_E_SUCC) return(TRC_E_IDD); // register trace for this idd if ((ret = trc_register_idd (idd)) != TRC_E_SUCC) { trc_destroy(trc); return(TRC_E_IDD); } idd_set_trc (idd, trc); // set ref count trc->create_ref = 0; // set backpointer trc->idd = idd; } // inc ref count trc->create_ref++; break; case TRC_OP_DESTROY: D_LOG(D_ENTRY, ("trc_control: DestroyTrace")); // if trc == NULL break; CheckNULLTrace (trc); // dec ref count if (--trc->create_ref) break; trc_deregister_idd(idd); trc_destroy(trc); idd_set_trc(idd, NULL); break; case TRC_OP_RESET : D_LOG(D_ENTRY, ("trc_control: ResetTrace")); // if trc == NULL break; CheckNULLTrace (trc); trc->stat.state = TRC_ST_STOP; trc->stat.entries = trc->stat.seq_1st = 0; trc->ent_put = trc->ent_get = trc->ent_num = trc->ent_seq = 0; break; case TRC_OP_STOP : D_LOG(D_ENTRY, ("trc_control: StopTrace")); // if trc == NULL break; CheckNULLTrace (trc); // check start flag if (--trc->start_ref) break; trc->stat.state = TRC_ST_STOP; /* issue idd command to stop trace */ NdisZeroMemory(&msg, sizeof(msg)); msg.opcode = CMD_TRC_OFF; if ( idd_send_msg((VOID*)arg, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) return(TRC_E_IDD); break; case TRC_OP_START : D_LOG(D_ENTRY, ("trc_control: StartTrace")); // if trc == NULL break; CheckNULLTrace (trc); trc->stat.state = TRC_ST_RUN; // check start flag if (trc->start_ref++) break; /* issue idd command to start trace */ NdisZeroMemory(&msg, sizeof(msg)); msg.opcode = CMD_TRC_ON; if ( idd_send_msg((VOID*)arg, &msg, IDD_PORT_CMD_TX, NULL, NULL) != IDD_E_SUCC ) return(TRC_E_IDD); break; case TRC_OP_SET_FILTER : D_LOG(D_ENTRY, ("trc_control: SetTraceFilter")); // if trc == NULL break; CheckNULLTrace (trc); trc->stat.filter = arg; break; default : return(TRC_E_PARAM); } /* if here, was successful */ return(TRC_E_SUCC); } /* get status of a trace context */ INT trc_get_status(VOID *trc_1, TRC_STATUS *stat) { TRC *trc = (TRC*)trc_1; D_LOG(D_ENTRY, ("trc_get_status: entry, trc: 0x%lx, stat: 0x%lx", trc, stat)); // if no obect exit if (trc == NULL) return (TRC_E_NOSUCH); *stat = trc->stat; stat->entries = trc->ent_num; stat->seq_1st = trc->ent_seq; return(TRC_E_SUCC); } /* get an entry by sequence number */ INT trc_get_entry(VOID *trc_1, ULONG seq, TRC_ENTRY *ent) { TRC *trc = (TRC*)trc_1; ULONG n, index; D_LOG(D_ENTRY, ("trc_get_entry: entry, trc: 0x%lx, seq: %ld, ent: 0x%lx", \ trc, seq, ent)); // if no obect exit if (trc == NULL) return(TRC_E_NOSUCH); /* find requested sequence number, temp!!!, using search! */ for ( n = 0 ; n < trc->ent_num ; n++ ) { index = (trc->ent_get + n) % trc->stat.depth; if ( trc->ent_tbl[index].seq == seq ) { /* found */ *ent = trc->ent_tbl[index]; return(TRC_E_SUCC); } } /* if here not found */ return(TRC_E_NOSUCH); } /* handler for trace and dump area data packets */ VOID trc__cmd_handler(VOID *idd_1, USHORT chan, ULONG Reserved, IDD_MSG *msg) { TRC *trc; TRC_ENTRY *ent; IDD *idd = (IDD*)idd_1; D_LOG(D_ENTRY, ("trc__cmd_handler: idd: %lx, chan: %d, msg: %lx", \ idd, chan, msg)); D_LOG(D_ENTRY, ("trc__cmd_handler: opcode: 0x%x, buflen: 0x%x, bufptr: %lx", \ msg->opcode, msg->buflen, msg->bufptr)); D_LOG(D_ENTRY, ("trc__cmd_handler: bufid: %lx, param: 0x%x", \ msg->bufid, msg->param)); // Get the trace object for this idd trc = idd_get_trc(idd); // if no obect exit if (trc == NULL || msg->bufid >= 2) return; /* if here it is a trace frame. param is rx/tx attribute */ /* establish entry to insert into & update vars */ /* check if trace enabled */ if ( trc->stat.state == TRC_ST_STOP ) return; D_LOG(D_ALWAYS, ("trc__cmd_handler: trc: %lx", trc)); /* check if frame filters in */ if ( !trc__filter(trc->stat.filter, msg->bufptr, msg->buflen) ) return; /* frames needs to be buffered, establish entry pointer */ ent = trc->ent_tbl + trc->ent_put; trc->ent_put = (trc->ent_put + 1) % trc->stat.depth; if ( trc->ent_num < trc->stat.depth ) trc->ent_num++; /* fill up entry */ ent->seq = trc->ent_seq++; KeQuerySystemTime(&ent->time_stamp); ent->attr = msg->bufid; ent->org_len = msg->buflen; ent->len = MIN(msg->buflen, sizeof(ent->data)); IddGetDataFromAdapter(idd, (PUCHAR)ent->data, (PUCHAR)msg->bufptr, (USHORT)ent->len); // NdisMoveMemory (ent->data, msg->bufptr, ent->len); } /* filter trace frame */ INT trc__filter(ULONG filter, CHAR *buf, ULONG len) { D_LOG(D_ENTRY, ("trc__filter: entry, filter: %ld, buf: 0x%lx, len: %ld",\ filter, buf, len)); /* not implemented, all frames filter in */ return(1); }