#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.194 2026/04/28 03:29:10 thorpej Exp $");
#include "opt_ddb.h"
#include "opt_modular.h"
#include "opt_panicbutton.h"
#include "opt_m68k_arch.h"
#include "opt_mvmeconf.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/signalvar.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/reboot.h>
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/mbuf.h>
#include <sys/msgbuf.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/core.h>
#include <sys/kcore.h>
#include <sys/vnode.h>
#include <sys/syscallargs.h>
#include <sys/ksyms.h>
#include <sys/module.h>
#include <sys/device.h>
#include <sys/cpu.h>
#include "ksyms.h"
#if NKSYMS || defined(DDB) || defined(MODULAR)
#include <sys/exec_elf.h>
#endif
#include <uvm/uvm_extern.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
#define _M68K_BUS_DMA_PRIVATE
#define _M68K_BUS_SPACE_PRIVATE
#include <machine/bus.h>
#undef _M68K_BUS_DMA_PRIVATE
#undef _M68K_BUS_SPACE_PRIVATE
#include <machine/pcb.h>
#include <machine/prom.h>
#include <machine/psl.h>
#include <machine/pte.h>
#include <machine/vmparam.h>
#include <m68k/include/cacheops.h>
#include <dev/cons.h>
#include <dev/mm.h>
#include <machine/kcore.h>
#include <mvme68k/dev/mainbus.h>
#include <m68k/seglist.h>
#ifdef DDB
#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
#include <ddb/db_output.h>
#endif
#define MAXMEM 64*1024
struct mvmeprom_brdid boardid;
#ifndef ETHER_DATA_BUFF_PAGES
#define ETHER_DATA_BUFF_PAGES 4
#endif
u_long ether_data_buff_size = ETHER_DATA_BUFF_PAGES * PAGE_SIZE;
uint8_t mvme_ea[6];
extern u_int lowram;
int delay_divisor = delay_divisor_est60(60);
void machine_init(paddr_t);
#ifdef MVME147
#include <mvme68k/dev/pccreg.h>
void mvme147_init(void);
#endif
#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
#include <dev/mvme/pcctworeg.h>
void mvme1xx_init(void);
#endif
void
machine_init(paddr_t nextpa)
{
extern paddr_t msgbufpa;
pager_map_size = phys_seg_list[0].ps_end / 2;
if (pager_map_size > (16 * 1024 * 1024))
pager_map_size = 16 * 1024 * 1024;
phys_seg_list[0].ps_start = phys_seg_list[0].ps_avail_start =
m68k_round_page(phys_seg_list[0].ps_start);
phys_seg_list[0].ps_end = phys_seg_list[0].ps_avail_end =
m68k_trunc_page(phys_seg_list[0].ps_end);
phys_seg_list[0].ps_avail_end -= m68k_round_page(MSGBUFSIZE);
msgbufpa = phys_seg_list[0].ps_avail_end;
machine_init_common(nextpa);
switch (machineid) {
#ifdef MVME147
case MVME_147:
mvme147_init();
break;
#endif
#ifdef MVME167
case MVME_167:
#endif
#ifdef MVME162
case MVME_162:
#endif
#ifdef MVME177
case MVME_177:
#endif
#ifdef MVME172
case MVME_172:
#endif
#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
mvme1xx_init();
break;
#endif
default:
panic("%s: impossible machineid", __func__);
}
}
#ifdef MVME147
void
mvme147_init(void)
{
bus_space_tag_t bt = &m68k_simple_bus_space;
bus_space_handle_t bh;
bus_space_map(bt, intiobase_phys + MAINBUS_PCC_OFFSET, PCCREG_SIZE, 0,
&bh);
bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERCLEAR);
bus_space_write_2(bt, bh, PCCREG_TMR1_PRELOAD, 0);
bus_space_write_1(bt, bh, PCCREG_TMR1_INTR_CTRL, 0);
for (delay_divisor = delay_divisor_est(delay_calibration_weight(16));
delay_divisor > 0; delay_divisor--) {
bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERSTART);
delay(10000);
bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERSTOP);
if (bus_space_read_2(bt, bh, PCCREG_TMR1_COUNT) > 1600)
break;
bus_space_write_1(bt, bh, PCCREG_TMR1_CONTROL, PCC_TIMERCLEAR);
}
if (delay_divisor == 0) {
delay_divisor = 1;
}
bus_space_unmap(bt, bh, PCCREG_SIZE);
cpuspeed_khz = delay_divisor_est(delay_divisor) * 1000;
}
#endif
#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
int get_cpuspeed(void);
void
mvme1xx_init(void)
{
bus_space_tag_t bt = &m68k_simple_bus_space;
bus_space_handle_t bh;
bus_space_map(bt,
intiobase_phys + MAINBUS_PCCTWO_OFFSET + PCCTWO_REG_OFF,
PCC2REG_SIZE, 0, &bh);
bus_space_write_1(bt, bh, PCC2REG_TIMER1_ICSR, 0);
if (cputype == CPU_68060) {
delay_divisor =
delay_divisor_est60(delay_calibration_weight(50));
} else {
delay_divisor =
delay_divisor_est40(delay_calibration_weight(25));
}
for (; delay_divisor > 0; delay_divisor--) {
bus_space_write_4(bt, bh, PCC2REG_TIMER1_COUNTER, 0);
bus_space_write_1(bt, bh, PCC2REG_TIMER1_CONTROL,
PCCTWO_TT_CTRL_CEN);
delay(10000);
bus_space_write_1(bt, bh, PCC2REG_TIMER1_CONTROL, 0);
if (bus_space_read_4(bt, bh, PCC2REG_TIMER1_COUNTER) > 10000)
break;
}
bus_space_unmap(bt, bh, PCC2REG_SIZE);
cpuspeed_khz = get_cpuspeed();
if (cpuspeed_khz < 12500 || cpuspeed_khz > 60000) {
printf("%s: Warning! Firmware has " \
"bogus CPU speed: `%s'\n", __func__, boardid.speed);
cpuspeed_khz = ((cputype == CPU_68060)
? delay_divisor_est60(delay_divisor)
: delay_divisor_est40(delay_divisor)) * 1000;
printf("%s: Approximating speed using delay_divisor\n",
__func__);
}
}
int
get_cpuspeed(void)
{
int rv, i;
for (i = 0, rv = 0; i < sizeof(boardid.speed); i++) {
if (boardid.speed[i] < '0' || boardid.speed[i] > '9')
return 0;
rv = (rv * 10) + (boardid.speed[i] - '0');
}
return rv * 10;
}
#endif
void
consinit(void)
{
cninit();
#if NKSYMS || defined(DDB) || defined(MODULAR)
{
extern char end[];
extern int *esym;
ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
(void *)&end, esym);
}
#endif
#ifdef DDB
if (boothowto & RB_KDB)
Debugger();
#endif
}
void
cpu_startup_print_total_memory(void (*pr)(const char *, ...)
__printflike(1, 2))
{
u_quad_t vmememsize;
char pbuf[9];
u_int i;
format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
(*pr)("total memory = %s", pbuf);
for (vmememsize = 0, i = 1; i < VM_PHYSSEG_MAX; i++) {
vmememsize +=
phys_seg_list[i].ps_end - phys_seg_list[i].ps_start;
}
if (vmememsize != 0) {
format_bytes(pbuf, sizeof(pbuf),
phys_seg_list[0].ps_end - phys_seg_list[0].ps_start);
(*pr)(" (%s on-board", pbuf);
format_bytes(pbuf, sizeof(pbuf), vmememsize);
(*pr)(", %s VMEbus)", pbuf);
}
(*pr)("\n");
}
void
machine_set_model(void)
{
char board_str[16];
char *suffix = (char *)&boardid.suffix;
int len = snprintf(board_str, sizeof(board_str), "%x", machineid);
if (suffix[0] != '\0' && len > 0 && len + 3 < sizeof(board_str)) {
board_str[len++] = suffix[0];
if (suffix[1] != '\0')
board_str[len++] = suffix[1];
board_str[len] = '\0';
}
cpu_setmodel("Motorola MVME-%s", board_str);
}
SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
{
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "machdep", NULL,
NULL, 0, NULL, 0,
CTL_MACHDEP, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_STRUCT, "console_device", NULL,
sysctl_consdev, 0, NULL, sizeof(dev_t),
CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
}
void
cpu_reboot(int howto, char *bootstr)
{
howto |= (boothowto & RB_SBOOT);
cpu_reboot_common(howto, bootstr);
}
int
nmihand(void *arg)
{
mvme68k_abort("ABORT SWITCH");
return 1;
}
void
mvme68k_abort(const char *cp)
{
#ifdef DDB
db_printf("%s\n", cp);
Debugger();
#else
#ifdef PANICBUTTON
panic(cp);
#else
printf("%s ignored\n", cp);
#endif
#endif
}