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

VxWorks

开发平台:

C/C++

  1. /* usrLib.c - user interface subroutine library */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 09d,14may02,fmk  add support for common symbols and load flags to ld
  8. 09c,10may02,pcm  changed sp help message from opt=0 to opt=0x19
  9. 09b,08mar02,jn   add error message for ld failing due to undefined symbols
  10. 09a,16oct01,jn   use symFindSymbol for symbol lookup (SPR #7453)
  11. 08z,16oct01,gls  update printLogo() copyright notice to 2002
  12.                  changed printLogo() and version() to use 
  13.  runtimeName and runtimeVersion
  14. 08y,01oct01,dcb  Fix SPR 21134.  Change code to remove compiler warnings.
  15. 08x,03apr01,kab  Fixed _WRS_ALTIVEC_SUPPORT
  16. 08w,28mar01,dtr  Putting in #if _WRS_ALTIVEC_SUPPORT.
  17. 08v,19mar01,dtr  Changing header file name altiVecLib.h .
  18. 08u,29jan01,dtr  Adding support for altivec register set.
  19. 08v,18feb99,jpd  Changed 1998 to 1999 in printLogo
  20. 08u,13nov98,cdp  make periodRun, repeatRun force Thumb state for all ARM CPUs
  21.  with ARM_THUMB==TRUE.
  22. 08v,27feb01,hk   update printLogo() copyright notice to cover 2001.
  23. 08u,21jun00,rsh  upgrade to dosFs 2.0
  24. 09d,31jul99,jkf  T2 merge, tidiness & spelling, 1998-2000.
  25. 09c,29sep98,lrn  merge DosFs 2.0 changes into T2.0 base
  26. 09b,14jul98,lrn  removed all RT-11 references, rt11FsLib is obsolete,
  27.  refuning configuration issues
  28. 09a,30jun98,lrn  moved I/O functions to usrFsLib.c, fixed warnings
  29. 08s,08mar98,ms   Changed 1997 to 1998 in printLogo
  30. 08r,14jul97,dgp  doc: add windsh x-ref to bootChange(), cd(), help(), ls(), 
  31.       mRegs(), & printErrno(), change ^D to CTRL-D in copy()
  32. 08t,09oct97,cdp  added ARM7TDMI_T (Thumb) support.
  33. 08s,26feb97,p_m  Changed 1996 to 1997 in printLogo (SPR# 8068).
  34.  removed pre 1995 history.
  35. 08r,10jan97,cdp  changed copyright to 1997.
  36. 08q,28nov96,cdp  added ARM support.
  37. 08p,13aug96,dbt  added test in changeFpReg to exit if string = "." (SPR #6740).
  38. 08o,09aug96,dbt  modified copy to correctly close file descriptors (SPR #1308).
  39. 08n,19jun96,dgp  doc: changed note on ll() with netDrv (SPR #6560), fixed 
  40.  rev nos.
  41. 08m,09may96,myz  removed #if statement for i960 in checkStack routine
  42. 08l,17jan96,kkk  changed copyright year from 1995 to 1996.
  43. 08k,06oct95,jdi  doc: changed Debugging .pG's to .tG "Shell", updated pathnames
  44.  for Tornado.
  45. 08j,12jun95,p_m  added reference to spyLib in man pages.
  46. 08i,27may95,p_m  added spy(), spyHelp(), spyReport(), spyClkStart()
  47.  spyClkStop(), spyStop() and spyTask().
  48. 08h,01may95,kkk  fixed incorrect modifications of mRegs (SPR #4241)
  49. 08g,30mar95,kdl  removed obsolete stat structure fields; removed unused d() var.
  50. 08f,24mar95,tpr  removed INTERRUPT line in checkStack() for the 060 (SPR #4107).
  51. 08e,20mar95,jdi  doc tweaks to d() and l().
  52. 08d,03mar95,jdi  fixed typo in man page for sp().
  53. 08c,10feb95,jdi  doc format tweaks.  Made substrcmp() NOMANUAL.
  54. 08b,18jan95,rhp  Doc: explain cd() does no checking for paths over netDrv.
  55. 08a,06jan95,kdl  Changed copyright to 1995.
  56. */
  57. /*
  58. This library consists of routines meant to be executed from the VxWorks
  59. shell.  It provides useful utilities for task monitoring and execution,
  60. system information, symbol table management, etc.
  61. Many of the routines here are simply command-oriented interfaces to more
  62. general routines contained elsewhere in VxWorks.  Users should feel free
  63. to modify or extend this library, and may find it preferable to customize
  64. capabilities by creating a new private library, using this one as a model,
  65. and appropriately linking the new one into the system.
  66. Some routines here have optional parameters.  If those parameters are zero,
  67. which is what the shell supplies if no argument is typed, default
  68. values are typically assumed.
  69. A number of the routines in this module take an optional task name or ID
  70. as an argument.  If this argument is omitted or zero, the "current" task
  71. is used.  The current task (or "default" task) is the last task
  72. referenced.  The usrLib library uses taskIdDefault() to set and get the
  73. last-referenced task ID, as do many other VxWorks routines.
  74. INCLUDE FILES: usrLib.h
  75. SEE ALSO: usrFsLib, tarLib, spyLib,
  76. .pG "Target Shell,"
  77. windsh,
  78. .tG "Shell"
  79. */
  80. /* LINTLIBRARY */
  81. #include "vxWorks.h"
  82. #if CPU_FAMILY!=I960
  83. #include "a_out.h"
  84. #else /* CPU_FAMILY!=I960 */
  85. #include "b_out.h"
  86. #endif /* CPU_FAMILY!=I960 */
  87. #include "ctype.h"
  88. #include "stdio.h"
  89. #include "ioLib.h"
  90. #include "loadLib.h"
  91. #include "memLib.h"
  92. #include "remLib.h"
  93. #include "string.h"
  94. #include "symLib.h"
  95. #include "ftpLib.h"
  96. #include "sysLib.h"
  97. #include "sysSymTbl.h"
  98. #include "usrLib.h"
  99. #include "version.h"
  100. #include "fppLib.h"
  101. #include "dirent.h"
  102. #include "sys/stat.h"
  103. #include "errnoLib.h"
  104. #include "fcntl.h"
  105. #include "unistd.h"
  106. #include "fioLib.h"
  107. #include "shellLib.h"
  108. #include "vxLib.h"
  109. #include "hostLib.h"
  110. #include "pathLib.h"
  111. #include "iosLib.h"
  112. #include "taskArchLib.h"
  113. #include "kernelLib.h"
  114. #include "logLib.h"
  115. #include "usrLib.h"
  116. #include "objLib.h"
  117. #include "private/cplusLibP.h"
  118. #include "netDrv.h"
  119. #include "smObjLib.h"
  120. #include "time.h"
  121. #include "private/taskLibP.h"
  122. #include "private/funcBindP.h"
  123. #include "nfsLib.h"
  124. #include "dosFsLib.h"
  125. #ifdef _WRS_ALTIVEC_SUPPORT
  126. #include "altivecLib.h"
  127. #endif /* _WRS_ALTIVEC_SUPPORT */
  128. #define MAX_BYTES_PER_LINE       16
  129. #define MAXLINE         80 /* max line length for input to 'm' routine */
  130. #define MAX_DSP_TASKS 500 /* max tasks that can be displayed */
  131. #define MAX_DATE_STRING 21 /* dates have 21 characters */
  132. #define SPY_NOT_SUPPORTED_MSG   "spy not configured into this system.n"
  133. #define USR_DEMANGLE_PRINT_LEN 256  /* Num chars of demangled names to print */
  134. /* sp parameters: change the help message, if these change! */
  135. int spTaskPriority = 100;
  136. int spTaskOptions = VX_SUPERVISOR_MODE | VX_FP_TASK | VX_STDIO;
  137. int spTaskStackSize = 20000;
  138. /* other globals */
  139. BOOL ldCommonMatchAll = TRUE;
  140. /* symbol types in system symbol table */
  141. LOCAL char *typeName [] =
  142.     {
  143.     "????",
  144.     "abs",
  145.     "text",
  146.     "data",
  147.     "bss",
  148.     };
  149. /* things used by lkAddr, lkAddrFind & lkAddrNext */
  150. #define NUM_SYMBLS 3
  151. typedef struct /* SYMBL - symbol table entry used by lkAddr */
  152.     {
  153.     unsigned int addr; /* address associated with symbol */
  154.     char *name; /* points to name in system symbol table */
  155.     SYM_TYPE type; /* type of this symbol table entry */
  156.     } SYMBL;
  157. typedef struct /* LKADDR_ARG */
  158.     {
  159.     int count; /* number of entries printed by lkAddr */
  160.     unsigned int addr; /* target address */
  161.     SYMBL symbl[NUM_SYMBLS];
  162.     } LKADDR_ARG;
  163. /* externals */
  164. IMPORT int sysClkRateGet (void);
  165. IMPORT char * vxRegIntStackBase; /* base of register interrupt stack */
  166. IMPORT char * vxMemIntStackBase; /* base of memory interrupt stack */
  167. #if (CPU_FAMILY == ARM)
  168. IMPORT char *vxSvcIntStackBase; /* SVC-mode stack for int code */
  169. IMPORT char *vxSvcIntStackEnd;
  170. IMPORT char *vxIrqIntStackBase; /* IRQ-mode stack for int code */
  171. IMPORT char *vxIrqIntStackEnd;
  172. #endif /* CPU_FAMILY == ARM */
  173. /* forward declarations */
  174. LOCAL BOOL lkAddrFind (char *name, unsigned int value, SYM_TYPE type,
  175.        LKADDR_ARG *arg);
  176. LOCAL BOOL lkAddrNext (char *name, unsigned int value, SYM_TYPE type,
  177.        LKADDR_ARG *arg);
  178. LOCAL BOOL lkAddrPrintSame (char *name, unsigned int value, SYM_TYPE type,
  179.             LKADDR_ARG *arg);
  180. LOCAL void printStackSummary (TASK_DESC *pTd);
  181. LOCAL void printSTE (unsigned int addr, char *name, SYM_TYPE type);
  182. LOCAL STATUS changeFpReg (char *pPrompt, double value, double *pValue);
  183. STATUS changeReg (char *pPrompt, void *value, int width);
  184. /*******************************************************************************
  185. *
  186. * help - print a synopsis of selected routines
  187. *
  188. * This command prints the following list of the calling sequences for
  189. * commonly used routines, mostly contained in usrLib.
  190. * .CS
  191. * help                       Print this list
  192. * ioHelp                     Print I/O utilities help info
  193. * dbgHelp                    Print debug help info
  194. * nfsHelp                    Print nfs help info
  195. * netHelp                    Print network help info
  196. * spyHelp                    Print task histogrammer help info
  197. * timexHelp                  Print execution timer help info
  198. * h         [n]              Print (or set) shell history
  199. * i         [task]           Summary of tasks' TCBs
  200. * ti        task             Complete info on TCB for task
  201. * sp        adr,args...      Spawn a task, pri=100, opt=0x19, stk=20000
  202. * taskSpawn name,pri,opt,stk,adr,args... Spawn a task
  203. * td        task             Delete a task
  204. * ts        task             Suspend a task
  205. * tr        task             Resume a task
  206. * d         [adr[,nunits[,width]]]   Display memory
  207. * m         adr[,width]      Modify memory
  208. * mRegs     [reg[,task]]     Modify a task's registers interactively
  209. * pc        [task]           Return task's program counter
  210. * version                    Print VxWorks version info, and boot line
  211. * iam     "user"[,"passwd"]  Set user name and passwd
  212. * whoami                     Print user name
  213. * devs                       List devices
  214. * ld        [syms[,noAbort][,"name"]] Load std in into memory
  215. *                              (syms = add symbols to table:
  216. *                               -1 = none, 0 = globals, 1 = all)
  217. * lkup      ["substr"]       List symbols in system symbol table
  218. * lkAddr    address          List symbol table entries near address
  219. * checkStack  [task]         List task stack sizes and usage
  220. * printErrno  value          Print the name of a status value
  221. * period    secs,adr,args... Spawn task to call function periodically
  222. * repeat    n,adr,args...    Spawn task to call function n times
  223. *                              (0=forever)
  224. * &NOTE:  Arguments specifying <task> can be either task ID or name.
  225. * .CE
  226. *
  227. * RETURNS: N/A
  228. *
  229. * SEE ALSO:
  230. * .pG "Target Shell"
  231. * windsh,
  232. * .tG "Shell"
  233. */
  234. void help (void)
  235.     {
  236.     static char *help_msg [] = {
  237.     /* page 1 */
  238.     "help                           Print this list",
  239.     "ioHelp                         Print I/O utilities help info",
  240.     "dbgHelp                        Print debugger help info",
  241.     "nfsHelp                        Print nfs help info",
  242.     "netHelp                        Print network help info",
  243.     "spyHelp                        Print task histogrammer help info",
  244.     "timexHelp                      Print execution timer help info",
  245.     "h         [n]                  Print (or set) shell history",
  246.     "i         [task]               Summary of tasks' TCBs",
  247.     "ti        task                 Complete info on TCB for task",
  248.     "sp        adr,args...          Spawn a task, pri=100, opt=0x19, stk=20000",
  249.     "taskSpawn name,pri,opt,stk,adr,args... Spawn a task",
  250.     "td        task                 Delete a task",
  251.     "ts        task                 Suspend a task",
  252.     "tr        task                 Resume a task",
  253.     "d         [adr[,nunits[,width]]] Display memory",
  254.     "m         adr[,width]          Modify memory",
  255.     "mRegs     [reg[,task]]         Modify a task's registers interactively",
  256.     "pc        [task]               Return task's program counter",
  257.     "iam       "user"[,"passwd"]   Set user name and passwd",
  258.     "whoami                         Print user name",
  259.     /* page 2 */
  260.     "devs                           List devices",
  261.     "ld        [syms[,noAbort][,"name"]] Load stdin, or file, into memory",
  262.     "                               (syms = add symbols to table:",
  263.     "                               -1 = none, 0 = globals, 1 = all)",
  264.     "lkup      ["substr"]         List symbols in system symbol table",
  265.     "lkAddr    address              List symbol table entries near address",
  266.     "checkStack  [task]             List task stack sizes and usage",
  267.     "printErrno  value              Print the name of a status value",
  268.     "period    secs,adr,args... Spawn task to call function periodically",
  269.     "repeat    n,adr,args...    Spawn task to call function n times (0=forever)",
  270.     "version                        Print VxWorks version info, and boot line",
  271.     "",
  272.     "NOTE:  Arguments specifying 'task' can be either task ID or name.",
  273.     NULL
  274.     };
  275.     FAST int ix;
  276.     char ch;
  277.     printf ("n");
  278.     for (ix = 0; help_msg [ix] != NULL; ix++)
  279. {
  280. if ((ix+1) % 20 == 0)
  281.     {
  282.     printf ("nType <CR> to continue, Q<CR> to stop: ");
  283.     fioRdString (STD_IN, &ch, 1);
  284.     if (ch == 'q' || ch == 'Q')
  285. break;
  286.     else
  287. printf ("n");
  288.     }
  289. printf ("%sn", help_msg [ix]);
  290. }
  291.     printf ("n");
  292.     }
  293. /*******************************************************************************
  294. *
  295. * netHelp - print a synopsis of network routines
  296. *
  297. * This command prints a brief synopsis of network facilities that are
  298. * typically called from the shell.
  299. * .CS
  300. * hostAdd      "hostname","inetaddr" - add a host to remote host table;
  301. *                                      "inetaddr" must be in standard
  302. *                                      Internet address format e.g. "90.0.0.4"
  303. * hostShow                           - print current remote host table
  304. * netDevCreate "devname","hostname",protocol
  305. *                                    - create an I/O device to access
  306. *                                      files on the specified host
  307. *                                      (protocol 0=rsh, 1=ftp)
  308. * routeAdd     "destaddr","gateaddr" - add route to route table
  309. * routeDelete  "destaddr","gateaddr" - delete route from route table
  310. * routeShow                          - print current route table
  311. * iam          "usr"[,"passwd"]      - specify the user name by which
  312. *                                      you will be known to remote
  313. *                                      hosts (and optional password)
  314. * whoami                             - print the current remote ID
  315. * rlogin       "host"                - log in to a remote host;
  316. *                                      "host" can be inet address or
  317. *                                      host name in remote host table
  318. *
  319. * ifShow       ["ifname"]            - show info about network interfaces
  320. * inetstatShow                       - show all Internet protocol sockets
  321. * tcpstatShow                        - show statistics for TCP
  322. * udpstatShow                        - show statistics for UDP
  323. * ipstatShow                         - show statistics for IP
  324. * icmpstatShow                       - show statistics for ICMP
  325. * arptabShow                         - show a list of known ARP entries
  326. * mbufShow                           - show mbuf statistics
  327. *
  328. * &EXAMPLE:  -> hostAdd "wrs", "90.0.0.2"
  329. *           -> netDevCreate "wrs:", "wrs", 0
  330. *           -> iam "fred"
  331. *           -> copy <wrs:/etc/passwd   /@ copy file from host "wrs" @/
  332. *           -> rlogin "wrs"            /@ rlogin to host "wrs"      @/
  333. * .CE
  334. *
  335. * RETURNS: N/A
  336. *
  337. * SEE ALSO:
  338. * .pG "Target Shell"
  339. */
  340. void netHelp (void)
  341.     {
  342.  static char *help_msg [] =
  343.  {
  344.     /* page 1 */
  345.  "hostAdd   "hostname","inetaddr"    - add a host to remote host table;",
  346.  "                                     "inetaddr" must be in standard",
  347.  "                                     Internet address format e.g. "90.0.0.4"",
  348.  "hostShow                           - print current remote host table",
  349.  "netDevCreate "devname","hostname",protocol",
  350.  "                                   - create an I/O device to access files", "                                     on the specified host",
  351.  "                                     (protocol 0=rsh, 1=ftp)",
  352.  "routeAdd     "destaddr","gateaddr" - add route to route table",
  353.  "routeDelete  "destaddr","gateaddr" - delete route from route table",
  354.  "",
  355.  "routeShow                          - print current route table",
  356.  "iam          "usr"[,"passwd"]      - specify the user name by which you",
  357.  "                                     will be known to remote hosts",
  358.  "                                     (and optional password)",
  359.  "whoami                             - print the current remote ID",
  360.  "rlogin       "host"                - log in to a remote host;",
  361.  "                                     "host" can be inet address or",
  362.  "                                     host name in remote host table",
  363.  "",
  364.  "",
  365.  /* page 2 */
  366.  "ifShow       ["ifname"]            - show info about network interfaces",
  367.  "inetstatShow                       - show all Internet protocol sockets",
  368.  "tcpstatShow                        - show statistics for TCP",
  369.  "udpstatShow                        - show statistics for UDP",
  370.  "ipstatShow                         - show statistics for IP",
  371.  "icmpstatShow                       - show statistics for ICMP",
  372.  "arptabShow                         - show a list of known ARP entries",
  373.  "mbufShow                           - show mbuf statistics",
  374.  "",
  375.  "EXAMPLE:   -> hostAdd "wrs", "90.0.0.2"",
  376.  "           -> netDevCreate "wrs:", "wrs", 0",
  377.  "           -> iam "fred"",
  378.  "           -> copy <wrs:/etc/passwd   /* copy file from host "wrs" */",
  379.  "           -> rlogin "wrs"            /* rlogin to host "wrs" */",
  380.  NULL
  381.  };
  382.     FAST int i;
  383.     char ch;
  384.     printf ("nn");
  385.     for (i = 0; help_msg [i] != NULL; i++)
  386. {
  387. if ((i+1) % 20 == 0)
  388.     {
  389.     printf ("nType <CR> to continue, Q<CR> to stop: ");
  390.     fioRdString (STD_IN, &ch, 1);
  391.     if (ch == 'q' || ch == 'Q')
  392. break;
  393.     else
  394. printf ("n");
  395.     }
  396. printf ("%sn", help_msg [i]);
  397. }
  398.     printf ("n");
  399.     }
  400. /*******************************************************************************
  401. *
  402. * bootChange - change the boot line
  403. *
  404. * This command changes the boot line used in the boot ROMs.  This is useful
  405. * during a remote login session.  After changing the boot parameters, you
  406. * can reboot the target with the reboot() command, and then terminate your
  407. * login ( ~. ) and remotely log in again.  As soon as the system has
  408. * rebooted, you will be logged in again.
  409. *
  410. * This command stores the new boot line in non-volatile RAM, if the target
  411. * has it.
  412. *
  413. * RETURNS: N/A
  414. *
  415. * SEE ALSO:
  416. * windsh,
  417. * .tG "Shell"
  418. */
  419. void bootChange (void)
  420.     {
  421.     bootParamsPrompt (sysBootLine);
  422.     (void)sysNvRamSet (sysBootLine, strlen (sysBootLine) + 1, 0);
  423.     }
  424. /*******************************************************************************
  425. *
  426. * periodRun - call a function periodically
  427. *
  428. * This command repeatedly calls a specified function, with up to eight of its
  429. * arguments, delaying the specified number of seconds between calls.
  430. *
  431. * Normally, this routine is called only by period(), which spawns
  432. * it as a task.
  433. *
  434. * RETURNS: N/A
  435. *
  436. * SEE ALSO: period(),
  437. * .pG "Target Shell"
  438. */
  439. void periodRun
  440.     (
  441.     int secs, /* no. of seconds to delay between calls */
  442.     FUNCPTR func, /* function to call repeatedly */
  443.     int arg1, /* first of eight args to pass to func */
  444.     int arg2,
  445.     int arg3,
  446.     int arg4,
  447.     int arg5,
  448.     int arg6,
  449.     int arg7,
  450.     int arg8
  451.     )
  452.     {
  453. #if ((CPU_FAMILY == ARM) && ARM_THUMB)
  454.     func = (FUNCPTR)((UINT32)func | 1); /* force Thumb state */
  455. #endif
  456.     FOREVER
  457. {
  458. (* func) (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  459. taskDelay (secs * sysClkRateGet ());
  460. }
  461.     }
  462. /*******************************************************************************
  463. *
  464. * period - spawn a task to call a function periodically
  465. *
  466. * This command spawns a task that repeatedly calls a specified function,
  467. * with up to eight of its arguments, delaying the specified number of
  468. * seconds between calls.
  469. *
  470. * For example, to have i() display task information every 5 seconds,
  471. * just type:
  472. * .CS
  473. *     -> period 5, i
  474. * .CE
  475. * NOTE
  476. * The task is spawned using the sp() routine.  See the description
  477. * of sp() for details about priority, options, stack size, and task ID.
  478. *
  479. * RETURNS: A task ID, or ERROR if the task cannot be spawned.
  480. *
  481. * SEE ALSO: periodRun(), sp(),
  482. * .pG "Target Shell,"
  483. * windsh,
  484. * .tG "Shell"
  485. */
  486. int period
  487.     (
  488.     int secs, /* period in seconds        */
  489.     FUNCPTR func, /* function to call repeatedly */
  490.     int arg1, /* first of eight args to pass to func */
  491.     int arg2,
  492.     int arg3,
  493.     int arg4,
  494.     int arg5,
  495.     int arg6,
  496.     int arg7,
  497.     int arg8
  498.     )
  499.     {
  500.     return (sp ((FUNCPTR)periodRun, secs, (int)func, arg1, arg2, arg3, arg4,
  501.        arg5, arg6, arg7));
  502.     }
  503. /*******************************************************************************
  504. *
  505. * repeatRun - call a function repeatedly
  506. *
  507. * This command calls a specified function <n> times, with up to eight of its
  508. * arguments.  If <n> is 0, the routine is called endlessly.
  509. *
  510. * Normally, this routine is called only by repeat(), which spawns it as a
  511. * task.
  512. *
  513. * RETURNS: N/A
  514. *
  515. * SEE ALSO: repeat(),
  516. * .pG "Target Shell"
  517. */
  518. void repeatRun
  519.     (
  520.     FAST int  n, /* no. of times to call func (0=forever) */
  521.     FAST FUNCPTR func, /* function to call repeatedly         */
  522.     int arg1, /* first of eight args to pass to func */
  523.     int arg2,
  524.     int arg3,
  525.     int arg4,
  526.     int arg5,
  527.     int arg6,
  528.     int arg7,
  529.     int arg8
  530.     )
  531.     {
  532.     FAST BOOL infinite = (n == 0);
  533. #if ((CPU_FAMILY == ARM) && ARM_THUMB)
  534.     func = (FUNCPTR)((UINT32)func | 1); /* force Thumb state */
  535. #endif
  536.     while (infinite || (--n >= 0))
  537. (* func) (arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  538.     }
  539. /*******************************************************************************
  540. *
  541. * repeat - spawn a task to call a function repeatedly
  542. *
  543. * This command spawns a task that calls a specified function <n> times, with
  544. * up to eight of its arguments.  If <n> is 0, the routine is called
  545. * endlessly, or until the spawned task is deleted.
  546. *
  547. * NOTE
  548. * The task is spawned using sp().  See the description of sp() for details
  549. * about priority, options, stack size, and task ID.
  550. *
  551. * RETURNS: A task ID, or ERROR if the task cannot be spawned.
  552. *
  553. * SEE ALSO: repeatRun(), sp(),
  554. * .pG "Target Shell,"
  555. * windsh,
  556. * .tG "Shell"
  557. */
  558. int repeat
  559.     (
  560.     FAST int  n, /* no. of times to call func (0=forever) */
  561.     FAST FUNCPTR func, /* function to call repeatedly         */
  562.     int arg1, /* first of eight args to pass to func */
  563.     int arg2,
  564.     int arg3,
  565.     int arg4,
  566.     int arg5,
  567.     int arg6,
  568.     int arg7,
  569.     int arg8
  570.     )
  571.     {
  572.     return (sp ((FUNCPTR)repeatRun, n, (int)func, arg1, arg2, arg3, arg4,
  573.     arg5, arg6, arg7));
  574.     }
  575. /*******************************************************************************
  576. *
  577. * sp - spawn a task with default parameters
  578. *
  579. * This command spawns a specified function as a task with the following
  580. * defaults:
  581. * .IP "priority:" 15
  582. * 100
  583. * .IP "stack size:"
  584. * 20,000 bytes
  585. * .IP "task ID:"
  586. * highest not currently used
  587. * .IP "task options:"
  588. * VX_FP_TASK - execute with floating-point coprocessor support.
  589. * .IP "task name:"
  590. * A name of the form `tN' where N is an integer which increments as new tasks
  591. * are spawned, e.g., `t1', `t2', `t3', etc.
  592. * .LP
  593. * The task ID is displayed after the task is spawned.
  594. *
  595. * This command is a short form of the underlying taskSpawn() routine,
  596. * convenient for spawning tasks in which the default parameters
  597. * are satisfactory.  If the default parameters are unacceptable, taskSpawn()
  598. * should be called directly.
  599. *
  600. * RETURNS: A task ID, or ERROR if the task cannot be spawned.
  601. *
  602. * SEE ALSO: taskLib, taskSpawn(),
  603. * .pG "Target Shell,"
  604. * windsh,
  605. * .tG "Shell"
  606. *
  607. * VARARGS1
  608. */
  609. int sp
  610.     (
  611.     FUNCPTR func, /* function to call       */
  612.     int arg1, /* first of nine args to pass to spawned task */
  613.     int arg2,
  614.     int arg3,
  615.     int arg4,
  616.     int arg5,
  617.     int arg6,
  618.     int arg7,
  619.     int arg8,
  620.     int arg9
  621.     )
  622.     {
  623.     int id;
  624.     if (func == (FUNCPTR)0)
  625. {
  626. printf ("sorry, won't spawn task at PC = 0.n");
  627. return (ERROR);
  628. }
  629.     /* spawn task, let taskSpawn pick the task ID, report success or failure */
  630.     id = taskSpawn ((char *) NULL, spTaskPriority, spTaskOptions,
  631.     spTaskStackSize, func, arg1, arg2, arg3, arg4, arg5,
  632.     arg6, arg7, arg8, arg9, 0);
  633.     if (id == ERROR)
  634. {
  635. printf ("not able to spawn task.n");
  636. return (ERROR);
  637. }
  638.     else
  639. {
  640. printf ("task spawned: id = %#x, name = %sn", id, taskName (id));
  641. return (id);
  642. }
  643.     }
  644. /******************************************************************************
  645. *
  646. * taskIdFigure - translate a task name or ID to a task ID
  647. *
  648. * Many routines in usrLib take a task ID (an integer) or a task name.  This
  649. * routine determines whether the parameter is a task name or a task ID and
  650. * returns the task ID.  If <taskNameOrId> is omitted or 0, the current task
  651. * is used.
  652. *
  653. * RETURNS: A task ID (an integer), or ERROR.
  654. *
  655. * SEE ALSO: taskNameToId(), taskLib
  656. *
  657. * NOMANUAL
  658. */
  659. int taskIdFigure
  660.     (
  661.     int taskNameOrId /* task name or task ID */
  662.     )
  663.     {
  664.     char name [10]; /* number to name */
  665.     int tid; /* task ID */
  666.     int bb; /* bit bucket */
  667.     if (taskNameOrId == 0) /* default task ID */
  668. return (taskIdDefault (0));
  669.     else if (taskIdVerify (taskNameOrId) == OK) /* try explicit ID */
  670. return (taskNameOrId);
  671.     sprintf (name, "%x", taskNameOrId);
  672.     if ((tid = taskNameToId (name)) != ERROR)
  673. return (tid); /* name is a number */
  674.     else if (vxMemProbe ((char *)taskNameOrId, O_RDONLY, 4, (char *)&bb) == OK)
  675. return (taskNameToId ((char *) taskNameOrId)); /* name is a string */
  676.     else
  677. return (ERROR); /* unreasonable name, bus error! */
  678.     }
  679. /*******************************************************************************
  680. *
  681. * checkStack - print a summary of each task's stack usage
  682. *
  683. * This command displays a summary of stack usage for a specified task, or
  684. * for all tasks if no argument is given.  The summary includes the total
  685. * stack size (SIZE), the current number of stack bytes used (CUR), the
  686. * maximum number of stack bytes used (HIGH), and the number of bytes never
  687. * used at the top of the stack (MARGIN = SIZE - HIGH).
  688. * For example:
  689. * .CS
  690. *     -> checkStack tShell
  691. *
  692. *         NAME         ENTRY      TID    SIZE   CUR  HIGH  MARGIN
  693. *     ------------ ------------ -------- ----- ----- ----- ------
  694. *     tShell       _shell       23e1c78   9208   832  3632   5576
  695. * .CE
  696. *
  697. * The maximum stack usage is determined by scanning down from the top of the
  698. * stack for the first byte whose value is not 0xee.  In VxWorks, when a task
  699. * is spawned, all bytes of a task's stack are initialized to 0xee.
  700. *
  701. * DEFICIENCIES
  702. * It is possible for a task to write beyond the end of its stack, but
  703. * not write into the last part of its stack.  This will not be detected
  704. * by checkStack().
  705. *
  706. * RETURNS: N/A
  707. *
  708. * SEE ALSO: taskSpawn(),
  709. * .pG "Target Shell,"
  710. * windsh,
  711. * .tG "Shell"
  712. */
  713. void checkStack
  714.     (
  715.     int taskNameOrId /* task name or task ID; 0 = summarize all */
  716.     )
  717.     {
  718.     FAST int nTasks; /* number of task */
  719.     FAST int ix; /* index */
  720.     FAST char  *pIntStackHigh; /* high interrupt stack usage */
  721.     int tid; /* task ID */
  722.     TASK_DESC td; /* task info structure */
  723.     int idList [MAX_DSP_TASKS]; /* list of active IDs */
  724.     static char checkStackHdr [] = "
  725.   NAME        ENTRY        TID     SIZE   CUR  HIGH  MARGINn
  726. ------------ ------------ -------- ----- ----- ----- ------n";
  727. #if (CPU_FAMILY == ARM)
  728.     char *intStackBase;
  729.     char *intStackEnd;
  730. #else  /* (CPU_FAMILY == ARM) */
  731. #   if (CPU != MC68060) /* we dont currently use this for MC68060 */
  732.     IMPORT char *vxIntStackBase;
  733. #   endif /* CPU != MC68060 */
  734.     IMPORT char *vxIntStackEnd;
  735. #   if    (CPU != MC68060) /* we dont currently use this for MC68060 */
  736.     char *intStackBase = vxIntStackBase;
  737. #   endif /* CPU != MC68060 */
  738.     char *intStackEnd  = vxIntStackEnd;
  739. #endif /* CPU_FAMILY == ARM */
  740.     if (taskNameOrId != 0)
  741. {
  742. /* do specified task */
  743. tid = taskIdFigure (taskNameOrId);
  744. if ((tid == ERROR) || (taskInfoGet (tid, &td) != OK))
  745.     printErr ("Task not found.n");
  746. else
  747.     {
  748.     printf (checkStackHdr);
  749.     printStackSummary (&td);
  750.     }
  751. }
  752.     else
  753. {
  754. /* do all tasks */
  755. printf (checkStackHdr);
  756. nTasks = taskIdListGet (idList, NELEMENTS (idList));
  757. taskIdListSort (idList, nTasks);
  758. for (ix = 0; ix < nTasks; ++ix)
  759.     if (taskInfoGet (idList [ix], &td) == OK)
  760. printStackSummary (&td);
  761. /* find int stack high usage */
  762. #if (CPU_FAMILY != AM29XXX) && (CPU_FAMILY != ARM)
  763. #if  (_STACK_DIR == _STACK_GROWS_DOWN)
  764. for (pIntStackHigh = intStackEnd; * (UINT8 *)pIntStackHigh == 0xee;
  765.      pIntStackHigh ++)
  766.      ;
  767. #else /* _STACK_DIR == _STACK_GROWS_DOWN) */
  768. for (pIntStackHigh = intStackEnd - 1; * (UINT8 *)pIntStackHigh == 0xee;
  769.      pIntStackHigh --)
  770.      ;
  771. #endif /* _STACK_DIR == _STACK_GROWS_DOWN) */
  772. #if (CPU != MC68060)
  773. printf ("%-12.12s %-12.12s", "INTERRUPT", "");
  774. printf (" %8s %5d %5d %5d %6d %sn",
  775.                  "", /* task name */
  776.                  (int)((intStackEnd - intStackBase) *_STACK_DIR), /* stack size */
  777.                  0, /* current */
  778.                  (int)((pIntStackHigh - intStackBase) *_STACK_DIR),
  779.   /* high stack usage */
  780.                  (int)((intStackEnd - pIntStackHigh) * _STACK_DIR), /* margin */
  781.                  (pIntStackHigh == intStackEnd) && /* overflow ? */
  782.  (intStackEnd != intStackBase != 0) ? /* no interrupt stack ? */
  783.                  "OVERFLOW" : "");
  784. #endif 
  785. #else
  786. #if CPU_FAMILY == AM29XXX
  787.        /*
  788. * Since the Am29k family uses 3 interrupt stacks (Exception Stack
  789. * Frame, handler register stack and memory stack), we must compute
  790. * each stack usage inside the global stack area allocated at each
  791. * interrupt. The ESF takes 1/5 of the global area, the register stack
  792. * takes also 1/5 of the global area, and the memory stack takes the
  793. * remainder (3/5). See kernelInit().
  794. */
  795. for (pIntStackHigh = vxRegIntStackBase;
  796.      * (UINT8 *)pIntStackHigh == 0xee; pIntStackHigh ++);
  797. printf ("%-12.12s %-12.12s", "INTERRUPT", "");
  798. printf (" %8s %5d %5d %5d %6d %sn",
  799.                 "", /* task name */
  800.                 (intStackBase - vxRegIntStackBase), /* ESF size */
  801.                 0, /* current */
  802.                 (intStackBase - pIntStackHigh), /* high stack usage */
  803.                 (pIntStackHigh - vxRegIntStackBase), /* margin */
  804.                 (pIntStackHigh == vxRegIntStackBase) && /* overflow ? */
  805. (intStackEnd != intStackBase != 0) ? /* no intr stack ? */
  806.                 "Ker stack OVERFLOW" : "- Kernel   -");
  807. for (pIntStackHigh = vxMemIntStackBase;
  808.      (* (UINT8 *)pIntStackHigh == 0xee) &&
  809.      (pIntStackHigh != vxRegIntStackBase); pIntStackHigh ++);
  810. printf ("%-12.12s %-12.12s", "", "");
  811. printf (" %8s %5d %5d %5d %6d %sn",
  812.                 "", /* task name */
  813.                 (vxRegIntStackBase - vxMemIntStackBase),/* Reg stack size */
  814.                 0, /* current */
  815.                 (vxRegIntStackBase - pIntStackHigh), /* high stack usage */
  816.                 (pIntStackHigh - vxMemIntStackBase), /* margin */
  817.                 (pIntStackHigh == vxMemIntStackBase) && /* overflow ? */
  818. (intStackEnd != intStackBase != 0) ? /* no intr stack ? */
  819.                 "Reg stack OVERFLOW" : "- Register -");
  820. for (pIntStackHigh = intStackEnd;
  821.      (* (UINT8 *)pIntStackHigh == 0xee) &&
  822.      (pIntStackHigh != vxMemIntStackBase); pIntStackHigh ++);
  823. printf ("%-12.12s %-12.12s", "", "");
  824. printf (" %8s %5d %5d %5d %6d %sn",
  825.                 "", /* task name */
  826.                 (vxMemIntStackBase - intStackEnd), /* Mem stack size */
  827.                 0, /* current */
  828.                 (vxMemIntStackBase - pIntStackHigh), /* high stack usage */
  829.                 (pIntStackHigh - intStackEnd), /* margin */
  830.                 (pIntStackHigh == intStackEnd) && /* overflow ? */
  831. (intStackEnd != intStackBase != 0) ? /* no intr stack ? */
  832.                 "Mem stack OVERFLOW" : "- Memory   -");
  833. #else
  834. #if (CPU_FAMILY == ARM)
  835.        /*                                       
  836. * The ARM processor has a separate stack for each of the two
  837. * interrupt modes, IRQ and FIQ, but FIQ is not handled within
  838. * VxWorks. The IRQ entry veneer switches to SVC mode (for
  839. * reentrancy) so there are still two interrupt stacks to print
  840. * out: IRQ and SVC mode.
  841.         */                                      
  842.                                                 
  843.         intStackBase = vxSvcIntStackBase;       
  844.         intStackEnd = vxSvcIntStackEnd;         
  845.         for (pIntStackHigh = intStackEnd;       
  846.              *(UINT8 *)pIntStackHigh == 0xEE && pIntStackHigh < intStackBase;
  847.              pIntStackHigh++)                   
  848.             ;                                   
  849.                                                 
  850.         printf ("%-12.12s %-12.12s", "INTERRUPT", "");
  851.         printf (" %8s %5d %5d %5d %6d %sn",    
  852.                  "",                                    /* task name */
  853.                  (int)(intStackBase - intStackEnd),     /* stack size */
  854.                  0,                                     /* current */
  855.                  (int)(intStackBase - pIntStackHigh),   /* high stack use */
  856.                  (int)(pIntStackHigh - intStackEnd),    /* margin */
  857.                  (pIntStackHigh == intStackEnd) &&      /* overflow ? */
  858.                  (intStackEnd != intStackBase != 0) ?   /* no int stack ? */
  859.                  "SVC stack OVERFLOW" : "- SVC -");
  860.                                                 
  861.                                                 
  862.         intStackBase = vxIrqIntStackBase;       
  863.         intStackEnd = vxIrqIntStackEnd;
  864.         for (pIntStackHigh = intStackEnd;
  865.              *(UINT8 *)pIntStackHigh == 0xEE && pIntStackHigh < intStackBase;
  866.              pIntStackHigh++)
  867.             ;
  868.  
  869.         printf ("%-12.12s %-12.12s", "", "");
  870.         printf (" %8s %5d %5d %5d %6d %sn",
  871.                  "",                                    /* task name */
  872.                  (int)(intStackBase - intStackEnd),     /* stack size */
  873.                  0,                                     /* current */
  874.                  (int)(intStackBase - pIntStackHigh),   /* high stack use */
  875.                  (int)(pIntStackHigh - intStackEnd),    /* margin */
  876.                  (pIntStackHigh == intStackEnd) &&      /* overflow ? */
  877.                  (intStackEnd != intStackBase != 0) ?   /* no int stack ? */
  878.                  "IRQ stack OVERFLOW" : "- IRQ -");
  879.  
  880. #endif /* CPU_FAMILY == ARM */
  881. #endif /* (CPU_FAMILY == AM29XXX) */
  882. #endif /* (CPU_FAMILY != AM29XXX) */
  883. }
  884.     }
  885. /*******************************************************************************
  886. *
  887. * printStackSummary - print task stack summary line
  888. *
  889. * This command is used by checkStack(), to print each task's stack summary line.
  890. */
  891. LOCAL void printStackSummary
  892.     (
  893.     TASK_DESC *pTd
  894.     )
  895.     {
  896.     FUNCPTR   entry; /* task's initial entry point */
  897.     FUNCPTR   symboladdr; /* address associated with 'name' */
  898.     SYMBOL_ID symId;
  899.     char      *name;       /* ptr to sym tbl copy of name of main routine */
  900.     char      demangled[USR_DEMANGLE_PRINT_LEN + 1];
  901.     char      *nameToPrint;
  902.     /* find task's initial entry point, and name (if any) in symbol table */
  903.     entry = pTd->td_entry;
  904.     symFindSymbol (sysSymTbl, NULL, (void *)entry, 
  905.    N_EXT | N_TEXT, N_EXT | N_TEXT, &symId);
  906.     symNameGet (symId, &name);
  907.     symValueGet (symId, (void **)&symboladdr); 
  908.     /* Print the summary of the TCB */
  909.     printf ("%-12.12s", pTd->td_name); /* print the name of the task */
  910.     if (entry == symboladdr) /* entry address (symbolic if poss.) */
  911.         {
  912. nameToPrint = cplusDemangle (name, demangled, sizeof (demangled));
  913. printf (" %-12.12s", nameToPrint);
  914.         }
  915.     else
  916. printf (" %#-12.12x", (int) entry);
  917. #if (CPU_FAMILY != AM29XXX)
  918.     printf (" %-8x %5d %5d ", pTd->td_id, pTd->td_stackSize,
  919.     pTd->td_stackCurrent);
  920.     if (pTd->td_options & VX_NO_STACK_FILL)
  921.         printf ("%5s %6s VX_NO_STACK_FILLn", "???", "???");
  922.     else
  923. printf ("%5d %6d %sn", pTd->td_stackHigh, pTd->td_stackMargin,
  924.      (pTd->td_stackMargin <= 0) ? "OVERFLOW" : "");
  925. #else
  926.     {
  927.     FAST char *pStackHigh;
  928.     UINT regStackEnd; /* end of the register stack */
  929.     int regStackSize; /* size of the register stack */
  930.     int regStackHigh; /* highest position into the register stack */
  931.     int regStackMargin; /* margin left in the register stack */
  932.     UINT memStackBase; /* base of the memory stack */
  933.     int memStackSize; /* size of the memory stack */
  934.     int memStackHigh; /* highest position into the memory stack */
  935.     int memStackMargin; /* margin left in the memory stack */
  936.     int memStackCurrent; /* current position into the memory stack */
  937.     REG_SET regSet;
  938.     /*
  939.      * Since the Am29k family uses 2 stacks (register stack and memory stack),
  940.      * we must compute each stack usage inside the global stack area allocated
  941.      * for each task. The register stack takes 1/4 of the global area, and the
  942.      * memory stack takes the remainder (3/4). See taskRegsInit().
  943.      */
  944.     regStackEnd = (UINT)pTd->td_pStackBase - ((UINT)pTd->td_pStackBase - 
  945.                   (UINT)pTd->td_pStackEnd) / 4;
  946.     if (pTd->td_options & VX_NO_STACK_FILL)
  947.         pStackHigh = (char *)regStackEnd;
  948.     else
  949.         for (pStackHigh = (char *)regStackEnd;
  950.              *(UINT8 *)pStackHigh == 0xee; pStackHigh ++);
  951.     regStackHigh = (int)(pTd->td_pStackBase - pStackHigh);
  952.     regStackSize = (UINT)pTd->td_pStackBase - regStackEnd;
  953.     regStackMargin = regStackSize - regStackHigh;
  954.     printf (" %-8x %5d %5d ", pTd->td_id, regStackSize,
  955.     pTd->td_stackCurrent);
  956.     if (pTd->td_options & VX_NO_STACK_FILL)
  957.         printf ("%5s %6s VX_NO_STACK_FILLn", "???", "???");
  958.     else
  959. printf ("%5d %6d %sn", regStackHigh, regStackMargin,
  960.      (regStackMargin <= 0) ? "Reg stack OVERFLOW" :
  961. "- Register -");
  962.     printf ("                                  ");
  963.     memStackBase = regStackEnd;
  964.     if (pTd->td_options & VX_NO_STACK_FILL)
  965.         pStackHigh = (char *)pTd->td_pStackLimit;
  966.     else
  967.         for (pStackHigh = (char *)pTd->td_pStackLimit;
  968.              (*(UINT8 *)pStackHigh == 0xee) &&
  969.              ((UINT)pStackHigh != memStackBase); pStackHigh ++);
  970.     memStackHigh = (int)(memStackBase - (UINT)pStackHigh);
  971.     memStackSize = memStackBase - (UINT)pTd->td_pStackLimit;
  972.     memStackMargin = memStackSize - memStackHigh;
  973.     taskRegsGet (pTd->td_id, &regSet);
  974.     memStackCurrent = (int)(regSet.msp - memStackBase) * _STACK_DIR;
  975.     if (memStackHigh < memStackCurrent) /* if msp is decremented but */
  976. memStackHigh = memStackCurrent; /* nothing is put in stack */
  977.     printf (" %5d %5d ", memStackSize, memStackCurrent);
  978.     if (pTd->td_options & VX_NO_STACK_FILL)
  979.         printf ("%5s %6s VX_NO_STACK_FILL", "???", "???");
  980.     else
  981. printf ("%5d %6d %sn", memStackHigh, memStackMargin,
  982.      (memStackMargin <= 0) ? "Mem stack OVERFLOW" :
  983. "- Memory   -");
  984.     }
  985. #endif /* (CPU_FAMILY != AM29XXX) */
  986.     }
  987. /*******************************************************************************
  988. *
  989. * i - print a summary of each task's TCB
  990. *
  991. * This command displays a synopsis of all the tasks in the system.
  992. * The ti() routine provides more complete information on a specific task.
  993. *
  994. * Both i() and ti() use taskShow(); see the documentation for taskShow() for 
  995. * a description of the output format.
  996. *
  997. * EXAMPLE:
  998. * .CS
  999. * -> i
  1000. *
  1001. *    NAME       ENTRY     TID    PRI   STATUS    PC       SP    ERRNO DELAY
  1002. * ---------- ---------- -------- --- --------- ------- -------- ----- -----
  1003. * tExcTask   _excTask    20fcb00   0 PEND      200c5fc  20fca6c     0     0
  1004. * tLogTask   _logTask    20fb5b8   0 PEND      200c5fc  20fb520     0     0
  1005. * tShell     _shell      20efcac   1 READY     201dc90  20ef980     0     0
  1006. * tRlogind   _rlogind    20f3f90   2 PEND      2038614  20f3db0     0     0
  1007. * tTelnetd   _telnetd    20f2124   2 PEND      2038614  20f2070     0     0
  1008. * tNetTask   _netTask    20f7398  50 PEND      2038614  20f7340     0     0
  1009. * value = 57 = 0x39 = '9'
  1010. * .CE
  1011. *
  1012. * CAVEAT
  1013. * This command should be used only as a debugging aid, since the information
  1014. * is obsolete by the time it is displayed.
  1015. *
  1016. * RETURNS: N/A
  1017. *
  1018. * SEE ALSO: ti(), taskShow(),
  1019. * .pG "Target Shell,"
  1020. * windsh,
  1021. * .tG "Shell"
  1022. */
  1023. void i
  1024.     (
  1025.     int taskNameOrId /* task name or task ID, 0 = summarize all */
  1026.     )
  1027.     {
  1028.     int tid;
  1029.     if (taskNameOrId == 0)
  1030. show (taskIdSelf (), 2); /* summarize all task's info */
  1031.     else
  1032. {
  1033. tid = taskIdFigure (taskNameOrId);
  1034. if ((tid == ERROR) || (taskIdVerify (tid) != OK))
  1035.     {
  1036.     printErr ("Task not found.n");
  1037.     return;
  1038.     }
  1039. show (tid, 0); /* summarize a task's info */
  1040. }
  1041.     }
  1042. /*******************************************************************************
  1043. *
  1044. * ti - print complete information from a task's TCB
  1045. *
  1046. * This command prints the task control block (TCB) contents, including
  1047. * registers, for a specified task.  If <taskNameOrId> is omitted or zero,
  1048. * the last task referenced is assumed.
  1049. *
  1050. * The ti() routine uses taskShow(); see the documentation for taskShow() for 
  1051. * a description of the output format.
  1052. *
  1053. * EXAMPLE:
  1054. * The following shows the TCB contents for the shell task:
  1055. * .CS
  1056. * -> ti
  1057. *
  1058. *   NAME      ENTRY     TID    PRI  STATUS      PC       SP    ERRNO  DELAY
  1059. * ---------- --------- -------- --- --------- -------- -------- ------ -----
  1060. * tShell     _shell     20efcac   1 READY      201dc90  20ef980      0     0
  1061. *
  1062. * stack: base 0x20efcac  end 0x20ed59c  size 9532   high 1452   margin 8080
  1063. *
  1064. * options: 0x1e
  1065. * &VX_UNBREAKABLE      VX_DEALLOC_STACK    VX_FP_TASK         VX_STDIO
  1066. *
  1067. *
  1068. * &D0 =       0   D4 =       0   A0 =       0   A4 =        0
  1069. * &D1 =       0   D5 =       0   A1 =       0   A5 =  203a084   SR =     3000
  1070. * &D2 =       0   D6 =       0   A2 =       0   A6 =  20ef9a0   PC =  2038614
  1071. * &D3 =       0   D7 =       0   A3 =       0   A7 =  20ef980
  1072. * value = 34536868 = 0x20efda4
  1073. * .CE
  1074. *
  1075. * RETURNS: N/A
  1076. *
  1077. * SEE ALSO:
  1078. * taskShow(),
  1079. * .pG "Target Shell,"
  1080. * windsh,
  1081. * .tG "Shell"
  1082. */
  1083. void ti
  1084.     (
  1085.     int taskNameOrId /* task name or task ID; 0 = use default */
  1086.     )
  1087.     {
  1088.     int tid = taskIdFigure (taskNameOrId);
  1089.     if ((tid == ERROR) || (taskIdVerify (tid) != OK))
  1090. {
  1091. printErr ("Task not found.n");
  1092. return;
  1093. }
  1094.     tid = taskIdDefault (tid); /* set the default task ID */
  1095.     show (tid, 1);
  1096.     }
  1097. /*******************************************************************************
  1098. *
  1099. * show - print information on a specified object
  1100. *
  1101. * This command prints information on the specified object.  System objects
  1102. * include tasks, local and shared semaphores, local and shared message
  1103. * queues, local and shared memory partitions, watchdogs, and symbol tables.
  1104. * An information level is interpreted by the objects show routine on a class
  1105. * by class basis.  Refer to the object's library manual page for more
  1106. * information.
  1107. *
  1108. * RETURNS: N/A
  1109. *
  1110. * SEE ALSO: i(), ti(), lkup(),
  1111. * .pG "Target Shell,"
  1112. * windsh,
  1113. * .tG "Shell"
  1114. */
  1115. void show
  1116.     (
  1117.     int objId, /* object ID */
  1118.     int level /* information level */
  1119.     )
  1120.     {
  1121.     int bb; /* bit bucket for vxMemProbe */
  1122.     if (ID_IS_SHARED (objId))
  1123. {
  1124. if (vxMemProbe ((char *) SM_OBJ_ID_TO_ADRS (objId), VX_READ, 4, 
  1125.                 (char *) &bb) == ERROR)
  1126.     {
  1127.     printf ("Object not found.n");
  1128.     return;
  1129.     }
  1130. if (_func_smObjObjShow != (FUNCPTR) NULL)
  1131.     {
  1132.     (*_func_smObjObjShow) (objId, level);
  1133.     return;
  1134.     }
  1135.         else
  1136.     {
  1137.     printf("Show routine of this object not configured into system.n");
  1138.     return;
  1139.     }
  1140. }
  1141.     /* check for invalid show routine reference */
  1142.     if ((vxMemProbe ((char *) objId, VX_READ, 4, (char *) &bb) == ERROR) ||
  1143. ((((OBJ_ID) ((int)objId + taskClassId->coreOffset))->pObjClass 
  1144.  != taskClassId) &&
  1145.          (vxMemProbe ((char *)((OBJ_ID)objId)->pObjClass,VX_READ,4,(char *)&bb)
  1146.   == ERROR)))
  1147. {
  1148. printf ("Object not found.n");
  1149. }
  1150.     else if (objShow ((OBJ_ID) objId, level) != OK)
  1151. {
  1152. if (errno == S_objLib_OBJ_NO_METHOD)
  1153.     printf("Show routine of this object not configured into system.n");
  1154. else
  1155.     printf ("Object not found.n");
  1156. }
  1157.     }
  1158. /*******************************************************************************
  1159. *
  1160. * ts - suspend a task
  1161. *
  1162. * This command suspends the execution of a specified task.  It simply calls
  1163. * taskSuspend().
  1164. *
  1165. * RETURNS: N/A
  1166. *
  1167. * SEE ALSO: tr(), taskSuspend(),
  1168. * .pG "Target Shell,"
  1169. * windsh,
  1170. * .tG "Shell"
  1171. */
  1172. void ts
  1173.     (
  1174.     int taskNameOrId /* task name or task ID */
  1175.     )
  1176.     {
  1177.     int tid = taskIdFigure (taskNameOrId);
  1178.     if (tid == ERROR) /* no ID found */
  1179. {
  1180. printErr ("Task not found.n");
  1181. return;
  1182. }
  1183.     if (tid == 0) /* default task ID never set */
  1184. printf ("sorry, the shell can't suspend itself.n");
  1185.     else if (taskSuspend (tid) != OK)
  1186. printErrno (0);
  1187.     }
  1188. /*******************************************************************************
  1189. *
  1190. * tr - resume a task
  1191. *
  1192. * This command resumes the execution of a suspended task.  It simply calls
  1193. * taskResume().
  1194. *
  1195. * RETURNS: N/A
  1196. *
  1197. * SEE ALSO: ts(), taskResume(),
  1198. * .pG "Target Shell,"
  1199. * windsh,
  1200. * .tG "Shell"
  1201. */
  1202. void tr
  1203.     (
  1204.     int taskNameOrId /* task name or task ID */
  1205.     )
  1206.     {
  1207.     int tid = taskIdFigure (taskNameOrId);
  1208.     if (tid == ERROR) /* no ID found */
  1209. printErr ("Task not found.n");
  1210.     else if (taskResume (tid) != OK)
  1211. printErrno (0);
  1212.     }
  1213. /*******************************************************************************
  1214. *
  1215. * td - delete a task
  1216. *
  1217. * This command deletes a specified task.  It simply calls taskDelete().
  1218. *
  1219. * RETURNS: N/A
  1220. *
  1221. * SEE ALSO: taskDelete(),
  1222. * .pG "Target Shell,"
  1223. * windsh,
  1224. * .tG "Shell"
  1225. */
  1226. void td
  1227.     (
  1228.     int taskNameOrId /* task name or task ID */
  1229.     )
  1230.     {
  1231.     int tid = taskIdFigure (taskNameOrId);
  1232.     if (tid == ERROR) /* no such task ID */
  1233. printErr ("Task not found.n");
  1234.     else if (tid == 0)
  1235. printf ("sorry, the shell can't delete itself.n");
  1236.     else if (taskDelete (tid) != OK)
  1237. printErrno (0);
  1238.     }
  1239. /*******************************************************************************
  1240. *
  1241. * version - print VxWorks version information
  1242. *
  1243. * This command prints the VxWorks version number, the date this copy of
  1244. * VxWorks was made, and other pertinent information.
  1245. *
  1246. * EXAMPLE
  1247. * .CS
  1248. * -> version
  1249. * VxWorks (for Mizar 7170) version 5.1
  1250. * Kernel: WIND version 2.1.
  1251. * Made on Tue Jul 27 20:26:23 CDT 1997.
  1252. * Boot line:
  1253. * enp(0,0)host:/usr/wpwr/target/config/mz7170/vxWorks e=90.0.0.50 h=90.0.0.4 u=target
  1254. * value = 1 = 0x1
  1255. * .CE
  1256. *
  1257. * RETURNS: N/A
  1258. *
  1259. * SEE ALSO:
  1260. * .pG "Target Shell,"
  1261. * windsh,
  1262. * .tG "Shell"
  1263. */
  1264. void version (void)
  1265.     {
  1266.     printf ("%s (for %s) version %s.n", runtimeName, sysModel (), 
  1267.     runtimeVersion);
  1268.     printf ("Kernel: %s.n", kernelVersion ());
  1269.     printf ("Made on %s.n", creationDate);
  1270.     printf ("Boot line:n%sn", sysBootLine);
  1271.     }
  1272. /*******************************************************************************
  1273. *
  1274. * getHex - convert a hex string into a 64 bit value
  1275. *
  1276. * This function converts a string containing hex digits into a binary value.
  1277. * The values is returned in the locations pointed to by pHiValue and pLoValue.
  1278. * These values can be concatenated together to produce a 64 bit value.
  1279. *
  1280. * RETURNS: OK or ERROR
  1281. *
  1282. * INTERNALS: Ideally this function should be replaced by a version of scanf
  1283. * that supports long longs.
  1284. * This function is derived from scanNum in fioLib.c
  1285. *
  1286. * NOMANUAL
  1287. */
  1288. LOCAL STATUS getHex
  1289.     (
  1290.     char *pStr, /* string to parse */
  1291.     ULONG *pHiValue, /* where to store high part of result */
  1292.     ULONG *pLoValue /* where to store low part of result */
  1293.     )
  1294.     {
  1295.     int         dig;                    /* current digit */
  1296.     BOOL        neg     = FALSE;        /* negative or positive? */
  1297.     FAST char * pCh     = pStr;         /* pointer to current character */
  1298.     FAST int    ch      = *pCh;         /* current character */
  1299.     FAST ULONG  hiValue = 0; /* high part of value accumulator */
  1300.     FAST ULONG  loValue = 0; /* low part of value accumulator */
  1301.  
  1302.     /* check for sign */
  1303.  
  1304.     if (ch == '+' || (neg = (ch == '-')))
  1305. ch = *++pCh;
  1306.  
  1307.      /* check for optional or 0x */
  1308.  
  1309.     if (ch == '0')
  1310. {
  1311. ch = *++pCh;
  1312. if (ch == 'x' || ch == 'X')
  1313.     ch = *++pCh;
  1314. }
  1315.  
  1316.     /* scan digits */
  1317.     while (ch != '')
  1318.         {
  1319.         if (isdigit (ch))
  1320.             dig = ch - '0';
  1321.         else if (islower (ch))
  1322.             dig = ch - 'a' + 10;
  1323.         else if (isupper (ch))
  1324.             dig = ch - 'A' + 10;
  1325.         else
  1326.             break;
  1327.  
  1328.         if (dig >= 16)
  1329.             break;
  1330.  
  1331. /* assume that accumulator parts are 32 bits long */
  1332. hiValue = (hiValue * 16) + (loValue >> 28);
  1333. loValue = loValue * 16 + dig;
  1334.  
  1335.         ch = *++pCh;
  1336.         }
  1337.  
  1338.  
  1339.     /* check that we scanned at least one character */
  1340.  
  1341.     if (pCh == pStr) {
  1342.         return (ERROR);
  1343. }
  1344.  
  1345.     /* return value to caller */
  1346.  
  1347.     if (neg) {
  1348. /* assume 2's complement arithmetic */
  1349. hiValue = ~hiValue;
  1350. loValue = ~loValue;
  1351. if (++loValue == 0)
  1352.     hiValue++;
  1353. }
  1354.     *pHiValue = hiValue;
  1355.     *pLoValue = loValue;
  1356.     return (ch != '' ? ERROR : OK);
  1357.     }
  1358. /*******************************************************************************
  1359. *
  1360. * m - modify memory
  1361. *
  1362. * This command prompts the user for modifications to memory in byte, short
  1363. * word, or long word specified by <width>, starting at the specified address.
  1364. * It prints each address and the current contents of that address, in turn.
  1365. * If <adrs> or <width> is zero or absent, it defaults to the previous value.
  1366. * The user can respond in one of several ways:
  1367. * .iP RETURN 11
  1368. * Do not change this address, but continue, prompting at the next address.
  1369. * .iP <number>
  1370. * Set the content of this address to <number>.
  1371. * .iP ". (dot)"
  1372. * Do not change this address, and quit.
  1373. * .iP EOF
  1374. * Do not change this address, and quit.
  1375. * .LP
  1376. * All numbers entered and displayed are in hexadecimal.
  1377. *
  1378. * RETURNS: N/A
  1379. *
  1380. * SEE ALSO: mRegs(),
  1381. * .pG "Target Shell,"
  1382. * windsh,
  1383. * .tG "Shell"
  1384. *
  1385. * INTERNAL: further improvement needed.  Add an additional paramater indicating
  1386. *            whether a read should be done or not before writing.
  1387. */
  1388. void m
  1389.     (
  1390.     void *adrs, /* address to change */
  1391.     int  width  /* width of unit to be modified (1, 2, 4, 8) */
  1392.     )
  1393.     {
  1394.     static void *lastAdrs; /* last location modified */
  1395.     static int  lastWidth = 2; /* last width - default to 2 */
  1396.     char line[MAXLINE + 1]; /* leave room for EOS */
  1397.     char *pLine; /* ptr to current position in line */
  1398.     ULONG hiValue; /* high part of value found in line */
  1399.     ULONG loValue; /* low part of value found in line */
  1400.     if (adrs != 0) /* set default address */
  1401. lastAdrs = adrs;
  1402.     if (width != 0) /* check valid width and set the default */
  1403. {
  1404. if (width != 1 && width != 2 && width != 4 && width != 8)
  1405.     width = 1;
  1406. lastWidth = width;
  1407. }
  1408.     /* round down to appropriate boundary */
  1409.     lastAdrs = (void *)((int)lastAdrs & ~(lastWidth - 1));
  1410.     for (;; lastAdrs = (void *)((int)lastAdrs + lastWidth))
  1411. {
  1412. /* prompt for substitution according to width */
  1413. switch (lastWidth)
  1414.     {
  1415.     case 1:
  1416.      printf ("%08x:  %02x-", (int) lastAdrs, *(UINT8 *)lastAdrs);
  1417.     break;
  1418.      case 2:
  1419. printf ("%08x:  %04x-", (int) lastAdrs, *(USHORT *)lastAdrs);
  1420. break;
  1421.     case 4:
  1422. printf ("%08x:  %08lx-", (int) lastAdrs, *(ULONG *)lastAdrs);
  1423. break;
  1424.     case 8:
  1425. #if _BYTE_ORDER==_LITTLE_ENDIAN
  1426. printf ("%08x:  %08lx%08lx-", (int) lastAdrs, *((ULONG *)lastAdrs+1),*(ULONG *)lastAdrs);
  1427. #endif
  1428. #if _BYTE_ORDER==_BIG_ENDIAN
  1429. printf ("%08x:  %08lx%08lx-", (int) lastAdrs, *(ULONG *)lastAdrs, *((ULONG *)lastAdrs+1));
  1430. #endif
  1431. break;
  1432.     default:
  1433. printf ("%08x:  %08x-", (int) lastAdrs, *(UINT8 *)lastAdrs);
  1434. break;
  1435.     }
  1436. /* get substitution value:
  1437.  *   skip empty lines (CR only);
  1438.  *   quit on end of file or invalid input;
  1439.  *   otherwise put specified value at address
  1440.  */
  1441. if (fioRdString (STD_IN, line, MAXLINE) == EOF)
  1442.     break;
  1443. line[MAXLINE] = EOS; /* make sure input line has EOS */
  1444. for (pLine = line; isspace (*(u_char *)pLine); ++pLine)
  1445. /* skip leading spaces*/
  1446.     ;
  1447. if (*pLine == EOS) /* skip field if just CR */
  1448.     continue;
  1449.         if (getHex (pLine, &hiValue, &loValue) != OK)
  1450.     break;
  1451. /* assign new value */
  1452. switch (lastWidth)
  1453.     {
  1454.     case 1:
  1455. *(UINT8 *)lastAdrs = (UINT8) loValue;
  1456. break;
  1457.     case 2:
  1458. *(USHORT *)lastAdrs = (USHORT) loValue;
  1459. break;
  1460.     case 4:
  1461. *(ULONG *)lastAdrs = (ULONG) loValue;
  1462. break;
  1463.     case 8:
  1464. #if _BYTE_ORDER==_LITTLE_ENDIAN
  1465. *(ULONG *)lastAdrs = (ULONG) loValue;
  1466. *((ULONG *)lastAdrs+1) = (ULONG) hiValue;
  1467. #endif
  1468. #if _BYTE_ORDER==_BIG_ENDIAN
  1469. *(ULONG *)lastAdrs = (ULONG) hiValue;
  1470. *((ULONG *)lastAdrs+1) = (ULONG) loValue;
  1471. #endif
  1472. break;
  1473.     default:
  1474. *(UINT8 *)lastAdrs = (UINT8) loValue;
  1475. break;
  1476.     }
  1477. }
  1478.     printf ("n");
  1479.     }
  1480. /*******************************************************************************
  1481. *
  1482. * d - display memory
  1483. *
  1484. * This command displays the contents of memory, starting at <adrs>.
  1485. * If <adrs> is omitted or zero, d() displays the next memory block, starting
  1486. * from where the last d() command completed.
  1487. *
  1488. * Memory is displayed in units specified by <width>.  If <nunits> is omitted
  1489. * or zero, the number of units displayed defaults to last use.  If
  1490. * <nunits> is non-zero, that number of units is displayed and that number
  1491. * then becomes the default.  If <width> is omitted or zero, it defaults
  1492. * to the previous value.  If <width> is an invalid number, it is set to 1.
  1493. * The valid values for <width> are 1, 2, 4, and 8.  The number of units d()
  1494. * displays is rounded up to the nearest number of full lines.
  1495. *
  1496. * RETURNS: N/A
  1497. *
  1498. * SEE ALSO: m(),
  1499. * .pG "Target Shell,"
  1500. * windsh,
  1501. * .tG "Shell"
  1502. */
  1503. void d
  1504.     (
  1505.     FAST void *adrs, /* address to display (if 0, display next block */
  1506.     int nunits, /* number of units to print (if 0, use default) */
  1507.     int width  /* width of displaying unit (1, 2, 4, 8) */
  1508.     )
  1509.     {
  1510.     static int dNitems = 0x80; /* default number of item to display */
  1511.     static int dWidth  = 2; /* default width */
  1512.     static void *last_adrs = 0; /* last location displayed */
  1513.     FAST int item; /* item counter displayed per line */
  1514.     char ascii [MAX_BYTES_PER_LINE + 1]; /* ascii buffer for displaying */
  1515.     int ix; /* temporary count */
  1516.     UINT8 *pByte; /* byte pointer for filling ascii buffer */
  1517.     UINT8 *tmpByte; /* temporary byte pointer */
  1518.     USHORT *tmpShort; /* temporary short word pointer */
  1519.     ULONG *tmpLong; /* temporary long word pointer */
  1520.     ascii [MAX_BYTES_PER_LINE] = EOS; /* put an EOS on the string */
  1521.     if (nunits == 0)
  1522. nunits = dNitems; /* no count specified: use default count */
  1523.     else
  1524. dNitems = nunits; /* change default count */
  1525.     if (width == 0)
  1526. width = dWidth;
  1527.     else
  1528. { /* check for valid width */
  1529. if (width != 1 && width != 2 && width != 4 && width != 8)
  1530.     width = 1;
  1531. dWidth = width;
  1532. }
  1533.     if (adrs == 0)  /* no address specified: use last address */
  1534. adrs = last_adrs;
  1535.     else
  1536. last_adrs = adrs;
  1537.     /* round address down to appropriate boundary */
  1538.     last_adrs = (void *)((int) last_adrs & ~(width - 1));
  1539.     /* print leading spaces on first line */
  1540.     bfill (ascii, 16, '.');
  1541.     printf ("%08x:  ", (int) last_adrs & ~0xf);
  1542.     for (item = 0; item < ((int) last_adrs & 0xf) / width; item++)
  1543. {
  1544. printf ("%*s ", 2*width, " ");
  1545. bfill (&ascii[item * width], 2*width, ' ');
  1546. }
  1547.     /* print out all the words */
  1548.     while (nunits-- > 0)
  1549. {
  1550. if (item == MAX_BYTES_PER_LINE/width)
  1551.     {
  1552.     /* end of line:
  1553.      *   print out ascii format values and address of next line */
  1554.     printf ("  *%16s*n%08x:  ", ascii, (int) last_adrs);
  1555.     bfill (ascii, MAX_BYTES_PER_LINE, '.'); /* clear out ascii buffer */
  1556.     item = 0; /* reset word count */
  1557.     }
  1558. switch (width) /* display in appropriate format */
  1559.     {
  1560.     case 1:
  1561. tmpByte = (UINT8 *)last_adrs;
  1562.         printf ("%02x", *tmpByte);
  1563. break;
  1564.     case 2:
  1565. tmpShort = (USHORT *)last_adrs;
  1566.         printf ("%04x", *tmpShort);
  1567. break;
  1568.     case 4:
  1569. tmpLong = (ULONG *)last_adrs;
  1570.         printf ("%08lx", *tmpLong);
  1571. break;
  1572.     case 8:
  1573. tmpLong = (ULONG *)last_adrs;
  1574. #if _BYTE_ORDER==_LITTLE_ENDIAN
  1575. printf ("%08lx%08lx", *(tmpLong+1), *tmpLong);
  1576. #endif
  1577. #if _BYTE_ORDER==_BIG_ENDIAN
  1578. printf ("%08lx%08lx", *tmpLong, *(tmpLong+1));
  1579. #endif
  1580. break;
  1581.     default:
  1582. tmpByte = (UINT8 *)last_adrs;
  1583.         printf ("%02x", *tmpByte);
  1584. break;
  1585.     }
  1586.         printf (" "); /* space between words */
  1587. /* set ascii buffer */
  1588. pByte = (UINT8 *) last_adrs;
  1589. for (ix = 0; ix < width; ix ++)
  1590.     {
  1591.     if (*pByte == ' ' || (isascii (*pByte) && isprint (*pByte)))
  1592. {
  1593.         ascii[item*width + ix] = *pByte;
  1594. }
  1595.     pByte ++;
  1596.     }
  1597. last_adrs = (void *)((int)last_adrs + width);
  1598. item++;
  1599. }
  1600.     /* print remainder of last line */
  1601.     for (; item < MAX_BYTES_PER_LINE/width; item++)
  1602. printf ("%*s ", 2*width, " ");
  1603.     printf ("  *%16s*n", ascii); /* print out ascii format values */
  1604.     }
  1605. /*******************************************************************************
  1606. *
  1607. * ld - load an object module into memory
  1608. *
  1609. * This command loads an object module from a file or from standard input.
  1610. * The object module must be in UNIX `a.out' format.  External references in
  1611. * the module are resolved during loading.  The <syms> parameter determines how
  1612. * symbols are loaded; possible values are:
  1613. *
  1614. *     0 - Add global symbols to the system symbol table.
  1615. *     1 - Add global and local symbols to the system symbol table.
  1616. *    -1 - Add no symbols to the system symbol table.
  1617. *
  1618. * If there is an error during loading (e.g., externals undefined, too many
  1619. * symbols, etc.), then shellScriptAbort() is called to stop any script that
  1620. * this routine was called from.  If <noAbort> is TRUE, errors are noted but
  1621. * ignored.
  1622. *
  1623. * The normal way of using ld() is to load all symbols (<syms> = 1) during
  1624. * debugging and to load only global symbols later.
  1625. *
  1626. * The routine ld() is a 'shell command'.  That is, it is designed to
  1627. * be used only in the shell, and not in code running on the target.
  1628. * In future releases, calling ld() directly from code may not be
  1629. * supported.
  1630. *
  1631. * COMMON SYMBOLS
  1632. * On the target shell, for the 'ld' command only, common symbol behavior is 
  1633. * determined by the value of the global variable, ldCommonMatchAll.
  1634. * The reasoning for ldCommonMatchAll matches the purpose
  1635. * of the windsh environment variable, LD_COMMON_MATCH_ALL as explained below.
  1636. *
  1637. * If ldCommonMatchAll is set to TRUE (equivalent to windsh
  1638. * "LD_COMMON_MATCH_ALL=on"), the loader trys to match a common symbol
  1639. * with an existing one.  If a symbol with the same name is already
  1640. * defined, the loader takes its address. Otherwise, the loader creates
  1641. * a new entry. If set to FALSE (equivalent to windsh
  1642. * "LD_COMMON_MATCH_ALL=off"), the loader does not try to find an
  1643. * existing symbol. It creates an entry for each common symbol.
  1644. *
  1645. * EXAMPLE
  1646. * The following example loads the `a.out' file `module' from the default file
  1647. * device into memory, and adds any global symbols to the symbol table:
  1648. * .CS
  1649. *     -> ld <module
  1650. * .CE
  1651. * This example loads `test.o' with all symbols:
  1652. * .CS
  1653. *     -> ld 1,0,"test.o"
  1654. * .CE
  1655. * RETURNS:
  1656. * MODULE_ID, or
  1657. * NULL if there are too many symbols, the object file format is invalid, or
  1658. * there is an error reading the file.
  1659. *
  1660. * SEE ALSO: loadLib,
  1661. * .pG "Target Shell,"
  1662. * windsh,
  1663. * .tG "Shell" 
  1664. */
  1665. MODULE_ID ld
  1666.     (
  1667.     int syms, /* -1, 0, or 1 */
  1668.     BOOL noAbort, /* TRUE = don't abort script on error */
  1669.     char *name /* name of object module, NULL = standard input */
  1670.     )
  1671.     {
  1672.     MODULE_ID  moduleId;
  1673.     int  fd;
  1674.     int         loadFlags;
  1675.     if (name != NULL)
  1676.         {
  1677.         fd = open (name, O_RDONLY, 0);
  1678.         if (fd == ERROR)
  1679.             {
  1680.             printErr ("ld error: unable to open "%s"n", name);
  1681.             return (NULL);
  1682.             }
  1683.         }
  1684.     else
  1685.         fd = STD_IN;
  1686.     /* convert to basic flags */
  1687.     switch (syms)
  1688. {
  1689. case NO_SYMBOLS:
  1690.     loadFlags = LOAD_NO_SYMBOLS;
  1691.     break;
  1692. case GLOBAL_SYMBOLS:
  1693.     loadFlags = LOAD_GLOBAL_SYMBOLS;
  1694.     break;
  1695. case ALL_SYMBOLS:
  1696.     loadFlags = LOAD_ALL_SYMBOLS;
  1697.     break;
  1698. default:
  1699.     loadFlags = syms;
  1700.         }
  1701.     if (ldCommonMatchAll)
  1702.         loadFlags = (loadFlags | LOAD_COMMON_MATCH_ALL);
  1703.     moduleId = loadModule (fd, loadFlags);
  1704.     if (name != NULL)
  1705.         close (fd);
  1706.     if (moduleId == NULL)
  1707. {
  1708. switch (errno)
  1709.     {
  1710.     case S_loadLib_TOO_MANY_SYMBOLS:
  1711. printErr ("ld error: too many symbols.n");
  1712. break;
  1713.     case S_symLib_SYMBOL_NOT_FOUND:
  1714. printErr ("ld error: Module contains undefined symbol(s) "
  1715.   "and may be unusable.n");
  1716. break;
  1717.     default:
  1718. printErr ("ld error: error loading file (errno = %#x).n",
  1719.     errno);
  1720. break;
  1721.     }
  1722. if (! noAbort)
  1723.     shellScriptAbort ();
  1724. }
  1725.     return (moduleId);
  1726.     }
  1727. /*******************************************************************************
  1728. *
  1729. * devs - list all system-known devices
  1730. *
  1731. * This command displays a list of all devices known to the I/O system.
  1732. *
  1733. * RETURNS: N/A
  1734. *
  1735. * SEE ALSO: iosDevShow(),
  1736. * .pG "Target Shell,"
  1737. * windsh,
  1738. * .tG "Shell"
  1739. */
  1740. void devs (void)
  1741.     {
  1742.     iosDevShow ();
  1743.     }
  1744. /*******************************************************************************
  1745. *
  1746. * lkup - list symbols
  1747. *
  1748. * This command lists all symbols in the system symbol table whose names
  1749. * contain the string <substr>.  If <substr> is omitted or is 0, a short
  1750. * summary of symbol table statistics is printed.  If <substr> is the empty
  1751. * string (""), all symbols in the table are listed.  
  1752. *
  1753. * This command also displays symbols that are local, i.e., symbols found in
  1754. * the system symbol table only because their module was loaded by ld().
  1755. *
  1756. * By default, lkup() displays 22 symbols at a time.  This can be changed 
  1757. * by modifying the global variable `symLkupPgSz'.  If this variable is set
  1758. * to 0, lkup() displays all the symbols without interruption.
  1759. *
  1760. * RETURNS: N/A
  1761. *
  1762. * SEE ALSO: symLib, symEach(),
  1763. * .pG "Target Shell,"
  1764. * windsh,
  1765. * .tG "Shell"
  1766. */
  1767. void lkup
  1768.     (
  1769.     char *substr /* substring to match */
  1770.     )
  1771.     {
  1772.     show ((int) sysSymTbl, (int) substr); /* symShow() does the work */
  1773.     }
  1774. /*******************************************************************************
  1775. *
  1776. * lkAddr - list symbols whose values are near a specified value
  1777. *
  1778. * This command lists the symbols in the system symbol table that
  1779. * are near a specified value.  The symbols that are displayed include:
  1780. * .iP "" 4
  1781. * symbols whose values are immediately less than the specified value
  1782. * .iP
  1783. * symbols with the specified value
  1784. * .iP
  1785. * succeeding symbols, until at least 12 symbols have been displayed
  1786. * .LP
  1787. *
  1788. * This command also displays symbols that are local, i.e., symbols found in
  1789. * the system symbol table only because their module was loaded by ld().
  1790. *
  1791. * INTERNAL
  1792. * The LKADDR_ARG structure is used to hold the target address, count, and
  1793. * the `best' symbols found by lkAddrFind() and lkAddrNext(), which are the
  1794. * routines that get called by symEach() for each symbol in the system
  1795. * symbol table.
  1796. *
  1797. * RETURNS: N/A
  1798. *
  1799. * SEE ALSO: symLib, symEach(),
  1800. * .pG "Target Shell,"
  1801. * windsh,
  1802. * .tG "Shell"
  1803. */
  1804. void lkAddr
  1805.     (
  1806.     unsigned int addr /* address around which to look */
  1807.     )
  1808.     {
  1809.     FAST int ix;
  1810.     LKADDR_ARG arg;
  1811.     arg.count = 0; /* haven't printed anything yet */
  1812.     arg.addr  = addr;
  1813.     for (ix = 0; ix < NUM_SYMBLS; ++ix)
  1814. arg.symbl[ix].addr = (unsigned int)NULL; /* clear little symbol table */
  1815.     /* call lkAddrFind for each symbol */
  1816.     symEach (sysSymTbl, (FUNCPTR)lkAddrFind, (int)&arg);
  1817.     /* print out the symbols found */
  1818.     for (ix = 0; ix < NUM_SYMBLS; ix++)
  1819. {
  1820. if (arg.symbl[ix].addr != (unsigned int)NULL)
  1821.     {
  1822.     arg.addr = arg.symbl[ix].addr;
  1823.     symEach (sysSymTbl, (FUNCPTR)lkAddrPrintSame, (int)&arg);
  1824.     }
  1825. }
  1826.     if (arg.symbl[2].addr == (unsigned int)NULL)
  1827. return; /* couldn't find anything greater */
  1828.     /* print until there are enough entries */
  1829.     while (arg.count < 12)
  1830. {
  1831. arg.addr = arg.symbl[2].addr;
  1832. arg.symbl[2].addr = (unsigned int)NULL;
  1833. /* find next entry */
  1834. symEach (sysSymTbl, (FUNCPTR)lkAddrNext, (int)&arg);
  1835. if (arg.symbl[2].addr == (unsigned int)NULL)
  1836.     break; /* couldn't find anything greater */
  1837. /* print them */
  1838. arg.addr = arg.symbl[2].addr;
  1839. symEach (sysSymTbl, (FUNCPTR)lkAddrPrintSame, (int)&arg);
  1840. }
  1841.     }
  1842. /*******************************************************************************
  1843. *
  1844. * lkAddrFind - support routine for lkAddr()
  1845. *
  1846. * This command is called by symEach() to deal with each symbol in the table.
  1847. * If the value associated with the symbol is equal to lkAddrTarg(), or closer
  1848. * to it than previous close values, the appropriate slot in the array `symbl'
  1849. * is filled with the data for this symbol.
  1850. *
  1851. * RETURNS: TRUE
  1852. */
  1853. LOCAL BOOL lkAddrFind
  1854.     (
  1855.     char *   name, /* name in system symbol table     */
  1856.     unsigned int value, /* value associated with name      */
  1857.     SYM_TYPE  type, /* type of this symbol table entry */
  1858.     LKADDR_ARG * arg /* handle for search parameters    */
  1859.     )
  1860.     {
  1861.     FAST unsigned int addr = value;
  1862.     if (addr < arg->addr)
  1863. {
  1864. if (addr > arg->symbl[0].addr)
  1865.     {
  1866.     /* found closer symbol that is less than target */
  1867.     arg->symbl[0].addr = addr;
  1868.     arg->symbl[0].name = name;
  1869.     arg->symbl[0].type = type;
  1870.     }
  1871. }
  1872.     else if (addr == arg->addr)
  1873. {
  1874. /* found target, fill in target entry */
  1875. arg->symbl[1].addr = addr;
  1876. arg->symbl[1].name = name;
  1877. arg->symbl[1].type = type;
  1878. }
  1879.     else if (addr > arg->addr)
  1880. {
  1881. if ((addr < arg->symbl[2].addr) ||
  1882.     (arg->symbl[2].addr == (unsigned int)NULL))
  1883.     {
  1884.     /* found closer symbol that is greater than target */
  1885.     arg->symbl[2].addr = addr;
  1886.     arg->symbl[2].name = name;
  1887.     arg->symbl[2].type = type;
  1888.     }
  1889. }
  1890.     return (TRUE);
  1891.     }
  1892. /*******************************************************************************
  1893. *
  1894. * lkAddrNext - another support routine for lkAddr()
  1895. *
  1896. * This command is called by symEach() to deal with each symbol in the table.
  1897. * If the value associated with the symbol is greater than target, but less
  1898. * than symbl[2].addr, it replaces symbl[2].addr.
  1899. *
  1900. * RETURNS: TRUE
  1901. */
  1902. LOCAL BOOL lkAddrNext
  1903.     (
  1904.     char *  name, /* name in system symbol table     */
  1905.     unsigned int value, /* value associated with name      */
  1906.     SYM_TYPE     type, /* type of this symbol table entry */
  1907.     LKADDR_ARG * arg  /* handle for search parameters    */
  1908.     )
  1909.     {
  1910.     FAST unsigned int addr = value;
  1911.     if (addr > arg->addr)
  1912. {
  1913. if (addr < arg->symbl[2].addr ||
  1914.     arg->symbl[2].addr == (unsigned int)NULL)
  1915.     {
  1916.     /* found closer symbol that is greater than target */
  1917.     arg->symbl[2].addr = addr;
  1918.     arg->symbl[2].name = name;
  1919.     arg->symbl[2].type = type;
  1920.     }
  1921. }
  1922.     return (TRUE);
  1923.     }
  1924. /*******************************************************************************
  1925. *
  1926. * lkAddrPrintSame - yet another support routine for lkAddr()
  1927. *
  1928. * This command is called by symEach() to deal with each symbol in the table.
  1929. * If the value associated with the symbol is equal to the target, print it.
  1930. *
  1931. * RETURNS: TRUE
  1932. */
  1933. LOCAL BOOL lkAddrPrintSame
  1934.     (
  1935.     char *  name, /* name in system symbol table     */
  1936.     unsigned int value, /* value associated with name      */
  1937.     SYM_TYPE     type, /* type of this symbol table entry */
  1938.     LKADDR_ARG * arg  /* handle for search parameters    */
  1939.     )
  1940.     {
  1941.     if (value == arg->addr)
  1942. {
  1943. printSTE (value, name, type);
  1944. arg->count++;
  1945. }
  1946.     return (TRUE);
  1947.     }
  1948. /*******************************************************************************
  1949. *
  1950. * printSTE - print symbol table entry
  1951. */
  1952. LOCAL void printSTE
  1953.     (
  1954.     unsigned int addr, /* address associated with name    */
  1955.     char *  name, /* name in system symbol table     */
  1956.     SYM_TYPE  type /* type of this symbol table entry */
  1957.     )
  1958.     {
  1959.     char demangled[USR_DEMANGLE_PRINT_LEN + 1];
  1960.     char *nameToPrint = cplusDemangle (name, demangled, sizeof (demangled));
  1961.     
  1962.     printf ("0x%08x %-25s %-8s", addr, nameToPrint, typeName[(type >> 1) & 7]);
  1963.     if ((type & N_EXT) == 0)
  1964. printf (" (local)");
  1965.     printf ("n");
  1966.     }
  1967. /*******************************************************************************
  1968. *
  1969. * substrcmp - determine if string <s1> is a slash-delineated word in string <s>
  1970. *
  1971. * This routine returns TRUE if string <s1> is a substring of <s>, where the
  1972. * substring is a word delineated by slashes.  If there are no slashes, both
  1973. * strings must be identical.
  1974. *
  1975. * EXAMPLES
  1976. *  substrcmp("/this/is/a/string/", "string") returns TRUE.
  1977. *  substrcmp("/this/is/a/string/", "str") returns FALSE.
  1978. *  substrcmp("string", "string") returns TRUE.
  1979. *
  1980. * RETURNS: TRUE or FALSE.
  1981. * NOMANUAL
  1982. */
  1983. BOOL substrcmp
  1984.     (
  1985.     char *s, /* pointer to string may have a slash */
  1986.     char *s1 /* pointer to the string to be found in the first one */
  1987.     )
  1988.     {
  1989.     char *pSubStr=s; /* pointer to string divided by slashes in the string */
  1990.     char *pSlash; /* pointer to slash in the first string */
  1991.     size_t strLen;
  1992.     BOOL found = FALSE;
  1993.     while (pSubStr != NULL)
  1994. {
  1995.         pSlash = index (pSubStr, '/');
  1996. if (pSlash == NULL)
  1997.     {
  1998.     found = (strcmp (pSubStr, s1) == 0);
  1999.     break;
  2000.     }
  2001. else
  2002.     {
  2003.     strLen = (int)pSlash - (int)pSubStr;
  2004.     if ((found = (strncmp (pSubStr, s1, strLen) == 0 &&
  2005.  (strlen(s1) == strLen))))
  2006. break;
  2007.     else
  2008. pSubStr = pSlash + 1; /* point to char next to slash */
  2009.     }
  2010. }
  2011.     return (found);
  2012.     }
  2013. /*******************************************************************************
  2014. *
  2015. * mRegs - modify registers
  2016. *
  2017. * This command modifies the specified register for the specified task.
  2018. * If <taskNameOrId> is omitted or zero, the last task referenced is assumed.
  2019. * If the specified register is not found, it prints out the valid register list
  2020. * and returns ERROR.  If no register is specified, it sequentially prompts
  2021. * the user for new values for a task's registers.  It displays each register
  2022. * and the current contents of that register, in turn.  The user can respond
  2023. * in one of several ways:
  2024. * .iP RETURN 11
  2025. * Do not change this register, but continue, prompting at the next register.
  2026. * .iP <number>
  2027. * Set this register to <number>.
  2028. * .iP ". (dot)"
  2029. * Do not change this register, and quit.
  2030. * .iP EOF
  2031. * Do not change this register, and quit.
  2032. * .LP
  2033. *
  2034. * All numbers are entered and displayed in hexadecimal, except
  2035. * floating-point values, which may be entered in double precision.
  2036. *
  2037. * RETURNS: OK, or ERROR if the task or register does not exist.
  2038. *
  2039. * SEE ALSO: m(),
  2040. * .pG "Target Shell"
  2041. * windsh,
  2042. * .tG "Shell"
  2043. */
  2044. STATUS mRegs
  2045.     (
  2046.     char *regName, /* register name, NULL for all */
  2047.     int   taskNameOrId /* task name or task ID, 0 = default task */
  2048.     )
  2049.     {
  2050.     WIND_TCB *ptcb;
  2051.     int tid; /* task ID */
  2052.     REG_SET regSet; /* register set */
  2053.     int ix; /* temporary loop count */
  2054.     ULONG *tmp; /* temporary long word pointer */
  2055.     FPREG_SET fpRegSet; /* fp register set */
  2056.     double *dTmp; /* temporary double word pointer */
  2057.     BOOL  fppOk; /* flag for supporting FPU */
  2058. #ifdef _WRS_ALTIVEC_SUPPORT
  2059.     ALTIVEC_CONTEXT avRegSet;
  2060.     BOOL  altivecOK;
  2061. #endif  /* _WRS_ALTIVEC_SUPPORT */
  2062.     BOOL done; /* indicates user wants to quit */
  2063.     int width; /* width of register to display */
  2064.     tid = taskIdFigure (taskNameOrId); /* translate to task ID */
  2065.     if (tid == ERROR) /* couldn't figure out super name */
  2066. return (ERROR);
  2067.     tid = taskIdDefault (tid); /* set the default ID */
  2068.     if (taskRegsGet (tid, &regSet) != OK)
  2069. return (ERROR);
  2070.     if ((fppOk = (fppProbe () == OK)))
  2071. {
  2072.         if (fppTaskRegsGet (tid, &fpRegSet) != OK)
  2073.     return (ERROR);
  2074. }
  2075. #ifdef _WRS_ALTIVEC_SUPPORT
  2076.     if ((altivecOK = altivecProbe ()) == OK)
  2077.       {
  2078.       ptcb = taskTcb(tid);
  2079.       if (altivecTaskRegsGet ((int)ptcb,&avRegSet) !=OK)
  2080. return (ERROR);
  2081.       }
  2082. #endif /* _WRS_ALTIVEC_SUPPORT */
  2083.     /* 
  2084.     *  Some architectures organize floats sequentially, but to
  2085.     *  display them as doubles the floats need to be word swapped.
  2086.     *  However, this needs to be reconsidered.  The fpp registers
  2087.     *  are swapped before scanning and later fppTaskRegsSet() is
  2088.     *  called that some or all of the fpp registers could still 
  2089.     *  remain unneccessary swapped. XXX
  2090.     */
  2091.     if (fppDisplayHookRtn != NULL)
  2092.         (* fppDisplayHookRtn) (&fpRegSet);
  2093. #ifdef _WRS_ALTIVEC_SUPPORT
  2094.     /*    if (altivecDisplayHookRtn != NULL)
  2095.         (* altivecDisplayHookRtn) (&avRegSet);
  2096.     */
  2097. #endif
  2098.     if (regName == (char *) NULL)
  2099. {
  2100. /* default - modify all registers */
  2101. done = FALSE;
  2102. for (ix = 0; taskRegName[ix].regName != (char *) NULL; ix ++)
  2103.     {
  2104.     tmp = (void *) ((int)&regSet + taskRegName[ix].regOff);
  2105. #if CPU_FAMILY==MIPS
  2106.     width = taskRegName[ix].regWidth;
  2107. #else
  2108.     width = 4;
  2109. #endif
  2110.     if (changeReg (taskRegName[ix].regName, tmp, width) == ERROR)
  2111. {
  2112. done = TRUE;
  2113. break;
  2114. }
  2115.     }
  2116. taskRegsSet (tid, &regSet);
  2117. if (done)
  2118.     return (OK);
  2119.         if (fppOk)
  2120.     {
  2121.     for (ix = 0; fpRegName[ix].regName != (char *) NULL; ix ++)
  2122. {
  2123. dTmp = (double *) ((int) &fpRegSet + fpRegName[ix].regOff);
  2124. if (changeFpReg (fpRegName[ix].regName, *dTmp,
  2125.  (double *) dTmp) ==ERROR)
  2126.     {
  2127.     done = TRUE;
  2128.     break;
  2129.     }
  2130. }
  2131.     fppTaskRegsSet (tid, &fpRegSet);
  2132.     if (done)
  2133. return (OK);
  2134.     for (ix = 0; fpCtlRegName[ix].regName != (char *) NULL; ix ++)
  2135. {
  2136. tmp = (void *) ((int) &fpRegSet + fpCtlRegName[ix].regOff);
  2137. #if CPU_FAMILY==MIPS
  2138. width = fpCtlRegName[ix].regWidth;
  2139. #else
  2140. width = 4;
  2141. #endif
  2142. if (changeReg (fpCtlRegName[ix].regName, tmp, width) ==ERROR)
  2143.     break;
  2144. }
  2145.     fppTaskRegsSet (tid, &fpRegSet);
  2146.     }
  2147. return (OK);
  2148. }
  2149.     else
  2150. {  /* check valid register and modify */
  2151. for (ix = 0; taskRegName[ix].regName != (char *) NULL; ix ++)
  2152.     {
  2153.     if (substrcmp (taskRegName[ix].regName, regName))
  2154. {
  2155.         tmp = (void *) ((int)&regSet + taskRegName[ix].regOff);
  2156. #if CPU_FAMILY==MIPS
  2157. width = taskRegName[ix].regWidth;
  2158. #else
  2159. width = 4;
  2160. #endif
  2161. if(changeReg (taskRegName[ix].regName, tmp, width)==ERROR)
  2162.     return (ERROR);
  2163. taskRegsSet (tid, &regSet);
  2164. return (OK);
  2165. }
  2166.     }
  2167. if (fppOk)
  2168.     {
  2169.     for (ix = 0; fpRegName[ix].regName != (char *) NULL; ix ++)
  2170. {
  2171. if (substrcmp (fpRegName[ix].regName, regName))
  2172.     {
  2173.     dTmp = (double *) ((int) &fpRegSet + fpRegName[ix].regOff);
  2174.     if (changeFpReg(fpRegName[ix].regName,*dTmp,dTmp) == ERROR)
  2175. return (ERROR);
  2176.     fppTaskRegsSet (tid, &fpRegSet);
  2177.     return (OK);
  2178.     }
  2179. }
  2180.     for (ix = 0; fpCtlRegName[ix].regName != (char *) NULL; ix ++)
  2181. {
  2182. if (substrcmp (fpCtlRegName[ix].regName, regName))
  2183.     {
  2184.     tmp = (void *) ((int) &fpRegSet+fpCtlRegName[ix].regOff);
  2185. #if CPU_FAMILY==MIPS
  2186.     width = fpCtlRegName[ix].regWidth;
  2187. #else
  2188.     width = 4;
  2189. #endif
  2190.     if (changeReg (fpCtlRegName[ix].regName,tmp,width) == ERROR)
  2191. return (ERROR);
  2192.     fppTaskRegsSet (tid, &fpRegSet);
  2193.     return (OK);
  2194.     }
  2195. }
  2196.     }
  2197.         /* not found, print out register list */
  2198.         printf ("mRegs: no such register %sn", regName);
  2199. printf ("available registers:n");
  2200. for (ix = 0; taskRegName[ix].regName != (char *) NULL; ix++)
  2201.     printf ("%s ", taskRegName[ix].regName);
  2202. printf ("n");
  2203.   if (fppOk)
  2204.     {
  2205.     for (ix = 0; fpRegName[ix].regName != (char *) NULL; ix++)
  2206. printf ("%s ", fpRegName[ix].regName);
  2207.     printf ("n");
  2208.     for (ix = 0; fpCtlRegName[ix].regName != (char *) NULL; ix++)
  2209. printf ("%s ", fpCtlRegName[ix].regName);
  2210.     printf ("n");
  2211.     }
  2212. #ifdef _WRS_ALTIVEC_SUPPORT
  2213. if(altivecOK)
  2214.   {
  2215.   /* altiVecCtxShow(tid); */
  2216.   }
  2217. #endif
  2218.         return (ERROR);
  2219.      }
  2220.     return (OK); /* if we ever reach here */
  2221.     }
  2222. /*******************************************************************************
  2223. *
  2224. * changeReg - prompt the user for a hexadecimal register value
  2225. *
  2226. * This command reads a hexadecimal value from 'stdin'.
  2227. * If a NULL string is read, the routine returns immediately.
  2228. * If an invalid hexadecimal value is read, ERROR is returned.
  2229. *
  2230. * RETURNS: OK or ERROR.
  2231. *
  2232. * NOMANUAL
  2233. */
  2234. STATUS changeReg
  2235.     (
  2236.     char * pPrompt, /* prompt string */
  2237.     void * pValue, /* ptr to input value, on return contains new*/
  2238.     int width /* width of register */
  2239.     )
  2240.     {
  2241.     char stringBuf [20]; /* buffer for input line */
  2242.     char * pLine; /* pointer into input line */
  2243.     ULONG hiValue = 0; /* high part of value accumulator */
  2244.     ULONG loValue = 0; /* low part of value accumulator */
  2245.     if (*pPrompt == EOS)
  2246. return (OK);
  2247.     /* display the current value */
  2248.     switch (width)
  2249.      {
  2250. case 1:
  2251.     printf ("%-6s: %02x - ", pPrompt, *(UINT8 *)pValue);
  2252.     break;
  2253. case 2:
  2254.     printf ("%-6s: %04x - ", pPrompt, *(USHORT *)pValue);
  2255.     break;
  2256. case 4:
  2257.     printf ("%-6s: %08lx - ", pPrompt, *(ULONG *)pValue);
  2258.     break;
  2259. case 8:
  2260. #if _BYTE_ORDER==_LITTLE_ENDIAN
  2261.     printf ("%-6s: %08lx%08lx - ", pPrompt, *((ULONG *)pValue+1),*(ULONG *)pValue);
  2262. #endif
  2263. #if _BYTE_ORDER==_BIG_ENDIAN
  2264.     printf ("%-6s: %08lx%08lx - ", pPrompt, *(ULONG *)pValue, *((ULONG *)pValue+1));
  2265. #endif
  2266.     break;
  2267. default:
  2268.     printf ("%-6s: %02x - ", pPrompt, *(UINT8 *)pValue);
  2269.     break;
  2270. }
  2271.     if (fioRdString (STD_IN, stringBuf, sizeof (stringBuf)) == EOF)
  2272. return (ERROR);
  2273.     stringBuf[sizeof(stringBuf)-1] = EOS; /* make sure input line has EOS */
  2274.     for (pLine = stringBuf; isspace (*(u_char*)pLine); ++pLine) /* skip leading spaces*/
  2275. ;
  2276.     if (*pLine == EOS) /* skip if just CR */
  2277.         return (OK);
  2278.     if (getHex (pLine, &hiValue, &loValue) != OK)
  2279.         return (ERROR);
  2280.     switch (width)
  2281. {
  2282. case 1:
  2283.     *(UINT8 *)pValue = (UINT8) loValue;
  2284.     break;
  2285. case 2:
  2286.     *(USHORT *)pValue = (USHORT) loValue;
  2287.     break;
  2288. case 4:
  2289.     *(ULONG *)pValue = (ULONG) loValue;
  2290.     break;
  2291. case 8:
  2292. #if _BYTE_ORDER==_LITTLE_ENDIAN
  2293.     *(ULONG *)pValue = (ULONG) loValue;
  2294.     *((ULONG *)pValue+1) = (ULONG) hiValue;
  2295. #endif
  2296. #if _BYTE_ORDER==_BIG_ENDIAN
  2297.     *(ULONG *)pValue = (ULONG) hiValue;
  2298.     *((ULONG *)pValue+1) = (ULONG) loValue;
  2299. #endif
  2300.     break;
  2301. default:
  2302.     *(UINT8 *)pValue = (UINT8) loValue;
  2303.     break;
  2304. }
  2305.     return (OK);
  2306.     }
  2307. /*******************************************************************************
  2308. *
  2309. * changeFpReg - prompt the user for a floating-point register value
  2310. *
  2311. * This command reads a floating-point value from stdin.
  2312. * If a NULL string is read, the routine returns immediately.
  2313. * If an invalid floating-point value is read, ERROR is returned.
  2314. *
  2315. * RETURNS: OK or ERROR.
  2316. */
  2317. LOCAL STATUS changeFpReg
  2318.     (
  2319.     char * pPrompt, /* prompt string */
  2320.     double  value, /* original value */
  2321.     double * pValue /* where to return new value */
  2322.     )
  2323.     {
  2324.     char stringBuf [20];
  2325.     double newValue;
  2326.     char excess;
  2327.     if (*pPrompt == EOS)
  2328.         return (OK);
  2329.     printf ("%-6s: %20g - ", pPrompt, value);
  2330.     if (fioRdString (STD_IN, stringBuf, sizeof (stringBuf)) == 1)
  2331. {
  2332. *pValue = value;
  2333. return (OK); /* just a CR */
  2334. }
  2335.     if (strcmp (".", stringBuf) == OK)
  2336. return (ERROR);
  2337.     if (sscanf (stringBuf, "%lf%1s", &newValue, &excess) != 1)
  2338. return (ERROR);
  2339.     *pValue = newValue;
  2340.     return (OK);
  2341.     }
  2342. #undef pc /* undefine predefined pc if any */
  2343. /*******************************************************************************
  2344. *
  2345. * pc - return the contents of the program counter
  2346. *
  2347. * This command extracts the contents of the program counter for a specified
  2348. * task from the task's TCB.  If <task> is omitted or 0, 
  2349. * the current task is used.
  2350. *
  2351. * RETURNS: The contents of the program counter.
  2352. *
  2353. * SEE ALSO: ti(),
  2354. * .pG "Target Shell"
  2355. */
  2356. int pc
  2357.     (
  2358.     int task /* task ID */
  2359.     )
  2360.     {
  2361.     REG_SET regSet;
  2362.     int tid = taskIdFigure (task);
  2363.     if (tid == ERROR)
  2364. return (ERROR);
  2365.     tid = taskIdDefault (tid);
  2366.     if (taskRegsGet (tid, &regSet) != OK)
  2367. return (ERROR);
  2368.     
  2369.     return (*(int *)((int) &regSet + PC_OFFSET));
  2370.     }
  2371. /*******************************************************************************
  2372. *
  2373. * printErrno - print the definition of a specified error status value
  2374. *
  2375. * This command displays the error-status string, corresponding to a
  2376. * specified error-status value.  It is only useful if the error-status
  2377. * symbol table has been built and included in the system.  If <errNo> is
  2378. * zero, then the current task status is used by calling errnoGet().
  2379. *
  2380. * This facility is described in errnoLib.
  2381. *
  2382. * RETURNS: N/A
  2383. *
  2384. * SEE ALSO: errnoLib, errnoGet(),
  2385. * .pG "Target Shell"
  2386. * windsh,
  2387. * .tG "Shell"
  2388. */
  2389. void printErrno
  2390.     (
  2391.     FAST int errNo /* status code whose name is to be printed */
  2392.     )
  2393.     {
  2394.     char *statName;     /* pointer to stat tbl copy of error string */ 
  2395.     void *pval;
  2396.     SYMBOL_ID symId;    /* symbol identifier */               
  2397.     /* if no errno specified, get current tasks errno */
  2398.     if (errNo == 0)
  2399. {
  2400. errNo = errnoGet ();
  2401. if (errNo == OK)
  2402.     {
  2403.     printf ("OK.n");
  2404.     return;
  2405.     }
  2406. }
  2407.     if (statSymTbl == NULL)
  2408. printf ("Error status symbol table not included (errno = %#x).n",
  2409. errNo);
  2410.     else
  2411. {
  2412. symFindSymbol (statSymTbl, NULL, (void *)errNo, 
  2413.        SYM_MASK_NONE, SYM_MASK_NONE, &symId);
  2414. symNameGet (symId, &statName);
  2415. symValueGet (symId, &pval);
  2416.         
  2417. if ((int)pval != errNo)
  2418.     printf ("Unknown errno = %#x.n", errNo);
  2419. else
  2420.     printf ("%sn", statName);
  2421. }
  2422.     }
  2423. /*******************************************************************************
  2424. *
  2425. * printLogo - print the VxWorks logo
  2426. *
  2427. * This command displays the VxWorks banner seen at boot time.  It also
  2428. * displays the VxWorks version number and kernel version number.
  2429. *
  2430. * RETURNS: N/A
  2431. *
  2432. * SEE ALSO:
  2433. * .pG "Target Shell,"
  2434. * windsh,
  2435. * .tG "Shell"
  2436. */
  2437. void printLogo (void)
  2438.     {
  2439.     static char *logo[] =
  2440. {
  2441. "n",
  2442. "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]",
  2443. "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]",
  2444. "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]",
  2445. "     ]]]]]]]]]]]  ]]]]     ]]]]]]]]]]       ]]              ]]]]         (R)",
  2446. "]     ]]]]]]]]]  ]]]]]]     ]]]]]]]]       ]]               ]]]]            ",
  2447. "]]     ]]]]]]]  ]]]]]]]]     ]]]]]] ]     ]]                ]]]]            ",
  2448. "]]]     ]]]]] ]    ]]]  ]     ]]]] ]]]   ]]]]]]]]]  ]]]] ]] ]]]]  ]]   ]]]]]",
  2449. "]]]]     ]]]  ]]    ]  ]]]     ]] ]]]]] ]]]]]]   ]] ]]]]]]] ]]]] ]]   ]]]]  ",
  2450. "]]]]]     ]  ]]]]     ]]]]]      ]]]]]]]] ]]]]   ]] ]]]]    ]]]]]]]    ]]]] ",
  2451. "]]]]]]      ]]]]]     ]]]]]]    ]  ]]]]]  ]]]]   ]] ]]]]    ]]]]]]]]    ]]]]",
  2452. "]]]]]]]    ]]]]]  ]    ]]]]]]  ]    ]]]   ]]]]   ]] ]]]]    ]]]] ]]]]    ]]]]",
  2453. "]]]]]]]]  ]]]]]  ]]]    ]]]]]]]      ]     ]]]]]]]  ]]]]    ]]]]  ]]]] ]]]]]",
  2454. "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]",
  2455. "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]       Development System",
  2456. "]]]]]]]]]]]]]]]]]]]]]]]]]]]]",
  2457. };
  2458.     FAST int ix;
  2459.     for (ix = 0; ix < (int)NELEMENTS(logo); ix++)
  2460. printf (" %sn", logo [ix]);
  2461.     printf (" %s%s%s%sn",
  2462. "]]]]]]]]]]]]]]]]]]]]]]]]]]]       ", runtimeName," version ", runtimeVersion);
  2463.     printf (" %s%sn",
  2464. "]]]]]]]]]]]]]]]]]]]]]]]]]]       KERNEL: ", kernelVersion ());
  2465.     printf (" %sn",
  2466. "]]]]]]]]]]]]]]]]]]]]]]]]]       Copyright Wind River Systems, Inc., 1984-2002");
  2467.     printf ("n");
  2468.     }
  2469. /*******************************************************************************
  2470. *
  2471. * logout - log out of the VxWorks system
  2472. *
  2473. * This command logs out of the VxWorks shell.  If a remote login is active
  2474. * (via `rlogin' or `telnet'), it is stopped, and standard I/O is restored to
  2475. * the console.
  2476. *
  2477. * SEE ALSO: rlogin(), telnet(), shellLogout(),
  2478. * .pG "Target Shell"
  2479. */
  2480. void logout (void)
  2481.     {
  2482.     shellLogout ();
  2483.     }
  2484. /*******************************************************************************
  2485. *
  2486. * h - display or set the size of shell history
  2487. *
  2488. * This command displays or sets the size of VxWorks shell history.  If no
  2489. * argument is specified, shell history is displayed.  If <size> is
  2490. * specified, that number of the most recent commands is saved for display.
  2491. * The value of <size> is initially 20.
  2492. *
  2493. * RETURNS: N/A
  2494. *
  2495. * SEE ALSO: shellHistory(), ledLib,
  2496. * .pG "Target Shell,"
  2497. * windsh,
  2498. * .tG "Shell"
  2499. */
  2500. void h
  2501.     (
  2502.     int size /* 0 = display, >0 = set history to new size */
  2503.     )
  2504.     {
  2505.     shellHistory (size);
  2506.     }
  2507. /*******************************************************************************
  2508. *
  2509. * spyReport - display task activity data
  2510. *
  2511. * This routine reports on data gathered at interrupt level for the amount of
  2512. * CPU time utilized by each task, the amount of time spent at interrupt level,
  2513. * the amount of time spent in the kernel, and the amount of idle time.  Time
  2514. * is displayed in ticks and as a percentage, and the data is shown since both
  2515. * the last call to spyClkStart() and the last spyReport().  If no interrupts
  2516. * have occurred since the last spyReport(), nothing is displayed.
  2517. *
  2518. * RETURNS: N/A
  2519. *
  2520. * SEE ALSO: spyLib, spyClkStart(),
  2521. * .pG "Target Shell"
  2522. */
  2523. void spyReport (void)
  2524.     {
  2525.     if (_func_spyReport != NULL)
  2526. (* _func_spyReport) ((FUNCPTR) printf);
  2527.     else
  2528. printf (SPY_NOT_SUPPORTED_MSG);
  2529.     }
  2530. /*******************************************************************************
  2531. *
  2532. * spyTask - run periodic task activity reports
  2533. *
  2534. * This routine is spawned as a task by spy() to provide periodic task
  2535. * activity reports.  It prints a report, delays for the specified number of
  2536. * seconds, and repeats.
  2537. *
  2538. * RETURNS: N/A
  2539. *
  2540. * SEE ALSO: spyLib, spy(),
  2541. * .pG "Target Shell"
  2542. */
  2543. void spyTask
  2544.     (
  2545.     int freq            /* reporting frequency, in seconds */
  2546.     )
  2547.     {
  2548.     if (_func_spyTask != NULL)
  2549. (* _func_spyTask) (freq, (FUNCPTR) printf);
  2550.     else
  2551. printf (SPY_NOT_SUPPORTED_MSG);
  2552.     }
  2553. /*******************************************************************************
  2554. *
  2555. * spy - begin periodic task activity reports
  2556. *
  2557. * This routine collects task activity data and periodically runs spyReport().
  2558. * Data is gathered <ticksPerSec> times per second, and a report is made every
  2559. * <freq> seconds.  If <freq> is zero, it defaults to 5 seconds.  If
  2560. * <ticksPerSec> is omitted or zero, it defaults to 100.
  2561. *
  2562. * This routine spawns spyTask() to do the actual reporting.
  2563. *
  2564. * It is not necessary to call spyClkStart() before running spy().
  2565. *
  2566. * RETURNS: N/A
  2567. *
  2568. * SEE ALSO: spyLib, spyClkStart(), spyTask(),
  2569. * .pG "Target Shell"
  2570. */
  2571. void spy
  2572.     (
  2573.     int freq,               /* reporting freq in sec, 0 = default of 5 */
  2574.     int ticksPerSec         /* interrupt clock freq, 0 = default of 100 */
  2575.     )
  2576.     {
  2577.     if (_func_spy != NULL)
  2578. (* _func_spy) (freq, ticksPerSec, (FUNCPTR) printf);
  2579.     else
  2580. printf (SPY_NOT_SUPPORTED_MSG);
  2581.     }
  2582. /*******************************************************************************
  2583. *
  2584. * spyClkStart - start collecting task activity data
  2585. *
  2586. * This routine begins data collection by enabling the auxiliary clock
  2587. * interrupts at a frequency of <intsPerSec> interrupts per second.  If
  2588. * <intsPerSec> is omitted or zero, the frequency will be 100.  Data from
  2589. * previous collections is cleared.
  2590. *
  2591. * RETURNS:
  2592. * OK, or ERROR if the CPU has no auxiliary clock, or if task create and
  2593. * delete hooks cannot be installed.
  2594. *
  2595. * SEE ALSO: spyLib, sysAuxClkConnect(),
  2596. * .pG "Target Shell"
  2597. */
  2598. STATUS spyClkStart
  2599.     (
  2600.     int intsPerSec      /* timer interrupt freq, 0 = default of 100 */
  2601.     )
  2602.     {
  2603.     if (_func_spyClkStart != NULL)
  2604. return ((* _func_spyClkStart) (intsPerSec, (FUNCPTR) printf));
  2605.     else
  2606. {
  2607. printf (SPY_NOT_SUPPORTED_MSG);
  2608. return (ERROR);
  2609. }
  2610.     }
  2611. /*******************************************************************************
  2612. *
  2613. * spyClkStop - stop collecting task activity data
  2614. *
  2615. * This routine disables the auxiliary clock interrupts.
  2616. * Data collected remains valid until the next spyClkStart() call.
  2617. *
  2618. * RETURNS: N/A
  2619. *
  2620. * SEE ALSO: spyLib, spyClkStart(),
  2621. * .pG "Target Shell"
  2622. */
  2623. void spyClkStop (void)
  2624.     {
  2625.     if (_func_spyClkStop != NULL)
  2626. (* _func_spyClkStop) ();
  2627.     else
  2628. printf (SPY_NOT_SUPPORTED_MSG);
  2629.     }
  2630. /*******************************************************************************
  2631. *
  2632. * spyStop - stop spying and reporting
  2633. *
  2634. * This routine calls spyClkStop().  Any periodic reporting by spyTask()
  2635. * is terminated.
  2636. *
  2637. * RETURNS: N/A
  2638. *
  2639. * SEE ALSO: spyLib, spyClkStop(), spyTask(),
  2640. * .pG "Target Shell"
  2641. */
  2642. void spyStop (void)
  2643.     {
  2644.     if (_func_spyStop != NULL)
  2645. (* _func_spyStop) ();
  2646.     else
  2647. printf (SPY_NOT_SUPPORTED_MSG);
  2648.     }
  2649. /*******************************************************************************
  2650. *
  2651. * spyHelp - display task monitoring help menu
  2652. *
  2653. * This routine displays a summary of spyLib utilities:
  2654. * .CS
  2655. * .ne 3
  2656. * spyHelp                       Print this list
  2657. * spyClkStart [ticksPerSec]     Start task activity monitor running
  2658. *                                 at ticksPerSec ticks per second
  2659. * spyClkStop                    Stop collecting data
  2660. * spyReport                     Prints display of task activity
  2661. *                                 statistics
  2662. * spyStop                       Stop collecting data and reports
  2663. * spy     [freq[,ticksPerSec]]  Start spyClkStart and do a report
  2664. *                                 every freq seconds
  2665. *
  2666. * ticksPerSec defaults to 100.  freq defaults to 5 seconds.
  2667. * .CE
  2668. *
  2669. * RETURNS: N/A
  2670. *
  2671. * SEE ALSO: spyLib,
  2672. * .pG "Target Shell"
  2673. */
  2674. void spyHelp (void)
  2675.     {
  2676.     static char *spy_help[] = {
  2677.     "spyHelp                       Print this list",
  2678.     "spyClkStart [ticksPerSec]     Start task activity monitor running",
  2679.     "                                at ticksPerSec ticks per second",
  2680.     "spyClkStop                    Stop collecting data",
  2681.     "spyReport                     Prints display of task activity",
  2682.     "                                statistics",
  2683.     "spyStop                       Stop collecting data and reports",
  2684.     "spy     [freq[,ticksPerSec]]  Start spyClkStart and do a report",
  2685.     "                                every freq seconds",
  2686.     "",
  2687.     "ticksPerSec defaults to 100.  freq defaults to 5 seconds.",
  2688.     "",
  2689.     };
  2690.     FAST int ix;
  2691.     /* check if facility is available */
  2692.     if (_func_spyTask == NULL)
  2693. {
  2694. printf (SPY_NOT_SUPPORTED_MSG);
  2695. return;
  2696. }
  2697.     for (ix = 0; ix < (int)NELEMENTS(spy_help); ix++)
  2698. printf ("%sn", spy_help [ix]);
  2699.     }