summaryrefslogblamecommitdiffstats
path: root/private/ntos/ndis/digi/pcimac/trc_core.c
blob: 4c802ec8cb14c958b7b4e3643422cb89113fd053 (plain) (tree)




































































































































































































































































































































































                                                                                                        
/*
 * TRC_CORE.C - trace core module
 */

#include	<ndis.h>
#include	<ndiswan.h>
#include	<mydefs.h>
#include	<mytypes.h>
#include	<util.h>
#include	<opcodes.h>
#include	<adapter.h>
#include	<idd.h>
#include	<mtl.h>
#include	<cm.h>
#include	<trc.h>
#include	<disp.h>

/* 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);
}