#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.82 2024/03/05 14:15:33 thorpej Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_modular.h"
#include "opt_execfmt.h"
#include "zsc.h"
#include "com.h"
#include "ksyms.h"
#include <sys/param.h>
#include <sys/boot_flag.h>
#include <sys/conf.h>
#include <sys/cpu.h>
#include <sys/device.h>
#include <sys/intr.h>
#include <sys/kcore.h>
#include <sys/ksyms.h>
#include <sys/kernel.h>
#include <sys/reboot.h>
#include <sys/systm.h>
#include <uvm/uvm_extern.h>
#include <ufs/mfs/mfs_extern.h>
#include <dev/clock_subr.h>
#include <dev/cons.h>
#ifdef DDB
#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
#endif
#include <machine/mainboard.h>
#include <machine/sysconf.h>
#include <machine/autoconf.h>
#include <machine/bootinfo.h>
#include <machine/prom.h>
struct vm_map *phys_map = NULL;
char *bootinfo = NULL;
phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
int mem_cluster_cnt;
void to_monitor(int) __dead;
void prom_halt(int) __dead;
#ifdef KGDB
void zs_kgdb_init(void);
void kgdb_connect(int);
#endif
int initcpu(void);
void configure(void);
void mach_init(int, char *[], char*[], u_int, char *);
int memsize_scan(void *);
#ifdef DEBUG
extern void stacktrace(void);
#endif
extern void prom_init(void);
extern void pizazz_init(void);
static void unimpl_cons_init(void);
static void unimpl_iointr(uint32_t, vaddr_t, uint32_t);
static int unimpl_memsize(void *);
static void unimpl_intr_establish(int, int (*)(void *), void *);
struct platform platform = {
.iobus = "iobus not set",
.cons_init = unimpl_cons_init,
.iointr = unimpl_iointr,
.memsize = unimpl_memsize,
.intr_establish = unimpl_intr_establish,
.clkinit = NULL,
};
extern struct consdev consdev_prom;
extern struct consdev consdev_zs;
static void null_cnprobe(struct consdev *);
static void prom_cninit(struct consdev *);
static int prom_cngetc(dev_t);
static void prom_cnputc(dev_t, int);
static void null_cnpollc(dev_t, int);
struct consdev consdev_prom = {
null_cnprobe,
prom_cninit,
prom_cngetc,
prom_cnputc,
null_cnpollc,
};
void
mach_init(int argc, char *argv[], char *envp[], u_int bim, char *bip)
{
u_long first, last;
char *kernend;
char *cp;
int i, howto;
extern char edata[], end[];
const char *bi_msg;
#if NKSYMS || defined(DDB) || defined(MODULAR)
char *ssym = 0;
char *esym = 0;
struct btinfo_symtab *bi_syms;
#endif
if (bim == BOOTINFO_MAGIC) {
struct btinfo_magic *bi_magic;
bootinfo = (char *)BOOTINFO_ADDR;
bi_magic = lookup_bootinfo(BTINFO_MAGIC);
if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC)
bi_msg = "invalid bootinfo structure.\n";
else
bi_msg = NULL;
} else
bi_msg = "invalid bootinfo (standalone boot?)\n";
kernend = (void *)mips_round_page(end);
memset(edata, 0, end - edata);
mips_vector_init(NULL, false);
#if NKSYMS || defined(DDB) || defined(LKM)
bi_syms = lookup_bootinfo(BTINFO_SYMTAB);
if (bi_syms != NULL) {
ssym = (void *)bi_syms->ssym;
esym = (void *)bi_syms->esym;
kernend = (void *)mips_round_page(esym);
}
#endif
prom_init();
consinit();
if (bi_msg != NULL)
printf(bi_msg);
uvm_md_init();
physmem = memsize_scan(kernend);
mem_clusters[0].start = 0;
mem_clusters[0].size = ctob(physmem);
mem_cluster_cnt = 1;
makebootdev(argv[0]);
boothowto = RB_AUTOBOOT;
for (i = 1; i < argc; i++) {
for (cp = argv[i]; *cp; cp++) {
if (*cp == '-')
continue;
howto = 0;
BOOT_FLAG(*cp, howto);
if (! howto)
printf("bootflag '%c' not recognised\n", *cp);
else
boothowto |= howto;
}
}
#if NKSYMS || defined(DDB) || defined(MODULAR)
if (esym)
ksyms_addsyms_elf(esym - ssym, ssym, esym);
#endif
#ifdef DDB
if (boothowto & RB_KDB)
Debugger();
#endif
#ifdef KGDB
zs_kgdb_init();
if (boothowto & RB_KDB)
kgdb_connect(0);
#endif
if (boothowto & RB_MINIROOT)
kernend += round_page(mfs_initminiroot(kernend));
first = round_page(MIPS_KSEG0_TO_PHYS(kernend));
last = mem_clusters[0].start + mem_clusters[0].size;
uvm_page_physload(atop(first), atop(last), atop(first), atop(last),
VM_FREELIST_DEFAULT);
mips_init_msgbuf();
pmap_bootstrap();
mips_init_lwp0_uarea();
pizazz_init();
}
void
cpu_startup(void)
{
cpu_startup_common();
}
void *
lookup_bootinfo(int type)
{
struct btinfo_common *bt;
char *help = bootinfo;
if (help == NULL)
return (NULL);
do {
bt = (struct btinfo_common *)help;
if (bt->type == type)
return ((void *)help);
help += bt->next;
} while (bt->next != 0 &&
(size_t)help < (size_t)bootinfo + BOOTINFO_SIZE);
return (NULL);
}
int waittime = -1;
void
prom_halt(int howto)
{
if (howto & RB_HALT)
MIPS_PROM(reinit)();
MIPS_PROM(reboot)();
}
void
cpu_reboot(volatile int howto, char *bootstr)
{
savectx(curpcb);
#ifdef DEBUG
if (panicstr)
stacktrace();
#endif
if (cold) {
howto |= RB_HALT;
goto haltsys;
}
if ((boothowto & RB_HALT) != 0)
howto |= RB_HALT;
boothowto = howto;
if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
waittime = 0;
vfs_shutdown();
}
splhigh();
#if 0
if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
#else
if (howto & RB_DUMP)
#endif
dumpsys();
haltsys:
doshutdownhooks();
pmf_system_shutdown(boothowto);
if ((howto & RB_POWERDOWN) == RB_POWERDOWN)
prom_halt(0x80);
printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
prom_halt(howto & RB_HALT);
}
int
initcpu(void)
{
spl0();
return 0;
}
static void
unimpl_cons_init(void)
{
panic("sysconf.init didn't set cons_init");
}
static void
unimpl_iointr(uint32_t status, vaddr_t pc, uint32_t ipending)
{
panic("sysconf.init didn't set intr");
}
static int
unimpl_memsize(void *first)
{
panic("sysconf.init didn't set memsize");
}
void
unimpl_intr_establish(int level, int (*func)(void *), void *arg)
{
panic("sysconf.init didn't init intr_establish");
}
void
delay(int n)
{
DELAY(n);
}
int
memsize_scan(void *first)
{
volatile int *vp, *vp0;
int mem, tmp, tmp0;
#define PATTERN1 0xa5a5a5a5
#define PATTERN2 ~PATTERN1
mem = btoc((paddr_t)first - MIPS_KSEG0_START);
vp = (int *)MIPS_PHYS_TO_KSEG1(mem << PGSHIFT);
vp0 = (int *)MIPS_PHYS_TO_KSEG1(0);
tmp0 = *vp0;
while (vp < (int *)MIPS_MAX_MEM_ADDR) {
tmp = *vp;
*vp = PATTERN1;
*vp0 = PATTERN2;
wbflush();
if (*vp != PATTERN1)
break;
*vp = PATTERN2;
*vp0 = PATTERN1;
wbflush();
if (*vp != PATTERN2)
break;
*vp = tmp;
vp += PAGE_SIZE/sizeof(int);
mem++;
}
*vp0 = tmp0;
return mem;
}
static void
null_cnprobe(struct consdev *cn)
{
}
static void
prom_cninit(struct consdev *cn)
{
extern const struct cdevsw cons_cdevsw;
cn->cn_dev = makedev(cdevsw_lookup_major(&cons_cdevsw), 0);
cn->cn_pri = CN_REMOTE;
}
static int
prom_cngetc(dev_t dev)
{
return MIPS_PROM(getchar)();
}
static void
prom_cnputc(dev_t dev, int c)
{
MIPS_PROM(putchar)(c);
}
static void
null_cnpollc(dev_t dev, int on)
{
}
void
consinit(void)
{
cn_tab = &consdev_zs;
(*cn_tab->cn_init)(cn_tab);
}