#include "ksyms.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/sysctl.h>
#include <sys/exec.h>
#include <sys/core.h>
#include <sys/kcore.h>
#include <net/if.h>
#include <uvm/uvm_extern.h>
#include <dev/cons.h>
#include <sh/bscreg.h>
#include <sh/cpgreg.h>
#include <sh/trap.h>
#include <sh/cache.h>
#include <sh/cache_sh4.h>
#include <sh/mmu_sh4.h>
#include <machine/cpu.h>
#include <machine/kcore.h>
#include <machine/pcb.h>
#include <landisk/landisk/landiskreg.h>
#ifdef DDB
#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
#include <ddb/db_interface.h>
#endif
char machine[] = MACHINE;
__dead void landisk_startup(int, char *);
__dead void main(void);
void cpu_init_kcore_hdr(void);
void blink_led(void *);
int led_blink;
extern u_int32_t getramsize(void);
struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 };
struct uvm_constraint_range *uvm_md_constraints[] = { NULL };
int safepri = 0;
void
cpu_startup(void)
{
extern char cpu_model[120];
strlcpy(cpu_model, "SH4 SH7751R", sizeof cpu_model);
sh_startup();
}
vaddr_t kernend;
char *esym;
__dead void
landisk_startup(int howto, char *_esym)
{
u_int32_t ramsize;
esym = _esym;
kernend = (vaddr_t)round_page((vaddr_t)esym);
boothowto = howto;
ramsize = getramsize();
sh_cpu_init(CPU_ARCH_SH4, CPU_PRODUCT_7751R);
consinit();
if (ramsize == 0 || ramsize > 512 * 1024 * 1024)
ramsize = IOM_RAM_SIZE;
physmem = atop(ramsize);
kernend = atop(round_page(SH3_P1SEG_TO_PHYS(kernend)));
uvm_page_physload(atop(IOM_RAM_BEGIN),
atop(IOM_RAM_BEGIN + ramsize), kernend,
atop(IOM_RAM_BEGIN + ramsize), 0);
cpu_init_kcore_hdr();
sh_proc0_init();
pmap_bootstrap();
#if defined(DDB)
db_machine_init();
ddb_init();
if (boothowto & RB_KDB) {
db_enter();
}
#endif
__asm volatile(
"jmp @%0\n\t"
" mov %1, sp"
:: "r" (main), "r" (proc0.p_md.md_pcb->pcb_sf.sf_r7_bank));
for (;;)
continue;
}
__dead void
boot(int howto)
{
if ((howto & RB_RESET) != 0)
goto doreset;
if (cold) {
if ((howto & RB_USERREQ) == 0)
howto |= RB_HALT;
goto haltsys;
}
boothowto = howto;
if ((howto & RB_NOSYNC) == 0) {
vfs_shutdown(curproc);
if ((howto & RB_TIMEBAD) == 0) {
resettodr();
} else {
printf("WARNING: not updating battery clock\n");
}
}
if_downall();
uvm_shutdown();
splhigh();
cold = 1;
if ((howto & RB_DUMP) != 0)
dumpsys();
haltsys:
config_suspend_all(DVACT_POWERDOWN);
if ((howto & RB_POWERDOWN) != 0) {
_reg_write_1(LANDISK_PWRMNG, PWRMNG_POWEROFF);
delay(1 * 1000 * 1000);
printf("POWEROFF FAILED!\n");
howto |= RB_HALT;
}
if ((howto & RB_HALT) != 0) {
printf("\n");
printf("The operating system has halted.\n");
printf("Please press any key to reboot.\n\n");
cnpollc(1);
cngetc();
cnpollc(0);
}
doreset:
printf("rebooting...\n");
machine_reset();
for (;;)
continue;
}
void
machine_reset(void)
{
_cpu_exception_suspend();
_reg_write_4(SH_(EXPEVT), EXPEVT_RESET_MANUAL);
(void)*(volatile uint32_t *)0x80000001;
for (;;) {
continue;
}
}
#if !defined(DONT_INIT_BSC)
void InitializeBsc(void);
void
InitializeBsc(void)
{
_reg_write_4(SH4_BCR1, BSC_BCR1_VAL);
_reg_write_2(SH4_BCR2, BSC_BCR2_VAL);
#if defined(SH4) && defined(SH7751R)
if (cpu_product == CPU_PRODUCT_7751R) {
#ifdef BSC_BCR3_VAL
_reg_write_2(SH4_BCR3, BSC_BCR3_VAL);
#endif
#ifdef BSC_BCR4_VAL
_reg_write_4(SH4_BCR4, BSC_BCR4_VAL);
#endif
}
#endif
_reg_write_4(SH4_WCR1, BSC_WCR1_VAL);
_reg_write_4(SH4_WCR2, BSC_WCR2_VAL);
#ifdef BSC_WCR3_VAL
_reg_write_4(SH4_WCR3, BSC_WCR3_VAL);
#endif
_reg_write_4(SH4_MCR, BSC_MCR_VAL);
#ifdef BSC_SDMR2_VAL
_reg_write_1(BSC_SDMR2_VAL, 0);
#endif
#ifdef BSC_SDMR3_VAL
_reg_write_1(BSC_SDMR3_VAL, 0);
#endif
#ifdef BSC_PCR_VAL
_reg_write_2(SH4_PCR, BSC_PCR_VAL);
#endif
_reg_write_2(SH4_RTCSR, BSC_RTCSR_VAL);
#ifdef BSC_RTCNT_VAL
_reg_write_2(SH4_RTCNT, BSC_RTCNT_VAL);
#endif
_reg_write_2(SH4_RTCOR, BSC_RTCOR_VAL);
#ifdef BSC_RFCR_VAL
_reg_write_2(SH4_RFCR, BSC_RFCR_VAL);
#endif
_reg_write_2(SH4_FRQCR, FRQCR_VAL);
}
#endif
u_int
cpu_dump(int (*dump)(dev_t, daddr_t, caddr_t, size_t), daddr_t *blknop)
{
extern cpu_kcore_hdr_t cpu_kcore_hdr;
char buf[dbtob(1)];
cpu_kcore_hdr_t *h;
kcore_seg_t *kseg;
int rc;
#ifdef DIAGNOSTIC
if (cpu_dumpsize() > btodb(sizeof buf)) {
printf("buffer too small in cpu_dump, ");
return (EINVAL);
}
#endif
bzero(buf, sizeof buf);
kseg = (kcore_seg_t *)buf;
h = (cpu_kcore_hdr_t *)(buf + ALIGN(sizeof(kcore_seg_t)));
CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t));
bcopy(&cpu_kcore_hdr, h, sizeof(*h));
h->kcore_kptp = SH3_P1SEG_TO_PHYS((vaddr_t)pmap_kernel()->pm_ptp);
rc = (*dump)(dumpdev, *blknop, buf, sizeof buf);
*blknop += btodb(sizeof buf);
return (rc);
}
u_int
cpu_dumpsize(void)
{
u_int size;
size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
return (btodb(roundup(size, dbtob(1))));
}
void
cpu_init_kcore_hdr(void)
{
extern cpu_kcore_hdr_t cpu_kcore_hdr;
cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
phys_ram_seg_t *seg = cpu_kcore_hdr.kcore_segs;
struct vm_physseg *physseg = vm_physmem;
u_int i;
bzero(h, sizeof(*h));
h->kcore_nsegs = min(NPHYS_RAM_SEGS, (u_int)vm_nphysseg);
for (i = h->kcore_nsegs; i != 0; i--) {
seg->start = ptoa(physseg->start);
seg->size = (psize_t)ptoa(physseg->end - physseg->start);
seg++;
physseg++;
}
}
int
cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen, struct proc *p)
{
int oldval, ret;
if (namelen != 1)
return (ENOTDIR);
switch (name[0]) {
case CPU_CONSDEV: {
dev_t consdev;
if (cn_tab != NULL)
consdev = cn_tab->cn_dev;
else
consdev = NODEV;
return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
sizeof consdev));
}
case CPU_LED_BLINK:
oldval = led_blink;
ret = sysctl_int(oldp, oldlenp, newp, newlen, &led_blink);
if (oldval != led_blink)
blink_led(NULL);
return (ret);
default:
return (EOPNOTSUPP);
}
}
void
blink_led(void *whatever)
{
static struct timeout blink_tmo;
u_int8_t ledctrl;
if (led_blink == 0) {
_reg_write_1(LANDISK_LEDCTRL,
LED_POWER_CHANGE | LED_POWER_VALUE);
return;
}
ledctrl = (u_int8_t)_reg_read_1(LANDISK_LEDCTRL) & LED_POWER_VALUE;
ledctrl ^= (LED_POWER_CHANGE | LED_POWER_VALUE);
_reg_write_1(LANDISK_LEDCTRL, ledctrl);
timeout_set(&blink_tmo, blink_led, NULL);
timeout_add(&blink_tmo,
((averunnable.ldavg[0] + FSCALE) * hz) >> FSHIFT);
}
unsigned int
cpu_rnd_messybits(void)
{
struct timespec ts;
nanotime(&ts);
return (ts.tv_nsec ^ (ts.tv_sec << 20));
}