| While the example program ran fine on our test system the customer could not get it to
work on thier system. They added a few mods to the example so that it would be closer to
the way they use their application used the shared destination. They were using a 8400
and a 7610. I'll include the final test code. But basically it ran fine on our Alpha
2100 with three nodes sending to the receiver process.
After we sent the customer Alpsys05_070 and Alplan04_062 the customers problem was
resolved. I do not know which ECO actually fixed the problem.
/***********************************************************************
COPYRIGHT (C) 1994 BY
DIGITAL EQUIPMENT CORPORATION, MAYNARD
MASSACHUSETTS. ALL RIGHTS RESERVED.
THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
TRANSFERRED.
THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
CORPORATION.
DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE ON
EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL EQUIPMENT CORPORATION.
SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY DIGITAL SOFTWARE
PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE
CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED.
------------------------------------------------------------------
name: ping
purpose: exercise ETHERNET/FDDI driver send and receive with shared
destination address.
inputs: ping p1 p2
where p1 - "PONG", post read AST and wait
"PING", send ASTBLKCNT packets, then sleep
p2 - ethernet device name (ie FXA0, XEB0 , EWA0 )
Define a symbol to run the program
$ping == "$v5user:[wing]ping.exe"
$ping PING XEB0 (invoke PONG process on node with CSMA/CD media)
$ping PONG FXA0 (invoke PING process on node with FDDI media)
Change the array's xmtdestaddr[6] and rcvdestaddr[6] to the correct
destination address for the transmitting and receiving node then compile.
If the controller is a FDDI then use the hardware address. If the controller
is an ethernet and DECnet has been started then use the MAC address otherwise
if DECnet has not been started on that controller then use the hardware
address.
Compiling instructions
For Alpha's
Compile: $ cc/standard=vaxc/nomember_align ping
Link: $ link ping
For Vaxes
Compile: $ cc/standard=vaxc ping
Link: $ link ping
environment - protocol type (PTY) 22-00 being used
***********************************************************************/
#include descrip
#include iodef
#include "nmadef"
#include ssdef
#include time
#include "sys$login:xmdef"
/* DATA TYPES */
/* the 8-bit types */
typedef unsigned char TEXT;
typedef unsigned char BYTE;
typedef char CHAR;
/* the 16-bit types */
typedef unsigned short WORD;
typedef short SHORT;
typedef short METACH;
/* the 32-bit types */
typedef int FILED;
typedef unsigned long LWORD;
typedef unsigned long POINTER;
typedef long LONG;
typedef int BOOL;
typedef int VOID;
/* other data types */
typedef unsigned BITS;
typedef double DOUBLE;
#define STRUCT struct
#define STRUCTURE struct
#define UNION union
/* declare */
#define SHARE const
#define NOSHARE noshare
#define ASTBLKCNT 50
/* reference */
#define EXTERN extern noshare
#define IMPORT extern const
/* module */
#define LOCAL static
#define READONLY static const
/* other */
#define FAST register
#define TRUE 1
#define FALSE 0
#define TRANSMITTER_COUNT 3
/*
--- Flags documented in I/O User's Guide: Part II; Page 6-33.
/*
--- declare iosb-structures following here, instead of in "invedef.h"
--- to use our local definition of an iosb-structure
*/
#pragma nomember_alignment
STRUCT setp
{
WORD bus; /* max rcv buffer size */
LONG buflen;
WORD bfn; /* # rcv buffers */
LONG bufnum;
WORD prm; /* promiscuous mode */
LONG prmstate;
WORD pad; /* pad state */
LONG padstate;
WORD crc; /* crc state */
LONG crcstate;
WORD pty; /* protocol type */
LONG entype;
WORD con; /* controller mode */
LONG constate;
WORD restart; /* restart channel on controller error */
LONG restart_enable;
/* additions for shared dest mode */
WORD access_mode;
LONG access_mode_type;
WORD shared_dest;
WORD des_size;
WORD set_clr;
BYTE add01;
BYTE add02;
BYTE add03;
BYTE add04;
BYTE add05;
BYTE add06;
};
/*
The destination address of the transmitting node used by
the receiving node's set mode qio. The receiving node
is started with PONG as a P1 paramater.
*/
BYTE xmtdestadd[TRANSMITTER_COUNT][6]={
{0x08,0x00,0x2b,0XA3,0x5c,0x49}, /* Nsabl1 */
{0xAA,0x00,0x04,0X00,0xCD,0xDC}, /* nmstang */
{0x08,0x00,0x2b,0XA3,0xAC,0x4A} /* VS4090 */
};
/*
The destination address of the receiving node used by
the transmitting nodes set mode qio. The receiving node
is started with PING as a P1 paramater.
*/
BYTE rcvdestadd[6]={0xAA,0x00,0x04,0X00,0x90,0xDD}; /* nsable */
/* ethernet frame */
STRUCT en_hdr { /* Ethernet Frame Header*/
BYTE dest[6]; /* Destination station */
BYTE source[6]; /* Source station */
WORD type; /* Ethernet type */
};
#define MAX_ETHER_FRAME 1514
#define MIN_ETHER_FRAME 60
#define ETHER_HDR_SIZE (sizeof (STRUCT en_hdr))
STRUCT frame_data_def
{
int seqnum;
BYTE ef_body[1496]; /*frame body*/
};
STRUCT en_frame
{
STRUCT en_hdr ef_header; /*frame header*/
STRUCT frame_data_def frame_data; /*frame data*/
};
STRUCT iosb
{
WORD w0, w1, w2, w3; /* 4 words in an io status block */
};
int sequence;
LOCAL STRUCT iosb xmtiosb = 0; /* xmt iosb */
LOCAL STRUCT iosb rcviosb[ASTBLKCNT]; /* rcv iosb */
LOCAL STRUCT en_frame tst_frame[ASTBLKCNT-1];
LOCAL STRUCT dp
{
BYTE dp_enaddr[6]; /*destination ethernet address*/
WORD dp_entype; /*destination port ethernet type*/
} destport; /*destination header */
LOCAL LONG vmschan[TRANSMITTER_COUNT];
int ping, i; /* ping = *argv[1] == '1' */
int frame_size;
/* declare rcv_ast function */
LOCAL VOID ast_rc( LWORD i );
/*****************************/
/*****--- Start of main () ----*******/
main( int argc, char *argv[] )
{
LONG status, bintime;
if (argc < 3)
{
printf( "missing p1 p2 (see source)\n" );
exit(0);
}
/* if ping process, ping = true */
ping = (strcmp( argv[1], "PING" ) == 0 ||
strcmp( argv[1], "ping" ) == 0); /* true if PING */
/* call IO$_SETMODE for transmitter process (PING MODE) */
if (ping) /* printf */
{
printf ("Value of Ping = %d\n",ping);
while (!attachnet( argv[2], rcvdestadd, 0 ))
sleep(5); /* try every minute until success */
}
/* call IO$_SETMODE for receiver process (PONG mode) */
if (!ping) /* printf */
{
printf ("Value of Ping = %d\n",ping);
for (i = 0; i < TRANSMITTER_COUNT; i++)
while (!attachnet( argv[2], xmtdestadd[i], i ))
sleep(5); /* try every minute until success */
}
/********************************************************************
NOTE:
Normally we would set the destination address and protocol type
for the transmit packet now. But with a Shared Destination
protocol this is not not required. The protocol type and
destination are set up during the IO$_SETMODE. All packets
transmitted on that channel will use the destination address and
protocol type passed on the IO$_SETMODE.
**********************************************************************/
sequence = 0;
/* Send 10 packets in row, then sleep for 5 seconds */
while (ping)
{
for (i=0; i<10; i++) {
sequence = sequence + 1;
tst_frame[0].frame_data.seqnum = sequence;
if (sequence&1)
frame_size = 1400;
else
frame_size = 46;
status = SYS$QIOW ( 0, vmschan[0], IO$_WRITEVBLK, &xmtiosb, 0,0,
&tst_frame[0].frame_data,
frame_size, 0,
0, &destport, 0 );
printf ("$QIO Write Status = %d\n",status);
printf(" IOSB w0:%d w1:%d w2:%d w3:%d\n",xmtiosb.w0,
xmtiosb.w1, xmtiosb.w2, xmtiosb.w3);
if (status != SS$_NORMAL || xmtiosb.w0 != SS$_NORMAL)
printf( "unable write, status %d/%d\n", status, xmtiosb.w0 );
else
printf( "Sequence # %d Sent, Size = %d bytes\n",
sequence,frame_size);
}
/* remove the sleep(5) to pound the receiver with packets */
/* sleep(5); */
} /* while ping forever */
/* receive side code , p1=pong */
while (!ping) /* pong means the receiving node */
{
for (i = 0; i < TRANSMITTER_COUNT; i++)
{
status = SYS$QIO ( 0, vmschan[i], IO$_READVBLK,
&rcviosb[i], ast_rc, i,
&tst_frame[i].frame_data, 1500, 0,
0, &tst_frame[i].ef_header, 0 );
printf ("AST # %d Posted\n",i);
if (status != SS$_NORMAL)
printf( "unable post read, status %d\n", status );
}
SYS$HIBER();
} /* end while pong forever */
} /* end of main */
/******************************************************************************
name: attachnet - attach to ethernet
purpose attaches process to a particular Ethernet controller
inputs: . network id
. protocol type
. multicast flag
. sys_fail on error flag
. Destination address BYTE array
outputs: . attached controller
logic: . convert ethernet address logical name to ascii equivalent
. validate ethernet address
. convert ethernet address address to proper address format
. if dynamic duffers specified for ptype
. . set NRCVBFRS to specified value for ptype
. shutdown controller
. setup port parameters
. start up port
. verify port characteristics via read back
revision history: Modified to receive a destination address byte array
-------------------------------------------------------------------
*****************************************************************************/
LOCAL BOOL attachnet( TEXT *devnam_p, BYTE destadd[], int connection )
{
BYTE xchar[512]; /* extended characteristics */
int j;
STRUCT /* descriptor for extended characteristics */
{
LWORD xcharlen;
BYTE *pxchar;
} xchardsc = { sizeof xchar, xchar };
/* setp, controler parameter descriptor for set up */
STRUCT setp setparam =
{
NMA$C_PCLI_BUS, 1500,
NMA$C_PCLI_BFN, 50,
NMA$C_PCLI_PRM, NMA$C_STATE_OFF,
NMA$C_PCLI_PAD, NMA$C_STATE_OFF,
NMA$C_PCLI_CRC, NMA$C_STATE_ON,
NMA$C_PCLI_PTY, 0x0022,
NMA$C_PCLI_CON, NMA$C_LINCN_NOR,
NMA$C_PCLI_RES, NMA$C_LINRES_ENA,
/* SHARED DESINATION ADDITIONS */
NMA$C_PCLI_ACC, NMA$C_ACC_LIM,
NMA$C_PCLI_DES, 8,NMA$C_LINMC_SET,
destadd[0],
destadd[1],
destadd[2],
destadd[3],
destadd[4],
destadd[5],
};
STRUCT /* descriptor for parameter block */
{
LONG setparamlen; /* length of parameter block */
STRUCT setp *psetparam;/* address of parameter block */
} setpdsc = { sizeof setparam, &setparam };
BYTE devchar[8]; /* space for sense characterisitics */
LWORD status; /* vms status */
LWORD l;
TEXT buf[30];
LONG dsc[] = { sprintf ( buf, "%s", devnam_p ), buf };
printf (" - registering - \n");
printf ("Shared protocol address is: %02X-%02X-%02X-%02X-%02X-%02X\n\n",
destadd[0],destadd[1],destadd[2],
destadd[3],destadd[4],destadd[5] ) ;
/* assign channel */
status = SYS$ASSIGN(
dsc, &vmschan[connection], 0, 0 );
if (status != SS$_NORMAL)
{
/* fail if error */
printf( "unable sys$assign, status=%d\n", status );
return FALSE;
}
/* shutdown controller
status = SYS$QIOW ( 0, vmschan[connection], IO$_SETMODE | IO$M_CTRL | IO$M_SHUTDOWN,
&xmtiosb, 0, 0, 0, 0, 0, 0, 0, 0 );
if (status != SS$_NORMAL || xmtiosb.w0 != SS$_NORMAL)
{
printf( "unable CONTROLLER SHUTDOWN, status %d/%d\n",
status, xmtiosb.w0 );
return FALSE;
} */
status = SYS$QIOW ( 0, vmschan[connection], IO$_SETMODE | IO$M_CTRL | IO$M_STARTUP,
&xmtiosb, 0, 0, 0, &setpdsc, 0, 0, 0, 0 );
if (status != SS$_NORMAL || xmtiosb.w0 != SS$_NORMAL)
{
printf( "unable STARTUP/INITIALIZE CONTROLLER, status %d/%d\n",
status, xmtiosb.w0 );
printf ("IOSB %d %d %d\n",xmtiosb.w1,xmtiosb.w2,xmtiosb.w3);
return FALSE;
}
/* read back controller characteristics */
status = SYS$QIOW ( 0, vmschan[connection], IO$_SENSEMODE | IO$M_CTRL,
&xmtiosb, 0, 0, devchar, &xchardsc, 0, 0, 0, 0 );
if ( status != SS$_NORMAL || xmtiosb.w0 != SS$_NORMAL )
{
printf( "unable SENSE CONTROLLER MODE, status %d/%d\n",
status, xmtiosb.w0 );
return FALSE;
}
return TRUE;
} /* end of attachnet */
/**********************************************************************
name: rcv_ast Receive AST routine
purpose Called when a Ethernet packet is received
inputs: . Data index number of received packet
outputs: . Prints info form received packet
logic: . Called when packet is received print out information to
standard out from ethernet data packet. Also prints out
ethernet address of transmitting node.
/*------------------------------------------------------------------------*/
LOCAL VOID ast_rc( LWORD i )
{
LONG status, bintime;
/* check read completion, error summary, and unit & line statuses */
if (rcviosb[i].w0 != SS$_NORMAL ||
*((LWORD *)&rcviosb[i].w2) & XM$M_ERR_FATAL ||
*((LWORD *)&rcviosb[i].w2) & XM$M_ERR_LOST ||
*((LWORD *)&rcviosb[i].w2) & XM$M_STS_BUFFAIL ||
*((LWORD *)&rcviosb[i].w2) & XM$M_STS_TIMO)
{
printf( "Read AST #%d, status %d/%d/%d/%d \n", i,
rcviosb[i].w0, rcviosb[i].w1,
rcviosb[i].w2, rcviosb[i].w3);
}
else
{
printf ("Read AST # %d, Sequence # %d received, size=%d\n",
i, tst_frame[i].frame_data.seqnum,rcviosb[i].w1);
printf (" Destination node is: %02X-%02X-%02X-%02X-%02X-%02X",
tst_frame[i].ef_header.dest[0],
tst_frame[i].ef_header.dest[1],
tst_frame[i].ef_header.dest[2],
tst_frame[i].ef_header.dest[3],
tst_frame[i].ef_header.dest[4],
tst_frame[i].ef_header.dest[5]);
printf (" Source node is: %02X-%02X-%02X-%02X-%02X-%02X\n\n",
tst_frame[i].ef_header.source[0],
tst_frame[i].ef_header.source[1],
tst_frame[i].ef_header.source[2],
tst_frame[i].ef_header.source[3],
tst_frame[i].ef_header.source[4],
tst_frame[i].ef_header.source[5]);
rcviosb[i].w0 = 0;
rcviosb[i].w1 = 0;
rcviosb[i].w2 = 0;
rcviosb[i].w3 = 0;
status = SYS$QIO( 0, vmschan[i], IO$_READVBLK,
&rcviosb[i], ast_rc, i,
&tst_frame[i].frame_data, 1500, 0,
0, &tst_frame[i].ef_header, 0 );
printf ("AST # %d Posted\n",i);
if (status != SS$_NORMAL)
printf( "ast_rc - unable post read, status %d\n", status );
}
} /* end of ast_rc */
|