1
0
Files
2022-09-29 17:59:04 +03:00

204 lines
4.3 KiB
C

#ident "IP20diags/uif/test.c: $Revision: 1.1 $"
/*
* test.c - diagnostic command parser
*/
#if IP20
/*
* This file provides a basic interface to any
* diagnostics that will be in the prom, so they can
* be run after booting the prom
*/
#include "sys/param.h"
#include "sys/types.h"
#include "sys/cpu.h"
#include "sys/sbd.h"
#include "libsc.h"
#include "libsk.h"
#include "uif.h"
/* test wrappers which parse and implement common options */
static int memtest(/* argc, argv */);
static int delaytest(/* argc, argv */);
/* imported test functions */
extern bool_t memaddruniq();
extern bool_t memwalkingbit();
extern bool_t memparity();
static struct cmd_table toplevel[] = {
{ "addr", memtest,
"address uniqueness: addr [-wiuf] RANGE ..." },
{ "data", memtest,
"walking bit: data [-bhwiuf] RANGE ..." },
{ "parity", memtest,
"parity checking: parity [-bhwiuf] [RANGE] ..." },
{ "delay", delaytest,
"test delay function: delay USEC ..." },
{ "help", help,
"test help: help [COMMAND ...]" },
{ 0, }
};
int
test(argc, argv, envp, parentct)
register int argc;
register char **argv;
register char **envp;
register struct cmd_table *parentct;
{
extern int *Reportlevel;
register struct cmd_table *ct;
*Reportlevel = DBG;
if (argc == 1) {
command_parser(toplevel, "test>> ", 0, parentct);
return 0;
}
--argc, argv++;
ct = lookup_cmd(toplevel, *argv);
if (ct == 0) {
return help(1, argv, envp, toplevel);
}
if ((*ct->ct_routine)(argc, argv, envp, toplevel) < 0)
usage(ct);
return 0;
}
/* XXX this is kind of coupled to PROM_STACK in IP20.h. BSS and the
* stack for the prom are below 4Mb and any memory above 4Mb is
* not really saved for anything
*/
#define MEMBASE_DEFAULT 0x400000
enum loopmode { ONCE, UNTIL_ERROR, FOREVER };
static int
delaytest(argc, argv)
int argc;
char **argv;
{
#ifdef NOTDEF
printf("cycles/instruction = %d\n", _cyclesperinst());
printf("ticks/1024inst = %d\n", _ticksper1024inst());
#endif /* NOTDEF */
while (--argc > 0) {
auto int usec;
if (*atob(*++argv, &usec))
return -1;
printf("About to delay ~%d microseconds...", usec);
DELAY(usec);
printf(" done.\n");
}
return 0;
}
static int
memtest(argc, argv)
register int argc;
register char **argv;
{
register enum loopmode mode;
register enum bitsense sense;
register int size;
struct range range;
register bool_t (*testit)();
register char *tname;
if (argc < 2 || argc > 3)
return -1;
tname = *argv;
mode = ONCE;
sense = BIT_TRUE;
size = sizeof(int);
while (--argc > 0 && (*++argv)[0] == '-') {
register char *ap;
for (ap = *argv + 1; *ap != '\0'; ap++)
switch (*ap) {
case 'b':
size = sizeof(char);
break;
case 'h':
size = sizeof(short);
break;
case 'w':
size = sizeof(int);
break;
case 'i':
sense = BIT_INVERT;
break;
case 'u':
mode = UNTIL_ERROR;
break;
case 'f':
mode = FOREVER;
break;
default:
return -1;
}
}
if (argc == 0)
return -1;
switch (tname[0]) {
case 'a': /* addr */
if (size != sizeof(int))
return -1;
testit = memaddruniq;
break;
case 'd': /* data */
testit = memwalkingbit;
break;
case 'p':
testit = memparity;
break;
}
while (--argc >= 0) {
if (!parse_range(*argv, size, &range)) {
if (strcmp(atob(*argv, &range.ra_count), "meg") != 0)
return -1;
range.ra_base = PHYS_TO_K1(MEMBASE_DEFAULT);
/* what a botch - sizeof is unsigned in MIPS-land */
range.ra_count =
((range.ra_count << 20) - MEMBASE_DEFAULT)
/ (signed int) sizeof(int);
range.ra_size = sizeof(int);
}
argv++;
switch (mode) {
case ONCE:
(void)(*testit)(&range, sense, RUN_UNTIL_DONE, memerr);
break;
case UNTIL_ERROR:
while ((*testit)(&range, sense, RUN_UNTIL_ERROR,
memerr)) {
/*
* The following allows interrupts from the
* keyboard to be serviced.
*/
printf(".");
}
break;
case FOREVER: {
register void (*errfun)() = memerr;
/*
* A bad cc -O2 bug will bite this code: because
* there is no exit from this block, the optimizer
* gets confused and saves regular and fp regs on
* the stack. Not so good without an FPU...
*/
for (;;) {
(void)(*testit)(&range, sense, RUN_UNTIL_DONE,
errfun);
errfun = 0;
}
}
}
}
return 0;
}
#endif /* IP20 */