11541Srgrimes/* $NetBSD: machdep.c,v 1.115 2024/03/05 14:15:33 thorpej Exp $ */ 21541Srgrimes 31541Srgrimes/* 41541Srgrimes * Copyright (c) 1988 University of Utah. 51541Srgrimes * Copyright (c) 1982, 1986, 1990, 1993 61541Srgrimes * The Regents of the University of California. All rights reserved. 71541Srgrimes * 81541Srgrimes * This code is derived from software contributed to Berkeley by 91541Srgrimes * the Systems Programming Group of the University of Utah Computer 101541Srgrimes * Science Department. 111541Srgrimes * 121541Srgrimes * Redistribution and use in source and binary forms, with or without 131541Srgrimes * modification, are permitted provided that the following conditions 141541Srgrimes * are met: 151541Srgrimes * 1. Redistributions of source code must retain the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer. 171541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 181541Srgrimes * notice, this list of conditions and the following disclaimer in the 191541Srgrimes * documentation and/or other materials provided with the distribution. 201541Srgrimes * 3. Neither the name of the University nor the names of its contributors 211541Srgrimes * may be used to endorse or promote products derived from this software 221541Srgrimes * without specific prior written permission. 231541Srgrimes * 241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3314478Shsu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3450477Speter * SUCH DAMAGE. 351541Srgrimes * 361541Srgrimes * from: Utah $Hdr: machdep.c 1.74 92/12/20$ 3745260Sbde * 385052Sbde * @(#)machdep.c 8.10 (Berkeley) 4/20/94 392165Spaul */ 4055205Speter 4118444Sbde#include <sys/cdefs.h> 4218444Sbde__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.115 2024/03/05 14:15:33 thorpej Exp $"); 4318429Sbde 4418429Sbde#include "opt_ddb.h" 451541Srgrimes#include "opt_compat_netbsd.h" 461541Srgrimes#include "opt_modular.h" 471541Srgrimes#include "opt_newsconf.h" 481541Srgrimes 491541Srgrimes#include <sys/param.h> 501541Srgrimes#include <sys/systm.h> 511541Srgrimes#include <sys/buf.h> 521541Srgrimes#include <sys/conf.h> 531541Srgrimes#include <sys/kernel.h> 541541Srgrimes#include <sys/device.h> 551541Srgrimes#include <sys/mbuf.h> 561541Srgrimes#include <sys/mount.h> 571541Srgrimes#include <sys/msgbuf.h> 581541Srgrimes#include <sys/proc.h> 594027Sphk#include <sys/reboot.h> 601541Srgrimes#include <sys/tty.h> 611541Srgrimes#include <sys/exec.h> 621541Srgrimes#include <sys/exec_aout.h> /* for MID_* */ 631541Srgrimes#include <sys/core.h> 6436735Sdfr#include <sys/kcore.h> 6537601Sdfr#include <sys/ksyms.h> 6637601Sdfr#include <sys/module.h> 6736735Sdfr#include <sys/cpu.h> 6836735Sdfr 691541Srgrimes#ifdef DDB 701541Srgrimes#include <machine/db_machdep.h> 711541Srgrimes#include <ddb/db_sym.h> 721541Srgrimes#include <ddb/db_extern.h> 731541Srgrimes#endif 741541Srgrimes#ifdef __ELF__ 751541Srgrimes#include <sys/exec_elf.h> 761541Srgrimes#endif 7714478Shsu 781541Srgrimes#include <machine/autoconf.h> 791541Srgrimes#include <machine/cpu.h> 801541Srgrimes#include <machine/reg.h> 811541Srgrimes#include <machine/pcb.h> 825052Sbde#include <machine/pte.h> 835052Sbde#include <machine/intr.h> 845052Sbde 851541Srgrimes#include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ 861541Srgrimes 871541Srgrimes#include <dev/cons.h> 8814478Shsu#include <dev/mm.h> 8914478Shsu 9014478Shsu#define MAXMEM 64*1024 /* XXX - from cmap.h */ 9114478Shsu#include <uvm/uvm_extern.h> 9214478Shsu 9314478Shsu#include <sys/sysctl.h> 941541Srgrimes 951541Srgrimes#include <news68k/news68k/machid.h> 961541Srgrimes#include <news68k/news68k/isr.h> 971541Srgrimes 9842264Sjkh#include "le.h" 991541Srgrimes#include "kb.h" 1001541Srgrimes#include "ms.h" 1011541Srgrimes#include "si.h" 1028876Srgrimes#include "ksyms.h" 1031541Srgrimes#include "romcons.h" 1041541Srgrimes/* XXX etc. etc. */ 1051541Srgrimes 1068876Srgrimes/* the following is used externally (sysctl_hw) */ 1078876Srgrimeschar machine[] = MACHINE; /* from <machine/param.h> */ 1081541Srgrimes 1091541Srgrimes/* Our exported CPU info; we can have only one. */ 1101541Srgrimesstruct cpu_info cpu_info_store; 11114478Shsu 1121541Srgrimesstruct vm_map *phys_map = NULL; 11314478Shsu 11414478Shsuint maxmem; /* max memory per process */ 11514478Shsu 11614478Shsuextern paddr_t avail_start, avail_end; 11714478Shsuextern int end, *esym; 11814478Shsuextern u_int lowram; 11914478Shsuextern u_int ctrl_led_phys; 1201541Srgrimes 12114478Shsu/* prototypes for local functions */ 12214478Shsustatic void identifycpu(void); 12314478Shsustatic void initcpu(void); 12414478Shsustatic int cpu_dumpsize(void); 1251541Srgrimesstatic int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); 12614478Shsustatic void cpu_init_kcore_hdr(void); 12714478Shsu 1281541Srgrimes#ifdef news1700 12914478Shsustatic void news1700_init(void); 13014478Shsustatic void parityenable(void); 1311541Srgrimesstatic void parityerror(void); 13214478Shsu#endif 1331541Srgrimes#ifdef news1200 1341541Srgrimesstatic void news1200_init(void); 1351541Srgrimes#endif 1361541Srgrimes 1371541Srgrimes/* functions called from locore.s */ 13814478Shsuvoid dumpsys(void); 13914478Shsuvoid news68k_init(void); 14014478Shsuvoid straytrap(int, u_short); 14114478Shsu 14214478Shsu/* 14314478Shsu * Machine-dependent crash dump header info. 14414478Shsu */ 14514478Shsucpu_kcore_hdr_t cpu_kcore_hdr; 14614478Shsu 14714478Shsu/* 14814478Shsu * Note that the value of delay_divisor is roughly 14914478Shsu * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020 1501541Srgrimes * and 68030 systems. 15114478Shsu */ 15214478Shsuint cpuspeed = 25; /* relative CPU speed; XXX skewed on 68040 */ 15314478Shsuint delay_divisor = 82; /* delay constant */ 15414478Shsu 15514478Shsu/* 15614478Shsu * Early initialization, before main() is called. 15714478Shsu */ 1581541Srgrimesvoid 15914478Shsunews68k_init(void) 1601541Srgrimes{ 16114478Shsu int i; 16214478Shsu 16314478Shsu /* 1641541Srgrimes * Tell the VM system about available physical memory. The 1651541Srgrimes * news68k only has one segment. 16614478Shsu */ 16714478Shsu uvm_page_physload(atop(avail_start), atop(avail_end), 16814478Shsu atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); 1691541Srgrimes 17014478Shsu /* Initialize system variables. */ 17114478Shsu switch (systype) { 17214478Shsu#ifdef news1700 17314478Shsu case NEWS1700: 17414478Shsu news1700_init(); 1751541Srgrimes break; 17614478Shsu#endif 17714478Shsu#ifdef news1200 1781541Srgrimes case NEWS1200: 1791541Srgrimes news1200_init(); 1801541Srgrimes break; 1811541Srgrimes#endif 1821541Srgrimes default: 18365921Sphk panic("impossible system type"); 18465921Sphk } 18565921Sphk 18665921Sphk /* 18765921Sphk * Initialize error message buffer (at end of core). 18865921Sphk * avail_end was pre-decremented in pmap_bootstrap to compensate. 18965921Sphk */ 19065921Sphk for (i = 0; i < btoc(MSGBUFSIZE); i++) 19165921Sphk pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, 19265921Sphk avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0); 19365921Sphk pmap_update(pmap_kernel()); 19465921Sphk initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 19565921Sphk} 19665921Sphk 19765921Sphk/* 1981541Srgrimes * cpu_startup: allocate memory for variable-sized tables, 1991541Srgrimes * initialize CPU, and do autoconfiguration. 2001541Srgrimes */ 2011541Srgrimesvoid 2021541Srgrimescpu_startup(void) 2031541Srgrimes{ 2041541Srgrimes vaddr_t minaddr, maxaddr; 2051541Srgrimes char pbuf[9]; 2061541Srgrimes#ifdef DEBUG 2071541Srgrimes extern int pmapdebug; 2081541Srgrimes int opmapdebug = pmapdebug; 2091541Srgrimes 2101541Srgrimes pmapdebug = 0; 2111541Srgrimes#endif 2121541Srgrimes 2131541Srgrimes if (fputype != FPU_NONE) 2141541Srgrimes m68k_make_fpu_idle_frame(); 2151541Srgrimes 2161541Srgrimes /* 2171541Srgrimes * Initialize the kernel crash dump header. 2181541Srgrimes */ 2191541Srgrimes cpu_init_kcore_hdr(); 2201541Srgrimes 22115571Sasami /* 22245260Sbde * Good {morning,afternoon,evening,night}. 22349617Simp */ 2241541Srgrimes printf("%s%s", copyright, version); 22550551Sphk identifycpu(); 22645260Sbde format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 22716363Sasami printf("total memory = %s\n", pbuf); 22816363Sasami 2291541Srgrimes minaddr = 0; 2301541Srgrimes 2311541Srgrimes /* 2321541Srgrimes * Allocate a submap for physio 2331541Srgrimes */ 2341541Srgrimes phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 2351541Srgrimes VM_PHYS_SIZE, 0, false, NULL); 2361541Srgrimes 2371541Srgrimes#ifdef DEBUG 2381541Srgrimes pmapdebug = opmapdebug; 2391541Srgrimes#endif 2401541Srgrimes format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 2411541Srgrimes printf("avail memory = %s\n", pbuf); 24215571Sasami 24333469Sjkh /* 24449617Simp * Set up CPU-specific registers, cache, etc. 24514478Shsu */ 2461541Srgrimes initcpu(); 2471541Srgrimes} 2481541Srgrimes 2491541Srgrimesint news_machine_id; 2501541Srgrimes 2511541Srgrimesstatic void 2521541Srgrimesidentifycpu(void) 2531541Srgrimes{ 2541541Srgrimes 2551541Srgrimes printf("SONY NET WORK STATION, Model %s, ", cpu_getmodel()); 2561541Srgrimes printf("Machine ID #%d\n", news_machine_id); 2571541Srgrimes 2581541Srgrimes delay_divisor = (20480 / cpuspeed + 5) / 10; /* XXX */ 2591541Srgrimes} 2601541Srgrimes 2611541Srgrimes/* 2621541Srgrimes * machine dependent system variables. 2631541Srgrimes */ 2641541SrgrimesSYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 2651541Srgrimes{ 2661541Srgrimes 2671541Srgrimes sysctl_createv(clog, 0, NULL, NULL, 2681541Srgrimes CTLFLAG_PERMANENT, 26945260Sbde CTLTYPE_NODE, "machdep", NULL, 27045260Sbde NULL, 0, NULL, 0, 2711541Srgrimes CTL_MACHDEP, CTL_EOL); 2721541Srgrimes 2731541Srgrimes sysctl_createv(clog, 0, NULL, NULL, 2741541Srgrimes CTLFLAG_PERMANENT, 2751541Srgrimes CTLTYPE_STRUCT, "console_device", NULL, 2761541Srgrimes sysctl_consdev, 0, NULL, sizeof(dev_t), 2771541Srgrimes CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 2781541Srgrimes} 2791541Srgrimes 2801541Srgrimesint waittime = -1; 2811541Srgrimes 2821541Srgrimesvoid 2831541Srgrimescpu_reboot(int howto, char *bootstr) 2841541Srgrimes{ 2851541Srgrimes struct pcb *pcb = lwp_getpcb(curlwp); 2861541Srgrimes 28744948Sgrog /* take a snap shot before clobbering any registers */ 28814478Shsu if (pcb != NULL) 2891541Srgrimes savectx(pcb); 2901541Srgrimes 2911541Srgrimes /* If system is cold, just halt. */ 2921541Srgrimes if (cold) { 2931541Srgrimes howto |= RB_HALT; 2941541Srgrimes goto haltsys; 2951541Srgrimes } 2961541Srgrimes 2971541Srgrimes boothowto = howto; 2981541Srgrimes if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 2991541Srgrimes waittime = 0; 3001541Srgrimes vfs_shutdown(); 3011541Srgrimes } 3021541Srgrimes 3031541Srgrimes /* Disable interrupts. */ 3041541Srgrimes splhigh(); 3051541Srgrimes 3061541Srgrimes /* If rebooting and a dump is requested, do it. */ 3071541Srgrimes if (howto & RB_DUMP) 3081541Srgrimes dumpsys(); 3091541Srgrimes 3101541Srgrimes haltsys: 3111541Srgrimes /* Run any shutdown hooks. */ 3121541Srgrimes doshutdownhooks(); 3131541Srgrimes 3141541Srgrimes pmf_system_shutdown(boothowto); 3151541Srgrimes 3161541Srgrimes#if defined(PANICWAIT) && !defined(DDB) 3171541Srgrimes if ((howto & RB_HALT) == 0 && panicstr) { 3181541Srgrimes printf("hit any key to reboot...\n"); 3191541Srgrimes cnpollc(1); 3201541Srgrimes (void)cngetc(); 3211541Srgrimes cnpollc(0); 3221541Srgrimes printf("\n"); 3231541Srgrimes } 32414478Shsu#endif 32514478Shsu 3261541Srgrimes /* Finally, halt/reboot the system. */ 3271541Srgrimes if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 3281541Srgrimes DELAY(1000000); 3291541Srgrimes doboot(RB_POWERDOWN); 33045260Sbde /* NOTREACHED */ 33145260Sbde } 33245260Sbde 3331541Srgrimes if (howto & RB_HALT) { 3341541Srgrimes printf("System halted.\n\n"); 3351541Srgrimes doboot(RB_HALT); 33614478Shsu /* NOTREACHED */ 33714478Shsu } 3381541Srgrimes 3391541Srgrimes printf("rebooting...\n"); 3401541Srgrimes DELAY(1000000); 3411541Srgrimes doboot(RB_AUTOBOOT); 3421541Srgrimes /* NOTREACHED */ 3431541Srgrimes} 3441549Srgrimes 3451549Srgrimes/* 34650551Sphk * Initialize the kernel crash dump header. 34716363Sasami */ 34816363Sasamistatic void 34916363Sasamicpu_init_kcore_hdr(void) 35016363Sasami{ 35116363Sasami cpu_kcore_hdr_t *h = &cpu_kcore_hdr; 35216363Sasami struct m68k_kcore_hdr *m = &h->un._m68k; 35316363Sasami 35416363Sasami memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); 35516363Sasami 35616363Sasami /* 35716363Sasami * Initialize the `dispatcher' portion of the header. 35816363Sasami */ 35916363Sasami strcpy(h->name, machine); 36016363Sasami h->page_size = PAGE_SIZE; 36116363Sasami h->kernbase = KERNBASE; 36216363Sasami 36316363Sasami /* 36416363Sasami * Fill in information about our MMU configuration. 36516363Sasami */ 36616363Sasami m->mmutype = mmutype; 36716363Sasami m->sg_v = SG_V; 36816363Sasami m->sg_frame = SG_FRAME; 36916363Sasami m->sg_ishift = SG_ISHIFT; 37016363Sasami m->sg_pmask = SG_PMASK; 37116363Sasami m->sg40_shift1 = SG4_SHIFT1; 37216363Sasami m->sg40_mask2 = SG4_MASK2; 37316363Sasami m->sg40_shift2 = SG4_SHIFT2; 3741549Srgrimes m->sg40_mask3 = SG4_MASK3; 3751549Srgrimes m->sg40_shift3 = SG4_SHIFT3; 3761549Srgrimes m->sg40_addr1 = SG4_ADDR1; 3773742Spaul m->sg40_addr2 = SG4_ADDR2; 37859771Sjlemon m->pg_v = PG_V; 37959771Sjlemon m->pg_frame = PG_FRAME; 38059771Sjlemon 3811549Srgrimes /* 3821549Srgrimes * Initialize pointer to kernel segment table. 3831549Srgrimes */ 3841549Srgrimes m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa); 3851549Srgrimes 3861549Srgrimes /* 3871549Srgrimes * Initialize relocation value such that: 3881549Srgrimes * 3891549Srgrimes * pa = (va - KERNBASE) + reloc 3901549Srgrimes */ 39137466Sbde m->reloc = lowram; 39237466Sbde 3931549Srgrimes /* 39416363Sasami * Define the end of the relocatable range. 3951549Srgrimes */ 3961549Srgrimes m->relocend = (uint32_t)&end; 3971549Srgrimes 3981549Srgrimes /* 3991541Srgrimes * news68k has one contiguous memory segment. 4001541Srgrimes */ 4011541Srgrimes m->ram_segs[0].start = lowram; 4021541Srgrimes m->ram_segs[0].size = ctob(physmem); 4031541Srgrimes} 4041541Srgrimes 4051541Srgrimes/* 4061541Srgrimes * Compute the size of the machine-dependent crash dump header. 4071541Srgrimes * Returns size in disk blocks. 4081541Srgrimes */ 4091541Srgrimes 41055205Speter#define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) 41151865Sbde#define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) 4125052Sbde 4135052Sbdestatic int 4145052Sbdecpu_dumpsize(void) 4155052Sbde{ 4165052Sbde 4175052Sbde return btodb(MDHDRSIZE); 4188876Srgrimes} 4195052Sbde 4205052Sbde/* 4215052Sbde * Called by dumpsys() to dump the machine-dependent header. 4228193Sjulian */ 4238193Sjulianstatic int 4248193Sjuliancpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) 4258193Sjulian{ 4268193Sjulian int buf[MDHDRSIZE / sizeof(int)]; 4278193Sjulian cpu_kcore_hdr_t *chdr; 4288193Sjulian kcore_seg_t *kseg; 42921986Sdg int error; 4308193Sjulian 4318193Sjulian kseg = (kcore_seg_t *)buf; 4325052Sbde chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / 43333742Sdg sizeof(int)]; 43433742Sdg 43546679Sphk /* Create the segment header. */ 43646679Sphk CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); 43746679Sphk kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); 43846679Sphk 43946679Sphk memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); 44046679Sphk error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); 44146679Sphk *blknop += btodb(sizeof(buf)); 44246679Sphk return error; 44346679Sphk} 44446679Sphk 44546679Sphk/* 44646679Sphk * These variables are needed by /sbin/savecore 4475052Sbde */ 4485052Sbdeuint32_t dumpmag = 0x8fca0101; /* magic number */ 44921986Sdgint dumpsize = 0; /* pages */ 4501541Srgrimeslong dumplo = 0; /* blocks */ 45146679Sphk 45246679Sphk/* 45346679Sphk * This is called by main to set dumplo and dumpsize. 45446679Sphk * Dumps always skip the first PAGE_SIZE of disk space 45546679Sphk * in case there might be a disk label stored there. 45646679Sphk * If there is extra space, put dump at the end to 45758942Sphk * reduce the chance that swapping trashes it. 45832995Sbde */ 45912478Sbdevoid 46058942Sphkcpu_dumpconf(void) 46112478Sbde{ 46259249Sphk int chdrsize; /* size of dump header */ 4637090Sbde int nblks; /* size of dump area */ 46459249Sphk 46551227Sbde if (dumpdev == NODEV) 4663940Sjkh return; 46749771Sphk nblks = bdev_size(dumpdev); 46858942Sphk chdrsize = cpu_dumpsize(); 4695052Sbde 4705052Sbde dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); 47149771Sphk 47248417Speter /* 47348417Speter * Check do see if we will fit. Note we always skip the 47448417Speter * first PAGE_SIZE in case there is a disk label there. 4753940Sjkh */ 47655205Speter if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { 4775052Sbde dumpsize = 0; 4785052Sbde dumplo = -1; 4795052Sbde return; 48055205Speter } 4811541Srgrimes 4821541Srgrimes /* 4831541Srgrimes * Put dump at the end of the partition. 4841541Srgrimes */ 4852165Spaul dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; 4865052Sbde} 487 488/* 489 * Dump physical memory onto the dump device. Called by cpu_reboot(). 490 */ 491void 492dumpsys(void) 493{ 494 const struct bdevsw *bdev; 495 daddr_t blkno; /* current block to write */ 496 /* dump routine */ 497 int (*dump)(dev_t, daddr_t, void *, size_t); 498 int pg; /* page being dumped */ 499 paddr_t maddr; /* PA being dumped */ 500 int error; /* error code from (*dump)() */ 501 502 /* XXX initialized here because of gcc lossage */ 503 maddr = lowram; 504 pg = 0; 505 506 /* Make sure dump device is valid. */ 507 if (dumpdev == NODEV) 508 return; 509 bdev = bdevsw_lookup(dumpdev); 510 if (bdev == NULL) 511 return; 512 if (dumpsize == 0) { 513 cpu_dumpconf(); 514 if (dumpsize == 0) 515 return; 516 } 517 if (dumplo <= 0) { 518 printf("\ndump to dev %u,%u not possible\n", 519 major(dumpdev), minor(dumpdev)); 520 return; 521 } 522 dump = bdev->d_dump; 523 blkno = dumplo; 524 525 printf("\ndumping to dev %u,%u offset %ld\n", 526 major(dumpdev), minor(dumpdev), dumplo); 527 528 printf("dump "); 529 530 /* Write the dump header. */ 531 error = cpu_dump(dump, &blkno); 532 if (error) 533 goto bad; 534 535 for (pg = 0; pg < dumpsize; pg++) { 536#define NPGMB (1024*1024/PAGE_SIZE) 537 /* print out how many MBs we have dumped */ 538 if (pg && (pg % NPGMB) == 0) 539 printf_nolog("%d ", pg / NPGMB); 540#undef NPGMB 541 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, 542 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 543 544 pmap_update(pmap_kernel()); 545 error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); 546 bad: 547 switch (error) { 548 case 0: 549 maddr += PAGE_SIZE; 550 blkno += btodb(PAGE_SIZE); 551 break; 552 553 case ENXIO: 554 printf("device bad\n"); 555 return; 556 557 case EFAULT: 558 printf("device not ready\n"); 559 return; 560 561 case EINVAL: 562 printf("area improper\n"); 563 return; 564 565 case EIO: 566 printf("i/o error\n"); 567 return; 568 569 case EINTR: 570 printf("aborted from console\n"); 571 return; 572 573 default: 574 printf("error %d\n", error); 575 return; 576 } 577 } 578 printf("succeeded\n"); 579} 580 581static void 582initcpu(void) 583{ 584} 585 586void 587straytrap(int pc, u_short evec) 588{ 589 590 printf("unexpected trap (vector offset %x) from %x\n", 591 evec & 0xFFF, pc); 592} 593 594/* XXX should change the interface, and make one badaddr() function */ 595 596int *nofault; 597 598int 599badaddr(void *addr, int nbytes) 600{ 601 int i; 602 label_t faultbuf; 603 604#ifdef lint 605 i = *addr; if (i) return 0; 606#endif 607 608 nofault = (int *) &faultbuf; 609 if (setjmp((label_t *)nofault)) { 610 nofault = (int *) 0; 611 return 1; 612 } 613 switch (nbytes) { 614 case 1: 615 i = *(volatile char *)addr; 616 break; 617 618 case 2: 619 i = *(volatile short *)addr; 620 break; 621 622 case 4: 623 i = *(volatile int *)addr; 624 break; 625 626 default: 627 panic("badaddr: bad request"); 628 } 629 __USE(i); 630 nofault = (int *) 0; 631 return 0; 632} 633 634int 635badbaddr(void *addr) 636{ 637 int i; 638 label_t faultbuf; 639 640 nofault = (int *) &faultbuf; 641 if (setjmp((label_t *)nofault)) { 642 nofault = (int *) 0; 643 return 1; 644 } 645 i = *(volatile char *)addr; 646 __USE(i); 647 nofault = (int *) 0; 648 return 0; 649} 650 651/* 652 * cpu_exec_aout_makecmds(): 653 * CPU-dependent a.out format hook for execve(). 654 * 655 * Determine of the given exec package refers to something which we 656 * understand and, if so, set up the vmcmds for it. 657 * 658 * XXX what are the special cases for the hp300? 659 * XXX why is this COMPAT_NOMID? was something generating 660 * hp300 binaries with an a_mid of 0? i thought that was only 661 * done on little-endian machines... -- cgd 662 */ 663int 664cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) 665{ 666#if defined(COMPAT_NOMID) || defined(COMPAT_44) 667 u_long midmag, magic; 668 u_short mid; 669 int error; 670 struct exec *execp = epp->ep_hdr; 671 672 midmag = ntohl(execp->a_midmag); 673 mid = (midmag >> 16) & 0xffff; 674 magic = midmag & 0xffff; 675 676 midmag = mid << 16 | magic; 677 678 switch (midmag) { 679#ifdef COMPAT_NOMID 680 case (MID_ZERO << 16) | ZMAGIC: 681 error = exec_aout_prep_oldzmagic(l, epp); 682 return(error); 683#endif 684#ifdef COMPAT_44 685 case (MID_HP300 << 16) | ZMAGIC: 686 error = exec_aout_prep_oldzmagic(l, epp); 687 return error; 688#endif 689 } 690#endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */ 691 692 return ENOEXEC; 693} 694 695/* 696 * System dependent initilization 697 */ 698 699static volatile uint8_t *dip_switch, *int_status; 700 701const uint8_t *idrom_addr; 702volatile uint8_t *ctrl_ast, *ctrl_int2; 703volatile uint8_t *ctrl_led; 704uint32_t sccport0a, lance_mem_phys; 705 706#ifdef news1700 707static volatile u_char *ctrl_parity, *ctrl_parity_clr, *parity_vector; 708 709struct news68k_model { 710 const int id; 711 const char *name; 712}; 713 714static const struct news68k_model news68k_models[] = { 715 { ICK001, "ICK001" }, /* 1 */ 716 { ICK00X, "ICK00X" }, /* 2 */ 717 { NWS799, "NWS-799" }, /* 3 */ 718 { NWS800, "NWS-800" }, /* 4 */ 719 { NWS801, "NWS-801" }, /* 5 */ 720 { NWS802, "NWS-802" }, /* 6 */ 721 { NWS711, "NWS-711" }, /* 7 */ 722 { NWS721, "NWS-721" }, /* 8 */ 723 { NWS1850, "NWS-1850" }, /* 9 */ 724 { NWS810, "NWS-810" }, /* 10 */ 725 { NWS811, "NWS-811" }, /* 11 */ 726 { NWS1830, "NWS-1830" }, /* 12 */ 727 { NWS1750, "NWS-1750" }, /* 13 */ 728 { NWS1720, "NWS-1720" }, /* 14 */ 729 { NWS1930, "NWS-1930" }, /* 15 */ 730 { NWS1960, "NWS-1960" }, /* 16 */ 731 { NWS712, "NWS-712" }, /* 17 */ 732 { NWS1860, "NWS-1860" }, /* 18 */ 733 { PWS1630, "PWS-1630" }, /* 19 */ 734 { NWS820, "NWS-820" }, /* 20 */ 735 { NWS821, "NWS-821" }, /* 21 */ 736 { NWS1760, "NWS-1760" }, /* 22 */ 737 { NWS1710, "NWS-1710" }, /* 23 */ 738 { NWS830, "NWS-830" }, /* 30 */ 739 { NWS831, "NWS-831" }, /* 31 */ 740 { NWS841, "NWS-841" }, /* 41 */ 741 { PWS1570, "PWS-1570" }, /* 52 */ 742 { PWS1590, "PWS-1590" }, /* 54 */ 743 { NWS1520, "NWS-1520" }, /* 56 */ 744 { PWS1550, "PWS-1550" }, /* 73 */ 745 { PWS1520, "PWS-1520" }, /* 74 */ 746 { PWS1560, "PWS-1560" }, /* 75 */ 747 { NWS1530, "NWS-1530" }, /* 76 */ 748 { NWS1580, "NWS-1580" }, /* 77 */ 749 { NWS1510, "NWS-1510" }, /* 78 */ 750 { NWS1410, "NWS-1410" }, /* 81 */ 751 { NWS1450, "NWS-1450" }, /* 85 */ 752 { NWS1460, "NWS-1460" }, /* 86 */ 753 { NWS891, "NWS-891" }, /* 91 */ 754 { NWS911, "NWS-911" }, /* 111 */ 755 { NWS921, "NWS-921" }, /* 121 */ 756 { 0, NULL } 757}; 758 759static void 760news1700_init(void) 761{ 762 struct oidrom idrom; 763 const char *t; 764 const uint8_t *p; 765 uint8_t *q; 766 u_int i; 767 768 dip_switch = (uint8_t *)(0xe1c00100); 769 int_status = (uint8_t *)(0xe1c00200); 770 771 idrom_addr = (uint8_t *)(0xe1c00000); 772 ctrl_ast = (uint8_t *)(0xe1280000); 773 ctrl_int2 = (uint8_t *)(0xe1180000); 774 ctrl_led = (uint8_t *)(ctrl_led_phys); 775 776 sccport0a = (0xe0d40002); 777 lance_mem_phys = 0xe0e00000; 778 779 p = idrom_addr; 780 q = (uint8_t *)&idrom; 781 782 for (i = 0; i < sizeof(idrom); i++, p += 2) 783 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f); 784 785 t = NULL; 786 for (i = 0; news68k_models[i].name != NULL; i++) { 787 if (news68k_models[i].id == idrom.id_model) { 788 t = news68k_models[i].name; 789 } 790 } 791 if (t == NULL) 792 panic("unexpected system model."); 793 794 cpu_setmodel("%s", t); 795 news_machine_id = (idrom.id_serial[0] << 8) + idrom.id_serial[1]; 796 797 ctrl_parity = (uint8_t *)(0xe1080000); 798 ctrl_parity_clr = (uint8_t *)(0xe1a00000); 799 parity_vector = (uint8_t *)(0xe1c00200); 800 801 parityenable(); 802 803 cpuspeed = 25; 804} 805 806/* 807 * parity error handling (vectored NMI?) 808 */ 809 810static void 811parityenable(void) 812{ 813 814#define PARITY_VECT 0xc0 815#define PARITY_PRI 7 816 817 *parity_vector = PARITY_VECT; 818 819 isrlink_vectored((int (*)(void *))parityerror, NULL, 820 PARITY_PRI, PARITY_VECT); 821 822 *ctrl_parity_clr = 1; 823 *ctrl_parity = 1; 824 825#ifdef DEBUG 826 printf("enable parity check\n"); 827#endif 828} 829 830static int innmihand; /* simple mutex */ 831 832static void 833parityerror(void) 834{ 835 836 /* Prevent unwanted recursion. */ 837 if (innmihand) 838 return; 839 innmihand = 1; 840 841#if 0 /* XXX need to implement XXX */ 842 panic("parity error"); 843#else 844 printf("parity error detected.\n"); 845 *ctrl_parity_clr = 1; 846#endif 847 innmihand = 0; 848} 849#endif /* news1700 */ 850 851#ifdef news1200 852static void 853news1200_init(void) 854{ 855 struct idrom idrom; 856 const uint8_t *p; 857 uint8_t *q; 858 int i; 859 860 dip_switch = (uint8_t *)0xe1680000; 861 int_status = (uint8_t *)0xe1200000; 862 863 idrom_addr = (uint8_t *)0xe1400000; 864 ctrl_ast = (uint8_t *)0xe1100000; 865 ctrl_int2 = (uint8_t *)0xe10c0000; 866 ctrl_led = (uint8_t *)ctrl_led_phys; 867 868 sccport0a = 0xe1780002; 869 lance_mem_phys = 0xe1a00000; 870 871 p = idrom_addr; 872 q = (uint8_t *)&idrom; 873 for (i = 0; i < sizeof(idrom); i++, p += 2) 874 *q++ = ((*p & 0x0f) << 4) | (*(p + 1) & 0x0f); 875 876 cpu_setmodel("%s", idrom.id_model); 877 news_machine_id = idrom.id_serial; 878 879 cpuspeed = 25; 880} 881#endif /* news1200 */ 882 883/* 884 * interrupt handlers 885 * XXX should do better handling XXX 886 */ 887 888void intrhand_lev3(void); 889void intrhand_lev4(void); 890 891void 892intrhand_lev3(void) 893{ 894 int stat; 895 896 stat = *int_status; 897 m68k_count_intr(3); 898#if 1 899 printf("level 3 interrupt: INT_STATUS = 0x%02x\n", stat); 900#endif 901} 902 903extern int leintr(int); 904extern int si_intr(int); 905 906void 907intrhand_lev4(void) 908{ 909 int stat; 910 911#define INTST_LANCE 0x04 912#define INTST_SCSI 0x80 913 914 stat = *int_status; 915 m68k_count_intr(4); 916 917#if NSI > 0 918 if (stat & INTST_SCSI) { 919 si_intr(0); 920 } 921#endif 922#if NLE > 0 923 if (stat & INTST_LANCE) { 924 leintr(0); 925 } 926#endif 927#if 0 928 printf("level 4 interrupt\n"); 929#endif 930} 931 932/* 933 * consinit() routines - from newsmips/cpu_cons.c 934 */ 935 936/* 937 * Console initialization: called early on from main, 938 * before vm init or startup. Do enough configuration 939 * to choose and initialize a console. 940 * XXX need something better here. 941 */ 942#define SCC_CONSOLE 0 943#define SW_CONSOLE 0x07 944#define SW_NWB512 0x04 945#define SW_NWB225 0x01 946#define SW_FBPOP 0x02 947#define SW_FBPOP1 0x06 948#define SW_FBPOP2 0x03 949#define SW_AUTOSEL 0x07 950 951extern struct consdev consdev_rom, consdev_zs; 952 953int tty00_is_console = 0; 954 955void 956consinit(void) 957{ 958 uint8_t dipsw; 959 960 dipsw = *dip_switch; 961 962 dipsw = ~dipsw; 963 964 switch (dipsw & SW_CONSOLE) { 965 default: /* XXX no real fb support yet */ 966#if NROMCONS > 0 967 cn_tab = &consdev_rom; 968 (*cn_tab->cn_init)(cn_tab); 969 break; 970#endif 971 case 0: 972 tty00_is_console = 1; 973 cn_tab = &consdev_zs; 974 (*cn_tab->cn_init)(cn_tab); 975 break; 976 } 977#if NKSYMS || defined(DDB) || defined(MODULAR) 978 ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr), 979 (void *)&end, esym); 980#endif 981#ifdef DDB 982 if (boothowto & RB_KDB) 983 Debugger(); 984#endif 985} 986 987int 988mm_md_physacc(paddr_t pa, vm_prot_t prot) 989{ 990 paddr_t memend; 991 992 /* 993 * news68k has one contiguous memory segment. 994 */ 995 memend = lowram + ctob(physmem); 996 997 if (lowram <= pa && pa < memend) 998 return 0; 999 1000 return EFAULT; 1001} 1002 1003int 1004mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled) 1005{ 1006 1007 *handled = false; 1008 return ISIIOVA(ptr) ? EFAULT : 0; 1009} 1010 1011#ifdef MODULAR 1012/* 1013 * Push any modules loaded by the bootloader etc. 1014 */ 1015void 1016module_init_md(void) 1017{ 1018} 1019#endif 1020