Home | History | Annotate | Line # | Download | only in amiga
      1 /*	$NetBSD: machdep.c,v 1.255 2024/03/05 14:15:28 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988 University of Utah.
      5  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
      6  * All rights reserved.
      7  *
      8  * This code is derived from software contributed to Berkeley by
      9  * the Systems Programming Group of the University of Utah Computer
     10  * Science Department.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  * from: Utah $Hdr: machdep.c 1.63 91/04/24$
     37  *
     38  *	@(#)machdep.c	7.16 (Berkeley) 6/3/91
     39  */
     40 
     41 #include "opt_ddb.h"
     42 #include "opt_compat_netbsd.h"
     43 #include "opt_fpu_emulate.h"
     44 #include "opt_lev6_defer.h"
     45 #include "opt_m060sp.h"
     46 #include "opt_modular.h"
     47 #include "opt_panicbutton.h"
     48 #include "opt_m68k_arch.h"
     49 
     50 #include "empm.h"
     51 
     52 #include <sys/cdefs.h>
     53 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.255 2024/03/05 14:15:28 thorpej Exp $");
     54 
     55 #include <sys/param.h>
     56 #include <sys/systm.h>
     57 #include <sys/callout.h>
     58 #include <sys/signalvar.h>
     59 #include <sys/kernel.h>
     60 #include <sys/proc.h>
     61 #include <sys/buf.h>
     62 #include <sys/reboot.h>
     63 #include <sys/conf.h>
     64 #include <sys/file.h>
     65 #include <sys/mbuf.h>
     66 #include <sys/msgbuf.h>
     67 #include <sys/vnode.h>
     68 #include <sys/device.h>
     69 #include <sys/queue.h>
     70 #include <sys/mount.h>
     71 #include <sys/core.h>
     72 #include <sys/kcore.h>
     73 #include <sys/ksyms.h>
     74 #include <sys/module.h>
     75 #include <sys/cpu.h>
     76 #include <sys/exec.h>
     77 
     78 #if defined(DDB) && defined(__ELF__)
     79 #include <sys/exec_elf.h>
     80 #endif
     81 
     82 #include <sys/exec_aout.h>
     83 
     84 #undef PS	/* XXX netccitt/pk.h conflict with machine/reg.h? */
     85 
     86 #define	MAXMEM	64*1024	/* XXX - from cmap.h */
     87 #include <uvm/uvm_extern.h>
     88 
     89 #include <sys/sysctl.h>
     90 
     91 #include <machine/db_machdep.h>
     92 #include <ddb/db_sym.h>
     93 #include <ddb/db_extern.h>
     94 
     95 #include <machine/reg.h>
     96 #include <machine/pcb.h>
     97 #include <machine/psl.h>
     98 #include <machine/pte.h>
     99 #include <machine/kcore.h>
    100 #include <dev/cons.h>
    101 #include <dev/mm.h>
    102 #include <amiga/amiga/isr.h>
    103 #include <amiga/amiga/custom.h>
    104 #ifdef DRACO
    105 #include <amiga/amiga/drcustom.h>
    106 #include <m68k/include/asm_single.h>
    107 #endif
    108 #include <amiga/amiga/cia.h>
    109 #include <amiga/amiga/cc.h>
    110 #include <amiga/amiga/memlist.h>
    111 #include <amiga/amiga/device.h>
    112 #if NEMPM > 0
    113 #include <amiga/pci/empmvar.h>
    114 #endif /* NEMPM > 0 */
    115 
    116 #include "fd.h"
    117 #include "ser.h"
    118 #include "ksyms.h"
    119 
    120 /* prototypes */
    121 void identifycpu(void);
    122 vm_offset_t reserve_dumppages(vm_offset_t);
    123 void dumpsys(void);
    124 void initcpu(void);
    125 void straytrap(int, u_short);
    126 void intrhand(int);
    127 #if NSER > 0
    128 void ser_outintr(void);
    129 #endif
    130 #if NFD > 0
    131 void fdintr(int);
    132 #endif
    133 
    134 volatile unsigned int intr_depth = 0;
    135 
    136 struct vm_map *phys_map = NULL;
    137 
    138 void *	msgbufaddr;
    139 paddr_t msgbufpa;
    140 
    141 int	machineid;
    142 int	maxmem;			/* max memory per process */
    143 
    144 extern  int   freebufspace;
    145 extern	u_int lowram;
    146 
    147 /* used in init_main.c */
    148 const char *cpu_type = "m68k";
    149 /* the following is used externally (sysctl_hw) */
    150 char	machine[] = MACHINE;	/* from <machine/param.h> */
    151 
    152 /* Our exported CPU info; we can have only one. */
    153 struct cpu_info cpu_info_store;
    154 
    155 /*
    156  * current open serial device speed;  used by some SCSI drivers to reduce
    157  * DMA transfer lengths.
    158  */
    159 int	ser_open_speed;
    160 
    161 #ifdef DRACO
    162 vaddr_t DRCCADDR;
    163 
    164 volatile u_int8_t *draco_intena, *draco_intpen, *draco_intfrc;
    165 volatile u_int8_t *draco_misc;
    166 volatile struct drioct *draco_ioct;
    167 #endif
    168 
    169  /*
    170  * Console initialization: called early on from main,
    171  * before vm init or startup.  Do enough configuration
    172  * to choose and initialize a console.
    173  */
    174 void
    175 consinit(void)
    176 {
    177 	/* initialize custom chip interface */
    178 #ifdef DRACO
    179 	if (is_draco()) {
    180 		/* XXX to be done */
    181 	} else
    182 #endif
    183 		custom_chips_init();
    184 
    185 	/* preconfigure graphics cards */
    186 	config_console();
    187 
    188 	/*
    189 	 * Initialize the console before we print anything out.
    190 	 */
    191 	cninit();
    192 
    193 #if NKSYMS || defined(DDB) || defined(MODULAR)
    194 	{
    195 		extern int end[];
    196 		extern int *esym;
    197 
    198 		ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
    199 		    (void *)&end, esym);
    200 	}
    201 #endif
    202 #ifdef DDB
    203         if (boothowto & RB_KDB)
    204                 Debugger();
    205 #endif
    206 }
    207 
    208 /*
    209  * cpu_startup: allocate memory for variable-sized tables,
    210  * initialize CPU, and do autoconfiguration.
    211  */
    212 void
    213 cpu_startup(void)
    214 {
    215 	u_int i;
    216 #ifdef DEBUG
    217 	extern int pmapdebug;
    218 	int opmapdebug = pmapdebug;
    219 #endif
    220 	vaddr_t minaddr, maxaddr;
    221 
    222 	/*
    223 	 * Initialize error message buffer (at end of core).
    224 	 */
    225 #ifdef DEBUG
    226 	pmapdebug = 0;
    227 #endif
    228 	/*
    229 	 * pmap_bootstrap has positioned this at the end of kernel
    230 	 * memory segment - map and initialize it now.
    231 	 */
    232 
    233 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
    234 		pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE,
    235 		    msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE,
    236 		    VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
    237 	pmap_update(pmap_kernel());
    238 	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
    239 
    240 	minaddr = 0;
    241 
    242 	/*
    243 	 * Allocate a submap for physio
    244 	 */
    245 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
    246 				   VM_PHYS_SIZE, 0, false, NULL);
    247 
    248 	/*
    249 	 * Good {morning,afternoon,evening,night}.
    250 	 */
    251 	banner();
    252 
    253 	/*
    254 	 * Get MMU/FPU type from bootstrap
    255 	 */
    256 	identifycpu();
    257 
    258 #ifdef DEBUG
    259 	pmapdebug = opmapdebug;
    260 #endif
    261 
    262 	/*
    263 	 * display memory configuration passed from loadbsd
    264 	 */
    265 	if (memlist->m_nseg > 0 && memlist->m_nseg < 16)
    266 		for (i = 0; i < memlist->m_nseg; i++)
    267 			printf("memory segment %d at %08x size %08x\n", i,
    268 			    memlist->m_seg[i].ms_start,
    269 			    memlist->m_seg[i].ms_size);
    270 
    271 #ifdef DEBUG_KERNEL_START
    272 	printf("calling initcpu...\n");
    273 #endif
    274 	/*
    275 	 * Set up CPU-specific registers, cache, etc.
    276 	 */
    277 	initcpu();
    278 
    279 #ifdef DEBUG_KERNEL_START
    280 	printf("survived initcpu...\n");
    281 #endif
    282 }
    283 
    284 /*
    285  * Info for CTL_HW
    286  */
    287 #if defined(M68060)
    288 int m68060_pcr_init = 0x21;	/* make this patchable */
    289 #endif
    290 
    291 
    292 void
    293 identifycpu(void)
    294 {
    295         /* there's alot of XXX in here... */
    296 	const char *mach, *mmu, *fpu;
    297 
    298 #ifdef M68060
    299 	char cpubuf[16];
    300 	u_int32_t pcr;
    301 #endif
    302 
    303 #ifdef DRACO
    304 	char machbuf[16];
    305 
    306 	if (is_draco()) {
    307 		snprintf(machbuf, sizeof(machbuf), "DraCo rev.%d", is_draco());
    308 		mach = machbuf;
    309 	} else
    310 #endif
    311 	if (is_a4000())
    312 		mach = "Amiga 4000";
    313 	else if (is_a3000())
    314 		mach = "Amiga 3000";
    315 	else if (is_a1200())
    316 		mach = "Amiga 1200";
    317 	else if (is_a600())
    318 		mach = "Amiga 600";
    319 	else
    320 		mach = "Amiga 500/2000";
    321 
    322 	fpu = NULL;
    323 #ifdef M68060
    324 	if (machineid & AMIGA_68060) {
    325 		__asm(".word 0x4e7a,0x0808; movl %%d0,%0" : "=d"(pcr) : : "d0");
    326 		snprintf(cpubuf, sizeof(cpubuf), "68%s060 rev.%d",
    327 		    pcr & 0x10000 ? "LC/EC" : "", (pcr>>8)&0xff);
    328 		cpu_type = cpubuf;
    329 		mmu = "/MMU";
    330 		if (pcr & 2) {
    331 			fpu = "/FPU disabled";
    332 			fputype = FPU_NONE;
    333 		} else if (m68060_pcr_init & 2){
    334 			fpu = "/FPU will be disabled";
    335 			fputype = FPU_NONE;
    336 		} else  if (machineid & AMIGA_FPU40) {
    337 			fpu = "/FPU";
    338 			fputype = FPU_68040; /* XXX */
    339 		}
    340 	} else
    341 #endif
    342 	if (machineid & AMIGA_68040) {
    343 		cpu_type = "m68040";
    344 		mmu = "/MMU";
    345 		fpu = "/FPU";
    346 		fputype = FPU_68040; /* XXX */
    347 	} else if (machineid & AMIGA_68030) {
    348 		cpu_type = "m68030";	/* XXX */
    349 		mmu = "/MMU";
    350 	} else {
    351 		cpu_type = "m68020";
    352 		mmu = " m68851 MMU";
    353 	}
    354 	if (fpu == NULL) {
    355 		if (machineid & AMIGA_68882) {
    356 			fpu = " m68882 FPU";
    357 			fputype = FPU_68882;
    358 		} else if (machineid & AMIGA_68881) {
    359 			fpu = " m68881 FPU";
    360 			fputype = FPU_68881;
    361 		} else {
    362 			fpu = " no FPU";
    363 			fputype = FPU_NONE;
    364 		}
    365 	}
    366 	cpu_setmodel("%s (%s CPU%s%s)", mach, cpu_type, mmu, fpu);
    367 	printf("%s\n", cpu_getmodel());
    368 }
    369 
    370 /*
    371  * machine dependent system variables.
    372  */
    373 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    374 {
    375 
    376 	sysctl_createv(clog, 0, NULL, NULL,
    377 		       CTLFLAG_PERMANENT,
    378 		       CTLTYPE_NODE, "machdep", NULL,
    379 		       NULL, 0, NULL, 0,
    380 		       CTL_MACHDEP, CTL_EOL);
    381 
    382 	sysctl_createv(clog, 0, NULL, NULL,
    383 		       CTLFLAG_PERMANENT,
    384 		       CTLTYPE_STRUCT, "console_device", NULL,
    385 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    386 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    387 }
    388 
    389 static int waittime = -1;
    390 
    391 void
    392 bootsync(void)
    393 {
    394 	if (waittime < 0) {
    395 		waittime = 0;
    396 		vfs_shutdown();
    397 	}
    398 }
    399 
    400 
    401 void
    402 cpu_reboot(register int howto, char *bootstr)
    403 {
    404 	struct pcb *pcb = lwp_getpcb(curlwp);
    405 #if NEMPM > 0
    406 	device_t empmdev;
    407 #endif /* NEMPM > 0 */
    408 
    409 	/* take a snap shot before clobbering any registers */
    410 	if (pcb != NULL)
    411 		savectx(pcb);
    412 
    413 	boothowto = howto;
    414 	if ((howto & RB_NOSYNC) == 0)
    415 		bootsync();
    416 
    417 	/* Disable interrupts. */
    418 	spl7();
    419 
    420 	/* If rebooting and a dump is requested do it. */
    421 	if (howto & RB_DUMP)
    422 		dumpsys();
    423 
    424 #if NEMPM > 0
    425 	if (howto & RB_POWERDOWN) {
    426 		empmdev = device_find_by_xname("empm0");
    427 		if (empmdev != NULL) {
    428 			empm_power_off(device_private(empmdev));
    429 		}
    430 	}
    431 #endif /* NEMPM > 0 */
    432 
    433 	if (howto & RB_HALT) {
    434 		printf("\n");
    435 		printf("The operating system has halted.\n");
    436 		printf("Please press any key to reboot.\n\n");
    437 		cnpollc(1);
    438 		cngetc();
    439 		cnpollc(0);
    440 	}
    441 
    442 	printf("rebooting...\n");
    443 	DELAY(1000000);
    444 	doboot();
    445 	/*NOTREACHED*/
    446 }
    447 
    448 
    449 u_int32_t dumpmag = 0x8fca0101;	/* magic number for savecore */
    450 int	dumpsize = 0;		/* also for savecore */
    451 long	dumplo = 0;
    452 cpu_kcore_hdr_t cpu_kcore_hdr;
    453 
    454 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
    455 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
    456 
    457 void
    458 cpu_dumpconf(void)
    459 {
    460 	cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
    461 	struct m68k_kcore_hdr *m = &h->un._m68k;
    462 	int nblks;
    463 	int i;
    464 	extern int end[];
    465 
    466 	memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
    467 
    468 	/*
    469 	 * Intitialize the `dispatcher' portion of the header.
    470 	 */
    471 	strcpy(h->name, machine);
    472 	h->page_size = PAGE_SIZE;
    473 	h->kernbase = KERNBASE;
    474 
    475 	/*
    476 	 * Fill in information about our MMU configuration.
    477 	 */
    478 	m->mmutype	= mmutype;
    479 	m->sg_v		= SG_V;
    480 	m->sg_frame	= SG_FRAME;
    481 	m->sg_ishift	= SG_ISHIFT;
    482 	m->sg_pmask	= SG_PMASK;
    483 	m->sg40_shift1	= SG4_SHIFT1;
    484 	m->sg40_mask2	= SG4_MASK2;
    485 	m->sg40_shift2	= SG4_SHIFT2;
    486 	m->sg40_mask3	= SG4_MASK3;
    487 	m->sg40_shift3	= SG4_SHIFT3;
    488 	m->sg40_addr1	= SG4_ADDR1;
    489 	m->sg40_addr2	= SG4_ADDR2;
    490 	m->pg_v		= PG_V;
    491 	m->pg_frame	= PG_FRAME;
    492 
    493 	/*
    494 	 * Initialize the pointer to the kernel segment table.
    495 	 */
    496 	m->sysseg_pa = (paddr_t)pmap_kernel()->pm_stpa;
    497 
    498 	/*
    499 	 * Initialize relocation value such that:
    500 	 *
    501 	 *	pa = (va - KERNBASE) + reloc
    502 	 */
    503 	m->reloc = lowram;
    504 
    505 	/*
    506 	 * Define the end of the relocatable range.
    507 	 */
    508 	m->relocend = (u_int32_t)&end;
    509 
    510 	/* XXX new corefile format, single segment + chipmem */
    511 	dumpsize = physmem;
    512 	m->ram_segs[0].start = lowram;
    513 	m->ram_segs[0].size  = ctob(physmem);
    514 	for (i = 0; i < memlist->m_nseg; i++) {
    515 		if ((memlist->m_seg[i].ms_attrib & MEMF_CHIP) == 0)
    516 			continue;
    517 		dumpsize += btoc(memlist->m_seg[i].ms_size);
    518 		m->ram_segs[1].start = 0;
    519 		m->ram_segs[1].size  = memlist->m_seg[i].ms_size;
    520 		break;
    521 	}
    522 	if (bdevsw_lookup(dumpdev) == NULL) {
    523 		dumpdev = NODEV;
    524 		return;
    525 	}
    526 	nblks = bdev_size(dumpdev);
    527 	if (nblks > 0) {
    528 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
    529 			dumpsize = btoc(dbtob(nblks - dumplo));
    530 		else if (dumplo == 0)
    531 			dumplo = nblks - btodb(ctob(dumpsize));
    532 	}
    533 	dumplo -= ctod(btoc(MDHDRSIZE));
    534 	/*
    535 	 * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?)
    536 	 * in case the dump device includes a disk label.
    537 	 */
    538 	if (dumplo < btodb(PAGE_SIZE))
    539 		dumplo = btodb(PAGE_SIZE);
    540 }
    541 
    542 /*
    543  * Doadump comes here after turning off memory management and
    544  * getting on the dump stack, either when called above, or by
    545  * the auto-restart code.
    546  */
    547 #define BYTES_PER_DUMP MAXPHYS	/* Must be a multiple of pagesize XXX small */
    548 static vm_offset_t dumpspace;
    549 
    550 vm_offset_t
    551 reserve_dumppages(vm_offset_t p)
    552 {
    553 	dumpspace = p;
    554 	return (p + BYTES_PER_DUMP);
    555 }
    556 
    557 void
    558 dumpsys(void)
    559 {
    560 	unsigned bytes, i, n, seg;
    561 	int     maddr, psize;
    562 	daddr_t blkno;
    563 	int     (*dump)(dev_t, daddr_t, void *, size_t);
    564 	int     error = 0;
    565 	kcore_seg_t *kseg_p;
    566 	cpu_kcore_hdr_t *chdr_p;
    567 	char	dump_hdr[MDHDRSIZE];
    568 	const struct bdevsw *bdev;
    569 
    570 	if (dumpdev == NODEV)
    571 		return;
    572 	bdev = bdevsw_lookup(dumpdev);
    573 	if (bdev == NULL || bdev->d_psize == NULL)
    574 		return;
    575 	/*
    576 	 * For dumps during autoconfiguration,
    577 	 * if dump device has already configured...
    578 	 */
    579 	if (dumpsize == 0)
    580 		cpu_dumpconf();
    581 	if (dumplo <= 0) {
    582 		printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
    583 		    minor(dumpdev));
    584 		return;
    585 	}
    586 	printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
    587 	    minor(dumpdev), dumplo);
    588 
    589 	psize = bdev_size(dumpdev);
    590 	printf("dump ");
    591 	if (psize == -1) {
    592 		printf("area unavailable.\n");
    593 		return;
    594 	}
    595 	kseg_p = (kcore_seg_t *)dump_hdr;
    596 	chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
    597 	memset(dump_hdr, 0, sizeof(dump_hdr));
    598 
    599 	/*
    600 	 * Generate a segment header
    601 	 */
    602 	CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
    603 	kseg_p->c_size = MDHDRSIZE - ALIGN(sizeof(*kseg_p));
    604 
    605 	/*
    606 	 * Add the md header
    607 	 */
    608 
    609 	*chdr_p = cpu_kcore_hdr;
    610 
    611 	bytes = ctob(dumpsize);
    612 	maddr = cpu_kcore_hdr.un._m68k.ram_segs[0].start;
    613 	seg = 0;
    614 	blkno = dumplo;
    615 	dump = bdev->d_dump;
    616 	error = (*dump) (dumpdev, blkno, (void *)dump_hdr, sizeof(dump_hdr));
    617 	blkno += btodb(sizeof(dump_hdr));
    618 	for (i = 0; i < bytes && error == 0; i += n) {
    619 		/* Print out how many MBs we have to go. */
    620 		n = bytes - i;
    621 		if (n && (n % (1024 * 1024)) == 0)
    622 			printf_nolog("%d ", n / (1024 * 1024));
    623 
    624 		/* Limit size for next transfer. */
    625 		if (n > BYTES_PER_DUMP)
    626 			n = BYTES_PER_DUMP;
    627 
    628 		if (maddr == 0) {	/* XXX kvtop chokes on this */
    629 			maddr += PAGE_SIZE;
    630 			n -= PAGE_SIZE;
    631 			i += PAGE_SIZE;
    632 			++blkno;	/* XXX skip physical page 0 */
    633 		}
    634 		(void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ);
    635 		error = (*dump) (dumpdev, blkno, (void *) dumpspace, n);
    636 		if (error)
    637 			break;
    638 		maddr += n;
    639 		blkno += btodb(n);	/* XXX? */
    640 		if (maddr >= (cpu_kcore_hdr.un._m68k.ram_segs[seg].start +
    641 		    cpu_kcore_hdr.un._m68k.ram_segs[seg].size)) {
    642 			++seg;
    643 			maddr = cpu_kcore_hdr.un._m68k.ram_segs[seg].start;
    644 			if (cpu_kcore_hdr.un._m68k.ram_segs[seg].size == 0)
    645 				break;
    646 		}
    647 	}
    648 
    649 	switch (error) {
    650 
    651 	case ENXIO:
    652 		printf("device bad\n");
    653 		break;
    654 
    655 	case EFAULT:
    656 		printf("device not ready\n");
    657 		break;
    658 
    659 	case EINVAL:
    660 		printf("area improper\n");
    661 		break;
    662 
    663 	case EIO:
    664 		printf("i/o error\n");
    665 		break;
    666 
    667 	default:
    668 		printf("succeeded\n");
    669 		break;
    670 	}
    671 	printf("\n\n");
    672 	delay(5000000);		/* 5 seconds */
    673 }
    674 
    675 void
    676 initcpu(void)
    677 {
    678 	/* XXX should init '40 vecs here, too */
    679 #if defined(M68060) || defined(M68040) || defined(DRACO) || defined(FPU_EMULATE)
    680 	typedef void trapfun(void);
    681 	extern trapfun *vectab[256];
    682 #endif
    683 
    684 #if defined(M68060) || defined(M68040)
    685 	extern trapfun addrerr4060;
    686 #endif
    687 
    688 #ifdef M68060
    689 	extern trapfun buserr60;
    690 #if defined(M060SP)
    691 	/*extern u_int8_t I_CALL_TOP[];*/
    692 	extern trapfun intemu60, fpiemu60, fpdemu60, fpeaemu60;
    693 	extern u_int8_t FP_CALL_TOP[];
    694 #else
    695 	extern trapfun illinst;
    696 #endif
    697 	extern trapfun fpfault;
    698 #endif
    699 
    700 #ifdef M68040
    701 	extern trapfun buserr40;
    702 #endif
    703 
    704 #ifdef DRACO
    705 	extern trapfun DraCoIntr, DraCoLev1intr, DraCoLev2intr;
    706 	u_char dracorev;
    707 #endif
    708 
    709 #ifdef FPU_EMULATE
    710 	extern trapfun fpemuli;
    711 #endif
    712 
    713 #ifdef M68060
    714 	if (machineid & AMIGA_68060) {
    715 		if (machineid & AMIGA_FPU40 && m68060_pcr_init & 2) {
    716 			/*
    717 			 * in this case, we're about to switch the FPU off;
    718 			 * do a FNOP to avoid stray FP traps later
    719 			 *
    720 			 * But we can't use fnop directly anymore as of
    721 			 * gcc-6 because it passes -mno-float to the assembler
    722 			 * because of -msoft-float and the assembler refuses
    723 			 * to assemble the instruction; adding -Wa,-mfloat
    724 			 * does not work either because the assembler then
    725 			 * complains about feature being turned off and on
    726 			 * so we just put in the opcode directly.
    727 			 */
    728 #if 0
    729 			__asm("fnop");
    730 #else
    731 			__asm(".word 0xf280,0x0000");
    732 #endif
    733 			/* ... and mark FPU as absent for identifyfpu() */
    734 			machineid &= ~(AMIGA_FPU40|AMIGA_68882|AMIGA_68881);
    735 		}
    736 		__asm volatile ("movl %0,%%d0; .word 0x4e7b,0x0808" : :
    737 			"d"(m68060_pcr_init):"d0" );
    738 
    739 		/* bus/addrerr vectors */
    740 		vectab[2] = buserr60;
    741 		vectab[3] = addrerr4060;
    742 #if defined(M060SP)
    743 
    744 		/* integer support */
    745 		vectab[61] = intemu60/*(trapfun *)&I_CALL_TOP[128 + 0x00]*/;
    746 
    747 		/* floating point support */
    748 		/*
    749 		 * XXX maybe we really should run-time check for the
    750 		 * stack frame format here:
    751 		 */
    752 		vectab[11] = fpiemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x30]*/;
    753 
    754 		vectab[55] = fpdemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x38]*/;
    755 		vectab[60] = fpeaemu60/*(trapfun *)&FP_CALL_TOP[128 + 0x40]*/;
    756 
    757 		vectab[54] = (trapfun *)&FP_CALL_TOP[128 + 0x00];
    758 		vectab[52] = (trapfun *)&FP_CALL_TOP[128 + 0x08];
    759 		vectab[53] = (trapfun *)&FP_CALL_TOP[128 + 0x10];
    760 		vectab[51] = (trapfun *)&FP_CALL_TOP[128 + 0x18];
    761 		vectab[50] = (trapfun *)&FP_CALL_TOP[128 + 0x20];
    762 		vectab[49] = (trapfun *)&FP_CALL_TOP[128 + 0x28];
    763 
    764 #else
    765 		vectab[61] = illinst;
    766 #endif
    767 		vectab[48] = fpfault;
    768 	}
    769 #endif
    770 
    771 /*
    772  * Vector initialization for special motherboards
    773  */
    774 #ifdef M68040
    775 #ifdef M68060
    776 	else
    777 #endif
    778 	if (machineid & AMIGA_68040) {
    779 		/* addrerr vector */
    780 		vectab[2] = buserr40;
    781 		vectab[3] = addrerr4060;
    782 	}
    783 #endif
    784 
    785 #ifdef FPU_EMULATE
    786 	if (!(machineid & (AMIGA_68881|AMIGA_68882|AMIGA_FPU40))) {
    787 		vectab[11] = fpemuli;
    788 		printf("FPU software emulation initialized.\n");
    789 	}
    790 #endif
    791 
    792 /*
    793  * Vector initialization for special motherboards
    794  */
    795 
    796 #ifdef DRACO
    797 	dracorev = is_draco();
    798 	if (dracorev) {
    799 		if (dracorev >= 4) {
    800 			vectab[24+1] = DraCoLev1intr;
    801 			vectab[24+2] = DraCoIntr;
    802 		} else {
    803 			vectab[24+1] = DraCoIntr;
    804 			vectab[24+2] = DraCoLev2intr;
    805 		}
    806 		vectab[24+3] = DraCoIntr;
    807 		vectab[24+4] = DraCoIntr;
    808 		vectab[24+5] = DraCoIntr;
    809 		vectab[24+6] = DraCoIntr;
    810 	}
    811 #endif
    812 }
    813 
    814 void
    815 straytrap(int pc, u_short evec)
    816 {
    817 	printf("unexpected trap format %x (vector offset %x) from %x\n",
    818 	       evec>>12, evec & 0xFFF, pc);
    819 /*XXX*/	panic("straytrap");
    820 }
    821 
    822 int	*nofault;
    823 
    824 int
    825 badaddr(register void *addr)
    826 {
    827 	int i;
    828 	label_t	faultbuf;
    829 
    830 	nofault = (int *) &faultbuf;
    831 	if (setjmp((label_t *)nofault)) {
    832 		nofault = NULL;
    833 		return 1;
    834 	}
    835 	i = *(volatile short *)addr;
    836 	__USE(i);
    837 	nofault = NULL;
    838 	return 0;
    839 }
    840 
    841 int
    842 badbaddr(register void *addr)
    843 {
    844 	int i;
    845 	label_t	faultbuf;
    846 
    847 	nofault = (int *) &faultbuf;
    848 	if (setjmp((label_t *)nofault)) {
    849 		nofault = NULL;
    850 		return 1;
    851 	}
    852 	i = *(volatile char *)addr;
    853 	__USE(i);
    854 	nofault = NULL;
    855 	return 0;
    856 }
    857 
    858 struct isr *isr_ports;
    859 #ifdef DRACO
    860 struct isr *isr_slot3;
    861 struct isr *isr_supio;
    862 #endif
    863 struct isr *isr_exter;
    864 
    865 void
    866 add_isr(struct isr *isr)
    867 {
    868 	struct isr **p, *q;
    869 
    870 #ifdef DRACO
    871 	switch (isr->isr_ipl) {
    872 	case 2:
    873 		p = &isr_ports;
    874 		break;
    875 	case 3:
    876 		p = &isr_slot3;
    877 		break;
    878 	case 5:
    879 		p = &isr_supio;
    880 		break;
    881 	default:	/* was case 6:; make gcc -Wall quiet */
    882 		p = &isr_exter;
    883 		break;
    884 	}
    885 #else
    886 	p = isr->isr_ipl == 2 ? &isr_ports : &isr_exter;
    887 #endif
    888 	while ((q = *p) != NULL)
    889 		p = &q->isr_forw;
    890 	isr->isr_forw = NULL;
    891 	*p = isr;
    892 	/* enable interrupt */
    893 #ifdef DRACO
    894 	if (is_draco())
    895 		switch(isr->isr_ipl) {
    896 			case 6:
    897 				single_inst_bset_b(*draco_intena, DRIRQ_INT6);
    898 				break;
    899 			case 2:
    900 				single_inst_bset_b(*draco_intena, DRIRQ_INT2);
    901 				break;
    902 			default:
    903 				break;
    904 		}
    905 	else
    906 #endif
    907 		custom.intena = isr->isr_ipl == 2 ?
    908 		    INTF_SETCLR | INTF_PORTS :
    909 		    INTF_SETCLR | INTF_EXTER;
    910 }
    911 
    912 void
    913 remove_isr(struct isr *isr)
    914 {
    915 	struct isr **p, *q;
    916 
    917 #ifdef DRACO
    918 	switch (isr->isr_ipl) {
    919 	case 2:
    920 		p = &isr_ports;
    921 		break;
    922 	case 3:
    923 		p = &isr_slot3;
    924 		break;
    925 	case 5:
    926 		p = &isr_supio;
    927 		break;
    928 	default:	/* XXX to make gcc -Wall quiet, was 6: */
    929 		p = &isr_exter;
    930 		break;
    931 	}
    932 #else
    933 	p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports;
    934 #endif
    935 
    936 	while ((q = *p) != NULL && q != isr)
    937 		p = &q->isr_forw;
    938 	if (q)
    939 		*p = q->isr_forw;
    940 	else
    941 		panic("remove_isr: handler not registered");
    942 	/* disable interrupt if no more handlers */
    943 #ifdef DRACO
    944 	switch (isr->isr_ipl) {
    945 	case 2:
    946 		p = &isr_ports;
    947 		break;
    948 	case 3:
    949 		p = &isr_slot3;
    950 		break;
    951 	case 5:
    952 		p = &isr_supio;
    953 		break;
    954 	case 6:
    955 		p = &isr_exter;
    956 		break;
    957 	}
    958 #else
    959 	p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports;
    960 #endif
    961 	if (*p == NULL) {
    962 #ifdef DRACO
    963 		if (is_draco()) {
    964 			switch(isr->isr_ipl) {
    965 				case 2:
    966 					single_inst_bclr_b(*draco_intena,
    967 					    DRIRQ_INT2);
    968 					break;
    969 				case 6:
    970 					single_inst_bclr_b(*draco_intena,
    971 					    DRIRQ_INT6);
    972 					break;
    973 				default:
    974 					break;
    975 			}
    976 		} else
    977 #endif
    978 			custom.intena = isr->isr_ipl == 6 ?
    979 			    INTF_EXTER : INTF_PORTS;
    980 	}
    981 }
    982 
    983 void
    984 intrhand(int sr)
    985 {
    986 	register unsigned int ipl;
    987 	register unsigned short ireq;
    988 	register struct isr **p, *q;
    989 
    990 	ipl = (sr >> 8) & 7;
    991 #ifdef REALLYDEBUG
    992 	printf("intrhand: got int. %d\n", ipl);
    993 #endif
    994 #ifdef DRACO
    995 	if (is_draco())
    996 		ireq = ((ipl == 1)  && (*draco_intfrc & DRIRQ_SOFT) ?
    997 		    INTF_SOFTINT : 0);
    998 	else
    999 #endif
   1000 		ireq = custom.intreqr;
   1001 
   1002 	switch (ipl) {
   1003 	case 1:
   1004 #ifdef DRACO
   1005 		if (is_draco() && (draco_ioct->io_status & DRSTAT_KBDRECV))
   1006 			drkbdintr();
   1007 #endif
   1008 		if (ireq & INTF_TBE) {
   1009 #if NSER > 0
   1010 			ser_outintr();
   1011 #else
   1012 			custom.intreq = INTF_TBE;
   1013 #endif
   1014 		}
   1015 
   1016 		if (ireq & INTF_DSKBLK) {
   1017 #if NFD > 0
   1018 			fdintr(0);
   1019 #endif
   1020 			custom.intreq = INTF_DSKBLK;
   1021 		}
   1022 		if (ireq & INTF_SOFTINT) {
   1023 			/* sicallback handling removed */
   1024 #ifdef DEBUG
   1025 			printf("intrhand: SOFTINT ignored\n");
   1026 #endif
   1027 			custom.intreq = INTF_SOFTINT;
   1028 		}
   1029 		break;
   1030 
   1031 	case 2:
   1032 		p = &isr_ports;
   1033 		while ((q = *p) != NULL) {
   1034 			if ((q->isr_intr)(q->isr_arg))
   1035 				break;
   1036 			p = &q->isr_forw;
   1037 		}
   1038 		if (q == NULL)
   1039 			ciaa_intr ();
   1040 #ifdef DRACO
   1041 		if (is_draco())
   1042 			single_inst_bclr_b(*draco_intpen, DRIRQ_INT2);
   1043 		else
   1044 #endif
   1045 			custom.intreq = INTF_PORTS;
   1046 
   1047 		break;
   1048 
   1049 #ifdef DRACO
   1050 	/* only handled here for DraCo */
   1051 	case 6:
   1052 		p = &isr_exter;
   1053 		while ((q = *p) != NULL) {
   1054 			if ((q->isr_intr)(q->isr_arg))
   1055 				break;
   1056 			p = &q->isr_forw;
   1057 		}
   1058 		single_inst_bclr_b(*draco_intpen, DRIRQ_INT6);
   1059 		break;
   1060 #endif
   1061 
   1062 	case 3:
   1063 	/* VBL */
   1064 		if (ireq & INTF_BLIT)
   1065 			blitter_handler();
   1066 		if (ireq & INTF_COPER)
   1067 			copper_handler();
   1068 		if (ireq & INTF_VERTB)
   1069 			vbl_handler();
   1070 		break;
   1071 #ifdef DRACO
   1072 	case 5:
   1073 		p = &isr_supio;
   1074 		while ((q = *p) != NULL) {
   1075 			if ((q->isr_intr)(q->isr_arg))
   1076 				break;
   1077 			p = &q->isr_forw;
   1078 		}
   1079 		break;
   1080 #endif
   1081 #if 0
   1082 /* now dealt with in locore.s for speed reasons */
   1083 	case 5:
   1084 		/* check RS232 RBF */
   1085 		serintr (0);
   1086 
   1087 		custom.intreq = INTF_DSKSYNC;
   1088 		break;
   1089 #endif
   1090 
   1091 	case 4:
   1092 #ifdef DRACO
   1093 #include "drsc.h"
   1094 		if (is_draco())
   1095 #if NDRSC > 0
   1096 			drsc_handler();
   1097 #else
   1098 			single_inst_bclr_b(*draco_intpen, DRIRQ_SCSI);
   1099 #endif
   1100 		else
   1101 #endif
   1102 		audio_handler();
   1103 		break;
   1104 	default:
   1105 		printf("intrhand: unexpected sr 0x%x, intreq = 0x%x\n",
   1106 		    sr, ireq);
   1107 		break;
   1108 	}
   1109 #ifdef REALLYDEBUG
   1110 	printf("intrhand: leaving.\n");
   1111 #endif
   1112 }
   1113 
   1114 bool
   1115 cpu_intr_p(void)
   1116 {
   1117 
   1118 	return intr_depth != 0;
   1119 }
   1120 
   1121 #if defined(DEBUG) && !defined(PANICBUTTON)
   1122 #define PANICBUTTON
   1123 #endif
   1124 
   1125 #ifdef PANICBUTTON
   1126 int panicbutton = 1;	/* non-zero if panic buttons are enabled */
   1127 int crashandburn = 0;
   1128 int candbdelay = 50;	/* give em half a second */
   1129 void candbtimer(void);
   1130 callout_t candbtimer_ch;
   1131 
   1132 void
   1133 candbtimer(void)
   1134 {
   1135 	crashandburn = 0;
   1136 }
   1137 #endif
   1138 
   1139 #if 0
   1140 /*
   1141  * Level 7 interrupts can be caused by the keyboard or parity errors.
   1142  */
   1143 nmihand(struct frame frame)
   1144 {
   1145 	if (kbdnmi()) {
   1146 #ifdef PANICBUTTON
   1147 		static int innmihand = 0;
   1148 
   1149 		/*
   1150 		 * Attempt to reduce the window of vulnerability for recursive
   1151 		 * NMIs (e.g. someone holding down the keyboard reset button).
   1152 		 */
   1153 		if (innmihand == 0) {
   1154 			innmihand = 1;
   1155 			printf("Got a keyboard NMI\n");
   1156 			innmihand = 0;
   1157 		}
   1158 		if (panicbutton) {
   1159 			if (crashandburn) {
   1160 				crashandburn = 0;
   1161 				panic(panicstr ?
   1162 				      "forced crash, nosync" : "forced crash");
   1163 			}
   1164 			crashandburn++;
   1165 			callout_reset(&candbtimer_ch, candbdelay,
   1166 			    candbtimer, NULL);
   1167 		}
   1168 #endif
   1169 		return;
   1170 	}
   1171 	if (parityerror(&frame))
   1172 		return;
   1173 	/* panic?? */
   1174 	printf("unexpected level 7 interrupt ignored\n");
   1175 }
   1176 #endif
   1177 
   1178 /*
   1179  * should only get here, if no standard executable. This can currently
   1180  * only mean, we're reading an old ZMAGIC file without MID, but since Amiga
   1181  * ZMAGIC always worked the `right' way (;-)) just ignore the missing
   1182  * MID and proceed to new zmagic code ;-)
   1183  */
   1184 int
   1185 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
   1186 {
   1187 #ifdef COMPAT_NOMID
   1188 	struct exec *execp = epp->ep_hdr;
   1189 
   1190 	if (!((execp->a_midmag >> 16) & 0x0fff)
   1191 	    && execp->a_midmag == ZMAGIC)
   1192 		return(exec_aout_prep_zmagic(l, epp));
   1193 #endif
   1194 	return ENOEXEC;
   1195 }
   1196 
   1197 #ifdef MODULAR
   1198 /*
   1199  * Push any modules loaded by the bootloader etc.
   1200  */
   1201 void
   1202 module_init_md(void)
   1203 {
   1204 }
   1205 
   1206 int _spllkm6(void);
   1207 int _spllkm7(void);
   1208 
   1209 #ifdef LEV6_DEFER
   1210 int _spllkm6(void) {
   1211 	return spl4();
   1212 };
   1213 
   1214 int _spllkm7(void) {
   1215 	return spl4();
   1216 };
   1217 
   1218 #else
   1219 
   1220 int _spllkm6(void) {
   1221 	return spl6();
   1222 };
   1223 
   1224 int _spllkm7(void) {
   1225 	return spl7();
   1226 };
   1227 
   1228 #endif
   1229 
   1230 #endif
   1231 
   1232 int ipl2spl_table[_NIPL] = {
   1233 	[IPL_NONE] = PSL_IPL0|PSL_S,
   1234 	[IPL_SOFTCLOCK] = PSL_IPL1|PSL_S,
   1235 	[IPL_VM] = PSL_IPL4|PSL_S,
   1236 #if defined(LEV6_DEFER)
   1237 	[IPL_SCHED] = PSL_IPL4|PSL_S,
   1238 	[IPL_HIGH] = PSL_IPL4|PSL_S,
   1239 #else /* defined(LEV6_DEFER) */
   1240 	[IPL_SCHED] = PSL_IPL6|PSL_S,
   1241 	[IPL_HIGH] = PSL_IPL7|PSL_S,
   1242 #endif /* defined(LEV6_DEFER) */
   1243 };
   1244 
   1245 int
   1246 mm_md_physacc(paddr_t pa, vm_prot_t prot)
   1247 {
   1248 
   1249 	return (pa >= 0xfffffffc || pa < lowram) ? EFAULT : 0;
   1250 }
   1251