760 lines
17 KiB
C
760 lines
17 KiB
C
/***********************************************************************\
|
|
* File: sysinit.c *
|
|
* *
|
|
* Contains the code which completes system startup, runs *
|
|
* standard diags, checks the system configuration state, *
|
|
* and finally calls main. *
|
|
* *
|
|
\***********************************************************************/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/cpu.h>
|
|
#include <sys/loaddrs.h>
|
|
#include <sys/sbd.h>
|
|
#include <pon.h>
|
|
#include <arcs/errno.h>
|
|
#include <arcs/io.h>
|
|
#include <arcs/hinv.h>
|
|
#include <gfxgui.h>
|
|
#include <style.h>
|
|
#include <libsc.h>
|
|
#include <libsk.h>
|
|
#include <sys/EVEREST/evmp.h>
|
|
#include <sys/EVEREST/evintr.h>
|
|
#include <sys/EVEREST/evconfig.h>
|
|
#include <sys/EVEREST/gda.h>
|
|
#include <sys/EVEREST/nvram.h>
|
|
#include <sys/EVEREST/evdiag.h>
|
|
#include <sys/EVEREST/diagval_strs.i>
|
|
|
|
extern int stdio_init;
|
|
extern void EnterInteractiveMode(void);
|
|
extern void sysctlr_message(char*);
|
|
extern void update_boot_stat(void);
|
|
extern int set_diagval_disable(int, int);
|
|
|
|
extern ushort calc_cksum(void);
|
|
extern void compare_checksums(void);
|
|
extern void update_checksum(void);
|
|
|
|
void main(void);
|
|
void fputest(void);
|
|
void init_prom_soft(int);
|
|
void reboot(void);
|
|
void config_cache(void);
|
|
void io4_config(void);
|
|
void fix_vpids(void);
|
|
void init_tlb(void);
|
|
void check_inventory(void);
|
|
|
|
int version(void);
|
|
|
|
extern int _prom;
|
|
extern int multi_io4;
|
|
extern int verbose_faults;
|
|
extern int doass;
|
|
extern int stdio_init;
|
|
extern struct string_list environ_str;
|
|
|
|
extern int read_serial(char*);
|
|
extern unchar get_cc_rev(int, int);
|
|
extern void set_cc_rev(void);
|
|
extern void replace_str(char *, char *, struct string_list *);
|
|
|
|
static void alloc_memdesc(void);
|
|
static void start_slave_loop(void);
|
|
#ifndef IP25
|
|
static void fix_ecc(int);
|
|
#endif
|
|
static void show_halt_msg(void);
|
|
static void fix_urgent(void);
|
|
#if IP19
|
|
static void store_my_checksums(void);
|
|
#endif /* IP19 */
|
|
static void init_piggyback(void);
|
|
|
|
void reboot(void);
|
|
|
|
#define MPCONF_LAUNCH_LEVEL 8
|
|
|
|
#define SLAVE_STACKSIZE 4096
|
|
|
|
#ifdef IP21
|
|
static void early_init_wg(void);
|
|
#endif
|
|
|
|
#if defined(DEBUG)
|
|
# define DPRINTF(x) printf x
|
|
#else
|
|
# define DPRINTF(x)
|
|
#endif
|
|
|
|
/*
|
|
* Set master control flags in the prom.
|
|
*/
|
|
|
|
void
|
|
sysinit(void)
|
|
{
|
|
int restart, i;
|
|
|
|
#ifdef SABLE
|
|
EVCFGINFO->ecfg_debugsw |= VDS_MANUMODE + VDS_DEBUG_PROM;
|
|
EVCFGINFO->ecfg_board[0].eb_type = EVTYPE_IP25;
|
|
EVCFGINFO->ecfg_board[0].eb_cpuarr[0].cpu_enable = 1;
|
|
EVCFGINFO->ecfg_memsize = 32768; /* 8 mb */
|
|
MPCONF[0].mpconf_magic = MPCONF_MAGIC;
|
|
MPCONF[0].virt_id = 0;
|
|
MPCONF[0].pr_id = get_prid();
|
|
#endif
|
|
|
|
/* Display the PROM header */
|
|
(void) version();
|
|
|
|
/* Initialize the globals pertaining to cache size */
|
|
printf("Sizing caches...\n");
|
|
sysctlr_message("Sizing caches...");
|
|
config_cache();
|
|
|
|
/* These need to be set to get stdio and certain prom initialization
|
|
* to behave correctly.
|
|
*/
|
|
_prom = 1;
|
|
stdio_init = 0;
|
|
|
|
/* It takes too long to start probe all of the SCSI busses on
|
|
* large Everest systems, so we set multi_io4 to 0 to force it
|
|
* to only probe the master IO4.
|
|
*/
|
|
multi_io4 = 0;
|
|
|
|
/* If the debug switch is set we dump verbose fault state.
|
|
* Otherwise, make errors terse.
|
|
*/
|
|
if (EVCFGINFO->ecfg_debugsw & VDS_DEBUG_PROM)
|
|
verbose_faults = 1;
|
|
else
|
|
verbose_faults = 0;
|
|
|
|
printf("Initializing exception vectors.\r\n");
|
|
_hook_exceptions();
|
|
set_SR(NORMAL_SR);
|
|
|
|
#ifdef IP21
|
|
printf("Initializing write-gatherer.\n");
|
|
early_init_wg();
|
|
#endif
|
|
|
|
printf("Initializing IO4 subsystems.\n");
|
|
(void) io4_config();
|
|
|
|
printf("Fixing vpids...\n");
|
|
(void) fix_vpids();
|
|
|
|
/* Set-up environment */
|
|
printf("Initializing environment\n");
|
|
sysctlr_message("Initing environment");
|
|
init_env();
|
|
|
|
update_boot_stat();
|
|
|
|
/* Initialize system serial number */
|
|
if (read_serial(EVCFGINFO->ecfg_snum) == -1)
|
|
printf("WARNING: serial number is invalid!!\n");
|
|
|
|
#if IP19 || IP25
|
|
/* Check CC chip revs (can't do this on IP21 until slaves are up) */
|
|
init_piggyback();
|
|
#endif
|
|
|
|
/*
|
|
* Run additional diags
|
|
*/
|
|
|
|
/* Initialize rest of the system software */
|
|
printf("Initializing software and devices.\r\n");
|
|
init_prom_soft(1);
|
|
|
|
|
|
printf("All initialization and diagnostics completed.\r\n");
|
|
|
|
sysctlr_message("Starting slaves...");
|
|
start_slave_loop();
|
|
|
|
/* Fix up the urgent timeout values */
|
|
fix_urgent();
|
|
|
|
#if IP19
|
|
/* Have each processor store its EAROM checksums.
|
|
* The IP21 prom does this now, also on TFP can't touch
|
|
* EAROM at this time.
|
|
*/
|
|
store_my_checksums();
|
|
#endif /* IP19 */
|
|
|
|
/* Avoid cache snooping problems. */
|
|
delay(200);
|
|
|
|
/*
|
|
* Be sure we do not have and pending interrupts from the slaves
|
|
* entering their slave loops. This can happen using the "pod"
|
|
* command - where the slaves then send a "i'm in pod" interrupt.
|
|
*/
|
|
for (i = 0; i < 128; i++) {
|
|
EV_SET_LOCAL(EV_CIPL0, (__uint64_t)i);
|
|
}
|
|
|
|
#if IP21
|
|
/* Check CC chip revs (can't do this on IP21 until slaves are up) */
|
|
set_cc_rev();
|
|
init_piggyback();
|
|
#endif
|
|
|
|
/* If we're on a graphics system, and the NOGFX bit is set,
|
|
* reboot the system. This is a failsafe for those times when
|
|
* graphics are down and no terminal is available.
|
|
*/
|
|
if (EVCFGINFO->ecfg_debugsw & VDS_NOGFX) {
|
|
replace_str("console", "d", &environ_str);
|
|
autoboot(0, "\nThe NOGFX debug switch is set; rebooting system...\n\n",
|
|
NULL);
|
|
}
|
|
|
|
compare_checksums();
|
|
|
|
check_inventory();
|
|
|
|
sysctlr_message("Startup complete.");
|
|
|
|
/* Do the right thing depending on how the RESTART stuff is set */
|
|
restart = get_nvreg(NVOFF_RESTART);
|
|
set_nvreg(NVOFF_RESTART, 0);
|
|
update_checksum();
|
|
switch (restart) {
|
|
case PROMOP_RESTART:
|
|
EnterInteractiveMode();
|
|
break;
|
|
|
|
case PROMOP_REBOOT:
|
|
reboot();
|
|
break;
|
|
|
|
default:
|
|
startup();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* init_prom_soft()
|
|
* Calls the initialization routines for the major
|
|
* PROM subsystems.
|
|
*/
|
|
|
|
void
|
|
init_prom_soft(int no_init_env)
|
|
{
|
|
sysctlr_message("Reiniting caches..");
|
|
config_cache();
|
|
flush_cache();
|
|
|
|
set_SR(NORMAL_SR); /* Set SR to its "normal" state */
|
|
_hook_exceptions();
|
|
|
|
if (!no_init_env)
|
|
init_env();
|
|
|
|
sysctlr_message("Initing saio...");
|
|
_init_saio();
|
|
|
|
init_tlb();
|
|
alloc_memdesc();
|
|
}
|
|
|
|
|
|
/*
|
|
* show_halt_msg()
|
|
* Display a nice friendly halt message for the user
|
|
*/
|
|
|
|
static void
|
|
show_halt_msg(void)
|
|
{
|
|
if (doGui()) setGuiMode(1,GUI_NOLOGO);
|
|
popupDialog("\n\nOkay to power off the system now.\n\n"
|
|
"Press RESET button to restart.",
|
|
0,DIALOGINFO,DIALOGCENTER|DIALOGBIGFONT);
|
|
}
|
|
|
|
|
|
/*
|
|
* halt()
|
|
* Bring the system to a quiescent state
|
|
*/
|
|
|
|
void
|
|
halt()
|
|
{
|
|
show_halt_msg();
|
|
}
|
|
|
|
|
|
/*
|
|
* powerdown()
|
|
* Attempt a soft power down of the system.
|
|
*/
|
|
|
|
void
|
|
powerdown(void)
|
|
{
|
|
cpu_soft_powerdown();
|
|
show_halt_msg();
|
|
}
|
|
|
|
|
|
/*
|
|
* restart()
|
|
* Attempt to restart the machine.
|
|
*/
|
|
|
|
void
|
|
restart(void)
|
|
{
|
|
static int restart_buttons[] = {DIALOGRESTART,-1};
|
|
if (doGui()) setGuiMode(1,GUI_NOLOGO);
|
|
popupDialog("\n\nYou may shutdown the system.\n\nPress any key to restart.",
|
|
restart_buttons, DIALOGINFO, DIALOGCENTER|DIALOGBIGFONT);
|
|
if (doGui()) setGuiMode(0, GUI_RESET);
|
|
startup();
|
|
}
|
|
|
|
|
|
/*
|
|
* reboot()
|
|
* This is supposed to try to reproduce the last system boot
|
|
* command.
|
|
*/
|
|
|
|
void
|
|
reboot(void)
|
|
{
|
|
int Verbose = 0; /* ??? */
|
|
|
|
if (!Verbose && doGui()) {
|
|
setGuiMode(1,0);
|
|
}
|
|
else {
|
|
p_panelmode();
|
|
p_cursoff();
|
|
}
|
|
if (ESUCCESS != autoboot(0, 0, 0)) {
|
|
putchar('\n');
|
|
setTpButtonAction(EnterInteractiveMode,TPBCONTINUE,WBNOW);
|
|
p_curson();
|
|
p_printf("Unable to boot; press any key to continue: ");
|
|
getchar();
|
|
putchar('\n');
|
|
}
|
|
|
|
/* If reboot fails, reinitialize software in case a partially
|
|
* booted program has messed up the prom state.
|
|
*/
|
|
EnterInteractiveMode(); /* should not get here */
|
|
}
|
|
|
|
|
|
/*
|
|
* enter_imode()
|
|
* Drop back into Interactive Mode.
|
|
*/
|
|
|
|
void
|
|
enter_imode(void)
|
|
{
|
|
_hook_exceptions();
|
|
_init_saio(); /* initialize saio library */
|
|
alloc_memdesc(); /* allocate memory descriptors for prom */
|
|
set_SR(NORMAL_SR);
|
|
main();
|
|
EnterInteractiveMode(); /* shouldn't get here */
|
|
}
|
|
|
|
|
|
/*
|
|
* alloc_memdesc()
|
|
* Allocate memory descriptors.
|
|
*/
|
|
|
|
static void
|
|
alloc_memdesc(void)
|
|
{
|
|
|
|
}
|
|
|
|
#ifndef IP25
|
|
static void
|
|
fix_ecc(int print)
|
|
{
|
|
int slot, proc;
|
|
uint spnum;
|
|
int vpid;
|
|
int ecchkdis;
|
|
|
|
spnum = load_double_lo((long long *)EV_SPNUM);
|
|
slot = (spnum & EV_SLOTNUM_MASK) >> EV_SLOTNUM_SHFT;
|
|
proc = (spnum & EV_PROCNUM_MASK) >> EV_PROCNUM_SHFT;
|
|
|
|
if ((get_prid() & C0_REVMASK) >= 0x40)
|
|
ecchkdis = 0;
|
|
else
|
|
ecchkdis = 1;
|
|
|
|
EV_SETCONFIG_REG(slot, proc, EV_ECCHKDIS, ecchkdis);
|
|
|
|
vpid = EVCFGINFO->ecfg_board[slot].eb_cpuarr[proc].cpu_vpid;
|
|
MPCONF[vpid].pr_id = (int)get_prid();
|
|
|
|
if (print)
|
|
printf("Set slot %d proc %d to %d\n", slot, proc, ecchkdis);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* boot_slaves()
|
|
* A simple stub routine which clears interrupts before dropping
|
|
* into the slave loop.
|
|
*/
|
|
|
|
static void
|
|
boot_slaves()
|
|
{
|
|
#if IP19
|
|
extern void ip19_cache_init(void);
|
|
#endif
|
|
int i;
|
|
|
|
#if IP19
|
|
/* The IP21 prom already does this and the EAROM can't be
|
|
* touched safely at this time on TFP.
|
|
*/
|
|
store_my_checksums();
|
|
ip19_cache_init();
|
|
#elif IP21
|
|
/* The cc rev number is in the spnum register so other processors
|
|
* can't look at it. we have to save it here so the master can look
|
|
* at it later.
|
|
*/
|
|
set_cc_rev();
|
|
#endif /* IP21 */
|
|
|
|
for (i = 0; i < EVINTR_MAX_LEVELS; i++)
|
|
EV_SET_LOCAL(EV_CIPL0, i);
|
|
|
|
#if TFP
|
|
fputest();
|
|
#endif
|
|
slave_loop();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* void start_slave_loop()
|
|
* Instructs the slave processors to jump to the slave_loop
|
|
* routine.
|
|
*/
|
|
|
|
static void
|
|
start_slave_loop(void)
|
|
{
|
|
uint cpu;
|
|
__psunsigned_t stack;
|
|
|
|
/* Don't start slave processors if the NO MP debug switch is set */
|
|
if (EVCFGINFO->ecfg_debugsw & VDS_NOMP) {
|
|
printf("NOTE: NO MP switch set -- skipping slave processor startup\n");
|
|
return;
|
|
}
|
|
|
|
for (cpu = 0; cpu < EV_MAX_CPUS; cpu++) {
|
|
if (cpu == cpuid()) {
|
|
printf("Bootmaster processor already started.\n");
|
|
#ifndef IP25
|
|
fix_ecc(0);
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
if (MPCONF[cpu].mpconf_magic != MPCONF_MAGIC ||
|
|
MPCONF[cpu].virt_id != cpu)
|
|
continue;
|
|
|
|
stack = SLAVESTACK_BASE + ((cpu + 1) * SLAVE_STACKSIZE) - 1;
|
|
stack &= ~0xf;
|
|
|
|
printf("Starting processor #%d\n", cpu);
|
|
|
|
launch_slave(cpu, (void (*)(int)) boot_slaves, 0, 0, 0,
|
|
(void*) stack);
|
|
|
|
/* Now actually launch the slave processors */
|
|
EV_SET_LOCAL(EV_SENDINT,
|
|
EVINTR_VECTOR(MPCONF_LAUNCH_LEVEL, MPCONF[cpu].phys_id));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* fix_urgent
|
|
* Sets the urgent timeout values for all of the processors in
|
|
* the system.
|
|
*/
|
|
|
|
static void
|
|
fix_urgent(void)
|
|
{
|
|
int slot, type;
|
|
int tout_value = ((_get_numcpus() > 15) ? 0xc80 : 0x80);
|
|
|
|
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
|
|
|
|
type = BOARD(slot)->eb_type;
|
|
if ((type == EVTYPE_IP19 || type == EVTYPE_IP21 || type == EVTYPE_IP25) &&
|
|
BOARD(slot)->eb_enabled) {
|
|
|
|
EV_SET_CONFIG(slot, EV_A_URGENT_TIMEOUT, tout_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#if IP19
|
|
|
|
static void
|
|
store_my_checksums(void)
|
|
{
|
|
int byte0;
|
|
int vpid;
|
|
unsigned short stored_checksum;
|
|
|
|
vpid = cpuid();
|
|
|
|
MPCONF[vpid].earom_cksum = calc_cksum();
|
|
delay(2);
|
|
stored_checksum = (load_double_lo((void *)EV_CKSUM1_LOC) << 8);
|
|
delay(2);
|
|
stored_checksum += load_double_lo((void *)EV_CKSUM0_LOC);
|
|
delay(2);
|
|
|
|
/* We want to update this guy atomically */
|
|
MPCONF[vpid].stored_cksum = stored_checksum;
|
|
|
|
byte0 = load_double_lo((void *)EV_EAROM_BASE);
|
|
delay(2);
|
|
|
|
/* If byte0 is wrong, correct it and set our diagval. */
|
|
|
|
#ifdef _MIPSEL
|
|
if (byte0 != (EV_EAROM_BYTE0 & ~EAROM_BE_MASK)) {
|
|
store_double_lo((void *)EV_EAROM_BASE,
|
|
(EV_EAROM_BYTE0 & ~EAROM_BE_MASK));
|
|
delay(2);
|
|
set_diagval_disable(vpid, EVDIAG_EAROM_REPAIRED);
|
|
}
|
|
|
|
#else
|
|
|
|
if (byte0 != (EV_EAROM_BYTE0 | EAROM_BE_MASK)) {
|
|
store_double_lo((void *)EV_EAROM_BASE,
|
|
(EV_EAROM_BYTE0 | EAROM_BE_MASK));
|
|
delay(2);
|
|
set_diagval_disable(vpid, EVDIAG_EAROM_REPAIRED);
|
|
}
|
|
|
|
#endif /* _MIPSEL */
|
|
|
|
}
|
|
#endif /* IP19 */
|
|
|
|
static void
|
|
init_piggyback(void)
|
|
{
|
|
#if defined(IP19)
|
|
# define MINREV 1
|
|
#elif defined(IP21)
|
|
# define MINREV 1
|
|
#elif defined(IP25)
|
|
# define MINREV 3
|
|
#endif
|
|
|
|
char *piggy;
|
|
unsigned char minrev;
|
|
int slot, slice, type;
|
|
|
|
minrev = 0xff;
|
|
|
|
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
|
|
for (slice = 0; slice < EV_CPU_PER_BOARD; slice++) {
|
|
if (BOARD(slot)->eb_cpuarr[slice].cpu_diagval == EVDIAG_NOTFOUND){
|
|
continue;
|
|
}
|
|
type = BOARD(slot)->eb_type;
|
|
switch(type) {
|
|
case EVTYPE_IP19:
|
|
case EVTYPE_IP21:
|
|
case EVTYPE_IP25:
|
|
if (BOARD(slot)->eb_enabled) {
|
|
unsigned char rev;
|
|
if (!BOARD(slot)->eb_cpuarr[slice].cpu_enable) {
|
|
continue;
|
|
}
|
|
rev = get_cc_rev(slot, slice);
|
|
BOARD(slot)->eb_un.ebun_cpu.eb_ccrev = rev;
|
|
DPRINTF(("0x%x/0x%x: CC rev(%d)\n", slot, slice, rev));
|
|
if (rev < minrev) {
|
|
minrev = rev;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
piggy = getenv("piggyback_reads");
|
|
if (piggy) {
|
|
if (*piggy == '0') {
|
|
DPRINTF(("Piggyback reads manually disabled\n"));
|
|
minrev = 1; /* old board, piggy back reads are broken... */
|
|
} else if (*piggy == '1') {
|
|
DPRINTF(("Piggyback reads manually enabled\n"));
|
|
minrev = MINREV + 1;
|
|
}
|
|
}
|
|
|
|
for (slot = 0; slot < EV_MAX_SLOTS; slot++) {
|
|
type = BOARD(slot)->eb_type;
|
|
if ((type==EVTYPE_IP19 || type==EVTYPE_IP21 || type==EVTYPE_IP25) &&
|
|
BOARD(slot)->eb_enabled) {
|
|
if (minrev > 1)
|
|
BOARD(slot)->eb_un.ebun_cpu.eb_brdflags |= EV_BFLAG_PIGGYBACK;
|
|
else
|
|
BOARD(slot)->eb_un.ebun_cpu.eb_brdflags &= ~EV_BFLAG_PIGGYBACK;
|
|
|
|
for (slice = 0; slice < EV_CPU_PER_BOARD; slice++) {
|
|
if ((BOARD(slot)->eb_cpuarr[slice].cpu_diagval ==
|
|
EVDIAG_NOTFOUND) ||
|
|
!BOARD(slot)->eb_cpuarr[slice].cpu_enable)
|
|
continue;
|
|
if (minrev > MINREV) {
|
|
EV_SETCONFIG_REG(slot, slice << EV_PROCNUM_SHFT,
|
|
EV_PGBRDEN, 1);
|
|
} else {
|
|
EV_SETCONFIG_REG(slot, slice << EV_PROCNUM_SHFT,
|
|
EV_PGBRDEN, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (minrev > MINREV) {
|
|
printf("Piggyback reads enabled.\n");
|
|
} else {
|
|
DPRINTF(("Piggyback reads disabled\n"));
|
|
}
|
|
}
|
|
|
|
#ifdef IP21
|
|
/*
|
|
* early_init_wg -- this function writes 64 words of data to the write gatherer,
|
|
* making it flush both of its a&b buffers and insuring that
|
|
* all the words in the DB chips have correct parity.
|
|
*
|
|
* This function should be called for each the processor in the system,
|
|
* by that processor (i.e. it doesn't do any good to run it 4 times on
|
|
* cpu 0, it needs to be run on each individual cpu).
|
|
*/
|
|
#define ROUNDUP(addr, alignment) \
|
|
(void *)((((__psunsigned_t)&addr) + (alignment - 1)) & ~(alignment - 1))
|
|
|
|
#define SETWG(addr) EV_SET_LOCAL(EV_WGDST, addr)
|
|
|
|
|
|
#define FLUSH \
|
|
{ \
|
|
volatile int i; \
|
|
\
|
|
*(volatile int *)0x8000000018300020 = 0; /* write to flush offset */ \
|
|
do { \
|
|
*(volatile int *)0x8000000018300028 = 0; /* write to sync offset */ \
|
|
} while (*(volatile long *)0x9000000018300000 & (0x3f3f)); \
|
|
\
|
|
for(i=0; i < 3000; i++); \
|
|
}
|
|
|
|
|
|
static void
|
|
early_init_wg(void)
|
|
{
|
|
int i, *iptr;
|
|
char *ptr;
|
|
long count, success=1;
|
|
|
|
ptr = (char *)WGTESTMEM_ADDR;
|
|
EV_SET_LOCAL(EV_WGDST, ptr);
|
|
|
|
/*
|
|
* cause a flush to happen to clear any junk that might
|
|
* happen to be in the write-gatherer after a reset.
|
|
*
|
|
* This could potentially cause a DB chip parity error
|
|
* and a data sent error on channel zero. If you get
|
|
* those, you're on your own. You could ignore them since
|
|
* they're only for junk data that we don't care about,
|
|
* but then again, I'm not sure.
|
|
*/
|
|
FLUSH;
|
|
|
|
count = 0;
|
|
while (count < 50) /* keep going until we succeed or the test gets boring */
|
|
{
|
|
success = 1;
|
|
|
|
for(i=0; i < 64; i++) /* write 64 words to flush out the write gather (both a&b buffers) */
|
|
{
|
|
*(volatile int *)0x8000000018300000 = i;
|
|
}
|
|
|
|
FLUSH;
|
|
|
|
for(i=0, iptr = (int *)ptr; i < 32; i+=2)
|
|
{
|
|
if (iptr[i] != i+1+32)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("1(%d): early_init_wg failed in checking data (0x%x != 0x%x)\n", count, iptr[i], i+1+32);
|
|
#endif
|
|
success = 0;
|
|
}
|
|
if (iptr[i+1] != i+32)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("2(%d): early_init_wg failed in checking data (0x%x != 0x%x)\n", count, iptr[i+1], i+32);
|
|
#endif
|
|
success = 0;
|
|
}
|
|
}
|
|
|
|
count++;
|
|
if (success == 1)
|
|
break;
|
|
}
|
|
|
|
if (count > 1)
|
|
{
|
|
printf(" WARNING: Write gatherer initialization failed %d time(s) before succeeding.\n",
|
|
count-1);
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|