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

1096 lines
28 KiB
C

#include <sys/types.h>
#include <sys/sbd.h>
#include <genpda.h>
/*#include <alocks.h>*/
#include <uif.h>
#include "ide.h"
#include "ide_mp.h"
#include "ide_sets.h"
#include "ide_msg.h"
#include <libsc.h>
#include <libsk.h>
#if EVEREST
#include <sys/EVEREST/evconfig.h>
#endif /* EVEREST */
/* imports */
extern int ide_update_prompt(void);
extern int ide_whoisthat(int, char *);
extern int ide_whoami(char *);
extern void ide_mpsetup(void);
static void ide_initpdas(void);
static int ide_cpu_probe(void);
extern int dump_cpu_info(void);
extern int dump_global_info(global_info_t *);
extern int print_stopped(void);
extern int show_addrmap(void);
#if EVEREST
static void ide_init_arrays(void);
static void ide_scanslots(void);
extern int dump_ev_bdinfo(boardinfo_t *);
#endif
#if MULTIPROCESSOR
extern void slave_startup(void *); /* declared in ide/csu.s */
static void launch_slaves(void);
#ifdef NOTYET
static int new_master(global_info_t *);
#endif
/* lock global information structure */
int ii_spl;
lock_t ide_info_lock;
#endif /* MULTIPROCESSOR */
extern gen_pda_t gen_pda_tab[MAXCPU];
extern arcs_reg_t excep_regs[MAXCPU][NREGS];
/*
* Only one processor may be executing as IDE_MASTER at any time; the
* remaining processors spin in slave loops waiting for the master to
* launch a diagnostic on their cpu. When ide initially boots, the
* processor which was designated 'bootmaster' by the prom inherits the
* IDE_MASTER mode, but any slave may become the master (and the former
* master becomes a slave) via the ide_switch_cpus() primitive. Only
* IDE_MASTER interprets scripts (which requires a large stack due to
* the resulting recursion), so the master stack floats with the IDE_MASTER
* designation. The outgoing master--now a slave--begins executing slave
* code only, using the standard-sized slave stack for that processor.
*/
/* SLAVE_STACKSIZE is passed in from ide/Makedefs */
#define BOS_TO_TOS(Sbottom, Ssize) (Sbottom + Ssize)
#define SLAVE_STACKADDR(VID) \
BOS_TO_TOS(((char *)slave_stacks + (SLAVE_STACKSIZE*VID)), SLAVE_STACKSIZE)
jmp_buf slave_jbufs[MAXCPU]; /* for uncaught slave-excepts.*/
jmp_buf wakeup_jbufs[MAXCPU]; /* awakened slaves use this */
char slave_stacks[MAXCPU][SLAVE_STACKSIZE];
char private_putbuf[MAXCPU][PUTBUFSIZE]; /* used by msg_printf */
ide_pda_t ide_pda_tab[MAXCPU];
/*
* initargv() and initenv() are called early in csu.s, but the master
* code can use the global string_list structs. 'environ',
* 'argv_str', and 'environ_str' must be in pdas and setup_gpdas()
* must be called before the init* fns.
*/
struct string_list argv_str_tab[MAXCPU];
struct string_list environ_str_tab[MAXCPU];
#if EVEREST
boardinfo_t evboards = { 0, 0, 0, 0, 0, 0 };
#endif /* EVEREST */
/* g_magic == IDE_IMAGIC when _ide_info is valid */
global_info_t _ide_info = {
(uint)-1, /* g_magic */
(uint)-1, /* vid_cnt */
(uint)-1, /* vid_max */
(uint)-1, /* master_vid */
(uint *)(__psint_t)-1, /* saved_normsp */
(uint *)(__psint_t)-1, /* saved_faultsp*/
NO_VID, /* talking_vid */
(set_t)0, /* waiting_vids */
(set_t)0, /* vid_set */
};
global_info_t *giptr = &_ide_info;
#ifdef notdef /* moved to libsk */
/*
* next 5 data arrays are now declared in libsk/lib/skutils.c, and are
* initialized by libsk/lib/skutils:setup_idarr(), which is called
* circuitously from ide_mpsetup(), invoked early in main.
*/
! int vid_to_phys_idx[MAXCPU]; /* vid --> phys_index */
! int phys_idx_to_vid[MAXCPU]; /* phys_index --> vid */
! int vid_to_slot[MAXCPU]; /* vid --> slot */
! int vid_to_slice[MAXCPU]; /* vid --> slice */
! cpuid_t ss_to_vid[_SLOTS][_SLICES]; /* <slot,slice> --> vid */
#endif /* notdef */
#if EVEREST
/*
* if bufptr != NULL, use sprintf to write virt_id's <vid,slot,slice>
* string to that buffer; else 'printf' the info. Also cross-checks
* the mapping of ide's array slot with that of the corresponding mpconf
* struct. If no errors, ide_whoisthat returns the phys_idx to which
* 'virt_id' corresponds, else < 0.
*/
int
ide_whoisthat(int virt_id, char *bufptr)
{
register uint slot, slice, phys_idx;
msg_printf(SUM,"ide_whoisthat(vid %d)\n", virt_id);
if (VID_OUTARANGE(virt_id))
return(ERR_VP_RANGE);
slot = vid_to_slot[virt_id];
slice = vid_to_slice[virt_id];
phys_idx = SS_TO_PHYS(slot, slice);
#if EVEREST
if (MPCONF[virt_id].phys_id != phys_idx) {
msg_printf(SUM,"ide ERROR, whoisthat: mpconf[vid %d]==%d, but\n\tide",
virt_id, MPCONF[virt_id].phys_id);
msg_printf(SUM, " shows vid (%d) --> phys %d (mpmagic 0x%x)\n",virt_id,
phys_idx, MPCONF[virt_id].mpconf_magic);
ide_panic("ide_whoisthat");
}
#endif
if (bufptr) {
if (IDE_ME(ide_mode) == IDE_MASTER)
sprintf(bufptr, "ide_master <%.2d/%.2d>: ", slot, slice);
else
sprintf(bufptr, "ide_slave <%.2d/%.2d>: ", slot, slice);
} else {
if (IDE_ME(ide_mode) == IDE_MASTER)
msg_printf(SUM, "ide_master <%.2d/%.2d>: ", slot, slice);
else
msg_printf(SUM, "ide_slave <%.2d/%.2d>: ", slot, slice);
}
return(phys_idx);
} /* ide_whoisthat */
#endif /* EVEREST */
#if EVEREST
/*
* cross checks its hw slot/slice with the phys_idx which
* the mpconf slot indexed by its pda's vid fetches.
*/
int
ide_whoami(char *inbuf)
{
char cbuf[2*MAXLINELEN], *cp = &cbuf[0];
register evreg_t slotproc;
register uint slot, slice, phys_idx, mpc_phys;
int error = 0;
int vid_me = cpuid();
int pda_virtid, pda_physid;
cbuf[0] = '\0';
if (inbuf)
inbuf[0] = '\0';
if (Reportlevel >= SUM) {
cp += sprintf(cbuf, " %s(v%d): %s\n",
(IDE_ME(ide_mode)==IDE_MASTER ? "IDE" : "ide"), vid_me,
(IDE_ME(ide_mode)==IDE_MASTER ? "-master-" : "-slave-"));
}
if (VID_OUTARANGE(vid_me)) {
msg_printf(IDE_ERR,
"ide_whoami: cpuid() %d out of range (largest assigned was %d)\n",
vid_me, _ide_info.vid_max);
ide_panic("ide_whoami");
}
pda_virtid = GPME(my_virtid);
pda_physid = GPME(my_physid);
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 (pda_virtid != vid_me || pda_physid != phys_idx) {
msg_printf(IDE_ERR,
" whoami: pda.vid %d vid_me %d pda.phys %d hwphys %d\n",
pda_virtid, vid_me, pda_physid, phys_idx);
error++;
}
if (VID_OUTARANGE(pda_virtid)) {
msg_printf(IDE_ERR,
" ide_whoami: pda.vid %d, cpuid said %d\n", pda_virtid, vid_me);
msg_printf(IDE_ERR," vid range is (0 <= vid <= %d)\n",
_ide_info.vid_max);
error++;
}
if (!error) {
mpc_phys = MPCONF[pda_virtid].phys_id;
if (mpc_phys != phys_idx) {
msg_printf(IDE_ERR," ide_whoami: mpconf maps vid %d --> ",
pda_virtid);
msg_printf(IDE_ERR,
" phys %d;\n\tbut gpda.vid == %d & our physid %d \n",
mpc_phys, GPRIVATE(vid_me,my_virtid), phys_idx);
}
}
if (error) {
msg_printf(IDE_ERR, " vid <--> phys_idx errors are fatal...\n");
ide_panic("ide_whoami");
}
if (Reportlevel >= VDBG) {
cp += sprintf(cp,
" ide_whoami: pda.vid %d:cpuid %d, pdaphys %d hwphys %d\n",
pda_virtid, vid_me, pda_physid, phys_idx);
}
if (cp != &cbuf[0]) {
if (inbuf)
strcpy(inbuf, cbuf);
else
if (Reportlevel >= SUM)
msg_printf(JUST_DOIT, "%s", cbuf);
}
return(strlen(cbuf));
} /* ide_whoami */
#elif IP30 && MULTIPROCESSOR
int
ide_whoami(char *bufptr)
{
int cpu = cpuid();
char *str = cpu == IDE_ME(ide_mode)==IDE_MASTER ? "master" : "slave";
if (bufptr) {
sprintf(bufptr,"IDE CPU %d [%s]\n",cpu,str);
return strlen(bufptr);
}
msg_printf(SUM, "IDE CPU %d [%s]\n",cpu,str);
return 0;
} /* ide_whoami */
#else /* !EVEREST: currently this means SP; return 0 */
/* guard against non-EVEREST MP machines (someday) getting this ifdef */
#ifdef MULTIPROCESSOR
dontcompile("#define ERROR, ide_mp.c: MULTIPROCESSOR and !EVEREST!")
#else
int
ide_whoami(char *bufptr)
{
msg_printf(SUM, " IDE");
if (bufptr != NULL) bufptr [0] = '\0';
return(0);
} /* ide_whoami */
#endif /* MULTIPROCESSOR */
#endif /* EVEREST version of ide_whoami */
/*
* ide_mpsetup() is called from ide's main(). The processor
* executing this routine is the initial ide_master.
*/
void
ide_mpsetup(void)
{
#if EVEREST
msg_printf(VRB,"\n *mpsetup: ");
#endif
#if _DO_IILOCK
initlock(&ide_info_lock);
#endif
#if EVEREST
ide_init_arrays();
#endif
ide_cpu_probe(); /* <slot,slice> <--> vid mappings */
#if EVEREST
ide_scanslots();
#endif
ide_initpdas();
/*
* sanity-check everything; with reportlevel <= SUM, if nothing's
* amiss nothing prints
*/
#ifdef EVEREST
dump_cpu_info();
#endif
dump_global_info(&_ide_info);
#if EVEREST
dump_ev_bdinfo(&evboards);
#endif
#ifdef MULTIPROCESSOR
launch_slaves();
#endif
if (Reportlevel >= VRB)
show_addrmap();
return;
} /* ide_mpsetup */
int
show_addrmap(void)
{
__psunsigned_t addr;
int len;
__psunsigned_t endaddr;
msg_printf(JUST_DOIT, " Addresses and lengths of major data structs:\n");
msg_printf(JUST_DOIT,
" MAXCPU %d, NREGS %d; sizeof gpda 0x%x, ide_pda 0x%x\n",
MAXCPU, NREGS, sizeof(gen_pda_t), sizeof(ide_pda_t));
addr = (__psunsigned_t)gen_pda_tab;
len = sizeof(gen_pda_tab);
endaddr = (addr+len);
msg_printf(JUST_DOIT, " &gen_pda_tab 0x%x, len 0x%x (end 0x%x)\n",
addr, len, endaddr);
msg_printf(JUST_DOIT, " &excep_regs 0x%x, length 0x%x (end 0x%x)\n",
excep_regs, sizeof(excep_regs),
((char *)excep_regs+sizeof(excep_regs)));
msg_printf(JUST_DOIT, " &ide_pda_tab 0x%x, length 0x%x (end 0x%x)\n",
ide_pda_tab, sizeof(ide_pda_tab),
(char *)ide_pda_tab + sizeof(ide_pda_tab));
msg_printf(JUST_DOIT, " &slave_stacks 0x%x, length 0x%x (end 0x%x)\n",
slave_stacks, sizeof(slave_stacks),
(char *)slave_stacks+sizeof(slave_stacks));
msg_printf(JUST_DOIT, " &private_putbuf 0x%x, length 0x%x (end 0x%x)\n",
private_putbuf, sizeof(private_putbuf),
((char *)private_putbuf+sizeof(private_putbuf)));
msg_printf(JUST_DOIT, " &slave_jbufs 0x%x, length 0x%x\n",
&slave_jbufs[0], sizeof(slave_jbufs));
msg_printf(JUST_DOIT, " &wakeup_jbufs 0x%x length 0x%x\n",
&wakeup_jbufs[0], sizeof(wakeup_jbufs));
msg_printf(JUST_DOIT, " &argv_str_tab 0x%x length 0x%x\n",
&argv_str_tab[0], sizeof(argv_str_tab));
msg_printf(JUST_DOIT, " &environ_str_tab 0x%x length 0x%x\n",
&environ_str_tab[0], sizeof(environ_str_tab));
return 0;
} /* show_addrmap */
static void
ide_initpdas(void)
{
register int vid, me = cpuid();
#if defined(PDADEBUG)
register int vid_max;
#endif
char * addr = slave_stacks[0];
uint len = sizeof(slave_stacks);
msg_printf(VRB," -initialize PDAs- ");
msg_printf(VRB, "&slave stacks[0] 0x%x, length 0x%x (end 0x%x)\n",
addr, len, (addr+len));
msg_printf(VDBG+1,
" >ide_initpdas: sizeof(ide_pda_t) %d, IDE_PDASIZE %d\n",
sizeof(ide_pda_t), IDE_PDASIZE);
if (sizeof(ide_pda_t) != IDE_PDASIZE) {
msg_printf(IDE_ERR,
"!!ide_initpdas: ide_pda_t struct (%d) != IDE_PDASIZE (%d)!!\n",
sizeof(ide_pda_t), IDE_PDASIZE);
ide_panic("ide_initpdas");
}
#if defined(PDADEBUG)
vid_max = (_ide_info.vid_max >= MAXCPU ? MAXCPU-1 : _ide_info.vid_max);
#endif
/* set up pda for all cpus */
for (vid = 0; vid < MAXCPU; vid++) {
register struct ide_pda_s *i_pdap;
register struct generic_pda_s *g_pdap;
register char *fstack;
register char *istack;
i_pdap = (struct ide_pda_s *)&ide_pda_tab[vid];
g_pdap = (struct generic_pda_s *)&gen_pda_tab[vid];
/* g_pdap->specific_pda = (void *)&ide_pda_tab[vid]; */
/*
* libsk/lib/fault.c:setup_gpdas() already grabbed master's SPs,
* so only the slaves' normal and exception SPs need initializing.
* Store the normal and fault-mode values of the stack on which
* the current master will run as a slave if he swaps jobs with
* a slave (when I implement this feature). The thread running
* as master always uses the master stack, leaving its slave
* stack idle.
*/
fstack = SLAVE_STACKADDR(vid);
istack = (fstack - EXSTKSZ);
if (vid != me) {
g_pdap->pda_fault_sp = (arcs_reg_t *)fstack;
g_pdap->pda_initial_sp = (arcs_reg_t *)istack;
g_pdap->stack_mode = MODE_NORMAL;
i_pdap->ide_mode = IDE_SLAVE;
} else {
i_pdap->ide_mode = IDE_MASTER;
_ide_info.saved_normsp = (uint *)istack;
_ide_info.saved_faultsp = (uint *)fstack;
}
/*
* ide_master uses the global copies of argv_str and environ_str;
* slaves must all have private copies in their pdas
*/
i_pdap->argv_str = (struct string_list *)&argv_str_tab[vid];
i_pdap->environ_str = (struct string_list *)&environ_str_tab[vid];
/*
* msg_printf() uses sprintf to format the requested message into
* a per-process private buffer located via the pda. This string
* is then transferred either into the large, shared circular
* buffer or written to tty or console, depending on the value
* of 'msg_where'. Only this final step requires locking.
*/
i_pdap->putbuf = private_putbuf[vid];
i_pdap->putbufndx = 0;
/*
* each processor has a private proc_talk_t struct, which
* allows the master and it to syncronize and exchange
* information during function launches. Currently none
* of the fields require locking as long as the master-slave
* protocol is observed.
*/
i_pdap->fn_addr = i_pdap->cleanup_addr = 0;
i_pdap->fn_return = i_pdap->cleanup_return = 0;
/* i_pdap->fn_handshake = i_pdap->cleanup_handshake = (voll_t)SLAVE_IDLE;*/
/*
* SLAVE_GO_HOME cmd with a pending doit causes slaves to go into
* ide_slave_wait() and ACK when they're there. Initialize the
* fields this way to sync-up at initialization time: master can't
* issue a command until the slaves set _DONE.
*/
i_pdap->doit_done = i_pdap->doit_done = STAT_SDOIT;
i_pdap->slave_cmd = i_pdap->slave_cmd = SLAVE_GO_HOME;
i_pdap->fn_argcv.argc = i_pdap->cleanup_argcv.argc = (int)0;
i_pdap->fn_argcv.argv = i_pdap->cleanup_argcv.argv = (char **)0;
/*
* each slave uses only one private setjmp buffer (when awakened
* to launch a diag). In order to switch masters, the exiting master
* must save its entire context for the entering slave to pick up.
*/
i_pdap->slave_jbuf = slave_jbufs[vid];
i_pdap->wakeup_jbuf = wakeup_jbufs[vid];
#if defined(PDADEBUG)
if (vid <= vid_max) {
msg_printf(VDBG+1,
" (v%d/p%d: %s: initial sp 0x%x, fault sp 0x%x ",
g_pdap->my_virtid, g_pdap->my_physid,
(vid==me ? "master" : "slave"), (int)g_pdap->pda_initial_sp,
(int)g_pdap->pda_fault_sp);
msg_printf(VDBG+1,
" stack_mode %d\n sjbuf 0x%x wjbuf 0x%x, regs 0x%x\n",
g_pdap->stack_mode,(int)i_pdap->slave_jbuf,
(int)i_pdap->wakeup_jbuf,(int)g_pdap->regs);
}
#endif /* PDADEBUG */
i_pdap->ide_pdamagic = IDE_PDAMAGIC;
}
} /* ide_initpdas */
#if MULTIPROCESSOR
static void
launch_slaves(void)
{
int vid, result;
int master_vid = cpuid();
#if 0
uint stack;
#endif
msg_printf(VRB," -launch slaves-\n");
if (IDE_ME(ide_pdamagic) != IDE_PDAMAGIC) {
msg_printf(IDE_ERR, "launch_slaves: IDE PDAs aren't initialized!\n");
ide_panic("launch_slaves");
}
for (vid = 0; vid <= _ide_info.vid_max; vid++) {
if (vid != master_vid) {
#if 0
stack = (uint)GPRIVATE(vid,pda_initial_sp);
#endif
#if defined(LAUNCH_DEBUG)
msg_printf(VDBG+1,
" launch vid %d (initial_sp 0x%x fault_sp 0x%x)\n",
vid, GPRIVATE(vid,pda_initial_sp), GPRIVATE(vid,pda_fault_sp));
#endif /* LAUNCH_DEBUG */
result = launch_slave(vid, slave_startup,0,0,0,
(char *)(GPRIVATE(vid,pda_initial_sp)));
if (result)
msg_printf(IDE_ERR,"launch_slaves: vid %d's launch res %d\n",
vid, result);
}
/* xxxxx need to set master's slave stack to work if ide_switch_cpus! xxxxx */
/* xxxxx and need to duplicate _fault_sp per slave (in arcs_mp) */
}
/* pause for a bit while the slaves start up: then they wait quietly */
us_delay(US_PER_SEC);
return;
} /* launch_slaves */
#endif /* MULTIPROCESSOR */
#if EVEREST
static void
ide_init_arrays(void)
{
int slot, slice, vid;
msg_printf(VDBG+1, " MAXCPU %d, slots %d, slices %d, empty %d\n",
MAXCPU, _SLOTS, _SLICES, MTY);
/* init structs non-zero for later bogosity checking */
for (vid = 0; vid < MAXCPU; vid++) {
vid_to_phys_idx[vid] = MTY;
phys_idx_to_vid[vid] = MTY;
vid_to_slot[vid] = MTY;
vid_to_slice[vid] = MTY;
}
for (slot = 0; slot < _SLOTS; slot++)
for (slice = 0; slice < _SLICES; slice++)
ss_to_vid[slot][slice] = (cpuid_t)MTY;
return;
} /* ide_init_arrays */
#endif /* EVEREST */
/*
* Probe everest hardware to find out where cpu boards are,
* and set up mappings between physical CPU IDs and logical
* CPU IDs according to PROM mappings.
*
* Some cpus may have been disabled by the PROM, but they
* may be enabled later under operator control.
*
* Returns maximum logical cpu ID (which should be the same as the
* maximum number of cpu's, though some may be disabled).
*/
static int
ide_cpu_probe(void)
{
int vid, vid_max=0, vid_cnt=0;
volatile int cpu_cnt;
set_t vid_set=0;
int vid_me = cpuid();
#if PROBE_DEBUG
char sbuf[128];
#endif
cpu_cnt = setup_idarr(vid_me, &vid_max, &vid_cnt);
_ide_info.vid_cnt = vid_cnt;
_ide_info.vid_max = vid_max;
_ide_info.master_vid = _ide_info.talking_vid = vid_me;
_ide_info.waiting_vids = 0;
/* _ide_info.c_pending = NON_COHERENT; */
/* _ide_info.c_state = NON_COHERENT; */
for (vid=0; vid <= vid_max; vid++)
#if EVEREST
if (vid_to_slot[vid])
#endif /* EVEREST */
vid_set |= (SET_ZEROBIT >> vid);
_ide_info.vid_set = vid_set;
_ide_info.g_magic = IDE_GMAGIC;
#if PROBE_DEBUG
if (Reportlevel >= VRB) {
sprintf_cset(sbuf, _ide_info.vid_set);
msg_printf(JUST_DOIT,"ide_cprobe: ret %d vid_cnt %d max %d set %s\n",
cpu_cnt, _ide_info.vid_cnt, _ide_info.vid_max, sbuf);
}
#endif
return(vid_cnt);
} /* ide_cpu_probe */
#if EVEREST
static void
ide_scanslots()
{
register uint slot, slice;
register uint vpcount = 0;
register uint virt_id;
register set_t vpset = 0;
evbrdinfo_t *brdp;
evcpucfg_t *cpup;
msg_printf(VRB," -hinv- ");
for (slot = 1; slot < EV_MAX_SLOTS; slot++) {
brdp = &(EVCFGINFO->ecfg_board[slot]);
switch(brdp->eb_type) {
case EVTYPE_IP19:
evboards.ip19++;
break;
case EVTYPE_IP21:
evboards.ip21++;
break;
case EVTYPE_IP25:
evboards.ip25++;
break;
case EVTYPE_IO4:
evboards.io4++;
break;
case EVTYPE_MC3:
evboards.mc3++;
break;
case EVTYPE_EMPTY:
evboards.mty++;
break;
default:
evboards.unknown++;
break;
}
}
return;
} /* ide_scanslots */
#endif /* EVEREST */
/* begin data-display routines */
#if EVEREST
int
dump_cpu_info()
{
int slot, slice, mvid, vid;
evreg_t cpumask = (EV_GET_LOCAL(EV_SYSCONFIG)&EV_CPU_MASK) >> EV_CPU_SHFT;
mvid = _ide_info.master_vid;
slot = vid_to_slot[mvid];
slice = vid_to_slice[mvid];
/* if reportlevel is < INFO, only abnormalities will show */
msg_printf(VRB, " cpu configinfo: %d vids (0..%d)",
_ide_info.vid_cnt, _ide_info.vid_max);
msg_printf(VDBG, " HW maximums: %d cpus, %d slots, %d slices/cpuboard\n",
MAXCPU, EV_BOARD_MAX, EV_CPU_PER_BOARD);
msg_printf(VDBG, " vid ---> <slot/slice> mappings: \n");
if (Reportlevel >= VDBG) {
for (vid = 0; vid < MAXCPU; vid++) {
slot = vid_to_slot[vid];
slice = vid_to_slice[vid];
if (vid <= _ide_info.vid_max) {
msg_printf(VRB, " vid %d --> <slot %d/slice %d>\n",
vid,slot,slice);
} else { /* no valid vids here: sanity check initialized values */
if (slot != MTY || slice != MTY)
msg_printf(IDE_ERR, "?? (maxvid %d) vindex %d: <%d/%d\n",
_ide_info.vid_max, vid, slot,slice);
}
}
}
/* translate <slot/slice> pair to corresponding virtual processor id */
msg_printf(VDBG, "\n <slot/slice)--> vid\n");
for (slot=0; slot < EV_BOARD_MAX; slot++) {
if (cpumask & 1) { /* slot has a cpu board in it */
msg_printf(VDBG, " slot %d cpu board: ", slot);
for (slice=0; slice<EV_CPU_PER_BOARD; slice++) {
vid = ss_to_vid[slot][slice];
if (vid == BAD_CPU) {
msg_printf(INFO,
"\n <cpu slice %d/slot %d is defective>\n",
slice, slot);
} else {
if (vid != EV_CPU_NONE)
msg_printf(VDBG, " slice %d->vid %d, ", slice, vid);
}
}
msg_printf(VDBG, "\n");
}
cpumask = cpumask >> 1;
}
return(0);
} /* dump_cpu_info */
#endif /* EVEREST */
int
dump_global_info(global_info_t *ginfop)
{
char setbuffer[SETBUFSIZ];
int vid;
#if EVEREST
uint slot, slice;
#endif /* EVEREST */
ASSERT(ginfop != NULL);
if (ginfop->g_magic != IDE_GMAGIC) {
msg_printf(IDE_ERR, "Invalid global-info magic # (0x%x, not 0x%x)\n",
ginfop->g_magic, IDE_GMAGIC);
ide_panic("dump_global_info");
}
vid = ginfop->master_vid;
if (VID_OUTARANGE(vid)) {
msg_printf(IDE_ERR, "global info: invalid master_vid (%d)\n", vid);
ide_panic("dump_global_info");
}
#if EVEREST
slot = vid_to_slot[vid];
slice = vid_to_slice[vid];
#endif /* EVEREST */
#if EVEREST
msg_printf(VRB,"\n ide_master(%d: %.2d/%.2d); talking vid %d\n",
ginfop->master_vid, slot, slice, ginfop->talking_vid);
#else
msg_printf(VRB,"\n ide_master %d; talking vid %d\n",
ginfop->master_vid, ginfop->talking_vid);
#endif /* EVEREST */
sprintf_cset(setbuffer, ginfop->vid_set);
msg_printf(VRB, " %d active processor%s: %s\n", (int)ginfop->vid_cnt,
_PLURAL(ginfop->vid_cnt), setbuffer);
if (Reportlevel >= VRB) {
if (ginfop->waiting_vids) {
sprintf_cset(setbuffer, ginfop->waiting_vids);
msg_printf(INFO, " waiting slaves: %s\n", setbuffer);
} else
msg_printf(INFO, " no waiting slaves\n");
}
msg_printf(VRB,
" IDE is operating in <%s> mode; message level is %d (0x%x)",
(_ide_info.c_state==COHERENT ? "coherent" : "non-coherent"),
Reportlevel, Reportlevel);
msg_printf(VDBG+1, " v_cnt %d, v_max %d magic 0x%x\n",
_ide_info.vid_cnt, _ide_info.vid_max, _ide_info.g_magic);
return(0);
} /* dump_global_info */
void
dump_idepda(int vid)
{
int vid_me = cpuid();
struct ide_pda_s *i_pdap;
i_pdap = (struct ide_pda_s *)&ide_pda_tab[vid];
if (vid == vid_me)
msg_printf(JUST_DOIT, "IDE PDA, vid %d (pda addr 0x%x, sp 0x%x)\n",
vid, i_pdap, get_sp());
else
msg_printf(JUST_DOIT, "IDE PDA, vid %d (pda addr 0x%x)\n",
vid, i_pdap);
msg_printf(JUST_DOIT,
" magic 0x%x, mode %d, argv_str 0x%x, env_str 0x%x\n",
i_pdap->ide_pdamagic, i_pdap->ide_mode, i_pdap->argv_str,
i_pdap->environ_str);
msg_printf(JUST_DOIT,
" slave_jbuf 0x%x, wakeup_jbuf 0x%x, putbuf 0x%x, putbufndx %d\n",
i_pdap->slave_jbuf, i_pdap->wakeup_jbuf, i_pdap->putbuf,
i_pdap->putbufndx);
return;
}
#if 0
static void
show_SPs(void)
{
register int vid, me = cpuid();
register int vid_max;
register char *fstack;
register char *istack;
vid_max = (_ide_info.vid_max >= MAXCPU ? MAXCPU-1 : _ide_info.vid_max);
msg_printf(JUST_DOIT," I'm vid %d: show SPs of vids 0..%d\n",me,vid_max);
for (vid = 0; vid <= vid_max; vid++) {
register struct ide_pda_s *i_pdap;
register struct generic_pda_s *g_pdap;
i_pdap = (struct ide_pda_s *)&ide_pda_tab[vid];
g_pdap = (struct generic_pda_s *)&gen_pda_tab[vid];
/* slave's normal and exception-stack pointers */
fstack = (char *)g_pdap->pda_fault_sp;
istack = (char *)g_pdap->pda_initial_sp;
if (vid <= vid_max) {
msg_printf(DBG," vid %d pid %d (mode %d): i_sp 0x%x f_sp 0x%x, ",
vid, g_pdap->my_physid, i_pdap->ide_mode,
istack, fstack);
msg_printf(DBG,"s-mode %d\n noflt 0x%x !1st %d 1st_epc 0x%x",
g_pdap->stack_mode,g_pdap->pda_nofault,g_pdap->notfirst,
g_pdap->first_epc);
msg_printf(DBG," sjbuf 0x%x wjbuf 0x%x regs 0x%x\n",
i_pdap->slave_jbuf,i_pdap->wakeup_jbuf,
g_pdap->regs);
}
}
} /* show_SPs */
#endif
#if EVEREST
int
dump_ev_bdinfo(boardinfo_t *bdp)
{
int total;
ASSERT(bdp != NULL);
total = bdp->ip19 + bdp->ip21 + bdp->ip25 + bdp->io4 + bdp->mc3;
if (Reportlevel < INFO) {
msg_printf(INFO, "\n Configuration: %d occupied slot%s:\n",
total, _PLURAL(total));
return(0);
}
msg_printf(INFO, "\n Configuration info: %d occupied slot%s:\n",
total, _PLURAL(total));
if (bdp->ip19)
msg_printf(JUST_DOIT, " %d IP19 board%s\n", bdp->ip19,
_PLURAL(bdp->ip19));
if (bdp->ip21)
msg_printf(JUST_DOIT, " %d IP21 board%s\n", bdp->ip21,
_PLURAL(bdp->ip21));
if (bdp->ip25)
msg_printf(JUST_DOIT, " %d IP25 board%s\n", bdp->ip25,
_PLURAL(bdp->ip25));
if (bdp->io4)
msg_printf(JUST_DOIT, " %d IO4 board%s\n", bdp->io4,
_PLURAL(bdp->io4));
if (bdp->mc3)
msg_printf(JUST_DOIT, " %d MC3 board%s\n", bdp->mc3,
_PLURAL(bdp->mc3));
if (bdp->unknown)
msg_printf(JUST_DOIT, "===> %d board%s were of unknown type\n",
bdp->unknown, _PLURAL(bdp->unknown));
msg_printf(JUST_DOIT, "\n");
return(0);
} /* dump_ev_bdinfo */
#endif /* EVEREST */
#if MULTIPROCESSOR
int
print_stopped(void)
{
char setbuffer[SETBUFSIZ];
set_t vset;
if (!_ide_info.waiting_vids) {
msg_printf(JUST_DOIT, " Currently no IDE slaves are available\n");
} else { /* just take a snapshot while holding the lock */
LOCK_IDE_INFO();
vset = _ide_info.waiting_vids;
UNLOCK_IDE_INFO();
sprintf_cset(setbuffer, vset);
msg_printf(JUST_DOIT, " waiting slaves: %s\n", setbuffer);
}
return(_ide_info.vid_cnt);
} /* print_stopped */
#endif /* MULTIPROCESSOR */
/* XXXXXXXXXXXXXXXXXXXXXXXX end of included fns XXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
#ifdef NOTYET
* int
* new_master(vp_info_t *vp)
* {
*
* CHANGE both slave and master's fault_sp PDA values
* change vp vid, slot,slice
*
* and update ide_update_prompt
*
* } /* new_master */
*
*
* /*
* * Functions to acquire and release control of the single
* * UART shared by multiple processors.
* */
* void
* ACQUIRE_USER_INTERFACE(void)
* {
* again:
*
* if (_ide_info.talking_vid == NO_VID) {
* _ide_info.talking_vid = cpuid();
* msg_printf(DBG, "(VID %d) ", cpuid());
* }
* if (_ide_info.talking_vid != cpuid()) {
* _ide_info.waiting_vids |= (1ULL<<cpuid());
* while (_ide_info.talking_vid != cpuid()) {
* if (cpuid() == 0) {
* if (early_exit_check()) {
* _ide_info.waiting_vids &= ~(1ULL<<cpuid());
* goto again;
* }
* }
* }
* _ide_info.waiting_vids &= ~(1ULL<<cpuid());
* ide_update_prompt();
*
* return;
* }
*
* }
*
* RELEASE_USER_INTERFACE(int id)
* {
* _ide_info.talking_vid = id;
* }
*
*
* extern int consgetc(int);
* int
* early_exit_check()
* {
* int retval = 0;
*
* if (_ide_info.talking_vid == NO_VID) {
* if ((char)consgetc(0) == 1 /* CNTRL-A */) {
* retval = 1;
* }
* }
*
* return(retval);
* }
#endif /* NOTYET */
#ifdef NONONO
> /*
> * Pass control of the user interface to the specified
> * processor, and wait 'till someone tells us what to do.
> */
> _switch_cpus(int argc, char **argv)
> {
> numinp_t newvid;
> int vid = cpuid();
>
> if (argc == 1) {
> msg_printf(SUM, "Currently connected to cpu 0x%x (slot=0x%x proc=0x%x)\n",
> vid, vid_to_slot[vid], vid_to_slice[vid]);
>
> print_stopped();
> return(0);
> }
>
> if (argc != 2)
> return(1);
>
> argv++;
> if (parse_sym(*argv, &newvid) && *atob_s(*argv, &newvid))
> _dbg_error("Illegal cpuid: %s", *argv);
> /* doesn't return */
>
> if ((newvid < 0) || (newvid > MAXCPU)) {
> msg_printf(SUM, "virt_id %d is out of range\n", newvid);
> return(1);
> }
>
> if (!(waiting_vids & (1ULL<<newvid))) {
> msg_printf(SUM, "cpu %s is not stopped\n", *argv);
> print_stopped();
> return(1);
> }
>
> RELEASE_USER_INTERFACE(newvid);
>
> new_master(&_ide_info);
> and update ide_prompt
>
> ACQUIRE_USER_INTERFACE();
> }
>
>
> void
> do_command_parser(void)
> {
> dbg_mode = MODE_DBGMON;
>
> ACQUIRE_USER_INTERFACE();
>
> if (setjmp(private._restart_buf)) {
> ACQUIRE_USER_INTERFACE();
> putchar('\n');
> }
>
> symmon_spl();
> command_parser(ctbl, PROMPT);
> }
#endif /* NONONO */
void
slave_dummy(void) {
msg_printf(SUM, "Slave executing dummy function\n");
}