1
0
Files
irix-657m-src/stand/arcs/ide/common/ide_prims.c
2022-09-29 17:59:04 +03:00

1792 lines
44 KiB
C

#ident "$Revision: 1.37 $"
/*
* arcs/ide/ide_prims.c: functions provided by IDE to diagnostic writers
*/
/*
* ide_prims.c contains routines which provide support to functions
* which are script-callable, but are themselves callable only internally.
* Routines which are called from ide scripts should not be in this file.
*/
#include <arcs/types.h>
#include <arcs/signal.h>
#include <sys/types.h>
#include <sys/sbd.h>
#include <sys/immu.h>
#include <sys/param.h>
#include <arcs/io.h>
#include <genpda.h>
#include <stringlist.h>
#include "libsc.h"
#include "uif.h"
#include <ide_msg.h>
#include <alocks.h>
#include "ide.h"
#include "ide_sets.h"
#include "ide_mp.h"
#include <libsc.h>
#include <libsk.h>
#if EVEREST
#include "sys/EVEREST/IP19addrs.h"
#include "sys/EVEREST/evconfig.h"
#include "sys/EVEREST/evmp.h"
#include "sys/EVEREST/evintr.h"
#include "sys/EVEREST/everest.h"
#endif /* EVEREST */
extern void _ide_init_hashtab(void);
extern int ide_update_prompt(void);
static void _initlog(void);
static int ide_init_consts(void);
static void ide_check_tblsizes(void);
extern int _get_arglist(char *, option_t *);
static int ide_getopt(int, char *const *, const char *);
static void _init_getopt(void);
extern int pager(char *, int, int *);
extern void _assert(const char *, const char *, int);
extern int _get_options(int, char **, char *, optlist_t *);
extern int _opt_index(char, char *);
extern void _dump_getopt_vars(int);
extern void _dump_argvs(int, char **);
extern int _dump_optlist(optlist_t *);
builtin_t *_get_tbl_entry(char *);
extern int get_mvid(void);
extern int _ide_usage(char *);
extern char *_strtok(register char *, const char *);
extern char *_strtok_r(char *, const char *, char **);
extern char *_strpbrk(register const char *, const char *);
extern size_t _strspn(const char *, const char *);
extern char *_strchr(const char *, int);
extern int _charcnt(const char *, char);
extern void ide_initargv(int *, char ***, struct string_list *);
extern int test_charcmd();
extern char *inv_findcpu(void);
extern int initmstats(void);
#if EVEREST
static int _slaves_to_prom(void);
#endif
extern int did_htab_init;
extern int sbtype_tblsiz, stype_tblsiz, sflag_tblsiz;
/*
* register-format descriptions, used by ide_printregs
*/
extern struct reg_desc sr_desc[], cause_desc[], r4k_config_desc[];
/*
* boot_rlevel determines the msg-verbosity level while IDE is booting
* (before scripts have access to $report). Since C won't preinitialize
* unions, point Reportlevel to boot_rlevel until Reportsym is initialized.
*/
ide_int_type boot_rlevel = INFO;
/*
* all other instances of "Reportlevel" in ide* files are #defined to
* be (*Reportlevel) to save changing all of them right now. The
* actual declaration must therefore be shielded. The 'Reportlevel'
* global is referenced frequently within IDE, so the the normal method
* of sharing the script-symbol values with IDE's runtime code--using
* findsym() to fetch the symbol, then using the value field of that
* symbol--was optimized as a pointer to that field.
*/
#undef Reportlevel
ide_int_type *Reportlevel = &boot_rlevel; /* use until Reportsym is set up */
#define Reportlevel (*Reportlevel)
/*
* Slave_Timeout can wait for initialization, since it is only (currently)
* used in parallel execution mode. By the time it is called, the values
* have been initialized. The speed optimization may be unnecessary, but
* since it is used in some tight polling loops it seemed like a good idea
*/
ide_int_type *_Slave_Timeout;
/*
* variables used by ide_getopt (adapted from libc's getopt())
*/
int optind = 1;
int optopt = 0;
int opterr = 1; /* suppress ide_getopt error message display if == 0 */
char *optarg = 0;
int _sp = 1;
/* msg_printf mustn't flash LEDs when system is running coherently */
volatile int _c_state = NON_COHERENT;
volatile int _c_pending = NON_COHERENT;
int pagesize;
int _ide_initialized = 0;
mp_logrec_t statlog[MAXDIAG];
int diag_tally = 0;
int __diag_cmd_syms = 0;
int __debug_cmd_syms = 0;
int __set_cmd_syms = 0;
int __ide_cmd_syms = 0;
#if defined(STKDEBUG)
extern int _dcache_size;
extern char master_stack[];
#if defined NOTYET
+ float ms_tos=0.0;
+ float ms_bos=0.0;
+ float ms_ssize = MASTER_STACKSIZE;
+ float ms_curlen=0.0, ms_sp_biggest;
+ float ms_sp_now;
#endif
int cp_dcache_size;
int cpied = 0;
#endif /* STKDEBUG */
builtin_t* diagcmds_ptr = diagcmds; /* can be used by module to pt to its cmds */
int* ndiagcmds_ptr = &ndiagcmds;
/* #define MSG_TEST */
/*
* build up symbol table
*/
int
ide_init(int argc, char *argv[])
{
int promptlen;
ULONG rc;
int cnt;
#if EVEREST
int slaveret = _slaves_to_prom();
unsigned long intlevel, olevel=0;
#endif
#ifdef STKDEBUG
char outbuf[MAXMSGLENGTH];
#endif
ASSERT(!_ide_initialized); /* buffered printing among other things */
#ifdef DEBUG
msg_printf(INFO, " %d symbols in freepool\n", _initsyms());
#else
(void)_initsyms();
#endif
_initlog();
_ide_init_hashtab(); /* zero hashtable pointers */
#if defined(STKDEBUG)
+ #ifdef NOTYET
+ ms_bos = (float)((int)(&master_stack[0]));
+ ms_tos = (float)(ms_bos + MASTER_STACKSIZE);
+ ms_sp_biggest = ms_tos; /* track biggest stack (most < top of stack) */
+ ms_ssize = MASTER_STACKSIZE;
+ ms_sp_now = (float)get_sp();
+
+ ASSERT(ms_sp_now < ms_tos);
+
+ sprintf(outbuf, " ide_init: &_dcache_size 0x%x, val 0x%x:\n",
+ (uint)&_dcache_size, _dcache_size);
+ msg_printf(JUST_DOIT, "%s", outbuf);
+
+ sprintf(outbuf, " TOS %.0f BOS %.0f size %.0f sp now %f\n",
+ ms_tos, ms_bos, ms_ssize, ms_sp_now);
+ msg_printf(JUST_DOIT, "%s", outbuf);
+ #endif
+ cp_dcache_size = _dcache_size;
+ cpied = 1;
+
#endif /* STKDEBUG */
msg_printf(VRB, "\n ide_init: -builtins-");
ide_init_builtins(nbuiltins, builtins, B_IDE_COMMANDS);
msg_printf(VRB, " -diagcmds- ");
ide_init_builtins(*ndiagcmds_ptr, diagcmds_ptr, B_DIAGNOSTICS);
/* must init consts only after builtins have been read-in */
cnt = ide_init_consts();
msg_printf(VRB, " - %d consts- ", cnt);
msg_printf(VRB, " -ide prompt- ");
promptlen = ide_update_prompt();
msg_printf(VRB, " strlen of new prompt is %d\n", promptlen);
ASSERT(promptlen < MAXPROMPTLEN);
msg_printf(VRB, "\n");
if (isgraphic(StandardOut)) {
pagesize = getHtpPs();
LOCK_ARCS_UI();
Write(StandardOut,"\033[37h",5,&rc); /* auto wrap on */
UNLOCK_ARCS_UI();
}
else
pagesize = 24;
#ifdef MSG_TEST
if (Reportlevel >= VDBG) {
int saveR = Reportlevel;
msg_printf(JUST_DOIT,
"\n Demo error message format and level-control facility\n");
saveR = Reportlevel;
Reportlevel = ERR;
msg_printf(JUST_DOIT,
"\n Reportlevel: %d (0x%x)\n", Reportlevel, Reportlevel);
msg_printf(ERR,
" This is the format of hw diagnostic error messages\n");
msg_printf(USER_ERR,
" This is user-error (script) message format\n");
msg_printf(IDE_ERR,
" This is the IDE-internal error message format\n");
Reportlevel = saveR;
}
#endif
#if 0
/* c_state(COHERENT); */
_c_state = NON_COHERENT; /* no LED flashing allowed now */
#endif
#if EVEREST
/* Clear the interrupts generated as a result of launching slaves into
* IP19prom. It takes a while for the slaves to send interrupt to the
* master. So clearing them here instead of _slaves_to_prom eliminates
* the delay we would have to put in _slaves_to_prom
*/
while (intlevel = EV_GET_LOCAL(EV_HPIL)){
EV_SET_LOCAL(EV_CIPL0, intlevel);
if (olevel == intlevel) /* Caution against stuck interrupts */
break;
else
olevel = intlevel;
}
#endif
init_context(argc,argv);
initmstats();
#ifdef IP32
initTiles();
#endif
_ide_initialized = IDE_PDAMAGIC; /* last thing */
return(0);
} /* ide_init */
#if EVEREST
static int
_slaves_to_prom()
{
unsigned cpu;
int res, cnt=0;
msg_printf(DBG, "\r _slaves_to_prom:\n");
/* Kick all of the slave processors back into the slave loop */
for (cpu = 0; cpu < EV_MAX_CPUS; cpu++) {
if (cpu == cpuid())
continue;
/* Skip MPCONF fields which are obviously bogus */
if (MPCONF[cpu].mpconf_magic != MPCONF_MAGIC ||
MPCONF[cpu].virt_id != cpu)
continue;
/* Try pushing all processors back into slave loop */
res = launch_slave(cpu, (void (*)(int)) IP19PROM_RESLAVE, 0, 0, 0, 0);
if (res) {
printf("\r _slaves_to_prom: cpu %d launch res %d\n",
cpu, res);
} else {
cnt++;
msg_printf(VDBG, "\r cpu %d launched into prom\n", cpu);
}
}
msg_printf(VRB, "\n %d slave%s sent into prom idle-loop\n",
cnt, _PLURAL(cnt));
return(cnt);
} /* _slaves_to_prom */
#endif /* EVEREST */
/*
* ide_init_consts must not be called until after the hash table has been
* completely initialized at bootup.
*/
static int
ide_init_consts(void)
{
sym_t *cmdsym, *valsym;
int count = 0;
ASSERT(_sympoolsize);
if (did_htab_init != 1) {
msg_printf(IDE_ERR,"hash table hasn't been initialized!!\n");
ide_panic("ide_init_consts");
}
valsym = findsym(REPORT_SNAME);
ASSERT(valsym);
#undef Reportlevel
Reportlevel = &(valsym->sym_i); /* now symbol's value is fetched */
#define Reportlevel (*Reportlevel)
#if IDEBUG
msg_printf(DBG," reportsym: name %s, btype %d, type %d, val %d\n",
valsym->sym_name,valsym->sym_basetype,valsym->sym_type,valsym->sym_i);
#endif
msg_printf(DBG, " bootup %s: %d\n", valsym->sym_name, Reportlevel);
count++;
valsym = findsym(STOUT_SNAME);
ASSERT(valsym);
/* symbols value fetched */
_Slave_Timeout = (ide_int_type *)&(valsym->sym_i);
msg_printf(DBG, " bootup %s: %d\n", valsym->sym_name, Slave_Timeout);
count++;
valsym = findsym(ERRLOGVAL_SNAME);
cmdsym = findsym(ERRLOGCMD_SNAME);
ASSERT(valsym);
ASSERT(cmdsym);
xenv_syms[ERRLOGGING].val_symp = valsym;
xenv_syms[ERRLOGGING].cmd_symp = cmdsym;
msg_printf(VRB, ", %s (command: `%s'): %s\n", valsym->sym_name,
cmdsym->sym_name, (valsym->sym_i==ENABLED ? "ON" : "OFF"));
count++;
valsym = findsym(ICEXECVAL_SNAME);
cmdsym = findsym(ICEXECCMD_SNAME);
ASSERT(valsym);
ASSERT(cmdsym);
xenv_syms[ICACHED_EXEC].val_symp = valsym;
xenv_syms[ICACHED_EXEC].cmd_symp = cmdsym;
msg_printf(VRB, ", %s (command: `%s') -- %s\n", valsym->sym_name,
cmdsym->sym_name, (valsym->sym_i==ENABLED ? "ON" : "OFF"));
count++;
valsym = findsym(QMODEVAL_SNAME);
cmdsym = findsym(QMODECMD_SNAME);
ASSERT(valsym);
ASSERT(cmdsym);
xenv_syms[QUICKMODE].val_symp = valsym;
xenv_syms[QUICKMODE].cmd_symp = cmdsym;
msg_printf(VRB, ", %s (command: `%s'): %s\n", valsym->sym_name,
cmdsym->sym_name, (valsym->sym_i==ENABLED ? "ON" : "OFF"));
count++;
valsym = findsym(C_ON_ERRVAL_SNAME);
cmdsym = findsym(C_ON_ERRCMD_SNAME);
ASSERT(valsym);
ASSERT(cmdsym);
xenv_syms[C_ON_ERROR].val_symp = valsym;
xenv_syms[C_ON_ERROR].cmd_symp = cmdsym;
msg_printf(VRB, ", %s (command `%s'): %s\n", valsym->sym_name,
cmdsym->sym_name, (valsym->sym_i==ENABLED ? "ON" : "OFF"));
count++;
return(count);
} /* ide_init_consts */
/*
* each diagnostic has <passcnt,failcnt> tuple per cpu.
* init_builtins assigns a sequence number to each SYM_DIAG
* symbol as it initializes the hash table; that number is
* the diag's error log.
* _doclearlog() and _dodumplog()--defined in ide_cmds.c--allow
* scripts to reinitialize the log's results (clearlog)
* and display the log's contents in various forms (dumplog).
*/
/*
* _initlog zeroes out the entire log. This routine must
* not be exported to the shell; _clear_errlog is provided to
* nondestructively reset the pass/fail counts upon command.
*/
/*ARGSUSED*/
static void
_initlog(void)
{
int diag;
msg_printf(VRB,
" _initlog: clear 0x%x (%d) bytes; start addr 0x%x\n",
sizeof(statlog), sizeof(statlog), statlog);
bzero(statlog, sizeof(statlog));
diag_tally = 0;
for (diag = 0; diag < MAXDIAG; diag++) {
statlog[diag].diagsym = ((sym_t *)(long)-1);
}
return;
} /* _initlog */
void
ide_init_builtins(int n, builtin_t *b, int tab_type)
{
char *systype = inv_findcpu();
sym_t *psym;
int i;
ASSERT(_sympoolsize);
if (did_htab_init != 1) {
msg_printf(IDE_ERR,"hash table hasn't been initialized!!\n");
ide_panic("ide_init_builtins");
}
ide_check_tblsizes();
for ( i = 0; i < n; i++, b++ ) {
psym = makesym();
if (tab_type == B_DIAGNOSTICS) {
if (b->addr == NULL) {
printf("Command %s was not found\n",b->name);
ide_panic("ide_init_builtins");
}
}
/*
* ide builtins, diags, and ide-internal debugging routines may
* all use either the sym_t* or the char* argv[] argument format.
* Routines that use sym_t* method are SCMDs, those using the
* char* method are CMDs. All of the set operations use the char*
* format, so we don't need SET_SCMDS. This code is pretty ugly:
* an attempt to obtain enough info to provide a more precise,
* intuitively-organized help facility and allow IDE to introduce
* diagnostics and display the results, while suppressing all that
* for all non-diagnostic script commands (like "print"). To do
* this, IDE assumes that no diagnostics are declared in 'builtins':
* they live in each architecture's 'cpu_diagcmds'. However,
* cpu-specific (but non-diagnostic) commands cannot go into
* 'builtins'; the CPUSPEC hack allows these commands to share
* the 'cpu_diagcmds' files with the diags.
*/
switch(b->type) {
case B_SCMD:
if (tab_type == B_DIAGNOSTICS)
psym->sym_flags |= SYM_DIAG;
/* fall through */
case B_CPUSPEC_SCMD:
case B_DEBUG_SCMD:
psym->sym_type = SYM_CMD;
psym->sym_func = (ide_int_type (*)())b->addr;
if (b->type == B_DEBUG_SCMD) /* ide-internal debugging fn */
psym->sym_flags |= SYM_DEBUG_CMD;
break;
/*
* All diags which invoke special execution features,
* and all ide SET primitives use the char *argv[] format
*/
case B_CMD:
if (tab_type == B_DIAGNOSTICS) {
psym->sym_flags |= SYM_DIAG;
__diag_cmd_syms++;
}
case B_CPUSPEC_CMD:
case B_DEBUG_CMD:
case B_SET_CMD:
psym->sym_type = SYM_CMD;
psym->sym_func = (ide_int_type (*)())b->addr;
psym->sym_flags |= SYM_CHARARGV;
if (b->type == B_DEBUG_CMD) {
psym->sym_flags |= SYM_DEBUG_CMD;
__debug_cmd_syms++;
} else if (b->type == B_SET_CMD) {
psym->sym_flags |= SYM_SET_CMD;
__set_cmd_syms++;
}
break;
case B_STR:
psym->sym_type = SYM_VAR;
psym->sym_basetype = SYMB_STR;
psym->sym_s = makestr((char *)b->addr);
break;
case B_SETSTR:
psym->sym_type = SYM_VAR;
psym->sym_basetype = SYMB_SETSTR;
psym->sym_s = makestr((char *)b->addr);
break;
case B_INT:
psym->sym_type = SYM_VAR;
psym->sym_basetype = SYMB_INT;
psym->sym_i = (ide_int_type) b->addr;
break;
default:
msg_printf(IDE_ERR,"ide_init_builtins: unknown type %d\n",b->type);
return;
}
psym->sym_name = b->name;
/* if there is an inviso period as the first character, skip it */
if (psym->sym_name[0] == '.')
psym->sym_name++;
if (psym->sym_flags & SYM_DIAG) {
if (diag_tally >= MAXDIAG) {
msg_printf(IDE_ERR,
"ide_init_builtins: ?!?bad diag_tally (%d)\n",diag_tally);
ide_panic("ide_init_builtins");
}
psym->sym_logidx = diag_tally;
statlog[diag_tally].diagsym = psym;
diag_tally++;
}
addsym(psym);
}
if (tab_type == B_DIAGNOSTICS) {
if (systype)
msg_printf(DBG,"\n %d %s Diagnostics\n\n", diag_tally, systype);
else
msg_printf(DBG,"\n %d diagnostics available\n", diag_tally);
}
return;
} /* ide_init_builtins */
#if EVEREST
int
ide_update_prompt()
{
sym_t *symptr;
char *xptr1;
int i;
uint my_vid = (uint)cpuid();
int slot, slice;
char outbuf[MAXMSGLENGTH];
char idstr[MAXPROMPTLEN], *cp=&idstr[0];
char newprompt[MAXPROMPTLEN];
char *npptr = newprompt, *opptr;
slot = vid_to_slot[my_vid];
slice = vid_to_slice[my_vid];
msg_printf(VDBG, "vid %d: slot %d slice %d\n", my_vid,slot,slice);
cp += sprintf(cp, "%d:%s%d/0%d", my_vid, (slot < 10 ? "0" : ""),
slot, slice);
ASSERT(cp < &idstr[MAXPROMPTLEN]);
#if defined(LAUNCH_DEBUG)
msg_printf(VDBG, " - ide_update_prompt: vid %d, idstr `%s' (len %d)\n",
my_vid, idstr, strlen(idstr));
#endif /* LAUNCH_DEBUG */
symptr = findsym("PS1");
if (!symptr) {
msg_printf(IDE_ERR, "ide_update_prompt: findsym of PS1 failed\n");
ide_panic("ide_update_prompt");
}
opptr = symptr->sym_s;
if (!(xptr1 = _strchr(opptr, '*'))) {
msg_printf(IDE_ERR,"!!!ide_update_prompt: _strchr `*' char failed\n");
return(2);
}
while (opptr != xptr1)
*npptr++ = *opptr++;
for (i = 0; i < strlen(idstr); i++)
*npptr++ = idstr[i];
opptr++; /* don't copy the place-holding '*' */
while (*opptr)
*npptr++ = *opptr++;
*npptr = '\0';
opptr = symptr->sym_s; /* we'll free this string */
symptr->sym_s = makestr((char *)newprompt);
destroystr(opptr);
#ifdef IF_TROUBLE
if (Reportlevel >= VDBG) {
msg_printf(DBG+1,"ide_update_prompt, new PS1: \"%s\"\n", symptr->sym_s);
}
#endif /* IF_TROUBLE */
return(strlen(symptr->sym_s));
} /* ide_update_prompt */
#else /* non-EVEREST architectures */
int
ide_update_prompt(void)
{
char *SP_ide_prompt = "ide>> ";
sym_t *symptr;
char *opptr;
symptr = findsym("PS1");
if (!symptr) {
msg_printf(IDE_ERR, "ide_update_prompt: findsym of PS1 failed!!\n");
ide_panic("ide_update_prompt");
}
opptr = symptr->sym_s; /* free this string */
symptr->sym_s = makestr((char *)SP_ide_prompt);
destroystr(opptr);
msg_printf(DBG, "ide_update_prompt, new PS1: \"%s\"\n", symptr->sym_s);
return(0);
} /* ide_update_prompt */
#endif /* EVEREST */
static void
ide_check_tblsizes(void)
{
int _err=0;
if (TBT_TOTAL != sym_tstr_tabsiz) {
msg_printf(IDE_ERR,
"sym_tstrs (sym type+btype) table size mismatch!\n");
msg_printf(JUST_DOIT,
" %d slots in sym_tstrs, %d total sym types+btypes!\n",
TBT_TOTAL, sym_tstr_tabsiz);
_err++;
}
if (SYM_FLAG_CNT != sflag_tblsiz) {
msg_printf(IDE_ERR, "sflags (sym flags) table size-mismatch!\n");
_err++;
}
if (_err)
ide_panic("ide_check_tblsizes");
return;
} /* ide_check_tblsizes */
/* #define LINESIZE 80 use bigger one defined elsewhere */
/* WARNING: this routine may not handle \t characters correctly */
int
pager(char *buffer, int pagesize, int *curline)
{
char linebuf[LINESIZE];
char *ptr1 = buffer;
char *ptr2;
char saved_ch;
while (1) {
if (*ptr1 == 0) /* nothing to display */
break;
if (*curline == pagesize - 2) { /* screen full */
msg_printf(JUST_DOIT,
"\n - Press <ENTER> to continue - ");
*curline = 0;
gets(linebuf);
}
ptr2 = index(ptr1, '\n'); /* find newline in text */
if (ptr2 == (char *)0) { /* no embedded \n */
if (strlen(ptr1) < LINESIZE) { /* length OK */
(*curline)++;
msg_printf(JUST_DOIT, "%s\n", ptr1);
break;
}
else { /* chop up text if necessary */
saved_ch = ptr1[LINESIZE - 1];
ptr1[LINESIZE - 1] = '\0';
(*curline)++;
msg_printf(JUST_DOIT, "%s\n", ptr1);
ptr1[LINESIZE - 1] = saved_ch;
ptr1 += LINESIZE - 1;
continue;
}
}
else { /* handle embedded \n character */
if (ptr2 - ptr1 < LINESIZE) {
(*curline)++;
*ptr2 = '\0';
msg_printf(JUST_DOIT, "%s\n", ptr1);
*ptr2 = '\n';
ptr1 = ptr2 + 1;
continue;
}
else { /* chop up text if necessary */
saved_ch = ptr1[LINESIZE - 1];
ptr1[LINESIZE - 1] = '\0';
(*curline)++;
msg_printf(JUST_DOIT, "%s\n", ptr1);
ptr1[LINESIZE - 1] = saved_ch;
ptr1 += LINESIZE - 1;
continue;
}
}
}
return 0;
} /* pager */
#if EVEREST
void
ide_panic(char *s)
{
char cbuf[2*MAXLINELEN];
register uint my_vid = (uint)cpuid();
register evreg_t slotproc;
register uint slot, slice, phys_idx;
char *who;
slotproc = EV_GET_LOCAL(EV_SPNUM);
slot = (slotproc & EV_SLOTNUM_MASK) >> EV_SLOTNUM_SHFT;
slice = (slotproc & EV_PROCNUM_MASK) >> EV_PROCNUM_SHFT;
phys_idx = SS_TO_PHYS(slot, slice);
if (IDE_ME(ide_mode)!=IDE_MASTER || _ide_info.master_vid!=my_vid)
who = "slave";
else
who = "master";
sprintf(cbuf, "IDE %s(%d:%s%d/0%d): %s", who, my_vid,
(slot < 10 ? "0" : ""), slot, slice,
(_SAFESTR(s) ? s : "<BAD PANIC STRING>"));
/*
* don't want to exit, because if we are on the graphics tube, the
* screen clears so fast that the message can't be read! (panic in
* libsa.a now loops for this reason.)
*/
panic(cbuf);
}
#else /* SP and non-Everest hardware */
void
ide_panic(char *s)
{
char cbuf[2*MAXLINELEN];
/*
* don't want to exit, because if we are on the graphics tube, the
* screen clears so fast that the message can't be read! (panic in
* libsa.a now loops for this reason.)
*/
sprintf(cbuf, "IDE: %s", (_SAFESTR(s) ? s : "<BAD PANIC STRING>"));
panic(cbuf);
/*NOTREACHED*/
}
#endif /* EVEREST */
#ifdef DEBUG
static char assbuf[240];
/* _assert grabbed from libc/port/gen/assert.c */
void
_assert(const char *assertion, const char *filename, int line_num)
{
static char linestr[] = ", line NNNNN\n";
register char *p = &linestr[7];
register int div, digit;
for (div = 10000; div != 0; line_num %= div, div /= 10)
if ((digit = line_num/div) != 0 || p != &linestr[7] || div == 1)
*p++ = digit + '0';
*p++ = '\n';
*p = '\0';
sprintf(assbuf,"assertion failed (%s), file %s%s",
assertion, filename, linestr);
ide_panic(assbuf);
} /* _assert */
#endif
/* arguments to options may be separated by commas, commas followed by
* a space, or just a space if the entire argument list is quoted */
#define ARGSEPS ", "
/* accepting only the options allowed by 'optstr', parse the argv
* strings, filling the optlist struct from the calling routine.
* For opts requiring arguments, set successive argument pointers
* to the head of each string-argument; also change the comma or
* <sp> argument delimiter (depending upon input-parameter format
* used by invoking routine) into a NULL byte to terminate each arg.
*/
int
_get_options(int argc, char **argv, char *optstr, optlist_t *optlistp)
{
int c, res;
option_t *optionp;
/* error-check incoming parameters */
if (!optlistp) {
msg_printf(IDE_ERR, "?? _get_options (via %s): NULL optlist ptr\n",
argv[0]);
return(NOOPTLIST);
}
if (argc <= 0) {
msg_printf(IDE_ERR, "?? _get_options (via %s): invalid argc (%d)\n",
argv[0], argc);
return(BADARGC);
}
optlistp->maxopts = (int)OPTCCNT(optstr);
ASSERT(optlistp->maxopts > 0 && optlistp->maxopts <= MAX_OPTS);
optlistp->optcount = 0;
optlistp->opts[0] = optlistp->opts[MAX_OPTARGS] = '\0';
#ifdef OPTION_DEBUG
if (Reportlevel >= OPTDBG) {
msg_printf(DBG, " _get_options: optstr \"%s\" maxopts %d\n\t",
optstr, optlistp->maxopts);
_dump_argvs(argc, argv);
msg_printf(DBG, "\n");
}
#endif
_init_getopt();
while ((c = ide_getopt(argc, argv, optstr)) != -1) {
#ifdef OPTION_DEBUG
if (Reportlevel >= OPTDBG) {
msg_printf(DBG, " opt == '%c' (0x%x); optcount %d\n",
(char)c,c,optlistp->optcount);
}
#endif
switch(c) {
case DD_RETURN: /* ide_getopt saw an explicit "--" */
#ifdef OPTION_DEBUG
if (Reportlevel >= OPTVDBG)
msg_printf(DBG, " _get_options: got DBLDASH!\n");
#endif
return(c);
case '?':
/* msg_printf(USER_ERR,"%s: bad opt '%c' (0x%x)\n",argv[0],c,c); */
return(c);
default:
/*
* all valid options come here. ide_getopt() sets/clears
* 'optarg' to indicate whether the fetched opt requires
* an argument. Also check now for too many opts.
*/
#ifdef OPTION_DEBUG
if (Reportlevel >= OPTVDBG) {
msg_printf(JUST_DOIT, " _get_options: opt %c, %s", (char)c,
(optarg ? "requires args\n" : "no args required\n"));
}
#endif
if (optlistp->optcount >= optlistp->maxopts) {
msg_printf(USER_ERR, "%s: too many options (> %d)\n", argv[0],
optlistp->optcount);
return(BADOPTCOUNT);
}
optlistp->opts[optlistp->optcount] = (char)c;
optlistp->opts[optlistp->optcount+1] = '\0';
optionp = (option_t *)&(optlistp->options[optlistp->optcount]);
optionp->opt = c;
optionp->argcount = 0;
optionp->args[0] = NULL;
/* if no args with this option, we're done with it */
if (!optarg) {
optlistp->optcount++;
break;
}
/* else grab arg or args */
if ((res = _get_arglist(optarg, optionp)) == 0) {
optlistp->optcount++;
break;
} else {
optlistp->opts[optlistp->optcount] = '\0';
msg_printf(DBG, "_get_options: _get_arglist returned %d\n",res);
return(res);
}
} /* switch */
} /* while */
optlistp->opts[optlistp->optcount] = '\0';
if (optlistp->optcount > optlistp->maxopts) {
msg_printf(USER_ERR,
"%s: too many opts (%d)\n", argv[0], optlistp->optcount);
return(BADOPTCOUNT);
}
#ifdef OPTION_DEBUG
if (Reportlevel & OPTDBG) {
msg_printf(DBG,
" _get_options: parsed %d opt%s (%s)\n", optlistp->optcount,
(optlistp->optcount == 1 ? "" : "s"), optlistp->opts);
if (Reportlevel & OPTVDBG)
_dump_optlist(optlistp);
}
#endif
return(0);
} /* _get_options */
int
_opt_index(char c, char *str)
{
char *cp;
if (!(cp = _strchr(str, c)))
return(-1);
else
return((int)(cp - str));
} /* _opt_index */
/*
* _get_arglist:
* 'argstr' points to head of an argument (argv) string.
* Accept arguments in <arg1,arg2,...>, <arg1, arg2,..>,
* or "arg1 arg2" format and place them in the option_t
* struct pointed to by 'optionp'.
*/
int
_get_arglist(char *argstr, option_t *optionp)
{
char *cptr;
if (!optionp) {
msg_printf(IDE_ERR, " _get_arglist: NULL optionp ptr\n");
return(NOOPTARG);
}
if ((Reportlevel & OPTVDBG) || Reportlevel >= VDBG) {
if (optionp->opt)
msg_printf(JUST_DOIT,
" _get_arglist: argstr \"%s\", opt '%c', argc %d\n",
argstr, (char)optionp->opt, optionp->argcount);
else
msg_printf(JUST_DOIT, " _get_arglist: argstr \"%s\", argc %d\n",
argstr, optionp->argcount);
}
optionp->argcount = 0; /* don't rely on calling routine */
cptr = _strtok(argstr, ARGSEPS); /* init _strtok and set up 0'th arg */
/* cptr returns NULL when user invokes fn with no parameters (argc==1) */
if (cptr == NULL) {
msg_printf(DBG+1,
"_get_arglist: _strtok returned NULL on 0'th call\n");
return(OPTARGERR);
}
optionp->args[optionp->argcount] = cptr;
optionp->argcount++;
while (optionp->argcount < MAX_OPTARGS) {
cptr = _strtok(NULL, ARGSEPS);
if (!cptr) { /* end of arg list */
break;
}
optionp->args[optionp->argcount] = cptr;
optionp->argcount++;
}
if (optionp->argcount >= MAX_OPTARGS) {
if (optionp->opt)
msg_printf(USER_ERR,"_get_arglist: '-%c' opt--too many args (%d)\n",
optionp->opt, optionp->argcount);
else
msg_printf(USER_ERR,"_get_arglist: too many args (%d)\n",
optionp->argcount);
return(BADARGCOUNT);
} else {
if (Reportlevel >= OPTVDBG) {
int i;
if (optionp->opt)
msg_printf(VDBG, " _get_arglist: %d arg%s to '%c' opt: ",
optionp->argcount,(optionp->argcount == 1 ? "" : "s"),
(char)optionp->opt);
else
msg_printf(VDBG, " _get_arglist: %d arg%s parsed\n",
optionp->argcount,(optionp->argcount == 1 ? "" : "s"));
for (i = 0; i < optionp->argcount; i++)
msg_printf(VDBG, " \"%s\"", optionp->args[i]);
msg_printf(VDBG, "\n");
}
return(0);
}
} /* _get_arglist */
void
_dump_getopt_vars(int retval)
{
if (retval != _SKIP_IT) {
if (retval > 0)
msg_printf(JUST_DOIT, "retval %d (0x%x or `%c'): ", retval,
retval, (char)retval);
else
msg_printf(JUST_DOIT, "retval %d: ", retval);
}
msg_printf(JUST_DOIT, "_sp %d, ind %d, opt %d, err %d, arg %s\n",
_sp, optind, optopt, opterr, (optarg ? optarg : "<NULL>"));
} /* dump_getopt_vars */
void
_dump_argvs(int argc, char **argv)
{
char outbuf[MAXLINELEN];
char *bptr = &outbuf[0];
int i;
outbuf[0] = '\0';
bptr += sprintf(bptr, " argc %d: ",argc);
if (Reportlevel >= VDBG)
bptr += sprintf(bptr, "(argv 0x%x): ",argv);
for (i = 0; i < argc; i++) {
bptr += sprintf(bptr, " `%s'", _SAFESTR(argv[i]));
}
if (argv[argc] != NULL) {
char *cp = argv[argc];
bptr += sprintf(bptr, "!! argc %d but argv[%d] !NULL", argc, argc);
for (i = 0; (i < 10 && *cp); i++) {
putchar(*cp++);
}
putchar('\n');
}
msg_printf(JUST_DOIT, "%s\n",outbuf);
} /* _dump_argvs */
int
_dump_optlist(optlist_t *optlistp)
{
option_t *optionp;
int option, arg;
if (Reportlevel & NAUSEOUS)
msg_printf(JUST_DOIT, " %d option%s: ",
optlistp->optcount, _PLURAL(optlistp->optcount));
for (option = 0; option < optlistp->optcount; option++) {
optionp = (option_t *)&(optlistp->options[option]);
msg_printf(JUST_DOIT, " option `%c', %s ", (char)optionp->opt,
(optionp->argcount ? "args: " : "no args"));
for (arg = 0; arg < optionp->argcount; arg++)
msg_printf(JUST_DOIT, " \"%s\"", optionp->args[arg]);
msg_printf(JUST_DOIT, "\n");
}
return 0;
} /* _dump_optlist */
/*
* ide_getopt() is lifted from libc's getopt(), with some modification (it
* didn't exist in libs{c,k}). ide_getopt() returns DD_RETURN when a "--"
* argument is encountered instead of EOF, which it returns when it finds
* an *implicit* end of args. ("--" signals the end of prepended special
* execution flags, which are stripped and interpretted by ide_dispatch).
*/
static int
ide_getopt(int argc, char *const *argv, const char *opts)
{
char c;
char *cp;
if(_sp == 1) {
if(optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
return(EOF);
else if(strcmp(argv[optind], "--") == NULL) {
optind++;
msg_printf((OPTVDBG|DBG), "\texit ide_getopt, case DBLDASH\n");
return(DD_RETURN);
}
}
optopt = c = (unsigned char)argv[optind][_sp];
if(c == ':' || (cp=_strchr(opts, c)) == NULL) {
if(opterr)
msg_printf(USER_ERR,
"ide_getopt, %s:1:Illegal option -- %c\n", argv[0], c);
if(argv[optind][++_sp] == '\0') {
optind++;
_sp = 1;
}
return('?');
}
if(*++cp == ':') {
if(argv[optind][_sp+1] != '\0')
optarg = &argv[optind++][_sp+1];
else if (++optind >= argc) {
if (opterr) /* suppress msg if opterr was set to 0 */
msg_printf(USER_ERR,
"%s: uxlibc:2:Option `%c' requires an argument\n",
argv[0], c);
_sp = 1;
return('?');
} else
optarg = argv[optind++];
_sp = 1;
} else {
if(argv[optind][++_sp] == '\0') {
_sp = 1;
optind++;
}
optarg = NULL;
}
if (Reportlevel >= OPTVDBG) {
msg_printf(VDBG, "\texiting ide_getopt normally: c = `%c'\n", c);
}
return(c);
} /* ide_getopt */
/*
* libc getopt is designed to be called once when a program begins to
* parse its arguments, so the necessary variables are statically
* initialized. This won't work for ide, which repeatedly calls
* functions whose parameters are in the <argc,argv> format.
*/
static void
_init_getopt(void)
{
_sp = opterr = optind = 1;
optopt = 0;
optarg = 0;
} /* _init_getopt */
builtin_t *
_get_tbl_entry(char *entryname)
{
int i;
for ( i = 0; i < nbuiltins; i++ )
if (!strcmp(entryname, builtins[i].name))
return(&builtins[i]);
return(NULL);
} /* _get_tbl_entry */
int
get_mvid(void)
{
return(_ide_info.master_vid);
}
int
_ide_usage(char *fnname)
{
builtin_t *bptr;
ASSERT(fnname != NULL);
bptr = _get_tbl_entry(fnname);
if (bptr) {
if (bptr->help[0] == NULL) {
msg_printf(JUST_DOIT, "%s: argument or option usage error\n",
fnname);
return(IENOHELPSTRING);
}
msg_printf(JUST_DOIT, "usage: %s\n",bptr->help);
return(0);
} else {
#ifdef IDEBUG
msg_printf(IDE_ERR, "_ide_usage: symbol for function `%s' not found!\n",
fnname);
#endif
return(IESYM_NOT_FOUND);
}
} /* _ide_usage */
/* ++++++++++++++++++++++++++ STRING PRIMITIVES +++++++++++++++++++++++++++++ */
/*
* uses _strpbrk and _strspn to break string into tokens on
* sequentially subsequent calls. returns NULL when no
* non-separator characters remain.
* `subsequent' calls are calls with first argument NULL.
*/
char *
_strtok(register char *string, const char *sepset)
{
register char *q, *r;
static char *savept;
/*first or subsequent call*/
if (string == NULL)
string = savept;
if(string == 0) { /* return if no tokens remaining */
msg_printf(DBG+4, "_strtok: NULL string arg\n");
return(NULL);
}
q = string + _strspn(string, sepset); /* skip leading separators */
if(*q == '\0') /* return if no tokens remaining */
return(NULL);
if((r = _strpbrk(q, sepset)) == NULL) /* move past token */
savept = 0; /* indicate this is last token */
else {
*r = '\0';
savept = r+1;
}
return(q);
} /* _strtok */
char *
_strtok_r(char *string, const char *sepset, char **lasts)
{
register char *q, *r;
/*first or subsequent call*/
if (string == NULL)
string = *lasts;
if(string == 0) /* return if no tokens remaining */
return(NULL);
q = string + _strspn(string, sepset); /* skip leading separators */
if(*q == '\0') /* return if no tokens remaining */
return(NULL);
if((r = _strpbrk(q, sepset)) == NULL) /* move past token */
*lasts = 0; /* indicate this is last token */
else {
*r = '\0';
*lasts = r+1;
}
return(q);
} /* _strtok_r */
/*
* Return ptr to first occurence of any character from `brkset'
* in the character string `string'; NULL if none exists.
*/
char *
_strpbrk(register const char *string, const char *brkset)
{
register const char *p;
do {
for(p=brkset; *p != '\0' && *p != *string; ++p)
;
if(*p != '\0')
return((char *)string);
}
while(*string++);
return(NULL);
} /* _strpbrk */
/*
* Return the number of characters in the maximum leading segment
* of string which consists solely of characters from charset.
*/
size_t
_strspn(const char *string, const char *charset)
{
register const char *p, *q;
for(q=string; *q != '\0'; ++q) {
for(p=charset; *p != '\0' && *p != *q; ++p)
;
if(*p == '\0')
break;
}
return(q-string);
} /* _strspn */
/*
* Return the ptr in sp at which the character c appears;
* NULL if not found
*/
char *
_strchr(const char *sp, int c)
{
char ch = (char)c;
do {
if(*sp == ch)
return((char *)sp);
} while(*sp++);
return(NULL);
} /* _strchr */
/*
* _charcnt: return the number of occurences of character 'c' in 'string'.
*/
int
_charcnt(const char *string, char c)
{
register int cnt = 0;
register const char *p;
for(p=string; *p != '\0'; ++p) {
if (*p == c)
cnt++;
}
return(cnt);
} /* _charcnt */
/*
* ide_initargv - copy incoming argv pointers and the strings to which
* they point someplace safe (into our pda). This routine was lifted
* from libsc, then modified to accept the destination of the copy
* as a third parameter.
*/
void
ide_initargv(int *ac, char ***av, struct string_list *argv_strp)
{
msg_printf(VDBG,
" ide_initargv: ac 0x%x, av 0x%x, argv_strp 0x%x\n",
ac, av, argv_strp);
init_str(argv_strp);
while ((*ac)--) {
if (**av)
new_str1(**av, argv_strp);
++(*av);
}
*ac = argv_strp->strcnt;
*av = argv_strp->strptrs;
}
int
_insert_arg(argdesc_t *argcvp, char *newarg, int argindex)
{
int argc, i;
char **argv;
if (!argcvp || !newarg || (argindex < 0)) {
msg_printf(IDE_ERR,
"_insert_arg, bad parms: cvp 0x%x, newarg 0x%x, idx %d\n",
argcvp, newarg, argindex);
ide_panic("_insert_arg");
}
argc = argcvp->argc;
argv = argcvp->argv;
if (Reportlevel >= VDBG) {
msg_printf(VDBG," _insert_arg: newarg '%s' argidx %d; in-args: ",
newarg, argindex);
_dump_argvs(argc, argv);
}
if (argindex > MAXARGC-1 || argc > MAXARGC-1) {
msg_printf(IDE_ERR, "\n!!! argindex %d or argc %d > %d!!\n",
argindex,argc,MAXARGC-1);
ide_panic("_insert_arg");
}
if (argv[argc]) {
msg_printf(IDE_ERR, "\n!!! argv[%d] not NULL! ('%s')\n",
argc,argv[argc]);
ide_panic("_insert_arg");
}
if (argindex > argc) {
msg_printf(IDE_ERR, "\n!!! argindex (%d) > argc (%d)\n",
argindex, argc);
ide_panic("_insert_arg");
}
for (i = argc; i > argindex; i--) {
argv[i] = argv[i-1];
}
argv[argindex] = newarg;
argcvp->argc++;
ASSERT(argcvp->argc < MAXARGC);
argv[argcvp->argc] = NULL;
if (Reportlevel >= VDBG) {
msg_printf(VDBG,"\n _insert_arg, modified args: ");
_dump_argvs(argcvp->argc, argcvp->argv);
msg_printf(VDBG,"\n");
}
return(0);
} /* _insert_arg */
/*
* 'optionp' points to an 'option_t' struct containing strings.
* _check_fns verifies that there's a SYM_CMD symbol for each string
* in the option_t args list, storing the sym_t ptrs in the caller's
* fnlist in the process. fnlistp->fncnt returns the number of
* verified functions. Stringnames which fail are not included in the
* tally or fncnt, but the entire list is checked regardless.
* _check_fns returns 0 if all incoming fnnames were ok, -1 otherwise.
* 'silent' suppresses all error message display other than those
* reporting ide-internal problems.
*/
int
_check_fns(option_t *optionp, fnlist_t *fnlistp)
{
int i, _error=0, rc=0;
sym_t *tsym;
char *fname;
if (!fnlistp) {
msg_printf(IDE_ERR," _check_fns: NULL fnlist pointer\n");
ide_panic("_check_fns");
}
if (!optionp || optionp->argcount <= 0 || optionp->argcount > MAX_OPTARGS) {
msg_printf(IDE_ERR, "_check_fns: bad option list\n");
ide_panic("_check_fns");
}
fnlistp->fncnt = 0;
for (i = 0; i < optionp->argcount; i++) {
fname = optionp->args[i];
tsym = findsym(fname);
if (!tsym) {
msg_printf(USER_ERR, "symbol for function `%s' not found\n", fname);
rc = OPTARGERR;
_error++;
continue;
}
if (tsym->sym_type != SYM_CMD) {
msg_printf(USER_ERR,
"symbol '%s' is type %d, not SYM_CMD (%d)\n", fname,
tsym->sym_type, SYM_CMD);
rc = ERRNOEXEC;
_error++;
continue;
}
if (tsym->sym_flags & SYM_UDEF) {
msg_printf(USER_ERR,
"'%s': exec of user-defined functions is illegal\n", fname);
rc = ERRNOEXEC;
_error++;
continue;
}
/* it's a legit C routine */
fnlistp->fn_symptrs[i] = tsym;
fnlistp->fncnt++;
}
if (Reportlevel >= VDBG) {
if (_error) {
msg_printf(VDBG," (%d bad fnname%s: verified %d fn%s)",
_error, _PLURAL(_error),
fnlistp->fncnt, _PLURAL(fnlistp->fncnt));
} else {
msg_printf(VDBG," verified %d fn%s", fnlistp->fncnt,
_PLURAL(fnlistp->fncnt));
}
if (Reportlevel > VDBG) {
msg_printf(JUST_DOIT,":\n ");
for (i = 0; i < fnlistp->fncnt; i++)
msg_printf(JUST_DOIT,"%s ",fnlistp->fn_symptrs[i]->sym_name);
} else {
msg_printf(JUST_DOIT,"\n");
}
}
return(rc);
} /* _check_fns */
/* ++++++++++++++++++++++++ END STRING PRIMITIVES +++++++++++++++++++++++++++ */
/*
* ide_dispatch calls _get_disopts when the arg list of a function begins
* with "--", indicating that the user wants special execution help.
* _get_disopts validates and strips all dispatcher flags, returning
* the function's argc in argc_ptr, the modified arg list in argv, and
* the list of dispatcher options it processed in optlistp. If the user
* doesn't end the spx flags with another "--", return SPXERR_NOARGEND.
* If _get_disopts succeeds, return 0.
*/
int
_get_disopts(argdesc_t *arginfop, optlist_t *optlistp)
{
int argc = arginfop->argc;
char **argv = arginfop->argv;
int res;
/* fetch the spx options via get_options() call. Adjust argptrs
* to make argv[0] show dispatcher as calling routine.
*/
ASSERT((argc > 1) && argv[1] && !strcmp(argv[1], "--"));
/* spx opts begin after 1st "--", so change that slot to point to
* dispatcher name and make it &argv[0]. */
argv++;
argv[0] = IDE_PMGR;
argc--;
#ifdef LAUNCH_DEBUG
if (Reportlevel & DISPVDBG) {
msg_printf(VDBG, " _get_disopts: optstr `%s';\n", SPX_OPTS);
msg_printf(VDBG,
" spx_argc %d, spx_argv[0] = `%s', spx_argv[1] = `%s'\n",
argc, argv[0], argv[1]);
}
#endif /* LAUNCH_DEBUG */
res = _get_options(argc, argv, SPX_OPTS, optlistp);
#ifdef LAUNCH_DEBUG
if (Reportlevel & DISPVDBG) {
msg_printf(VDBG," _get_disopts after `--': %d opts parsed\n ",
optlistp->optcount);
_dump_optlist(optlistp);
_dump_getopt_vars(res);
}
#endif /* LAUNCH_DEBUG */
if (res != DD_RETURN) {
msg_printf(USER_ERR,
"_get_disopts: must end spx options with \"--\"\n");
if (Reportlevel >= DISPDBG) {
_dump_optlist(optlistp);
_dump_getopt_vars(res);
}
return(SPXERR_NOARGEND);
}
/* if we're here, the arg list contained only valid spx opts and was
* correctly terminated. argv[optind-1] points to the 2nd "--";
* this will be the diag's argv[0], so swap pointers and adjust
* the outgoing arg{c,v}.
*/
argv[optind-1] = arginfop->argv[0];
arginfop->argv = &argv[optind-1];
arginfop->argc = argc - (optind-1);
return(0);
} /* _get_disopts */
/*
* begin ide execution-environment querying and setting routines
*/
/*
* 'which' determines the environment variable, 'changeit' is 0 if only
* querying, else non-zero; if changing, 'newval' contains new value.
*/
int
_ide_xenv(xenv_index_t which, int changeit, int newval)
{
sym_t *tsym;
if (which < 0 || which >= XENV_COMPONENTS) {
msg_printf(IDE_ERR, "ide_xenv: bad 'which' (%d)\n",which);
ide_panic("ide_xenv");
}
if (!(tsym = xenv_syms[which].val_symp)) {
msg_printf(IDE_ERR, "ide_xenv: %d's value symbol not initialized!!\n",
which);
ide_panic("ide_xenv");
}
if (!(xenv_syms[which].cmd_symp)) {
msg_printf(IDE_ERR, "ide_xenv: %d's cmd symbol not initialized!!\n",
which);
ide_panic("ide_xenv");
}
if (!changeit) {
return(tsym->sym_i ? ENABLED : DISABLED);
} else {
if (newval)
tsym->sym_i = ENABLED;
else
tsym->sym_i = DISABLED;
return(tsym->sym_i ? ENABLED : DISABLED);
}
} /* _ide_xenv */
/*
* error_logging: return 1 If IDE is currently logging the results of
* diagnostic execution, 0 Otherwise.
*/
int
error_logging(void)
{
return(_ide_xenv(ERRLOGGING, 0, 0));
}
/*
* icached_exec(): return 1 If IDE is adjusting the PCs of diagnostics
* to be in K0 space before invoking them, 0 Otherwise (IDE is linked
* in K1SEG to allow it to execute on machines with broken caches).
*/
int
icached_exec(void)
{
return(_ide_xenv(ICACHED_EXEC, 0, 0));
}
/*
* quick_mode(): return 1 If IDE is running in Quick mode, 0 Otherwise.
*/
int
quick_mode()
{
return(_ide_xenv(QUICKMODE, 0, 0));
}
/*
* Return: 1 if flag is set to continue executing a diagnostic in spite of
* errors. 0 Otherwise.
*/
int
continue_on_error()
{
return(_ide_xenv(C_ON_ERROR, 0, 0));
}
__psunsigned_t
icache_it(void * addr)
{
__psunsigned_t caddr = (__psunsigned_t)addr;
if (IS_KSEG0(addr)) {
msg_printf(DBG, " ?fn address (0x%x) is already in K0SEG!\n", addr);
} else if (IS_KSEG2(addr)) {
msg_printf(JUST_DOIT, " ?fnaddr (0x%x) is in K2SEG!\n", addr);
} else if (IS_KUSEG(addr)) {
caddr = PHYS_TO_K0(addr);
msg_printf(JUST_DOIT,
"WARNING: fnaddr (0x%x) in KUSEG! Launching icached (0x%x)\n",
addr, caddr);
} else {
caddr = K1_TO_K0(addr);
msg_printf(DBG, " -run icached (0x%x --> 0x%x)\n", addr, caddr);
}
return(caddr);
} /* icache_it */
#define CONFIG_RWBITS (CONFIG_IC|CONFIG_DB|CONFIG_CU|CONFIG_K0)
int
_ide_printregs(void)
{
uint vid_me = (uint)cpuid();
ulong SR, cause;
k_machreg_t sp;
#if R4000
uint config;
#endif
SR = get_sr();
sp = get_sp();
cause = get_cause();
msg_printf(JUST_DOIT, "\n %s(v%d): SR %R, sp 0x%x\n",
(IDE_ME(ide_mode) == IDE_MASTER ? "MASTER" : " slave"),
vid_me, SR, sr_desc, sp);
msg_printf(JUST_DOIT, " [ignore IP8==(CNT/CMP)]: cause %R\n",
cause, cause_desc);
#if R4000
if (_SHOWIT(DBG+1)) {
config = r4k_getconfig();
if (!_SHOWIT(DBG+1)) /* only display the bits SW can change */
config &= CONFIG_RWBITS;
msg_printf(JUST_DOIT, " SW-writeable config bits: %R\n\n",
config, r4k_config_desc);
}
#endif
return(vid_me);
} /* _ide_printregs */