Table of Contents NMS Glossary Previous Page Next Page Version


Chapter 7

Demonstration Program


7.1 Description
7.2 Virtual Port Configuration
7.3 Functions
7.3.1 main
7.3.2 RxMsg
7.3.3 TxVport
7.3.4 TraceRX, TraceTX
7.3.5 VerifyCtl
7.3.6 MsgName
7.3.7 usage
7.4 Source Code

7.1 DescriptionTop of Page

The example application (vpddemo) opens a dual port RAM channel using the CPI library cpi_open function and issues an ATTACH of the virtual port number indicated on the command line. If the ATTACH succeeds, vpddemo issues an ENABLE. Once the ENABLE succeeds, vpddemo issues a TX of the size and content indicated on the command line. Every time the TX completion is received, the TX is re-issued.

All frames that vpddemo receives are counted but mean nothing to the application.

Any time an even multiple of 100 successful transmits or 100 receives is reached, an output line displays.

7.2 Virtual Port ConfigurationTop of Page

The file vpd.cfg (included with the demo source code) can be used to define 3 virtual ports mapped to resources assigned to the physical SCCs that lead out the serial daughter board.

Modifying the resource definitions to map to time division multiplexed (TDM) streams [over the MVIP bus] causes the same virtual ports to pass data over MVIP instead of out the physical SCC ports.

7.3 FunctionsTop of Page

This section provides a brief description of each function found in the demonstration program.

7.3.1 mainTop of Page

This function parses the command line, opens the dual port RAM channel used to communicate with the $vpd task on the communication processor, and issues an ATTACH request for the virtual port indicated on the command line.

7.3.2 RxMsgTop of Page

This function is called for each frame received over the dual port RAM channel. Received frames include responses to requests issued by the demonstration program and any data frames received over the virtual port.

7.3.3 TxVportTop of Page

This function issues a transmit request for a data frame.

7.3.4 TraceRX, TraceTXTop of Page

These functions produce a trace line (to standard out) that breaks down the request/response. Use command line option: -t 0 to turn this tracing off (or -t 2 to display trace lines for all data requests/responses).

7.3.5 VerifyCtlTop of Page

This function performs a quick verification that the key provided in a response packet (or receive notification packet) is the key that was passed by the demonstration program when the ATTACH was issued. It is good programming practice to verify any pointer received from an external source before using that pointer.

7.3.6 MsgNameTop of Page

This function returns the ASCII name of the message indicated by the packet passed to it. This name is used to produce the trace lines (see Section 7.3.4, TraceRX, TraceTX).

7.3.7 usageTop of Page

Displays the optional parameters of the vpddemo demonstration program.

7.4 Source CodeTop of Page

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


Table of Contents NMS Glossary Previous Page Next Page Version


Want to send us feedback on our documentation? Email: Tech_Pubs@nmss.com
Copyright © 2000, Natural MicroSystems, Inc. All rights reserved.