- Following is a copy of the source code for vpddemo:
/**********************************************************************
**
** PROPRIETARY NOTICE
**
** Copyright (c) 1996,1997
** By Natural MicroSystems
**
**
** The following is licensed program material and is considered
** proprietary and confidential. No part of this program can be
** reproduced or used in any form or by any means without the
** express written permission of Natural MicroSystems.
**
*******************************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "txcpi.h"
#include "vpdapi.h"
/* global Dual Port Ram packet for general use */
CPIPKT global_pkt;
TXVPD_DPR_REQ *g_req = (TXVPD_DPR_REQ *)&global_pkt;
TXVPD_DPR_RSP *g_rsp = (TXVPD_DPR_RSP *)&global_pkt;
TX_HANDLE handle; /* handle associated with attach */
/* example transmit description structure */
typedef struct __txdesc
{
unsigned long usecount;
} TXDESC;
/* example attach control structure */
typedef struct __atchctl
{
unsigned char attached; /* TRUE = successfully attached */
unsigned char avail;
unsigned long cpctl; /* CP control key received on attach response */
} ATCHCTL;
ATCHCTL attach;
unsigned long txsucc = 0; /* count of successful TXs */
unsigned long rxsucc = 0; /* count of receive notifications */
/* ----- command line parameters */
short chan = 17; /* default channel to listen on */
unsigned short vport = 1; /* virtual port to attach to */
unsigned char msgtrc = 1; /* message trace level */
unsigned short datalen = 32; /* data length of spewed data */
unsigned char baseaddr = 1; /* base address [2nd byte of frame] */
unsigned char board = 1; /* board number to attach to */
char *vpdmsgname[] =
{
"0",
"DEFINE", /* 0x01 - TxVpdDefine */
"DESTROY", /* 0x02 - TxVpdDestroy */
"CONFIG", /* 0x03 - TxVpdConfig */
"VPORT", /* 0x04 - TxVpdVport */
"MVIPCFG", /* 0x05 - TxVpdMvipCfg */
"T1E1CFG", /* 0x06 - TxVpdT1E1Cfg */
"ATTACH", /* 0x07 - TxVpdAttach */
"DETACH", /* 0x08 - TxVpdDetach */
"REGSIGS", /* 0x09 - TxVpdRegsigs */
"VPSTATS", /* 0x0A - TxVpdVpstats */
"CLRSTATS", /* 0x0B - TxVpdClrstats */
"ENABLE", /* 0x0C - TxVpdEnable */
"DISABLE", /* 0x0D - TxVpdDisable */
"TX", /* 0x0E - TxVpdTx */
"RX", /* 0x0F - receive notif */
"enough room to sprintf the unknown msg number"
};
/*################################################################
* General Internal Functions:
###############################################################*/
/*****************************************************************************
* usage - display usage help
*****************************************************************************/
void usage()
{
printf("\n");
printf(" usage: vpddemo -c <DPR channel to use> [DEF:17]\n");
printf(" -b <board number to attach to> [DEF:1]\n");
printf(" -v <vport # to attach to> [DEF:1]\n");
printf(" -a <address byte> [DEF:1]\n");
printf(" -l <length of spew data> [DEF:32]\n");
printf(" -t <msg trace level> [DEF:1]\n");
printf(" 0:quiet, 1:no TX/no RX, 2:all TX/RX\n");
printf(" -? Show Usage\n");
printf("\n");
}
/*****************************************************************************
* MsgName
*****************************************************************************/
char *MsgName( unsigned char msgnum )
{
if (msgnum <= TXVPD_DPR_RX)
return( vpdmsgname[msgnum] );
else
{
sprintf( vpdmsgname[TXVPD_DPR_RX + 1], "Unknown Msg #%d", msgnum );
return( vpdmsgname[TXVPD_DPR_RX + 1] );
}
}
/*****************************************************************************
* VerifyCtl
*****************************************************************************/
unsigned char VerifyCtl( ATCHCTL *ctl )
{
if (ctl != &attach)
{
printf( "!!! Received packet did not reference valid CTL !!!\n" );
return( FALSE );
}
else
return( TRUE );
}
*****************************************************************************
* TraceRX
*****************************************************************************/
void TraceRX( TXVPD_DPR_RSP *rsp, ATCHCTL *ctl )
{
short i;
unsigned char *dprdata = (unsigned char *)&rsp->data;
char outLine[256];
char asciidata[16+2];
char hexdata[3*16+2];
char next_hex[3+2];
char statuscode[16];
TXVPD_DPR_REQ *req;
if ( (msgtrc < 2) &&
((rsp->rsp.msg.msgnum == TXVPD_DPR_RX) || (rsp->rsp.msg.msgnum == TXVPD_DPR_TX)) )
return; /* do not trace received frames or tx complete notifs
* (unless msg trace level high enough) */
/* ----- create ASCII log message describing packet just received */
if (msgtrc != 0)
{ /* not running in quiet mode so trace all received packets */
hexdata[0] = 0;
for( i = 0; ( (i < (rsp->rsp.hdr.len - sizeof(TX_DPR_REQHDR))) && (i < 16) ); i++ )
{
sprintf( next_hex, "%02X ", (unsigned short)dprdata[i] );
strcat( hexdata, next_hex );
if ( (dprdata[i] < ' ') || (dprdata[i] > '}') )
asciidata[i] = '.';
else
asciidata[i] = (char)dprdata[i];
}
asciidata[i] = 0;
statuscode[0] = 0;
if (rsp->rsp.msg.msgtype == TXMSG_RESULT)
sprintf( statuscode, "{$%X}", rsp->rsp.status );
sprintf( outLine, "RX (%d:%d-%d:%d l:%d) [%ld] %c%c-%s %s [%s| %s]\n",
rsp->rsp.hdr.srcchan, rsp->rsp.hdr.srcboard, /* source */
rsp->rsp.hdr.dstchan, rsp->rsp.hdr.dstboard, /* dest */
rsp->rsp.hdr.len, /* total length */
rsp->rsp.msg.msgid, /* seq # */
rsp->rsp.msg.msgdir, rsp->rsp.msg.msgtype, /* msg direction and type*/
MsgName( rsp->rsp.msg.msgnum ), /* msg name */
statuscode, /* result (if response) */
hexdata, asciidata ); /* data beyond msg hdr */
printf(outLine);
}
}
/*****************************************************************************
* TraceTX
*****************************************************************************/
void TraceTX( TXVPD_DPR_REQ *req )
{
short i;
unsigned char *dprdata = (unsigned char *)&req->data;
char outLine[256];
char asciidata[16+2];
char hexdata[3*16+2];
char next_hex[3+2];
/* ----- create ASCII log message describing packet just received */
if (msgtrc != 0)
{ /* not running in quiet mode so trace all transmitted packets */
hexdata[0] = 0;
for( i = 0; ( (i < (req->req.hdr.len - sizeof(TX_DPR_REQHDR))) && (i < 16) ); i++ )
{
sprintf( next_hex, "%02X ", (unsigned short)dprdata[i] );
strcat( hexdata, next_hex );
if ( (dprdata[i] < ' ') || (dprdata[i] > '}') )
asciidata[i] = '.';
else
asciidata[i] = (char)dprdata[i];
}
asciidata[i] = 0;
sprintf( outLine, "TX (%d:%d-%d:%d l:%d) [%ld] %c%c-%s [%s| %s]\n",
req->req.hdr.srcchan, req->req.hdr.srcboard,/* source */
req->req.hdr.dstchan, req->req.hdr.dstboard,/* dest */
req->req.hdr.len, /* total length */
req->req.msg.msgid, /* seq # */
req->req.msg.msgdir, req->req.msg.msgtype, /* msg direction/type */
MsgName( req->req.msg.msgnum ), /* msg name */
hexdata, asciidata ); /* data beyond msg hdr*/
printf(outLine);
}
}
/*****************************************************************************
* TxVport - attempt to TX frame through vport (report errors)
*****************************************************************************/
short TxVport( unsigned short datalen, ATCHCTL *ctl, TXVPD_DPR_REQ *req )
{
short status;
unsigned short i,j;
status = TxVpdTx( handle, datalen, ctl, ctl->cpctl, req );
if (status == 0)
{
if (msgtrc > 1)
TraceTX( req ); /* trace TX only if msgtrc indicates repeat tracing */
}
else
printf( "Failed TxVpdTx [%s]\n", TxVpdErrorStr( status ) );
return( status );
}
/*################################################################
* Received Message Handling Function:
*##############################################################*/
/*****************************************************************************
* RxMsg - function called whenever Dual Port Ram packet received
*
* This routine handles all received vport packets.
* These packets are either responses to requests issued by vpddemo
* or notifications of received data frames.
*****************************************************************************/
short RxMsg(short rxlen)
{
short status = 0;
ATCHCTL *ctl;
TXVPD_DPR_REQ *req;
if (g_rsp->rsp.msg.msgtype == TXMSG_RESULT)
ctl = (ATCHCTL *)g_rsp->data.u.vpid.vpdatchkey; /* get back our attach cntrl struct */
else /* assume NOTIF */
ctl = (ATCHCTL *)g_req->data.u.vpid.vpdatchkey; /* get attach control struct (RX) */
if (VerifyCtl( ctl ) == FALSE)
return( 1 ); /* get out if not our CTL */
TraceRX( g_rsp, ctl ); /* trace packet just received */
/* ----- handle based on type of packet received */
if (g_rsp->rsp.msg.msgtype == TXMSG_RESULT)
{ /* result received */
if (g_rsp->rsp.status != 0)
{ /* failed response */
switch (g_rsp->rsp.msg.msgnum)
{ /* handle error based on type */
case TXVPD_DPR_ATTACH:
case TXVPD_DPR_DISABLE:
case TXVPD_DPR_DETACH:
case TXVPD_DPR_ENABLE:
case TXVPD_DPR_TX:
return( 1 ); /* for demo, treat all fails the same */
break;
} /* END: handle error based on type */
}
else
{ /* handle successful responses based on type of request */
switch (g_rsp->rsp.msg.msgnum)
{ /* handle by type */
case TXVPD_DPR_ATTACH:
ctl->attached = TRUE; /* remember for graceful shutdown */
ctl->cpctl = g_rsp->data.u.vpid.vpdcpctl; /* remember attach key assigned by CP */
status = TxVpdEnable( handle, ctl, ctl->cpctl, g_req );
if (status == 0)
TraceTX( g_req );
else
{
printf( "Failed TxVpdEnable [%s]\n", TxVpdErrorStr( status ) );
return( 1 );
}
break;
case TXVPD_DPR_ENABLE:
memset( g_req->data.u.data.vpddata, baseaddr, datalen );
g_req->req.msg.msgkey = (unsigned long)g_req; /* so rsp identifies req pkt */
printf( "Starting to TX [%d byte frames filled with $%X]\n",
datalen, (unsigned short)baseaddr );
status = TxVport( datalen, ctl, g_req );
break;
case TXVPD_DPR_DISABLE:
status = TxVpdDetach( handle, ctl, ctl->cpctl, g_req );
if (status == 0)
TraceTX( g_req );
else
{
printf( "Failed TxVpdDetach [%s]\n", TxVpdErrorStr( status ) );
return( 1 );
}
break;
case TXVPD_DPR_DETACH:
return( 1 ); /* return non-zero to force exit from dispatch loop */
break;
case TXVPD_DPR_TX:
req = (TXVPD_DPR_REQ *)g_rsp->rsp.msg.msgkey; /* original request */
if (req != g_req)
{
printf( "Error: TX response notif msgkey wrong!\n" );
return( 1 );
}
else
{
txsucc++;
if ((txsucc/100)*100 == txsucc)
printf( "Transmitted %ld frames so far\n", txsucc );
}
TxVport( datalen, ctl, g_req );
break;
} /* END: handle by type */
} /* END: handle successful responses based on type of request */
} /* END: result received */
else if (g_rsp->rsp.msg.msgtype == TXMSG_NOTIF)
{ /* receive notification received */
rxsucc++;
if ((rxsucc/100)*100 == rxsucc)
printf( "Received %ld frames so far\n", rxsucc );
}
return ( status );
}
/*################################################################
* MAIN Routine:
*###############################################################*/
/*****************************************************************************
* main
*****************************************************************************/
main(argc, argv)
int argc;
char *argv[];
{
long cps[MAXBOARD + 1];
short i,j;
char *str = NULL;
char sbuf[CPSTRSIZE];
char *vstr = sbuf; /* dummy for old cpi_init */
short port;
short status;
short rxlen;
printf("\n");
printf("Virtual Port Demo Application V1.0\n");
printf("Copyright 1996-7, Natural MicroSystems\n");
printf("\n");
/* ----- parse command line */
i = 1;
while (i < argc)
{
str = argv[i];
if (*str == '-')
{
switch (*++str)
{
case 'c': /* which channel should we listen on? */
case 'C':
if (isdigit(*(str + 1)))
{
chan = atoi(++str);
}
else
{
i++;
chan = atoi(argv[i]);
}
break;
case 'a': /* what base address should be used? */
case 'A':
if (isdigit(*(str + 1)))
{
baseaddr = atoi(++str);
}
else
{
i++;
baseaddr = atoi(argv[i]);
}
break;
case 'b': /* which board should we attach to? */
case 'B':
if (isdigit(*(str + 1)))
{
board = atoi(++str);
}
else
{
i++;
board = atoi(argv[i]);
}
break;
case 'v': /* what virtual port should we attach to? */
case 'V':
if (isdigit(*(str + 1)))
{
vport = atoi(++str);
}
else
{
i++;
vport = atoi(argv[i]);
}
break;
case 't': /* what message trace level should be used? */
case 'T':
if (isdigit(*(str + 1)))
{
msgtrc = (unsigned char)atoi(++str);
}
else
{
i++;
msgtrc = (unsigned char)atoi(argv[i]);
}
TxVpdControl( msgtrc );
break;
case 'l': /* what data length should be spewed? */
case 'L':
if (isdigit(*(str + 1)))
{
datalen = atoi(++str);
}
else
{
i++;
datalen = atoi(argv[i]);
}
if (datalen == 0)
datalen = 32;
break;
default:
usage(TRUE);
exit(1);
}
}
++i;
}
if (chan < 1)
{
usage(TRUE);
exit(1);
}
/* ----- initialize CPI library connection */
cpi_init(0, &vstr);
cpi_get_resources(MAXBOARD, cps);
if ( (board > MAXBOARD) || (cps[board] == 0) )
{
printf( "Board #%d not present!\n", (short)board );
exit(1);
}
/* ----- setup for receiving */
port = PORT(board,chan);
handle = cpi_open(port, CPIM_PORT, NULL);
if (handle == CPI_INVALID_HANDLE)
{
printf( "Error: could not open driver [%s]\n", TxVpdErrorStr((short)cpi_get_last_error()));
exit(1);
}
/* ----- attach to VPORT */
attach.attached = FALSE;
status = TxVpdAttach( handle, vport, &attach, g_req );
if (status == 0)
TraceTX( g_req );
else
{
printf( "Failed TxVpdAttach [%s]\n", TxVpdErrorStr( status ) );
exit(1);
}
/* ----- enter main dispatch loop */
status = 0; /* no errors/timeout yet */
while (status == 0)
{
rxlen = sizeof( CPIPKT ); /* set size of buffer we can receive */
status = cpi_wait_msg( handle, &global_pkt, &rxlen, 5000); /* wait for msg (5 secs max) */
if (status != 0)
printf( "Error: cpi_wait_msg [%s]\n", TxVpdErrorStr((short)cpi_get_last_error()));
else
status = RxMsg( rxlen ); /* handle received message */
}
/* ----- disable VPORT (triggering DETACH on response) */
if (attach.attached == FALSE)
{
cpi_close( handle ); /* not attached so just close and get out */
exit(1);
}
status = TxVpdDisable( handle, &attach, attach.cpctl, g_req );
if (status == 0)
TraceTX( g_req );
else
{
printf( "Failed TxVpdDisable [%s]\n", TxVpdErrorStr( status ) );
exit(1);
}
/* ----- wait for disable (and detach) to complete */
while (status == 0)
{
rxlen = sizeof( CPIPKT ); /* set size of buffer we can receive */
status = cpi_wait_msg( handle, &global_pkt, &rxlen, 5000); /* wait for msg (5 secs max) */
if (status != 0)
printf( "Error: cpi_wait_msg [%s]\n", TxVpdErrorStr((short)cpi_get_last_error()));
else
status = RxMsg( rxlen ); /* handle received message */
}
/* ----- close CPI handles */
cpi_close( handle );
return (0);
}