pkLib.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:68k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* pkLib.c - BSP PortKit Validation Suite support routines */
  2. /* Copyright 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02c,20jun02,jtp  evaluate config.h macros at runtime (SPR #78881).
  8. 02b,24jan02,pmr  using volatile declarations for for-loop-generated delays.
  9. 02a,22jan02,pmr  fixed non-ANSI compliant code in pkTimestampTestLong();
  10.  corrected use of NULL; fixed warnings.
  11. 01z,12dec01,pch  Don't use strncmp on binary data; make NvRam buffers global
  12.  to assist debugging.
  13. 01y,16oct99,sbs  corrected documentation.
  14. 01x,30sep99,sbs  changed pkUdpEchoT function arguments (SPR #27842).
  15.                  added pkCatastrophicTest and pkCatastrophicClean to fix
  16.                  problems with error2 test and wtxtcl (SPR #27822).
  17. 01w,23feb99,sbs  added pkPrintTest1 and made some changes to make
  18.                  VTS compatible with Tornado 2.0 (SPR #22425).
  19. 01v,22jul98,sbs  added htons() for port assignment in pkUdpEchoT().
  20.                  (SPR #20680)
  21. 01u,27may98,dat  removed ARM specific changes 01s and 01t.
  22. 01t,27apr98,cdp  make ARM pkTestNvRam buffers static to avoid stack overflow.
  23. 01s,09apr98,cdp  fix buffer alignment for ARM in pkTestNvRam.
  24. 01r,21oct97,db   fixed retrial of UDP packets in pkUdpEchoT().
  25. 01q,04sep97,sbs  added pkPrintSerialOutput, pkSerialTestInit, pkSerialTest
  26.                  and pkSerChanOutput.
  27. 01p,28aug97,sbs  addded pkBusErrorTest for error1 test and changed scsi
  28.                  routines to handle a larger buffer size.
  29. 01o,21aug97,db   renamed pkUdpEchoTest to pkUdpEchoT. added error handling.
  30. 01n,31jul97,db   included pingLib.h.
  31. 01m,19jul97,db   added pkTimestampTestShort and pkTimestampTestLong(timestamp
  32.  test), pkUdpEchoTest and pkPing (network test) and pkIntGet
  33.  and pkIntSet(busTas test). Removed conditional includes of
  34.  header files and macros.
  35. 01l,24jun97,sbs  added pkPrintTest() and pkDivideZeroTest() for serial line
  36.                  testing and divide by zero testing respectively.
  37. 01k,02jun97,sbs  changed sp() in pkLoopbackTest to taskSpawn().
  38. 01j,02aug96,mas  added support for BSP-specific TAS clear routine in busTas.
  39. 01i,15jun96,dat  changed calc of # scsi blks to avoid overflow.
  40. 01h,15feb96,dat  limited pkRead to less than 512K cycles.
  41.  Changed pkGetMacroValue to do a table walk.
  42. 01h,02dec93,dzb  added pkTimestampTest().
  43. 01g,05may93,dzb  combined pkGet<macro>()'s into pkGetMacroValue().
  44.                  integrated serial loopback and network udp echo tests.
  45.  added multiple serial loopback test.  ANSIfied.
  46.  added serial console echo test.  removed pkTasInit().
  47.  removed cache coherency code from busTas test.
  48.            +caf  wrote sequential serial loopback test.
  49.    +rfs  wrote pkUdpEchod().
  50. 01f,19feb93,dzb  doc fixes.  included additional header files.
  51.  added support for non-writeable nvram. fixed ANSI warnings.
  52.  added check for existing physical SCSI device.
  53.            +caf  changed VOID to void. changed READ to VX_READ. changed WRITE
  54.  to VX_WRITE. changed copyright notice. fixed ANSI warnings.
  55.  changed bitBucket from char to long in pkRead().
  56. 01d,30apr92,caf  added pkTestNvRam().
  57. 01c,07apr92,caf  don't #include header files when building documentation.
  58. 01b,31mar92,caf  added pkGet...() routines to read macros compiled into BSP.
  59.                  changed copyright notice. changed void to VOID.
  60.                  added routines for SCSI write/read/verify test.
  61.                  added routines for sysBusTas() test.
  62. 01a,01mar92,caf  written.
  63. */
  64. /*
  65. DESCRIPTION
  66. This library contains support routines for the BSP Developer's kit
  67. Validation Test Suite.
  68. This module should be copied in the BSP directory (with sysLib.c,
  69. config.h, etc.) and compiled by simply typing:
  70.     % make pkLib.o
  71. Alternatively, this module may be linked in with the VxWorks image during
  72. compilation.  This can be done by either adding "pkLib.o" to the MACH_EXTRA
  73. macro in the makefiles, or by including "ADDED_MODULES=pkLib.o" on the command
  74. line when building the VxWorks image.  This approach is necessary when using
  75. standalone ROMS without network initialization, as pkLib.o cannot be
  76. downloaded to the target during the tests.
  77. The object module will have a couple of unresolved references, which
  78. will be resolved by linking with VxWorks running on the target, or
  79. rebuilding the VxWorks image on the host to include this module.
  80. The routines contained in this library are called by the Expect scripts
  81. during the BSP tests.  They contain operations that cannot be executed
  82. directly from the shell by the scripts.
  83. */
  84. /* includes */
  85. #ifndef DOC
  86. #include "vxWorks.h"
  87. #include "vxLib.h"
  88. #include "ioLib.h"
  89. #include "taskLib.h"
  90. #include "sysLib.h"
  91. #include "cacheLib.h"
  92. #include "string.h"
  93. #include "stdio.h"
  94. #include "config.h"
  95. #include "usrLib.h"
  96. #include "sockLib.h"
  97. #include "logLib.h"
  98. #include "in.h"
  99. #include "intLib.h"
  100. #include "tickLib.h"
  101. #include "semLib.h"
  102. #include "wdLib.h"
  103. #include "pingLib.h"
  104. #include "selectLib.h"
  105. #include <sys/types.h>
  106. #include <sys/socket.h>
  107. #include <netinet/in.h>
  108. #include <time.h>
  109. #include <signal.h>
  110. /* header files used by timestamp test */
  111. #include "drv/timer/timestampDev.h"
  112. #include "intLib.h"
  113. #include "tickLib.h"
  114. /* header file used by scsi test */
  115. #include "scsiLib.h"
  116. #ifdef INCLUDE_SM_NET
  117. IMPORT VOIDFUNCPTR smUtilTasClearRtn;
  118. #endif /* INCLUDE_SM_NET */
  119. #endif /* DOC */
  120. /* defines */
  121. #define PK_LOOP_PAT_LEN (255) /* length of loopback ASCII pattern */
  122. #define PK_LOOP_OUT_LEN (300) /* length of loopback output buffer */
  123. #define PK_LOOP_TASK_NUM (4) /* num of multiple loopback tasks */
  124. #define PK_READ_MAX_TESTS (128*1024) /* max number of pkRead tests */
  125. #define PK_TS_ERR               1.0      /* acceptable timestamp % error */
  126. #define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
  127. #define PK_MAX_SER_STR          20      /* max strings to receive(serial test)*/
  128. #define PK_MAX_STR              20      /* max string length */
  129. #define PATTERN_INC_LAW 0
  130. /* values used to prefill RW_TEST_UNIT */
  131. #define DEF_BUF_SIZE  (64 * 1024) /* default buffer size (64K) */
  132. #define DEF_LAW PATTERN_INC_LAW /* incremental law */
  133. #define ST_PATTERN 0xa5a5a5a5 /* start pattern */
  134. #define DEF_NB_BUF 1 /* write one buffer */
  135. /* get field from SCSI_BLK_DEV to SCSI_PHYS_DEV */
  136. #define BLK_TO_PHYS(p,tag) (((SCSI_BLK_DEV*)p)->pScsiPhysDev->tag)
  137. /* check for bad buffer size */
  138. #define  IF_BAD_BUFSIZE(pBlkDev,size) 
  139.          if ((size % ((SCSI_BLK_DEV*)pBlkDev)->pScsiPhysDev->blockSize) != 0)
  140. typedef union /* equivalence int char[] */
  141.     {
  142.     int ival;
  143.     UINT8 uint8val[4];
  144.     } EQUI_INT_UINT8;
  145. typedef struct /* structure used to start a RW test */
  146.     {
  147.     /* value to initialize to start the test */
  148.     BLK_DEV *pBlk; /* pointer to the block device to test */
  149.     UINT8 *ptR; /* pointer to the read Buffer */
  150.     UINT8 *ptW; /* pointer to the write Buffer */
  151.     UINT32 size; /* buffer size to use */
  152.     int nbBuf; /* # of buffer to write/Read */
  153.     int law; /* law use to fill the patterns */
  154.     int stBlk; /* # of the first block to start */
  155.     int nbLoop; /* # of loop for the test */
  156.     int startPattern; /* value for the first pattern */
  157.     /* local value use by the routine useful for post checking */
  158.     TBOOL abort; /* flag to abort the test */
  159.     TBOOL abortOnError; /* stop at the first error */
  160.     int countErr; /* error counter */
  161.     int curStartPattern; /* first pattern to fill buffers */
  162.     int curPattern; /* current pattern  used */
  163.     int curCycle; /* # of Current cycle executed */
  164.     int curBuf; /* # of Current buffer tested */
  165.     int curBlk; /* # of the current block device */
  166.     } RW_TEST_UNIT;
  167. /* defines used by pkUdpEchoT */
  168. #define MAX_PKT         4096            /* largest packet used */
  169. #define N_SIZES         16              /* number of different packet sizes */
  170. #define RESEND 1 /* times to resend before error */
  171. #ifndef IPPORT_ECHO
  172. #define IPPORT_ECHO 7 /* standard UDP echo port */
  173. #endif
  174. /* globals */
  175. int pkLoopbackAbort = 0; /* non-zero for loopback task exit */
  176. int pkMultiLoopCount [NUM_TTY][PK_LOOP_TASK_NUM]; /* multi loopback data */
  177. int pkSeqLoopCount [NUM_TTY][2]; /* seq loopback data */
  178. int pkLoopFd [NUM_TTY]; /* array of loopback serial dev desc */
  179. int pkLoopTask [NUM_TTY]; /* count of multi loopback tasks */
  180. int pkLoopInit = 0; /* init loopback data arrays ? */
  181. SEM_ID  tsTmoSem;                       /* ID of timestamp timeout semaphore */
  182. WDOG_ID tsTmoWd;                        /* ID of timestamp timeout watchdog */
  183. int tsInit=FALSE; /* TRUE if tsTmoSem and tsTmoWd exist */
  184. char    pkSerChanInput[PK_MAX_SER_STR][PK_MAX_STR]; /* serial I/O string array */
  185. int     pkSerChanAbort=0;               /* non-zero for serial I/O task exit */
  186. int     pkConsoleEchoAbort = 0 ;
  187. RW_TEST_UNIT testUnit; /* accessible from VxWorks shell */
  188. RW_TEST_UNIT *pTestUnit = &testUnit;    /* pointer to testUnit */
  189. /* Globals for udpEchod */
  190. int flagInitUdp = FALSE;
  191. int     skt1 = -1;                  /* socket descriptor */
  192. struct  sockaddr_in sin;
  193. struct  sockaddr_in from;
  194. static  char buf [MAX_PKT];           /* pkt buffer */
  195. /* Globals for udpEchoTest */
  196. int    resendCnt = 0; /* times a single packet was resent */
  197. int    resendTotal = 0; /* total number of packets resent */
  198. int    packetTMO; /* packet timeout before resending */
  199. int    packetNum; /* current packet number being sent */
  200. int    curPktSiz;                       /* current packet size sent/received */
  201. int    skt;                             /* socket descriptor */
  202. int    sktAddrLen;                      /* length of socket addr */
  203. struct sockaddr_in serv_addr;           /* target socket data */
  204. char   dataOut [MAX_PKT];               /* outgoing pkt buf */
  205. char   dataIn  [MAX_PKT];               /* incoming pkt buf */
  206. int    pktSizes [N_SIZES] =
  207.     {
  208.     128, 256, 512, 768,
  209.     1024, 1280, 1536, 1792,
  210.     2048, 2304, 2560, 2816,
  211.     3072, 3328, 3584, 3840
  212.     };                                  /* various packet sizes */
  213. /* locals */
  214. LOCAL int loopState [NUM_TTY]; /* current state of seq loopback input */
  215. /* forward declarations */
  216. STATUS pkRead();
  217. void pkIncrement();
  218. int     pkGetMacroValue();
  219. void    pkTasTest();
  220. STATUS  pkTestRamByte();
  221. STATUS pkConsoleEcho();
  222. LOCAL BOOL pkMultiLoopHook();
  223. LOCAL BOOL pkSeqLoopHook();
  224. STATUS pkLoopbackTest();
  225. STATUS pkSeqLoopShow();
  226. STATUS pkMultiLoopShow();
  227. STATUS pkUdpEchod();
  228. void pkUdpInit();
  229.         STATUS  pkTimestampTest();
  230. STATUS  pkTimestampTestShort();
  231. void    pkTimestampTestLong();
  232.         STATUS  pkTimestampTestInit();
  233.         void    pkPrintTest();
  234.         void    pkDivideZeroTest();
  235. int pkIntGet();
  236. void pkIntSet();
  237. STATUS pkTestNvRam();
  238. STATUS pkBufFillPattern();
  239. STATUS pkBlkWrite();
  240. STATUS pkBlkRead();
  241. STATUS pkTestUnit();
  242. STATUS pkTestOneUnit();
  243.         void    pkSerialTest();
  244.         void    pkSerChanOutput();
  245. /*******************************************************************************
  246. *
  247. * pkRead - probe memory from start to end <length> bytes at a time
  248. *
  249. * This routine probes memory from the start address to the end address
  250. * using vxMemProbe(), <length> bytes at a time.  As soon as an error is
  251. * detected, the routine returns an ERROR.
  252. *
  253. * RETURNS: OK, or ERROR if <startAdrs> through (<endAdrs> - 1) not readable.
  254. */
  255. STATUS pkRead
  256.     (
  257.     char *startAdrs, /* start of range to test */
  258.     char *endAdrs, /* end of range to test   */
  259.     int length /* 1, 2, or 4 bytes       */
  260.     )
  261.     {
  262.     char * loopAdrs;
  263.     long bitBucket;
  264.     STATUS retValue = OK;
  265.     int increment = 1;
  266.     int size;
  267.     size = ((UINT)endAdrs - (UINT)startAdrs) / length;
  268.     /* limit the number of test cycles */
  269.     if (size >= (UINT)PK_READ_MAX_TESTS)
  270. increment = (size / (UINT)PK_READ_MAX_TESTS) * 2;
  271.     for (loopAdrs = startAdrs;
  272. loopAdrs < endAdrs;
  273. loopAdrs += (length * increment))
  274. {
  275. if (vxMemProbe (loopAdrs, VX_READ, length, (char *) &bitBucket)
  276.     == ERROR)
  277.     {
  278.     /* probe caused a bus error or address misalignment */
  279.     retValue = ERROR;
  280.     break;
  281.     }
  282. }
  283.     return retValue;
  284.     }
  285. /*******************************************************************************
  286. *
  287. * pkIncrement - increment a counter
  288. *
  289. * This routine adds one to the integer pointed to by <pCount>.
  290. *
  291. * RETURNS: N/A
  292. */
  293. void pkIncrement
  294.     (
  295.     int *pCount /* address to increment */
  296.     )
  297.     {
  298.     ++ *pCount;
  299.     }
  300. /*******************************************************************************
  301. *
  302. * pkGetMacroValue - read a macro value
  303. *
  304. * This routine returns the value of the macro associated with <macroName>,
  305. * else the value -1 (ERROR) is returned.
  306. *
  307. * RETURNS: Value associated with macroName, or ERROR (-1).
  308. */
  309. int pkGetMacroValue
  310.     (
  311.     char *macroName /* name of desired macro */
  312.     )
  313.     {
  314.     /*
  315.      * Note: since the config macros may contain an expression that does
  316.      * not have a constant integer value, it is important to evaluate
  317.      * them inline here, rather than place them in a static array
  318.      * initializer, which would be evaluated only at compile time.
  319.      */
  320. #ifdef LOCAL_MEM_LOCAL_ADRS
  321.     if (strcmp (macroName, "LOCAL_MEM_LOCAL_ADRS") == 0)
  322. return (int)LOCAL_MEM_LOCAL_ADRS;
  323. #endif
  324. #ifdef ROM_BASE_ADRS
  325.     if (strcmp (macroName, "ROM_BASE_ADRS") == 0)
  326. return (int)ROM_BASE_ADRS;
  327. #endif
  328. #ifdef ROM_SIZE
  329.     if (strcmp (macroName, "ROM_SIZE") == 0)
  330. return (int)ROM_SIZE;
  331. #endif
  332. #ifdef NV_RAM_SIZE
  333.     if (strcmp (macroName, "NV_RAM_SIZE") == 0)
  334. return (int)NV_RAM_SIZE;
  335. #endif
  336. #ifdef CONSOLE_TTY
  337.     if (strcmp (macroName, "CONSOLE_TTY") == 0)
  338. return (int)CONSOLE_TTY;
  339. #endif
  340. #ifdef SLIP_TTY
  341.     if (strcmp (macroName, "SLIP_TTY") == 0)
  342. return (int)SLIP_TTY;
  343. #endif
  344. #ifdef SYS_CLK_RATE_MIN
  345.     if (strcmp (macroName, "SYS_CLK_RATE_MIN") == 0)
  346. return (int)SYS_CLK_RATE_MIN;
  347. #endif
  348. #ifdef SYS_CLK_RATE_MAX
  349.     if (strcmp (macroName, "SYS_CLK_RATE_MAX") == 0)
  350. return (int)SYS_CLK_RATE_MAX;
  351. #endif
  352. #ifdef AUX_CLK_RATE_MIN
  353.     if (strcmp (macroName, "AUX_CLK_RATE_MIN") == 0)
  354. return (int)AUX_CLK_RATE_MIN;
  355. #endif
  356. #ifdef AUX_CLK_RATE_MAX
  357.     if (strcmp (macroName, "AUX_CLK_RATE_MAX") == 0)
  358. return (int)AUX_CLK_RATE_MAX;
  359. #endif
  360. #ifdef EXC_MSG_ADRS
  361.     if (strcmp (macroName, "EXC_MSG_ADRS") == 0)
  362. return (int)EXC_MSG_ADRS;
  363. #endif
  364. #ifdef PK_LOOP_TASK_NUM
  365.     if (strcmp (macroName, "PK_LOOP_TASK_NUM") == 0)
  366. return (int)PK_LOOP_TASK_NUM;
  367. #endif
  368.     return (int)ERROR;
  369.     }
  370. /*******************************************************************************
  371. *
  372. * pkTasTest - test-and-set test
  373. *
  374. * This routine, in conjunction with another pkTasTest() task, tests the
  375. * test-and-set mechanism.  Both tasks (each on a separate target board)
  376. * spin on the semaphore pointed to by <semaphore> using sysBusTas() for
  377. * mutual exclusion.  When this routine gets the semaphore, it increments
  378. * the <count> if it matches <odd>.  It then enters a busy-wait loop
  379. * <delay> times, giving the other task a chance to take the semaphore.
  380. * It may be necessary to tune this task by increasing or decreasing <delay
  381. * if one task (board) is much faster than the other.
  382. *
  383. * RETURNS: N/A (does not return)
  384. */
  385. void pkTasTest
  386.     (
  387.     char *semaphore, /* semaphore to spin on */
  388.     UINT32 *count, /* counter address */
  389.     BOOL odd, /* odd/even assignment */
  390.     UINT32 delay /* delay so other task gets time */
  391.     )
  392.     {
  393.     volatile UINT32 busyWait;
  394.     taskDelay (sysClkRateGet ()); /* wait 1 second */
  395.     FOREVER
  396. if (sysBusTas (semaphore))
  397.     {
  398.     /* check <odd> and bump counter if matches */
  399.     if ((((* count) & 1) && odd) || ((!((* count) & 1)) && !odd))
  400. (* count) ++;
  401. #ifdef INCLUDE_SM_NET
  402.     /* use the utility routine, if available */
  403.     if (smUtilTasClearRtn != NULL)
  404. (smUtilTasClearRtn)(semaphore);
  405.     else
  406. #endif /* INCLUDE_SM_NET */
  407.     * semaphore = 0;
  408.     /* enter busy-wait loop to give other task a chance */
  409.     for (busyWait = 0; busyWait < delay; busyWait ++)
  410. ; /* wait */
  411.     }
  412.     }
  413. /*******************************************************************************
  414. *
  415. * pkTestRamByte - test read and write access to one byte of RAM
  416. *
  417. * This routine uses vxMemProbe() to check that <adrs> may be written to
  418. * and read from.
  419. *
  420. * RETURNS: OK, or ERROR if <adrs> is not both readable and writable.
  421. */
  422. STATUS pkTestRamByte
  423.     (
  424.     char *adrs /* address to test */
  425.     )
  426.     {
  427.     char testR; /* scratchpad for read */
  428.     char write1; /* 1st value to write  */
  429.     char write2; /* 2nd value to write  */
  430.     (void) vxMemProbe (adrs, VX_READ, 1, &write2); /* save current value  */
  431.     write1 = (write2 == 3) ? 1 : 3; /* write1 != write2    */
  432.     return ((vxMemProbe (adrs, VX_WRITE, 1, &write1) != OK) ||
  433.     (vxMemProbe (adrs, VX_READ, 1, &testR) != OK)   ||
  434.     (testR != write1)                               ||
  435.     (vxMemProbe (adrs, VX_WRITE, 1, &write2) != OK) ||
  436.     (vxMemProbe (adrs, VX_READ, 1, &testR) != OK)   ||
  437.     (testR != write2)) ? ERROR : OK;
  438.     }
  439. #ifdef NV_RAM_SIZE
  440. char vtsOrigBootLine [NV_RAM_SIZE + 2]; /* original boot line */
  441. unsigned char vtsNvRamBuf1 [NV_RAM_SIZE + 2]; /* scratch buffer 1   */
  442. unsigned char vtsNvRamBuf2 [NV_RAM_SIZE + 2]; /* scratch buffer 2   */
  443. /*******************************************************************************
  444. *
  445. * pkTestNvRam - collection of non-volatile RAM tests
  446. *
  447. * This routine contains several tests to check the board's non-volatile
  448. * RAM.  The parameter <testNum> indicates which test will be run.
  449. *
  450. * If the macro NV_RAM_SIZE_WRITEABLE is defined, only that number of bytes
  451. * is used for tests which write to nvram.
  452. *
  453. * The tests in this routine write and read various patterns to and from nvram,
  454. * making sure no errors are detected.  Additionally, parameter checking is
  455. * performed on the sysNvRamGet() and sysNvRamSet() routines.
  456. *
  457. * RETURNS: OK, or ERROR if <testNum> is invalid or the test fails.
  458. */
  459. STATUS pkTestNvRam
  460.     (
  461.     int testNum /* test number (1-8) */
  462.     )
  463.     {
  464.     static int          writeableSize; /* writeable nvram sz */
  465.     FAST int ii; /* scratch loop index */
  466.     STATUS retValue = ERROR; /* return value       */
  467.     int offset = -NV_BOOT_OFFSET; /* offset to nv start */
  468. #ifdef NV_RAM_SIZE_WRITEABLE
  469.     writeableSize=NV_RAM_SIZE_WRITEABLE;
  470. #else /* NV_RAM_SIZE_WRITEABLE */
  471.     writeableSize=NV_RAM_SIZE;
  472. #endif /* NV_RAM_SIZE_WRITEABLE */
  473.     if (writeableSize > NV_RAM_SIZE)
  474.         return(retValue);
  475.     switch (testNum)
  476. {
  477. case 1: /* sysNvRamGet() of boot line */
  478.     {
  479.     if (sysNvRamGet((char *)vtsNvRamBuf1, NV_RAM_SIZE, offset) == ERROR)
  480. break;
  481.             /* store the original bootline */
  482.     bcopy ((char *) vtsNvRamBuf1, (char *) vtsNvRamBuf2, NV_RAM_SIZE);
  483.     bcopy ((char *) vtsNvRamBuf1, vtsOrigBootLine, NV_RAM_SIZE);
  484.             for (ii = 0; ii < NV_RAM_SIZE; ii ++) /* complement string */
  485.                 vtsNvRamBuf1 [ii] ^= 0xff;
  486.     (void) sysNvRamGet ((char *) vtsNvRamBuf1, NV_RAM_SIZE, offset);
  487.     if (memcmp((char *)vtsNvRamBuf1, (char *)vtsNvRamBuf2, NV_RAM_SIZE)
  488. == 0)
  489. retValue = OK;
  490.     break;
  491.     }
  492. case 2: /* sysNvRamSet() and sysNvRamGet() of complemented boot line  */
  493.     {
  494.     if (sysNvRamGet((char *)vtsNvRamBuf1, NV_RAM_SIZE, offset) == ERROR)
  495. break;
  496.             for (ii = 0; ii < NV_RAM_SIZE; ii ++) /* complement string */
  497.                 vtsNvRamBuf1 [ii] ^= 0xff;
  498.     if (sysNvRamSet((char *)vtsNvRamBuf1, writeableSize, offset)
  499. == ERROR)
  500. break;
  501.     (void) sysNvRamGet ((char *) vtsNvRamBuf2, NV_RAM_SIZE, offset);
  502.     if (memcmp((char *)vtsNvRamBuf1,(char *)vtsNvRamBuf2, writeableSize)
  503. == 0)
  504. retValue = OK;
  505.     break;
  506.     }
  507. case 3: /* sysNvRamGet() with length zero */
  508.     {
  509.     if (NV_RAM_SIZE < 3)
  510. break;
  511.     vtsNvRamBuf1 [0] = '1';
  512.     vtsNvRamBuf1 [1] = '2';
  513.     vtsNvRamBuf1 [2] = '3';
  514.     if (sysNvRamGet ((char *) (vtsNvRamBuf1 + 1), 0, offset) == ERROR)
  515. break;
  516.     /* verify a zero in vtsNvRamBuf [1], while vtsNvRamBuf [0] and vtsNvRamBuf [2] unchanged  */
  517.     if ((vtsNvRamBuf1 [0] == '1') && (vtsNvRamBuf1 [1] == 0)
  518. && (vtsNvRamBuf1 [2] == '3'))
  519. retValue = OK;
  520.     break;
  521.     }
  522. case 4: /* sysNvRamSet() parameter checking */
  523.     {
  524.     if ((sysNvRamSet((char *)vtsNvRamBuf1, -1, offset)    == ERROR) &&
  525. (sysNvRamSet((char *)vtsNvRamBuf1, 0, offset - 1) == ERROR) &&
  526. (sysNvRamSet((char *)vtsNvRamBuf1, writeableSize + 1, offset)
  527.   == ERROR) &&
  528. (sysNvRamSet((char *)vtsNvRamBuf1,0, offset + writeableSize + 1)
  529.   == ERROR) &&
  530. (sysNvRamSet((char *)vtsNvRamBuf1, writeableSize / 2 + 1,
  531.       offset + (writeableSize / 2) + 1)   == ERROR))
  532. {
  533. retValue = OK;
  534. }
  535.     break;
  536.     }
  537. case 5: /* sysNvRamGet() parameter checking */
  538.     {
  539.     if ((sysNvRamGet((char *)vtsNvRamBuf1, -1, offset)    == ERROR) &&
  540. (sysNvRamGet((char *)vtsNvRamBuf1, 0, offset - 1) == ERROR) &&
  541. (sysNvRamGet((char *)vtsNvRamBuf1, NV_RAM_SIZE + 1, offset)
  542.   == ERROR) &&
  543. (sysNvRamGet((char *)vtsNvRamBuf1, 0, offset + NV_RAM_SIZE + 1)
  544.   == ERROR) &&
  545. (sysNvRamGet((char *)vtsNvRamBuf1, NV_RAM_SIZE / 2 + 1,
  546.       offset + (NV_RAM_SIZE / 2) + 1)   == ERROR))
  547. {
  548. retValue = OK;
  549. }
  550.     break;
  551.     }
  552. case 6: /* sysNvRamSet() and sysNvRamGet() of 0xff data */
  553.     {
  554.     if (writeableSize < 4)
  555. break;
  556.     vtsNvRamBuf1 [0] = vtsNvRamBuf1 [1]
  557.     = vtsNvRamBuf1 [2] = vtsNvRamBuf1 [3] = 0xff;
  558.     vtsNvRamBuf2 [0] = vtsNvRamBuf2 [1]
  559.     = vtsNvRamBuf2 [2] = vtsNvRamBuf2 [3] = 0x55;
  560.     if (sysNvRamSet ((char *) vtsNvRamBuf1, 4, offset) == ERROR)
  561. break;
  562.     if (sysNvRamGet ((char *) vtsNvRamBuf2, 3, offset) == ERROR)
  563. break;
  564.     if ((vtsNvRamBuf2 [0] == 0xff) && (vtsNvRamBuf2 [1] == 0xff) &&
  565. (vtsNvRamBuf2 [2] == 0xff) && (vtsNvRamBuf2 [3] == 0x00))
  566. {
  567. retValue = OK;
  568. }
  569.     break;
  570.     }
  571. case 7: /* sysNvRamSet() and sysNvRamGet() of 0x00 data */
  572.     {
  573.     if (writeableSize < 4)
  574. break;
  575.     vtsNvRamBuf1 [0] = vtsNvRamBuf1 [1]
  576.     = vtsNvRamBuf1 [2] = vtsNvRamBuf1 [3] = 0x00;
  577.     vtsNvRamBuf2 [0] = vtsNvRamBuf2 [1]
  578.     = vtsNvRamBuf2 [2] = vtsNvRamBuf2 [3] = 0xff;
  579.     if (sysNvRamSet ((char *) vtsNvRamBuf1, 4, offset) == ERROR)
  580. break;
  581.     if (sysNvRamGet ((char *) vtsNvRamBuf2, 3, offset) == ERROR)
  582. break;
  583.     if ((vtsNvRamBuf2 [0] == 0x00) && (vtsNvRamBuf2 [1] == 0x00) &&
  584. (vtsNvRamBuf2 [2] == 0x00) && (vtsNvRamBuf2 [3] == 0x00))
  585. {
  586. retValue = OK;
  587. }
  588.     break;
  589.     }
  590. case 8: /* sysNvRamSet() and sysNvRamGet() of boot line */
  591.     {
  592.     if (sysNvRamSet (vtsOrigBootLine, writeableSize, offset) == ERROR)
  593. break;
  594.     if (sysNvRamGet((char *)vtsNvRamBuf1, NV_RAM_SIZE, offset) == ERROR)
  595. break;
  596.     if (memcmp(vtsOrigBootLine, (char *)vtsNvRamBuf1, writeableSize)
  597. == 0)
  598. retValue = OK;
  599.     break;
  600.     }
  601. default:
  602.     {
  603.     break;
  604.     }
  605. }
  606.     return (retValue);
  607.     }
  608. #endif /* NV_RAM_SIZE */
  609. /*******************************************************************************
  610. *
  611. * pkConsoleEcho - routine to put console into echo mode
  612. *
  613. * This routine puts the serial console in raw mode, then turns on the character
  614. * echo mode bit.  The console will remain in echo mode until <numToEcho>
  615. * characters have been echoed, or an "eof" (ASCII 0x04) is received.  If
  616. * <numToEcho> is zero, the only way to exit echo mode is to send an "eof".
  617. *
  618. * RETURNS: OK or ERROR.
  619. */
  620. STATUS pkConsoleEcho
  621.     (
  622.     int numToEcho /* number of characters to echo (0 means infinite) */
  623.     )
  624.     {
  625.     if (numToEcho < 0)
  626. {
  627. printf ("pkConsoleEcho: invalid parametern");
  628. return (ERROR);
  629. }
  630.     /* set the serial console to echo chars */
  631.     (void) ioctl (0, FIOSETOPTIONS, OPT_RAW);
  632.     (void) ioctl (1, FIOSETOPTIONS, OPT_RAW);
  633.     (void) ioctl (0, FIOSETOPTIONS, OPT_ECHO);
  634.     /* continue to echo until <numToEcho> exhausted or "eof" received  */
  635.       while ( ! pkConsoleEchoAbort)
  636. {
  637.         getc(stdin) ;
  638. if (numToEcho)
  639.     if (-- numToEcho == 0)
  640. break;
  641.         }
  642.     /* reset the console back to terminal mode */
  643.     (void) ioctl (0, FIOSETOPTIONS, OPT_TERMINAL);
  644.     (void) ioctl (1, FIOSETOPTIONS, OPT_TERMINAL);
  645.     return (OK);
  646.     }
  647. /*******************************************************************************
  648. *
  649. * pkSeqLoopHook - sequential serial loopback test input hook routine
  650. *
  651. * This routine monitors serial inputs for the sequential serial loopback test.
  652. * Whenever a character is written to serial port <channel>, this routine is
  653. * called.  It updates the count of characters written to <channel> and checks
  654. * that <inChar> matches the expected character from the sequential pattern
  655. * being sent in pkLoopbackTest(0,X,X,X).
  656. *
  657. * RETURNS: TRUE.
  658. */
  659. LOCAL BOOL pkSeqLoopHook
  660.     (
  661.     int channel, /* channel number */
  662.     int inChar /* input character */
  663.     )
  664.     {
  665.     char matchChar; /* expected input character */
  666.     if ((channel >= 0) && (channel < NUM_TTY))
  667. {
  668. ++ pkSeqLoopCount [channel][0]; /* bump character counter */
  669. /* find next character in pattern, and bump state counter */
  670. if (loopState [channel] < PK_LOOP_OUT_LEN - 1)
  671.     matchChar = 0x00 + ((loopState [channel] ++) % PK_LOOP_PAT_LEN);
  672. else
  673.     {
  674.     /* output buffer turned over */
  675.     matchChar = '0' + (channel % 10); /* '0' ... '9' */
  676.     loopState [channel] = 0;
  677.     }
  678. if (inChar != matchChar) /* mismatch? */
  679.     {
  680.     ++ pkSeqLoopCount [channel][1]; /* bump error counter */
  681.             loopState [channel]++; /* compensate for dropped char */
  682.             }
  683. }
  684.     return (TRUE); /* no further processing of the character */
  685.     }
  686. /*******************************************************************************
  687. *
  688. * pkMultiLoopHook - multiple loopback test input hook routine
  689. *
  690. * This routine monitors serial inputs for the multiple serial loopback test.
  691. * Whenever a character is written to serial port <channel>, this routine is
  692. * called.  It updates the count of characters written to <channel> from the
  693. * task (pkLoopbackTest(1,X,X,X)) associated with <inChar>.
  694. *
  695. * RETURNS: TRUE.
  696. */
  697. LOCAL BOOL pkMultiLoopHook
  698.     (
  699.     int channel, /* channel number */
  700.     int inChar /* input character */
  701.     )
  702.     {
  703.     int offset; /* offset to access correct data location */
  704.     if ((channel >= 0) && (channel < NUM_TTY))
  705. {
  706. offset = inChar - 'A';
  707. ++ pkMultiLoopCount [channel][offset]; /* bump character counter */
  708. }
  709.     return (TRUE); /* no further processing of the character */
  710.     }
  711. /*******************************************************************************
  712. *
  713. * pkLoopbackTest - loopback test routine
  714. *
  715. * This routine is called to perform either one of two tests, based upon
  716. * the value of <mTest>.
  717. *
  718. * If <mTest> is 0, the sequential serial loopback test is run.  This test will
  719. * write a sequential pattern of characters over and over, until <numToSend>
  720. * chars are sent. If <numToSend>=0, then an infinite number of chars are sent.
  721. * Characters are sent at <baud> baud rate to serial port <channel>.
  722. *
  723. * Else, if <mTest> is 1, the multiple serial test is started.  This test will
  724. * recursively call pkLoopbackTest() until PK_LOOP_TASK_NUM number of calls
  725. * have taken place.  Each call results in a task that will write <numToSend>
  726. * unique characters to serial port <channel> at baud rate <baud>.
  727. * If <numToSend>=0, then an infinite number of chars are sent.  The initial
  728. * pkLoopbackTest opens the file descriptor to the serial port, makes the
  729. * recursive calls, waits for the other tasks to end, and then closes the file
  730. * descriptor.
  731. *
  732. * NOTE: Transmission will abort if the global variable <pkLoopbackAbort> is
  733. * set to a non-zero value.
  734. *
  735. * RETURNS: OK or ERROR.
  736. */
  737. STATUS pkLoopbackTest
  738.     (
  739.     int mTest, /* 0 = sequential test, 1 = multiple task test */
  740.     int channel, /* channel number to test */
  741.     int baud, /* baud rate for test */
  742.     int numToSend /* number of chars to send (0 means infinite) */
  743.     )
  744.     {
  745.     char loopName [10]; /* more than enough chars for "tyCo/NN" */
  746.     char inBuf;         /* one character input buffer */
  747.     char letterL = 'L'; /* one character output buffer */
  748.     char outBuf [PK_LOOP_OUT_LEN]; /* loopback pattern output buffer */
  749.     int  call=0; /* number of tasks open in multiple test */
  750.     int  loopFd; /* file descriptor for <channel> */
  751.     int  mule; /* scratch */
  752.     int  numSent=0; /* characters sent so far in loop */
  753.     /* check for valid parameters */
  754.     if ((channel == CONSOLE_TTY) || (channel < 0) || (channel >= NUM_TTY) ||
  755.         (baud == 0) || (numToSend < 0) || ((mTest != 0) && (mTest != 1)))
  756. {
  757. printf ("pkLoopbackTest: Error: invalid parametern");
  758. return (ERROR);
  759. }
  760.     /* if running multiple loopback test, initialize data structures (once) */
  761.     if (mTest == 1)
  762. {
  763.         if (pkLoopInit == 0)
  764.             {
  765.     pkLoopInit = 1;
  766.       for (mule = 0; mule < NUM_TTY; mule ++)
  767.           pkLoopTask [mule] = 0;
  768.             }
  769. #if (PK_LOOP_TASK_NUM < 1)
  770. printf ("pkLoopbackTest: Error: set for too few tasksn");
  771. return (ERROR);
  772. #else /* PK_LOOP_TASK_NUM */
  773.         /* increment number of multiple loopback tasks open */
  774.         call = pkLoopTask [channel] ++;
  775. #endif /* PK_LOOP_TASK_NUM */
  776.   }
  777.     /* on first call of multiple - always on sequential */
  778.     if (call == 0)
  779. {
  780. /* open file descriptor for the loopback device */
  781.         sprintf (loopName,"/tyCo/%d",channel);
  782.         pkLoopFd [channel] = open (loopName, O_RDWR, 0);
  783. loopFd = pkLoopFd [channel];
  784.         if (loopFd == ERROR)
  785.     {
  786.     printf ("pkLoopbackTest: Error: failed to open %sn", loopName);
  787.     return (ERROR);
  788.     }
  789.         /* set baud and mode, flush the buffers */
  790.         (void) ioctl (loopFd, FIOBAUDRATE, baud);
  791.         (void) ioctl (loopFd, FIOSETOPTIONS, OPT_RAW);
  792.         (void) ioctl (loopFd, FIOFLUSH, 0);
  793.         /* verify loopback operation (one character not counted in <numSent>) */
  794.         inBuf = ~letterL; /* inBuf differs from outBuf */
  795.         (void) write (loopFd, &letterL, 1); /* send a char */
  796.         taskDelay (sysClkRateGet() / 4); /* allow time for loopback */
  797.         (void) ioctl (loopFd, FIONREAD, (int) (&mule)); /* any character? */
  798.         if (mule == 1)
  799.     (void) read (loopFd, &inBuf, 1); /* read it */
  800.         if (inBuf != letterL) /* mismatch? */
  801.     {
  802.     printf ("pkLoopbackTest: Error: loopback connection failedn");
  803.     (void) close (loopFd);
  804.     return (ERROR);
  805.     }
  806.        /* declare argument to be passed to protocol hook - the channel # */
  807.         (void) ioctl (loopFd, FIOPROTOARG, channel);
  808.         /* clear input counters for this channel (in case we've run before) */
  809. if (mTest == 0)
  810.     {
  811.     /* attach hook for receiving chars */
  812.             (void) ioctl (loopFd, FIOPROTOHOOK, (int) pkSeqLoopHook);
  813.     pkSeqLoopCount [channel][0] = 0;
  814.     pkSeqLoopCount [channel][1] = 0;
  815.     }
  816.         else
  817.     {
  818.     /* attach hook for receiving chars */
  819.             (void) ioctl (loopFd, FIOPROTOHOOK, (int) pkMultiLoopHook);
  820.     for (mule = 0; mule < PK_LOOP_TASK_NUM; mule ++)
  821.         pkMultiLoopCount [channel][mule] = 0;
  822.     }
  823.         loopState [channel] = 0;
  824.         }
  825.     else
  826.        loopFd = pkLoopFd [channel];
  827.     /* initialize output buffer */
  828.     if (mTest == 0)
  829.         {
  830.         for (mule = 0; mule < PK_LOOP_OUT_LEN - 1; mule ++)
  831.             outBuf [mule] = 0x00 + (mule % PK_LOOP_PAT_LEN); /* 'A' ... 'Z' */
  832.         outBuf [mule] = '0' + (channel % 10);               /* '0' ... '9' */
  833.         }
  834.     else
  835. {
  836.         for (mule = 0; mule < PK_LOOP_OUT_LEN; mule ++)
  837.             outBuf [mule] = 'A' + call; /* 'A' ... 'Z' */
  838.         /* start another loopback task for multiple loopback test */
  839.         if (call < (PK_LOOP_TASK_NUM - 1))
  840.               taskSpawn (NULL, 100, VX_FP_TASK, 20000, pkLoopbackTest, 1,
  841.                (int) channel, (int) baud, (int) numToSend, (int) NULL,
  842.                (int) NULL, (int) NULL, (int) NULL, (int) NULL, (int) NULL);
  843. }
  844.     /* write the characters out */
  845.     while ((numSent < numToSend) || (numToSend == 0))
  846. {
  847. /* check abort flag */
  848. if (pkLoopbackAbort)
  849.     break;
  850. /* write the output buffer */
  851. if (numToSend)
  852.     mule = MIN (PK_LOOP_OUT_LEN, numToSend - numSent);/* # bytes? */
  853.         else
  854.     mule = PK_LOOP_OUT_LEN;
  855. (void) write (loopFd, outBuf, mule);
  856. numSent += mule;
  857. }
  858.     /* wait for i/o to complete */
  859.     if (mTest == 1)
  860. pkLoopTask [channel] --;
  861.     if (call == 0)
  862.         {
  863.         do
  864.             {
  865.             taskDelay (sysClkRateGet() / 4);
  866.             (void) ioctl (loopFd, FIONWRITE, (int) (&mule)); /* wait for out */
  867.             } while (mule != 0);
  868.         taskDelay (sysClkRateGet());
  869.         /* the first multiple task waits for all other multiple tasks to end */
  870.         if (mTest == 1)
  871.             while (pkLoopTask [channel] != 0)
  872.                 taskDelay (sysClkRateGet());
  873.         (void) ioctl (loopFd, FIOPROTOHOOK, 0);
  874.         (void) close (loopFd);
  875.         }
  876.     return (OK);
  877.     }
  878. /*******************************************************************************
  879. *
  880. * pkSeqLoopShow - display results of sequential loopback test
  881. *
  882. * This routine displays the data generated from running the sequential serial
  883. * loopback test (pkLoopbackTest(0,X,X,X)).  The output consists of a count
  884. * of characters written to serial port <channel> during the test.  Included is
  885. * a count of errors encountered (an error was recorded any time a character
  886. * was received out of order).
  887. *
  888. * RETURNS: OK or ERROR.
  889. */
  890. STATUS pkSeqLoopShow
  891.     (
  892.     int channel /* serial channel */
  893.     )
  894.     {
  895.     if ((channel == CONSOLE_TTY) || (channel < 0) || (channel >= NUM_TTY))
  896. {
  897. printf ("pkSeqLoopShow: Error: invalid parametern");
  898. return (ERROR);
  899. }
  900.     printf ("characters = %dn", pkSeqLoopCount [channel][0]);
  901.     printf ("errors = %dn", pkSeqLoopCount [channel][1]);
  902.     printf ("OKn");
  903.     return (OK);
  904.     }
  905. /*******************************************************************************
  906. *
  907. * pkMultiLoopShow - display results of multiple loopback test
  908. *
  909. * This routine displays the data generated from running the multiple serial
  910. * loopback test (pkLoopbackTest(1,X,X,X)).  The output consists of a list
  911. * of tasks and the number of characters each task has written to the
  912. * serial port specified by <channel>.
  913. *
  914. * RETURNS: OK or ERROR.
  915. */
  916. STATUS pkMultiLoopShow
  917.     (
  918.     int channel /* serial channel */
  919.     )
  920.     {
  921.     int mule; /* task counter */
  922.     if ((channel == CONSOLE_TTY) || (channel < 0) || (channel >= NUM_TTY))
  923. {
  924. printf ("pkMultiLoopShow: Error: invalid parametern");
  925. return (ERROR);
  926. }
  927.     else
  928.         {
  929.         for (mule = 0; mule < PK_LOOP_TASK_NUM; mule ++)
  930.             {
  931.             printf ("task = %d    ", mule + 1);
  932.     printf ("count = %dn", pkMultiLoopCount [channel][mule]);
  933.     }
  934.         printf ("OKn");
  935.         }
  936.     return (OK);
  937.     }
  938. /*******************************************************************************
  939. *
  940. * pkUdpEchod - echo daemon for UDP packets
  941. *
  942. * This routine is an echo daemon for UDP/IP networking packets.  Packets
  943. * up to 4096 bytes are read in from port 7 (the standard UDP echo port) and
  944. * then are written back to port 7.
  945. *
  946. * The function pkUdpInit() is called to create a socket and bind it.
  947. *
  948. * RETURNS: does not return unless error (error number given)
  949. */
  950. int pkUdpEchod (void)
  951.     {
  952.     int cnt;                     /* size of packet received */
  953.     int fromLen;                 /* size of host sock structure */
  954.     fromLen = sizeof(from);
  955.     if (!flagInitUdp)
  956.      {
  957.      pkUdpInit();
  958.      }
  959.     /* loop, reading from socket, and echoing */
  960.     while (1)
  961.         {
  962.         cnt = recvfrom (skt1, (char *) buf, sizeof (buf), 0,
  963. (struct sockaddr *) &from, &fromLen);
  964.         if (cnt > 0)
  965.             sendto (skt1, (char *) buf, cnt, 0, (struct sockaddr *) &from,
  966.     sizeof (from));
  967.         }
  968.     }
  969. /*******************************************************************************
  970. *
  971. * pkUdpInit - initialize socket for UDP test
  972. *
  973. * This routine opens a socket and binds it to port 7.
  974. *
  975. * RETURNS: N/A
  976. */
  977. void pkUdpInit (void)
  978.     {
  979.     int sktBufSiz;               /* size of largest packet */
  980.     int fromLen;                 /* size of host sock structure */
  981.     bzero ((char *) &sin, sizeof (sin));        /* clr sock addrs */
  982.     bzero ((char *) &from, sizeof (from));
  983.     skt1 = socket (AF_INET, SOCK_DGRAM, 0);      /* open socket */
  984.     if (skt1 < 0)
  985.         {
  986.         logMsg ("pkUdpEchod: socket errorn",0,0,0,0,0,0);
  987.         exit (1);
  988.         }
  989.     sin.sin_family = AF_INET;                   /* fill in our sock addr */
  990.     sin.sin_port = htons (IPPORT_ECHO);                   /* the ECHO port */
  991.     /* bind our sock addr */
  992.     if (bind (skt1, (struct sockaddr *) &sin, sizeof (sin)) < 0)
  993.         {
  994.         logMsg ("pkUdpEchod: bind errorn",0,0,0,0,0,0);
  995.         close (skt1);
  996.         exit (2);
  997.         }
  998.     fromLen = sizeof (from);                    /* get size of sock addr */
  999.     sktBufSiz = sizeof (buf);         /* increase size of socket buffers */
  1000.     if (setsockopt (skt1, SOL_SOCKET, SO_SNDBUF, (char *) &sktBufSiz,
  1001.         sizeof (sktBufSiz)) < 0)
  1002.         {
  1003.         close (skt1);
  1004.         logMsg ("pkUdpEchod: setsockopt errorn",0,0,0,0,0,0);
  1005.         exit (3);
  1006.         }
  1007.     if (setsockopt (skt1, SOL_SOCKET, SO_RCVBUF, (char *) &sktBufSiz,
  1008.         sizeof (sktBufSiz)) < 0)
  1009.         {
  1010.         close (skt1);
  1011.         logMsg ("pkUdpEchod: setsockopt errorn",0,0,0,0,0,0);
  1012.         exit (4);
  1013.         }
  1014.     flagInitUdp = TRUE;
  1015.     }
  1016. #ifdef INCLUDE_TIMESTAMP
  1017. /*******************************************************************************
  1018. *
  1019. * pkTimestamp - tests sysTimestamp() and sysTimestampLock()
  1020. *
  1021. * This routine calls the function sysTimestamp() or sysTimestampLock()(after
  1022. * locking interrupts) depending on the boolean parameter locked.
  1023. *
  1024. * RETURNS: tick counter value
  1025. */
  1026. UINT32 pkTimestamp
  1027.     (
  1028.     BOOL locked
  1029.     )
  1030.     {
  1031.     int lockKey;
  1032.     UINT32 tickRet;
  1033.     if (!locked)
  1034.         return (sysTimestampLock ());
  1035.     lockKey = intLock ();
  1036.     tickRet = sysTimestamp ();
  1037.     intUnlock (lockKey);
  1038.     return (tickRet);
  1039.     }
  1040. /*******************************************************************************
  1041. *
  1042. * pkTimestampRoll - returns a counter value or the current tick
  1043. *
  1044. * This routine reads the location pointed to by tickCounter if non null, or
  1045. * returns the current system clock tick.
  1046. *
  1047. * RETURNS: counter value or clock tick
  1048. */
  1049. UINT32 pkTimestampRoll
  1050.     (
  1051.     UINT *tickCounter
  1052.     )
  1053.     {
  1054.     if (tickCounter == 0)
  1055. return (tickGet());
  1056.     else
  1057. return (*tickCounter);
  1058.     }
  1059. /*******************************************************************************
  1060. *
  1061. * pkTimestampTestShort - short-term test of timestamp timer
  1062. *
  1063. * This routine performs a short-term test of the timestamp timer. It reads
  1064. * values with a delay in-between. The test is repeated up to 16 times. If
  1065. * the counter is always increasing the test is successful.
  1066. *
  1067. * RETURNS: OK if success, ERROR otherwise.
  1068. */
  1069. STATUS pkTimestampTestShort
  1070.     (
  1071.     UINT *tickCounter,
  1072.     BOOL locked
  1073.     )
  1074.     {
  1075.     UINT countVal [2];
  1076.     UINT32 tickVal [2];
  1077.     STATUS retValue = OK;
  1078.     int ix;
  1079.     volatile int iy;
  1080.     /* short term test: make sure timestamp is incrementing */
  1081.     for (ix = 0; (ix < 0x10) && (retValue == OK); ix++)
  1082.      {
  1083.         countVal [0] = pkTimestampRoll (tickCounter);
  1084.         tickVal [0]  = pkTimestamp (locked);
  1085. for (iy = 0; iy < 1000; iy++)
  1086. ;
  1087.         tickVal [1]  = pkTimestamp (locked);
  1088.         countVal [1] = pkTimestampRoll (tickCounter);
  1089. if ((tickVal [0] >= tickVal [1]) && (countVal [0] >= countVal [1]))
  1090. retValue = ERROR;
  1091. }
  1092.         return (retValue);
  1093.     }
  1094. /*******************************************************************************
  1095. *
  1096. * pkTimestampTestInit - initialize timestamp test
  1097. *
  1098. * This routine creates a semahore and a watchdog timer for the timestamp
  1099. * test. The ids are stored in two global variables and a flag is set if
  1100. * the two are created successfuly.
  1101. *
  1102. * RETURNS: OK if success, ERROR otherwise.
  1103. */
  1104. STATUS pkTimestampTestInit()
  1105.     {
  1106.     tsTmoSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
  1107.     tsTmoWd  = wdCreate ();
  1108.     if ((tsTmoSem == NULL) || (tsTmoWd == NULL))
  1109.         {
  1110.         tsInit = FALSE;
  1111.         return ERROR;
  1112.         }
  1113.     else
  1114.         {
  1115.         tsInit = TRUE;
  1116.         return OK;
  1117.         }
  1118.     }
  1119. /*******************************************************************************
  1120. *
  1121. * pkTimestampTestLong - long-term timestamp test
  1122. *
  1123. * This routine performs a long-term timestamp test.
  1124. *
  1125. * RETURNS: OK, or ERROR.
  1126. */
  1127. void pkTimestampTestLong
  1128.     (
  1129.     UINT *tickCounter,
  1130.     int timeout,
  1131.     BOOL locked,
  1132.     int nslices
  1133.     )
  1134.     {
  1135.     UINT * pCountVal = malloc (nslices * 2 * sizeof (UINT));
  1136.     UINT32 * pTickVal = malloc (nslices * 2 * sizeof (UINT32));
  1137.     UINT * pCountPtr = pCountVal;
  1138.     UINT32 * pTickPtr = pTickVal;
  1139.     UINT32 calcTicks;
  1140.     volatile UINT32 tsBucket;
  1141.     float errorVal;
  1142.     int second;
  1143.     int delay;
  1144.     int ix;
  1145.     STATUS retValue = OK;
  1146.     second = timeout / nslices;
  1147.     delay = second * sysClkRateGet();
  1148.     calcTicks = second * sysTimestampFreq();
  1149.     if (tsInit == FALSE)
  1150.         {
  1151.         if (pkTimestampTestInit() == ERROR)
  1152.          {
  1153.          printf("FAIL long-term timestamp testn");
  1154.     goto pkTimestampTestLongExit;
  1155.     }
  1156.          }
  1157.     printf ("nStarting long-term timestamp test.n");
  1158.     printf ("This test will run for approximately %.1f minute(s).nn",
  1159. (float) timeout/60);
  1160.     for (ix = 0; ix < nslices; ix++)
  1161. {
  1162.         if (wdStart (tsTmoWd, delay, semGive, (int) tsTmoSem) == ERROR)
  1163.          {
  1164.      printf("FAIL long-term timestamp testn");
  1165.         goto pkTimestampTestLongExit;
  1166. }
  1167.         *pCountPtr++ = pkTimestampRoll (tickCounter);
  1168.         *pTickPtr++ = pkTimestamp (locked);
  1169.         while ((semTake (tsTmoSem, NO_WAIT)) != OK)
  1170.     {
  1171.             taskDelay (2);
  1172.     tsBucket = pkTimestamp (locked);
  1173.     }
  1174.         *pCountPtr++ = pkTimestampRoll (tickCounter);
  1175.         *pTickPtr++ = pkTimestamp (locked);
  1176. printf ("pkTimestampTest: %d/%d through testn", (ix + 1), nslices);
  1177. }
  1178.     /* convert to total ticks */
  1179.     for (pTickPtr = pTickVal, pCountPtr = pCountVal, ix = 0; 
  1180.  ix < (nslices << 1); ix++, pTickPtr++, pCountPtr++)
  1181. {
  1182. *pTickPtr += *pCountPtr * sysTimestampPeriod();
  1183. }
  1184.     /* convert to relative ticks and compute percent error */
  1185.     printf ("ncalculated ticks: %un", calcTicks);
  1186.     pTickPtr = pTickVal;
  1187.     for (ix = 0, pCountPtr = pCountVal; ix < nslices; ix++, pCountPtr++)
  1188. {
  1189. /* the following two lines put the difference between two consecutive
  1190.  * entries in the pTickVal array into the appropriate slot in the 
  1191.  * pCountVal array.
  1192.  */
  1193. *pCountPtr = *pTickPtr++;
  1194. *pCountPtr = *pTickPtr++ - *pCountPtr;
  1195. /* calculate *percent* error */
  1196. errorVal = 100 * ((float) calcTicks - (float) *pCountPtr) /
  1197.   (float) calcTicks;
  1198. printf ("Period %d:  measured ticks: %u,  percent error: %fn",
  1199.     (ix + 1), *pCountPtr, errorVal);
  1200.         if (errorVal < 0)
  1201.     errorVal *= -1;
  1202.         if (errorVal > (float) PK_TS_ERR)
  1203.     retValue = ERROR;
  1204.         }
  1205.     if (retValue == ERROR)
  1206.      printf("FAIL: long-term timestamp testn");
  1207.     else
  1208.      printf("PASS: long-term timestamp testn");
  1209. pkTimestampTestLongExit:
  1210.     free (pCountVal);
  1211.     free (pTickVal);
  1212.     }
  1213. #endif /* INCLUDE_TIMESTAMP */
  1214. #ifdef INCLUDE_SCSI
  1215. /* the following are for testing SCSI */
  1216. /*******************************************************************************
  1217. *
  1218. * pkBufFillPattern - write a pattern to a memory buffer
  1219. *
  1220. * This routine write a pattern in a memory buffer.  <startPattern> indicates
  1221. * the
  1222. * pattern and the buffer will be fill with data0, data0+inc,....,datan+inc
  1223. * according to the filling law chosen.
  1224. *
  1225. * INTERNAL:
  1226. * Only the law with the increment 0x01010101 is implemented.
  1227. * A another law should be to write:
  1228. * data0, ~data0,data0+inc,~data0+inc, ...,datan+inc,~datan+inc.
  1229. *
  1230. * RETURNS: OK or ERROR.
  1231. */
  1232. STATUS pkBufFillPattern
  1233.     (
  1234.     UINT8 *pBuffer, /* pointer to the buffer              */
  1235.     UINT32 size, /* size in bytes of the buf to fill   */
  1236.     int law, /* rules to fill the buffer           */
  1237.     int *startPattern, /* value of the start pattern         */
  1238.     int *endPattern /* where return the end value pattern */
  1239.     )
  1240.     {
  1241.     EQUI_INT_UINT8  pattern;
  1242.     int  ix;
  1243.     int  iy;
  1244.     int  firstBlock;
  1245.     int  lastBlock;
  1246.     int * pt = (int *)pBuffer;
  1247.     UCHAR * upt;
  1248.     if (pBuffer == NULL)
  1249. return (ERROR);
  1250.     if (size < sizeof (pattern.ival))
  1251. return (ERROR);
  1252.     switch (law)
  1253. {
  1254. case PATTERN_INC_LAW:
  1255.     {
  1256.     /* incremental law */
  1257.     iy = 0;
  1258.     pattern.ival = *startPattern;
  1259.     firstBlock = size / sizeof (pattern.ival);
  1260.     lastBlock = size % sizeof (pattern.ival);
  1261.     for (ix = 0; ix <= (firstBlock-1); ix ++)
  1262. {
  1263. *pt = pattern.ival;
  1264. pattern.ival = pattern.ival + (int) 0x01010101;
  1265. pt ++;
  1266. }
  1267.     /* fill last block in byte mode if the remain modulo exist */
  1268.     ix = (ix * 4) - 1;
  1269.     upt = (UCHAR *) pt;
  1270.     while (lastBlock != 0)
  1271. {
  1272.  *upt = pattern.uint8val[ix % 4];
  1273. if ((iy % 4) == 3)
  1274.     pattern.ival = pattern.ival + 0x01010101;
  1275. ix ++;
  1276. iy ++;
  1277. upt ++;
  1278. lastBlock --;
  1279. }
  1280.     break;
  1281.     }
  1282. default:
  1283.     {
  1284.     printErr ("pkBufFillPattern: law not implemented : ERRORn");
  1285.     return (ERROR);
  1286.     }
  1287. }
  1288.     *endPattern = pattern.ival;
  1289.     return (OK);
  1290.     }
  1291. /*******************************************************************************
  1292. *
  1293. * pkBlkWrite - write blocks to a SCSI device
  1294. *
  1295. * Write a buffer to a SCSI device.  The buffer size must be a multiple
  1296. * of the block size of the device.  <blockNumber> is used both to describe
  1297. * the writing position and next free position when the function returns.
  1298. *
  1299. * RETURNS: OK, or ERROR if parameters don't match or the write failed.
  1300. */
  1301. STATUS pkBlkWrite
  1302.     (
  1303.     SCSI_BLK_DEV *pBlkDev, /* pointer to the block device     */
  1304.     char *pBuffer, /* pointer to the buffer Read      */
  1305.     UINT32 size, /* size of the pBuffer area        */
  1306.     int *blockNumber /* logical # of the block to write */
  1307.     )
  1308.     {
  1309.     int numSects;
  1310.     int secSize = BLK_TO_PHYS(pBlkDev,blockSize);
  1311.     /* check pBlkDev */
  1312.     if  (pBlkDev == (SCSI_BLK_DEV *)NULL)
  1313. {
  1314. printErr ("pkBlkWrite: pBlkDev is NULL : ERRORn");
  1315. return (ERROR);
  1316. }
  1317.     /* check for range block */
  1318.     if (((* blockNumber) > ((SCSI_BLK_DEV *) pBlkDev)->blkDev.bd_nBlocks) ||
  1319.         ((* blockNumber) < ((SCSI_BLK_DEV *) pBlkDev)->blockOffset))
  1320. {
  1321. printErr ("scsiWriteBlocks: blockNumber out of range : ERRORn");
  1322. return (ERROR);
  1323. }
  1324.     /* check if size ok */
  1325.     if (size == (int) NULL)
  1326. {
  1327.         printErr ("scsiWriteBlocks: buffer size is NULL : ERRORn");
  1328. return (ERROR);
  1329. }
  1330.     /* check if buffer size fits sector size */
  1331.     IF_BAD_BUFSIZE (pBlkDev,size)
  1332. {
  1333.         printErr ("scsiWriteBlocks: buffer size invalid : ERRORn");
  1334. return (ERROR);
  1335. }
  1336.     numSects = size / secSize;
  1337.     if (scsiWrtSecs (pBlkDev,*blockNumber,numSects, pBuffer) == ERROR)
  1338. {
  1339. printErr ("pkBlkWrite: returned ERRORn");
  1340. return (ERROR);
  1341. }
  1342.     *blockNumber = *blockNumber + numSects;
  1343.     return (OK);
  1344.     }
  1345. /*******************************************************************************
  1346. *
  1347. * pkBlkRead - read blocks from a SCSI device
  1348. *
  1349. * Read a buffer from a SCSI device.  The buffer size must be a multiple
  1350. * of the block size of the device.  <blockNumber> is used both to describe
  1351. * the reading position and next free position when the function returns.
  1352. *
  1353. * RETURNS: OK, or ERROR if parameters don't match or the read failed.
  1354. */
  1355. STATUS pkBlkRead
  1356.     (
  1357.     SCSI_BLK_DEV *pBlkDev, /* pointer to the block device     */
  1358.     char *pBuffer, /* pointer to the buffer Read      */
  1359.     UINT32 size, /* size of the pBuffer area        */
  1360.     int *blockNumber /* logical # of the block to write */
  1361.     )
  1362.     {
  1363.     int numSects;
  1364.     int secSize = BLK_TO_PHYS(pBlkDev,blockSize);
  1365.     /* check pBlkDev */
  1366.     if  (pBlkDev == (SCSI_BLK_DEV *) NULL)
  1367. {
  1368. printErr ("pkBlkRead: pBlkDev is NULL : ERRORn");
  1369. return (ERROR);
  1370. }
  1371.     /* check for range block */
  1372.     if (((* blockNumber) > ((SCSI_BLK_DEV *) pBlkDev)->blkDev.bd_nBlocks) ||
  1373.         ((* blockNumber) < ((SCSI_BLK_DEV *) pBlkDev)->blockOffset))
  1374. {
  1375. printErr ("pkBlkRead: blockNumber out of range : ERRORn");
  1376. }
  1377.     /* check if size ok */
  1378.     if (size == 0)
  1379.         {
  1380.         printErr ("pkBlkRead: buffer size is 0 : ERRORn");
  1381.         return (ERROR);
  1382.         }
  1383.     /* make sure the buffer size fits the sector size */
  1384.     IF_BAD_BUFSIZE (pBlkDev,size)
  1385. {
  1386.         printErr ("pkBlkRead: buffer size not a multiple of block size : ERRORn");
  1387. return (ERROR);
  1388. }
  1389.     /* use previous IF_BAD_BUFSIZE to get an integer sector count */
  1390.     numSects = size / secSize;
  1391.     if (scsiRdSecs (pBlkDev,*blockNumber,numSects, pBuffer) == ERROR)
  1392. {
  1393. printErr ("pkBlkRead: returning ERRORn");
  1394. return (ERROR);
  1395. }
  1396.     *blockNumber = *blockNumber + numSects;
  1397.     return (OK);
  1398.     }
  1399. /*******************************************************************************
  1400. *
  1401. * pkTestUnit - test a SCSI device by writing, reading and verifying data
  1402. *
  1403. * This routine tests write and read operation to a SCSI device.
  1404. * The unique parameter is pointer to a structure info.  First it writes
  1405. * a pattern to a range of blocks on the device.  Then it reads the range
  1406. * of blocks and verifies the pattern.  The pattern is generated by
  1407. * pkBufFillPattern().
  1408. *
  1409. * RETURNS: OK, or ERROR if the parameters are bad or the test fails.
  1410. *
  1411. * SEE ALSO: pkBufFillPattern()
  1412. */
  1413. STATUS pkTestUnit
  1414.     (
  1415.     RW_TEST_UNIT *pTestInfo  /* structure describes test to run */
  1416.     )
  1417.     {
  1418.     FAST RW_TEST_UNIT * p = pTestInfo;
  1419.     FAST SCSI_BLK_DEV * pB = (SCSI_BLK_DEV *) (p->pBlk);
  1420.     int iWrite;
  1421.     int iRead;
  1422.     int iLoop;
  1423.     int temp;
  1424.     int curEndPattern;
  1425.     /* check parameters */
  1426.     if (pB == (SCSI_BLK_DEV *) NULL)
  1427. {
  1428.         printErr ("pkTestUnit: pBlkDev is NULL : ERRORn");
  1429.         return (ERROR);
  1430. }
  1431.     if (p->nbLoop == 0)
  1432. {
  1433.         printErr ("pkTestUnit: nbLoop is 0 : ERRORn");
  1434.         return (ERROR);
  1435. }
  1436.     if (p->size == 0)
  1437. {
  1438.         printErr ("pkTestUnit: bufSize is 0 : ERRORn");
  1439.         return (ERROR);
  1440. }
  1441.     if (p->nbBuf == 0)
  1442. {
  1443.         printErr ("pkTestUnit: nbBufWrite is 0 : ERRORn");
  1444.         return (ERROR);
  1445. }
  1446.     IF_BAD_BUFSIZE(pB, p->size)
  1447. {
  1448.         printErr ("pkTestUnit: bufSize not a multiple of block size : ERRORn");
  1449. return (ERROR);
  1450. }
  1451.     /* check if enough place on the device for a cycle */
  1452.     temp = ((p->size / BLK_TO_PHYS(pB, blockSize)) *  p->nbBuf);
  1453.     if ((temp > (pB->blkDev.bd_nBlocks)) ||
  1454. ((temp + p->stBlk) > (pB->blkDev.bd_nBlocks + pB->blockOffset)))
  1455. {
  1456.         printErr ("pkTestUnit: not enough room for a cycle : ERRORn");
  1457. return (ERROR);
  1458. }
  1459.     /* allocate buffers */
  1460.     if ((p->ptR = (UINT8 *) malloc(p->size)) == NULL)
  1461. {
  1462.         printErr ("pkTestUnit: ptRead allocation failed : ERRORn");
  1463. return (ERROR);
  1464. }
  1465.     if ((p->ptW = (UINT8 *) malloc(p->size)) == NULL)
  1466. {
  1467.         printErr ("pkTestUnit: ptWrite allocation failed : ERRORn");
  1468.         free (p->ptR);
  1469. return (ERROR);
  1470. }
  1471.     /* main loop on nbLoop */
  1472.     p->curStartPattern = p->startPattern;
  1473.     p->countErr = 0;
  1474.     for (iLoop = 0; iLoop < p->nbLoop; iLoop ++)
  1475. {
  1476. p->curBlk = p->stBlk;
  1477. p->curPattern = p->curStartPattern;
  1478. /* refresh curCycle for spy */
  1479.         p->curCycle = iLoop;
  1480. /* check for abort */
  1481. if (p->abort == TRUE)
  1482.    return (OK);
  1483. /* write loop */
  1484.         for (iWrite = 0; iWrite < p->nbBuf; iWrite ++)
  1485.     {
  1486.     if (iWrite == 0)
  1487. {
  1488. printf ("pkTestUnit: beginning write loopn");
  1489. }
  1490.     if (iWrite == p->nbBuf / 2)
  1491. {
  1492. printf ("pkTestUnit: half way through write loopn");
  1493. }
  1494.     /* check for abort */
  1495.     if (p->abort == TRUE)
  1496.                return (OK);
  1497.     /* fill the buffer with pattern according to the law */
  1498.     if ((pkBufFillPattern (p->ptW, p->size, p->law,
  1499.                      &p->curPattern,
  1500.              &curEndPattern)) == ERROR)
  1501.                 {
  1502. printErr ("pkTestUnit: fatal fill buffer error : ERRORn");
  1503. return (ERROR);
  1504. }
  1505.     if (pkBlkWrite (pB, (char *) p->ptW, p->size, &p->curBlk) == ERROR)
  1506.                 {
  1507. printErr ("pkTestUnit: fatal write error : ERRORn");
  1508. return (ERROR);
  1509. }
  1510.             (p->curPattern) ++;
  1511.             }
  1512. p->curBlk = p->stBlk;
  1513. p->curPattern = p->curStartPattern;
  1514. /* read loop */
  1515.         for (iRead = 0; iRead < p->nbBuf; iRead ++)
  1516.     {
  1517.     if (iRead == 0)
  1518. {
  1519. printf ("pkTestUnit: beginning read loopn");
  1520. }
  1521.     if (iRead == p->nbBuf / 2)
  1522. {
  1523. printf ("pkTestUnit: half way through read loopn");
  1524. }
  1525.     /* check for abort */
  1526.     if (p->abort == TRUE)
  1527. {
  1528. return (OK);
  1529. }
  1530.     if ((pkBufFillPattern (p->ptW, p->size, p->law,
  1531.              &p->curPattern, &curEndPattern)) == ERROR)
  1532.                 {
  1533. printErr ("pkTestUnit: fatal fill buffer error : ERRORn");
  1534. return (ERROR);
  1535. }
  1536.     if (pkBlkRead (pB, (char *) p->ptR , p->size, &p->curBlk) == ERROR)
  1537.                 {
  1538. printErr ("pkTestUnit: fatal read error : ERRORn");
  1539. return (ERROR);
  1540. }
  1541.            /* compare buffers */
  1542.    if (bcmp ((char *) p->ptR,(char *) p->ptW, p->size) != 0)
  1543.        {
  1544.        (p->countErr) ++;
  1545.        printErr ("    Loop  :0x%08xn", iLoop);
  1546.        printErr ("    Buffer:0x%08xn", iRead);
  1547.                printErr ("pkTestUnit: buffer compare error : ERRORn");
  1548.        /* check for abort on Error */
  1549.        if (p->abortOnError == TRUE)
  1550.    return (OK);
  1551.        }
  1552.             p->curPattern ++;
  1553.             } /* nbBufRead */
  1554.         /* inc start pattern for the next cycle */
  1555. p->curStartPattern ++;
  1556.         } /* nbLoop */
  1557.     /* release resources */
  1558.     free (p->ptR);
  1559.     free (p->ptW);
  1560.     return (p->countErr);
  1561.     }
  1562. /*******************************************************************************
  1563. *
  1564. * pkTestOneUnit - test one SCSI unit
  1565. *
  1566. * This routine creates a SCSI device as specified by <devId> and <devLun> then
  1567. * calls pkTestUnit() to perform a read/write test on the device.
  1568. * Because it uses a global RW_TEST_UNIT structure it is not reentrant.
  1569. *
  1570. * If <bufSize> = 0, use default of DEF_BUF_SIZE.
  1571. * If <nbBuf>   = 0, use default of DEF_NB_BUF.
  1572. * If <nbLoop>  = 0, write/read entire device.
  1573. *
  1574. * NOTE:
  1575. * Warning!  This routine calls scsiPhysDevCreate() and scsiBlkDevCreate().
  1576. * All data on the file system will be erased.
  1577. *
  1578. * RETURNS: OK, or ERROR if test fails.
  1579. *
  1580. * SEE ALSO: pkTestUnit()
  1581. */
  1582. STATUS pkTestOneUnit
  1583.     (
  1584.     int devId, /* scsi id of the device */
  1585.     int devLun, /* lun id of the devicer */
  1586.     UINT32 bufSize, /* buffer size to use */
  1587.     int nbBuf, /* number of buffers to write */
  1588.     int nbLoop /* number of loops to perform */
  1589.     )
  1590.     {
  1591.     SCSI_PHYS_DEV *pPhysDev;
  1592.     BLK_DEV *pBlkDev;
  1593.     STATUS status;
  1594.     /* create physical SCSI device */
  1595.     if ((pPhysDev=scsiPhysDevIdGet(0,devId,devLun))==(SCSI_PHYS_DEV *)NULL)
  1596.         if ((pPhysDev=scsiPhysDevCreate(pSysScsiCtrl,devId,devLun,0,NONE,0,0,0))         == (SCSI_PHYS_DEV *) NULL)
  1597.             {
  1598.     printErr ("pkTestOneUnit: scsiPhysDevCreate() failed : ERRORn");
  1599.     return (ERROR);
  1600.     }
  1601.     /* create logical SCSI device */
  1602.     if ((pBlkDev = scsiBlkDevCreate (pPhysDev, 0, 0)) == NULL)
  1603. {
  1604.         printErr ("pkTestOneUnit: scsiBlkDevCreate() failed : ERRORn");
  1605. return (ERROR);
  1606.         }
  1607.     /* fill in the RW_TEST_UNIT information */
  1608.     pTestUnit->pBlk = pBlkDev;
  1609.     pTestUnit->size = (bufSize == 0) ? DEF_BUF_SIZE : bufSize;
  1610.     pTestUnit->nbBuf = (nbBuf == 0) ? DEF_NB_BUF : nbBuf;
  1611.     if (nbLoop == 0)
  1612.         {
  1613.         /* entire device */
  1614.         UINT32 nbblock       = ((SCSI_BLK_DEV *) pBlkDev)->blkDev.bd_nBlocks;
  1615.         UINT32 blsize        = BLK_TO_PHYS (pBlkDev, blockSize);
  1616.         pTestUnit->nbBuf  = nbblock / (pTestUnit->size / blsize);
  1617.         pTestUnit->nbLoop = 1;
  1618.         }
  1619.     else
  1620.         pTestUnit->nbLoop = nbLoop;
  1621.     pTestUnit->startPattern = ST_PATTERN; /* start pattern */
  1622.     pTestUnit->law          = DEF_LAW; /* fill law */
  1623.     pTestUnit->abortOnError = TRUE; /* set abort on data error */
  1624.     pTestUnit->abort        = FALSE; /* disable abort flag */
  1625.     /* call pkTestUnit() */
  1626.     status = (pkTestUnit (pTestUnit) || pTestUnit->countErr) ? ERROR : OK;
  1627.     /* releases resources and return */
  1628.     scsiPhysDevDelete (pPhysDev);
  1629.     if (status == OK)
  1630.         printf("PASSn");
  1631.     else
  1632.         printf("ERRORn");
  1633.     return (status);
  1634.     }
  1635. #endif /* INCLUDE_SCSI */
  1636. /*******************************************************************************
  1637. *
  1638. * pkPrintTest - print the given string to the console.
  1639. *
  1640. * This routine prints the given string.
  1641. *
  1642. * RETURNS: N/A
  1643. */
  1644. void pkPrintTest
  1645.     (
  1646.     char *mesg, /* message to be printed */
  1647.     int delayTime /* task delay if required */
  1648.     )
  1649.     {
  1650.     taskDelay(delayTime);
  1651.     printf("%sn",mesg);
  1652.     }
  1653. /*******************************************************************************
  1654. *
  1655. * pkPrintTest1 - print the given string to the console.
  1656. *
  1657. * This routine prints the given string.
  1658. *
  1659. * RETURNS: N/A
  1660. */
  1661. void pkPrintTest1
  1662.     (
  1663.     int fd,
  1664.     char *mesg, /* message to be printed */
  1665.     int delayTime /* task delay if required */
  1666.     )
  1667.     {
  1668.     taskDelay(delayTime);
  1669.     write(fd, mesg, strlen(mesg));
  1670.     }
  1671. /*******************************************************************************
  1672. *
  1673. * pkDivideZeroTest - used to check for divide by zero exception.
  1674. *
  1675. *
  1676. * RETURNS: N/A
  1677. */
  1678. void  pkDivideZeroTest (void)
  1679.       {
  1680.       int a;
  1681.       int b=5;
  1682.       int c=0;
  1683.       taskDelay(200);
  1684.       a=b/c;
  1685.       printf("The value of a is %dn", a);
  1686.       }
  1687. /******************************************************************************
  1688. *
  1689. * pkUdpEchoT - main routine to open sockets, send and receive packets
  1690. *
  1691. * This routine opens an internet socket with a remote target, which is assumed
  1692. * to be running a UDP echo server.  Once connected, a loop is entered where
  1693. * UDP packets of differing sizes are sent to, and received from, the target.
  1694. * Each returning packet is checked for the correct size and content.  A
  1695. * packet sent, but not received back within the timeout may be resent by
  1696. * alarm_handler().  The test passes, exiting with value 0, if all packets
  1697. * were sent and received, regardless of how many individual packets
  1698. * needed to be resent. The IP address of the remote target has to be supplied
  1699. * with all individual bytes as seperate arguments.
  1700. *
  1701. * RETURNS: exit status: 0 if OK
  1702. */
  1703. void pkUdpEchoT
  1704.     (
  1705.     int addr1,  /* first byte in the IP address */
  1706.     int addr2,
  1707.     int addr3,
  1708.     int addr4,  /* last byte in the IP address */
  1709.     int     packetsToSend,
  1710.     int     timeout
  1711.     )
  1712.     {
  1713.     int    div; /* divisor for status messages */
  1714.     int    tenth = 0; /* status message counter */
  1715.     int    ix, iy;                      /* loop counters */
  1716.     int    cnt; /* count of bytes sent/received */
  1717.     int    prevPktSiz = -99; /* packet size just sent */
  1718.     int    localSktAddrLen; /* local copy of sktAddrLen */
  1719.     short  *pShort;                     /* counter to form output buffer */
  1720.     struct sockaddr_in cli_addr;        /* host socket data */
  1721.     int    sktBufSiz;
  1722.     struct fd_set readFs;
  1723.     int    ret;
  1724.     struct timeval pktTimeout;
  1725.     u_long  inetAdrs;
  1726.     char inetDotAdrs[60];
  1727.     sprintf(inetDotAdrs, "%d.%d.%d.%d", addr1, addr2, addr3, addr4);
  1728.     inetAdrs = inet_addr(inetDotAdrs);
  1729.     /* convert command line args */
  1730.     if (packetsToSend < 1)
  1731. {
  1732. printf ("Error: no packets to sendn");
  1733. fflush (stdout);
  1734. exit (9);
  1735. }
  1736.     /* check if inet address is non-null */
  1737.     if (inetAdrs == 0)
  1738.         {
  1739.         printf ("Error: illegal inet addressn");
  1740.         exit (9);
  1741.         }
  1742.     /* turn off timer if bad arg */
  1743.     packetTMO = timeout;
  1744.     if (packetTMO < 0)
  1745. packetTMO = 0;
  1746.     pktTimeout.tv_sec  = 0;
  1747.     pktTimeout.tv_usec = packetTMO * 1000;
  1748.     /* open the socket */
  1749.     skt = socket (AF_INET, SOCK_DGRAM, 0);
  1750.     if (skt < 0)
  1751.         {
  1752.         printf ("Error: socket() failuren");
  1753. fflush (stdout);
  1754.         exit (2);
  1755.         }
  1756.     /* prepare our sock addr */
  1757.     sktAddrLen = sizeof (struct sockaddr_in);
  1758.     (void) memset (&cli_addr, 0, sktAddrLen);           /* clr it */
  1759.     cli_addr.sin_family = AF_INET;                      /* fill in family */
  1760.     cli_addr.sin_port = 0;                              /* port */
  1761.     /* bind our addr to the socket */
  1762.     if (bind (skt, (struct sockaddr *) &cli_addr, sktAddrLen) < 0)
  1763.         {
  1764.         printf ("Error: bind() failuren");
  1765. fflush (stdout);
  1766.         close (skt);
  1767.         exit (3);
  1768.         }
  1769.     /* specify max buffer size on send/receive */
  1770.     sktBufSiz = sizeof (buf);         /* increase size of socket buffers */
  1771.     if (setsockopt (skt, SOL_SOCKET, SO_SNDBUF, (char *) &sktBufSiz,
  1772.         sizeof (sktBufSiz)) < 0)
  1773.         {
  1774.         close (skt);
  1775.         printf ("Error: setsockopt() failuren");
  1776. fflush (stdout);
  1777.         exit (3);
  1778.         }
  1779.     if (setsockopt (skt, SOL_SOCKET, SO_RCVBUF, (char *) &sktBufSiz,
  1780.         sizeof (sktBufSiz)) < 0)
  1781.         {
  1782.         close (skt);
  1783.         printf ("Error: setsockopt() failuren");
  1784. fflush (stdout);
  1785.         exit (4);
  1786.         }
  1787.     /* prepare server's sock addr */
  1788.     (void) memset (&serv_addr, 0, sktAddrLen);          /* clr it */
  1789.     serv_addr.sin_family = AF_INET;                     /* fill in family */
  1790.     serv_addr.sin_addr.s_addr = inetAdrs;    /* get IP addr */
  1791.     serv_addr.sin_port = htons(IPPORT_ECHO);            /* the ECHO port */
  1792.     /*
  1793.      * Prepare the outgoing data.
  1794.      * The buffer is treated as an array of short integers,
  1795.      * each is sequentially numbered, starting from zero.
  1796.      */
  1797.     pShort = (short *) dataOut;
  1798.     for (ix = 0; ix < (MAX_PKT/sizeof (short)); ix++)
  1799.         *pShort++ = ix;
  1800.     /* Main loop.  Send a packet and wait for it to come back */
  1801.     div=packetsToSend/10;
  1802.     printf("Sending %d packetsn", packetsToSend);
  1803.     fflush (stdout);
  1804.     for (packetNum = 0; packetNum < packetsToSend; packetNum++)
  1805.         {
  1806.         /* print status message */
  1807.         if (div > 0)
  1808.     if ((packetNum % div) == (div -1))
  1809.         printf ("%d/10 through UDP echo testn", ++tenth);
  1810. fflush (stdout);
  1811.         curPktSiz = pktSizes [packetNum % N_SIZES];
  1812.         /* send a packet */
  1813.         cnt = sendto (skt, dataOut, curPktSiz, 0,
  1814.       (struct sockaddr *) &serv_addr, sktAddrLen);
  1815.         /* check that entire packet was sent */
  1816.         if (cnt != curPktSiz)
  1817.             {
  1818.             printf ("Error: could not send packet #%d, size %dn",
  1819.     packetNum, curPktSiz);
  1820.     fflush (stdout);
  1821.             exit (4);
  1822.             }
  1823.         /* expect it back - clear out previously resent packets */
  1824.         do {
  1825.             FD_ZERO (&readFs);
  1826.             FD_SET (skt, &readFs);
  1827.             ret = select (skt +1, &readFs, NULL, NULL, &pktTimeout);
  1828.             if (ret == 0)
  1829.                {
  1830.             if (resendCnt++ == RESEND)
  1831.            {
  1832.            /* already resent specified times - fail */
  1833.                    close (skt);
  1834.            printf ("Error: timed out waiting for packet #%dn",
  1835.                     packetNum);
  1836.                    printf ("UDP echo test failedn");
  1837.                    fflush (stdout);
  1838.            exit (7);
  1839.            }
  1840.                else
  1841.                    {
  1842.            resendTotal ++;   /* bump counter */
  1843.                    printf("Timed out Resending packet:%d trial:%dn",
  1844.                              packetNum, resendCnt);
  1845.                    fflush (stdout);
  1846.                    cnt = sendto (skt, dataOut, curPktSiz, 0,
  1847.                 (struct sockaddr *) &serv_addr, sktAddrLen);
  1848.                    /* check that entire packet was sent */
  1849.                    if (cnt != curPktSiz)
  1850.                       {
  1851.                       printf ("Error: could not send packet #%d, size %dn",
  1852.                packetNum, curPktSiz);
  1853.               fflush (stdout);
  1854.                       exit (4);
  1855.                       }
  1856.                    }
  1857.                }
  1858.             else if (ret == ERROR)
  1859.                {
  1860.                printf ("Error: select failedn");
  1861.                close (skt);
  1862.                exit(9);
  1863.                }
  1864.             else
  1865.                {
  1866.                localSktAddrLen = sktAddrLen;
  1867.                cnt = recvfrom (skt, dataIn, curPktSiz, 0,
  1868.     (struct sockaddr *) &serv_addr, &localSktAddrLen);
  1869.        }
  1870. } while ((cnt == prevPktSiz) || (cnt == -1));
  1871.         resendCnt = 0;
  1872. /* check that packet received is correct size */
  1873.         if (cnt != curPktSiz)
  1874.             {
  1875.             printf ("Error: remote host echoed wrong size in packet #%dn",
  1876.     packetNum);
  1877.     fflush (stdout);
  1878.     close (skt);
  1879.             exit (5);
  1880.             }
  1881.         /* verify the received data */
  1882.         for (iy = curPktSiz; iy--;)
  1883.             {
  1884.             if (dataIn [iy] != dataOut [iy])
  1885.                 {
  1886.                 printf ("Error: echoed data does not match in packet #%dn",
  1887. packetNum);
  1888. close (skt);
  1889.         fflush (stdout);
  1890.                 exit (6);
  1891.                 }
  1892.             }
  1893.         prevPktSiz = curPktSiz;
  1894.         }
  1895.     /* print exit messages - test passed */
  1896.     printf ("nnTotal packets resent: %dn", resendTotal);
  1897.     printf ("UDP echo test passedn");
  1898.     printf ("END OF UDP TESTn");
  1899.     fflush (stdout);
  1900.     close (skt);
  1901.     exit (0);
  1902.     }
  1903. /*******************************************************************************
  1904. *
  1905. * pkIntGet - read an int at a given address
  1906. *
  1907. * RETURNS: content of address.
  1908. *
  1909. * SEE ALSO: pkTestSet()
  1910. */
  1911. int pkIntGet
  1912.    (
  1913.    int *pMem
  1914.    )
  1915.    {
  1916.    return *pMem;
  1917.    }
  1918. /*******************************************************************************
  1919. *
  1920. * pkIntSet - store an int at a given address
  1921. *
  1922. * RETURNS: N/A
  1923. *
  1924. * SEE ALSO: pkTestGet()
  1925. */
  1926. void pkIntSet
  1927.    (
  1928.    int *pMem,
  1929.    int val
  1930.    )
  1931.    {
  1932.    *pMem = val;
  1933.    }
  1934. /*******************************************************************************
  1935. *
  1936. * pkPing - perform a call to ping()
  1937. *
  1938. *
  1939. * RETURNS: N/A
  1940. *
  1941. */
  1942. void pkPing
  1943.    (
  1944.    int addrByte0, /* most significant byte of IP address */
  1945.    int  addrByte1,
  1946.    int  addrByte2,
  1947.    int  addrByte3, /* least sigificant byte of IP address */
  1948.    int  numPkts, /* number of packets to send */
  1949.    int options
  1950.    )
  1951.    {
  1952.    char  buffer[60];
  1953.    sprintf(buffer, "%d.%d.%d.%d", addrByte0, addrByte1, addrByte2, addrByte3);
  1954.    ping(buffer, numPkts, options);
  1955.    }
  1956. /*******************************************************************************
  1957. *
  1958. * pkBusErrorTest - performs a string comparison with an invalid address to cause
  1959. *                  bus error exception
  1960. *
  1961. *
  1962. * RETURNS: returns 0 or 1 depending on string compare result otherwise should
  1963. *           cause a bus error
  1964. *
  1965. */
  1966. int pkBusErrorTest
  1967.     (
  1968.     char * str2
  1969.     )
  1970.     {
  1971.     char * str1 = "This is a sample string" ;
  1972.     for(; *str1 == *str2 ; str1++ , str2++)
  1973.         if (*str1 == '')
  1974.         return 0 ;
  1975.     return 1 ;
  1976.     }
  1977. /*****************************************************************************
  1978. *
  1979. * pkPrintSerialOutput - calls pkPrintTest() given the count.
  1980. *
  1981. *
  1982. * RETURNS: N/A
  1983. *
  1984. */
  1985. void pkPrintSerialOutput
  1986.     (
  1987.     int count
  1988.     )
  1989.     {
  1990.     int i;
  1991.     for(i=0; i<count; i++)
  1992.         {
  1993.         pkPrintTest("abcdefghijklmnopqrstuvwxyz" , 1) ;
  1994.         }
  1995.     }
  1996. /*****************************************************************************
  1997. *
  1998. * pkSerialTestInit - initializes the console settings.
  1999. *
  2000. *
  2001. * RETURNS: N/A
  2002. *
  2003. */
  2004. void pkSerialTestInit()
  2005.     {
  2006.     int term1, term2;
  2007.     term1 = ioGlobalStdGet(0);
  2008.     term2 = ioGlobalStdGet(1);
  2009.     (void) ioctl (term1, FIOSETOPTIONS, OPT_TERMINAL);
  2010.     (void) ioctl (term2, FIOSETOPTIONS, OPT_TERMINAL);
  2011.     }
  2012. /*****************************************************************************
  2013. *
  2014. * pkSerialTest - scans console for input strings and stores them in a global
  2015. *                array
  2016. *
  2017. *
  2018. * RETURNS: N/A
  2019. *
  2020. */
  2021. void pkSerialTest()
  2022.     {
  2023.     int i=0;
  2024.     while (i < 15)
  2025.         {
  2026.         if (pkSerChanAbort)
  2027.             break ;
  2028.         scanf("%s",pkSerChanInput[i]) ;
  2029.         i++ ;
  2030.         }
  2031.     }
  2032. /*****************************************************************************
  2033. *
  2034. * pkSerChanOutput - prints the contents of the global array received by
  2035. *                   pkSerialTest()
  2036. *
  2037. *
  2038. * RETURNS: N/A
  2039. *
  2040. */
  2041. void pkSerChanOutput
  2042.     (
  2043.     int index
  2044.     )
  2045.     {
  2046.     int term;
  2047.     term = ioGlobalStdGet(1);
  2048.     if (index < 15)
  2049.         {
  2050. write(term, pkSerChanInput[index], strlen(pkSerChanInput[index]));
  2051. }
  2052.     }
  2053. /*****************************************************************************
  2054. *
  2055. * pkCatastrophicTest - performs catastrophic test given an error address.
  2056. *
  2057. * This functions connects 'strcmp' routine to the system clock interrupt
  2058. * with an invalid address as the argument. This should cause a catastrophic
  2059. * error on the target and the target should reboot with an exception.
  2060. *
  2061. * RETURNS: ERROR if no exception is generated.
  2062. *
  2063. */
  2064. STATUS pkCatastrophicTest
  2065.     (
  2066.     UINT32 obErrAdrs
  2067.     )
  2068.     {
  2069.     sysClkDisable();
  2070.     if ((sysClkConnect((FUNCPTR) strcmp, obErrAdrs) == ERROR))
  2071.         return(ERROR);
  2072.     sysClkEnable();
  2073.     return(ERROR);
  2074.     }
  2075. /******************************************************************************
  2076. *
  2077. * pkCatastrophicClean - clean-up for pkCatastrophicTest() routine.
  2078. *
  2079. * This functions does clean-up if pkCatastrophicTest() function fails and
  2080. * ensures proper operation of system clock.
  2081. *
  2082. * RETURNS: N/A
  2083. *
  2084. */
  2085. VOID pkCatastrophicClean ()
  2086.     {
  2087.     sysClkDisable();
  2088.     sysClkConnect((FUNCPTR) tickAnnounce, 0);
  2089.     sysClkEnable();
  2090.     }