Home | History | Annotate | Line # | Download | only in amiga
      1 /*	$NetBSD: machdep.c,v 1.280 2026/04/28 03:29:09 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_fpu_emulate.h"
     43 #include "opt_lev6_defer.h"
     44 #include "opt_m060sp.h"
     45 #include "opt_modular.h"
     46 #include "opt_panicbutton.h"
     47 #include "opt_m68k_arch.h"
     48 
     49 #include "empm.h"
     50 
     51 #include <sys/cdefs.h>
     52 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.280 2026/04/28 03:29:09 thorpej Exp $");
     53 
     54 #include <sys/param.h>
     55 #include <sys/systm.h>
     56 #include <sys/callout.h>
     57 #include <sys/signalvar.h>
     58 #include <sys/kernel.h>
     59 #include <sys/proc.h>
     60 #include <sys/buf.h>
     61 #include <sys/reboot.h>
     62 #include <sys/conf.h>
     63 #include <sys/file.h>
     64 #include <sys/mbuf.h>
     65 #include <sys/msgbuf.h>
     66 #include <sys/vnode.h>
     67 #include <sys/device.h>
     68 #include <sys/queue.h>
     69 #include <sys/mount.h>
     70 #include <sys/core.h>
     71 #include <sys/kcore.h>
     72 #include <sys/ksyms.h>
     73 #include <sys/module.h>
     74 #include <sys/cpu.h>
     75 #include <sys/exec.h>
     76 
     77 #if defined(DDB) && defined(__ELF__)
     78 #include <sys/exec_elf.h>
     79 #endif
     80 
     81 #undef PS	/* XXX netccitt/pk.h conflict with machine/reg.h? */
     82 
     83 #define	MAXMEM	64*1024	/* XXX - from cmap.h */
     84 #include <uvm/uvm_extern.h>
     85 
     86 #include <sys/sysctl.h>
     87 
     88 #include <machine/db_machdep.h>
     89 #include <ddb/db_sym.h>
     90 #include <ddb/db_extern.h>
     91 
     92 #include <machine/reg.h>
     93 #include <machine/pcb.h>
     94 #include <machine/psl.h>
     95 #include <machine/pte.h>
     96 #include <machine/kcore.h>
     97 #include <machine/vectors.h>
     98 #include <dev/cons.h>
     99 #include <dev/mm.h>
    100 #include <amiga/amiga/isr.h>
    101 #include <amiga/amiga/custom.h>
    102 #ifdef DRACO
    103 #include <amiga/amiga/drcustom.h>
    104 #include <m68k/include/asm_single.h>
    105 #endif
    106 #include <amiga/amiga/cia.h>
    107 #include <amiga/amiga/cc.h>
    108 #include <amiga/amiga/memlist.h>
    109 #include <amiga/amiga/device.h>
    110 #if NEMPM > 0
    111 #include <amiga/pci/empmvar.h>
    112 #endif /* NEMPM > 0 */
    113 
    114 #ifdef M68060
    115 #include <m68k/pcr.h>
    116 #endif
    117 
    118 #include "fd.h"
    119 #include "ser.h"
    120 #include "ksyms.h"
    121 
    122 /* prototypes */
    123 vm_offset_t reserve_dumppages(vm_offset_t);
    124 void dumpsys(void);
    125 void intrhand(int);
    126 #if NSER > 0
    127 void ser_outintr(void);
    128 #endif
    129 #if NFD > 0
    130 void fdintr(int);
    131 #endif
    132 
    133 volatile unsigned int intr_depth = 0;
    134 
    135 int	machineid;
    136 int	maxmem;			/* max memory per process */
    137 
    138 extern  int   freebufspace;
    139 extern	u_int lowram;
    140 
    141 /*
    142  * current open serial device speed;  used by some SCSI drivers to reduce
    143  * DMA transfer lengths.
    144  */
    145 int	ser_open_speed;
    146 
    147 #ifdef DRACO
    148 vaddr_t DRCCADDR;
    149 
    150 volatile u_int8_t *draco_intena, *draco_intpen, *draco_intfrc;
    151 volatile u_int8_t *draco_misc;
    152 volatile struct drioct *draco_ioct;
    153 #endif
    154 
    155 struct pmap_bootmap machine_bootmap[] = {
    156 	/* XXX */
    157 	{ .pmbm_vaddr = -1 },
    158 };
    159 
    160  /*
    161  * Console initialization: called early on from main,
    162  * before vm init or startup.  Do enough configuration
    163  * to choose and initialize a console.
    164  */
    165 void
    166 consinit(void)
    167 {
    168 	/* initialize custom chip interface */
    169 #ifdef DRACO
    170 	if (is_draco()) {
    171 		/* XXX to be done */
    172 	} else
    173 #endif
    174 		custom_chips_init();
    175 
    176 	/* preconfigure graphics cards */
    177 	config_console();
    178 
    179 	/*
    180 	 * Initialize the console before we print anything out.
    181 	 */
    182 	cninit();
    183 
    184 #if NKSYMS || defined(DDB) || defined(MODULAR)
    185 	{
    186 		extern int end[];
    187 		extern int *esym;
    188 
    189 		ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
    190 		    (void *)&end, esym);
    191 	}
    192 #endif
    193 #ifdef DDB
    194 	if (boothowto & RB_KDB)
    195 		Debugger();
    196 #endif
    197 }
    198 
    199 /*
    200  * cpu_startup: allocate memory for variable-sized tables,
    201  * initialize CPU, and do autoconfiguration.
    202  */
    203 void
    204 cpu_startup(void)
    205 {
    206 	cpu_startup_common();
    207 
    208 	/*
    209 	 * display memory configuration passed from loadbsd
    210 	 */
    211 	if (memlist->m_nseg > 0 && memlist->m_nseg < 16) {
    212 		for (u_int i = 0; i < memlist->m_nseg; i++) {
    213 			printf("memory segment %d at %08x size %08x\n", i,
    214 			    memlist->m_seg[i].ms_start,
    215 			    memlist->m_seg[i].ms_size);
    216 		}
    217 	}
    218 }
    219 
    220 void
    221 machine_set_model(void)
    222 {
    223 	const char *mach;
    224 
    225 #ifdef DRACO
    226 	char machbuf[16];
    227 
    228 	if (is_draco()) {
    229 		snprintf(machbuf, sizeof(machbuf), "DraCo rev.%d", is_draco());
    230 		mach = machbuf;
    231 	} else
    232 #endif
    233 	if (is_a4000())
    234 		mach = "Amiga 4000";
    235 	else if (is_a3000())
    236 		mach = "Amiga 3000";
    237 	else if (is_a1200())
    238 		mach = "Amiga 1200";
    239 	else if (is_a600())
    240 		mach = "Amiga 600";
    241 	else
    242 		mach = "Amiga 500/2000";
    243 
    244 	cpu_setmodel("%s", mach);
    245 }
    246 
    247 /*
    248  * machine dependent system variables.
    249  */
    250 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    251 {
    252 
    253 	sysctl_createv(clog, 0, NULL, NULL,
    254 		       CTLFLAG_PERMANENT,
    255 		       CTLTYPE_NODE, "machdep", NULL,
    256 		       NULL, 0, NULL, 0,
    257 		       CTL_MACHDEP, CTL_EOL);
    258 
    259 	sysctl_createv(clog, 0, NULL, NULL,
    260 		       CTLFLAG_PERMANENT,
    261 		       CTLTYPE_STRUCT, "console_device", NULL,
    262 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    263 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    264 }
    265 
    266 void
    267 machine_powerdown(void)
    268 {
    269 #if NEMPM > 0
    270 	device_t empmdev = device_find_by_xname("empm0");
    271 	if (empmdev != NULL) {
    272 		empm_power_off(device_private(empmdev));
    273 	}
    274 #endif /* NEMPM > 0 */
    275 }
    276 
    277 u_int32_t dumpmag = 0x8fca0101;	/* magic number for savecore */
    278 int	dumpsize = 0;		/* also for savecore */
    279 long	dumplo = 0;
    280 cpu_kcore_hdr_t cpu_kcore_hdr;
    281 
    282 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
    283 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
    284 
    285 void
    286 cpu_dumpconf(void)
    287 {
    288 	cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
    289 	struct m68k_kcore_hdr *m = &h->un._m68k;
    290 	int nblks;
    291 	int i;
    292 	extern int end[];
    293 
    294 	memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
    295 
    296 	/*
    297 	 * Intitialize the `dispatcher' portion of the header.
    298 	 */
    299 	strcpy(h->name, machine);
    300 	h->page_size = PAGE_SIZE;
    301 	h->kernbase = KERNBASE;
    302 
    303 	/*
    304 	 * Fill in information about our MMU configuration.
    305 	 */
    306 	m->mmutype	= mmutype;
    307 	m->sg_v		= SG_V;
    308 	m->sg_frame	= SG_FRAME;
    309 	m->sg_ishift	= SG_ISHIFT;
    310 	m->sg_pmask	= SG_PMASK;
    311 	m->sg40_shift1	= SG4_SHIFT1;
    312 	m->sg40_mask2	= SG4_MASK2;
    313 	m->sg40_shift2	= SG4_SHIFT2;
    314 	m->sg40_mask3	= SG4_MASK3;
    315 	m->sg40_shift3	= SG4_SHIFT3;
    316 	m->sg40_addr1	= SG4_ADDR1;
    317 	m->sg40_addr2	= SG4_ADDR2;
    318 	m->pg_v		= PG_V;
    319 	m->pg_frame	= PG_FRAME;
    320 
    321 	/*
    322 	 * Initialize the pointer to the kernel segment table.
    323 	 */
    324 	m->sysseg_pa = (paddr_t)pmap_kernel()->pm_stpa;
    325 
    326 	/*
    327 	 * Initialize relocation value such that:
    328 	 *
    329 	 *	pa = (va - KERNBASE) + reloc
    330 	 */
    331 	m->reloc = lowram;
    332 
    333 	/*
    334 	 * Define the end of the relocatable range.
    335 	 */
    336 	m->relocend = (u_int32_t)&end;
    337 
    338 	/* XXX new corefile format, single segment + chipmem */
    339 	dumpsize = physmem;
    340 	m->ram_segs[0].start = lowram;
    341 	m->ram_segs[0].size  = ctob(physmem);
    342 	for (i = 0; i < memlist->m_nseg; i++) {
    343 		if ((memlist->m_seg[i].ms_attrib & MEMF_CHIP) == 0)
    344 			continue;
    345 		dumpsize += btoc(memlist->m_seg[i].ms_size);
    346 		m->ram_segs[1].start = 0;
    347 		m->ram_segs[1].size  = memlist->m_seg[i].ms_size;
    348 		break;
    349 	}
    350 	if (bdevsw_lookup(dumpdev) == NULL) {
    351 		dumpdev = NODEV;
    352 		return;
    353 	}
    354 	nblks = bdev_size(dumpdev);
    355 	if (nblks > 0) {
    356 		if (dumpsize > btoc(dbtob(nblks - dumplo)))
    357 			dumpsize = btoc(dbtob(nblks - dumplo));
    358 		else if (dumplo == 0)
    359 			dumplo = nblks - btodb(ctob(dumpsize));
    360 	}
    361 	dumplo -= ctod(btoc(MDHDRSIZE));
    362 	/*
    363 	 * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?)
    364 	 * in case the dump device includes a disk label.
    365 	 */
    366 	if (dumplo < btodb(PAGE_SIZE))
    367 		dumplo = btodb(PAGE_SIZE);
    368 }
    369 
    370 /*
    371  * Doadump comes here after turning off memory management and
    372  * getting on the dump stack, either when called above, or by
    373  * the auto-restart code.
    374  */
    375 static vm_offset_t dumpspace;
    376 
    377 vm_offset_t
    378 reserve_dumppages(vm_offset_t p)
    379 {
    380 	dumpspace = p;
    381 	return (p + PAGE_SIZE);
    382 }
    383 
    384 void
    385 dumpsys(void)
    386 {
    387 	unsigned bytes, i, n, seg;
    388 	int     maddr, psize;
    389 	daddr_t blkno;
    390 	int     (*dump)(dev_t, daddr_t, void *, size_t);
    391 	int     error = 0;
    392 	kcore_seg_t *kseg_p;
    393 	cpu_kcore_hdr_t *chdr_p;
    394 	char	dump_hdr[MDHDRSIZE];
    395 	const struct bdevsw *bdev;
    396 
    397 	if (dumpdev == NODEV)
    398 		return;
    399 	bdev = bdevsw_lookup(dumpdev);
    400 	if (bdev == NULL || bdev->d_psize == NULL)
    401 		return;
    402 	/*
    403 	 * For dumps during autoconfiguration,
    404 	 * if dump device has already configured...
    405 	 */
    406 	if (dumpsize == 0)
    407 		cpu_dumpconf();
    408 	if (dumplo <= 0) {
    409 		printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
    410 		    minor(dumpdev));
    411 		return;
    412 	}
    413 	printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
    414 	    minor(dumpdev), dumplo);
    415 
    416 	psize = bdev_size(dumpdev);
    417 	printf("dump ");
    418 	if (psize == -1) {
    419 		printf("area unavailable.\n");
    420 		return;
    421 	}
    422 	kseg_p = (kcore_seg_t *)dump_hdr;
    423 	chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
    424 	memset(dump_hdr, 0, sizeof(dump_hdr));
    425 
    426 	/*
    427 	 * Generate a segment header
    428 	 */
    429 	CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
    430 	kseg_p->c_size = MDHDRSIZE - ALIGN(sizeof(*kseg_p));
    431 
    432 	/*
    433 	 * Add the md header
    434 	 */
    435 
    436 	*chdr_p = cpu_kcore_hdr;
    437 
    438 	bytes = ctob(dumpsize);
    439 	maddr = cpu_kcore_hdr.un._m68k.ram_segs[0].start;
    440 	seg = 0;
    441 	blkno = dumplo;
    442 	dump = bdev->d_dump;
    443 	error = (*dump) (dumpdev, blkno, (void *)dump_hdr, sizeof(dump_hdr));
    444 	blkno += btodb(sizeof(dump_hdr));
    445 	for (i = 0; i < bytes && error == 0; i += n) {
    446 		/* Print out how many MBs we have to go. */
    447 		n = bytes - i;
    448 		if (n && (n % (1024 * 1024)) == 0)
    449 			printf_nolog("%d ", n / (1024 * 1024));
    450 
    451 		/* Limit size for next transfer. */
    452 		if (n > PAGE_SIZE)
    453 			n = PAGE_SIZE;
    454 
    455 		if (maddr == 0) {	/* XXX kvtop chokes on this */
    456 			maddr += PAGE_SIZE;
    457 			n -= PAGE_SIZE;
    458 			i += PAGE_SIZE;
    459 			++blkno;	/* XXX skip physical page 0 */
    460 		}
    461 		pmap_enter(pmap_kernel(), dumpspace, maddr,
    462 		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
    463 		pmap_update(pmap_kernel());
    464 		error = (*dump) (dumpdev, blkno, (void *) dumpspace, n);
    465 		if (error)
    466 			break;
    467 		maddr += n;
    468 		blkno += btodb(n);	/* XXX? */
    469 		if (maddr >= (cpu_kcore_hdr.un._m68k.ram_segs[seg].start +
    470 		    cpu_kcore_hdr.un._m68k.ram_segs[seg].size)) {
    471 			++seg;
    472 			maddr = cpu_kcore_hdr.un._m68k.ram_segs[seg].start;
    473 			if (cpu_kcore_hdr.un._m68k.ram_segs[seg].size == 0)
    474 				break;
    475 		}
    476 	}
    477 
    478 	switch (error) {
    479 
    480 	case ENXIO:
    481 		printf("device bad\n");
    482 		break;
    483 
    484 	case EFAULT:
    485 		printf("device not ready\n");
    486 		break;
    487 
    488 	case EINVAL:
    489 		printf("area improper\n");
    490 		break;
    491 
    492 	case EIO:
    493 		printf("i/o error\n");
    494 		break;
    495 
    496 	default:
    497 		printf("succeeded\n");
    498 		break;
    499 	}
    500 	printf("\n\n");
    501 	delay(5000000);		/* 5 seconds */
    502 }
    503 
    504 struct isr *isr_ports;
    505 #ifdef DRACO
    506 struct isr *isr_slot3;
    507 struct isr *isr_supio;
    508 #endif
    509 struct isr *isr_exter;
    510 
    511 void
    512 add_isr(struct isr *isr)
    513 {
    514 	struct isr **p, *q;
    515 
    516 #ifdef DRACO
    517 	switch (isr->isr_ipl) {
    518 	case 2:
    519 		p = &isr_ports;
    520 		break;
    521 	case 3:
    522 		p = &isr_slot3;
    523 		break;
    524 	case 5:
    525 		p = &isr_supio;
    526 		break;
    527 	default:	/* was case 6:; make gcc -Wall quiet */
    528 		p = &isr_exter;
    529 		break;
    530 	}
    531 #else
    532 	p = isr->isr_ipl == 2 ? &isr_ports : &isr_exter;
    533 #endif
    534 	while ((q = *p) != NULL)
    535 		p = &q->isr_forw;
    536 	isr->isr_forw = NULL;
    537 	*p = isr;
    538 	/* enable interrupt */
    539 #ifdef DRACO
    540 	if (is_draco())
    541 		switch(isr->isr_ipl) {
    542 			case 6:
    543 				single_inst_bset_b(*draco_intena, DRIRQ_INT6);
    544 				break;
    545 			case 2:
    546 				single_inst_bset_b(*draco_intena, DRIRQ_INT2);
    547 				break;
    548 			default:
    549 				break;
    550 		}
    551 	else
    552 #endif
    553 		custom.intena = isr->isr_ipl == 2 ?
    554 		    INTF_SETCLR | INTF_PORTS :
    555 		    INTF_SETCLR | INTF_EXTER;
    556 }
    557 
    558 void
    559 remove_isr(struct isr *isr)
    560 {
    561 	struct isr **p, *q;
    562 
    563 #ifdef DRACO
    564 	switch (isr->isr_ipl) {
    565 	case 2:
    566 		p = &isr_ports;
    567 		break;
    568 	case 3:
    569 		p = &isr_slot3;
    570 		break;
    571 	case 5:
    572 		p = &isr_supio;
    573 		break;
    574 	default:	/* XXX to make gcc -Wall quiet, was 6: */
    575 		p = &isr_exter;
    576 		break;
    577 	}
    578 #else
    579 	p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports;
    580 #endif
    581 
    582 	while ((q = *p) != NULL && q != isr)
    583 		p = &q->isr_forw;
    584 	if (q)
    585 		*p = q->isr_forw;
    586 	else
    587 		panic("remove_isr: handler not registered");
    588 	/* disable interrupt if no more handlers */
    589 #ifdef DRACO
    590 	switch (isr->isr_ipl) {
    591 	case 2:
    592 		p = &isr_ports;
    593 		break;
    594 	case 3:
    595 		p = &isr_slot3;
    596 		break;
    597 	case 5:
    598 		p = &isr_supio;
    599 		break;
    600 	case 6:
    601 		p = &isr_exter;
    602 		break;
    603 	}
    604 #else
    605 	p = isr->isr_ipl == 6 ? &isr_exter : &isr_ports;
    606 #endif
    607 	if (*p == NULL) {
    608 #ifdef DRACO
    609 		if (is_draco()) {
    610 			switch(isr->isr_ipl) {
    611 				case 2:
    612 					single_inst_bclr_b(*draco_intena,
    613 					    DRIRQ_INT2);
    614 					break;
    615 				case 6:
    616 					single_inst_bclr_b(*draco_intena,
    617 					    DRIRQ_INT6);
    618 					break;
    619 				default:
    620 					break;
    621 			}
    622 		} else
    623 #endif
    624 			custom.intena = isr->isr_ipl == 6 ?
    625 			    INTF_EXTER : INTF_PORTS;
    626 	}
    627 }
    628 
    629 void
    630 intrhand(int sr)
    631 {
    632 	register unsigned int ipl;
    633 	register unsigned short ireq;
    634 	register struct isr **p, *q;
    635 
    636 	ipl = (sr >> 8) & 7;
    637 #ifdef REALLYDEBUG
    638 	printf("intrhand: got int. %d\n", ipl);
    639 #endif
    640 #ifdef DRACO
    641 	if (is_draco())
    642 		ireq = ((ipl == 1)  && (*draco_intfrc & DRIRQ_SOFT) ?
    643 		    INTF_SOFTINT : 0);
    644 	else
    645 #endif
    646 		ireq = custom.intreqr;
    647 
    648 	switch (ipl) {
    649 	case 1:
    650 #ifdef DRACO
    651 		if (is_draco() && (draco_ioct->io_status & DRSTAT_KBDRECV))
    652 			drkbdintr();
    653 #endif
    654 		if (ireq & INTF_TBE) {
    655 #if NSER > 0
    656 			ser_outintr();
    657 #else
    658 			custom.intreq = INTF_TBE;
    659 #endif
    660 		}
    661 
    662 		if (ireq & INTF_DSKBLK) {
    663 #if NFD > 0
    664 			fdintr(0);
    665 #endif
    666 			custom.intreq = INTF_DSKBLK;
    667 		}
    668 		if (ireq & INTF_SOFTINT) {
    669 			/* sicallback handling removed */
    670 #ifdef DEBUG
    671 			printf("intrhand: SOFTINT ignored\n");
    672 #endif
    673 			custom.intreq = INTF_SOFTINT;
    674 		}
    675 		break;
    676 
    677 	case 2:
    678 		p = &isr_ports;
    679 		while ((q = *p) != NULL) {
    680 			if ((q->isr_intr)(q->isr_arg))
    681 				break;
    682 			p = &q->isr_forw;
    683 		}
    684 		if (q == NULL)
    685 			ciaa_intr ();
    686 #ifdef DRACO
    687 		if (is_draco())
    688 			single_inst_bclr_b(*draco_intpen, DRIRQ_INT2);
    689 		else
    690 #endif
    691 			custom.intreq = INTF_PORTS;
    692 
    693 		break;
    694 
    695 #ifdef DRACO
    696 	/* only handled here for DraCo */
    697 	case 6:
    698 		p = &isr_exter;
    699 		while ((q = *p) != NULL) {
    700 			if ((q->isr_intr)(q->isr_arg))
    701 				break;
    702 			p = &q->isr_forw;
    703 		}
    704 		single_inst_bclr_b(*draco_intpen, DRIRQ_INT6);
    705 		break;
    706 #endif
    707 
    708 	case 3:
    709 	/* VBL */
    710 		if (ireq & INTF_BLIT)
    711 			blitter_handler();
    712 		if (ireq & INTF_COPER)
    713 			copper_handler();
    714 		if (ireq & INTF_VERTB)
    715 			vbl_handler();
    716 		break;
    717 #ifdef DRACO
    718 	case 5:
    719 		p = &isr_supio;
    720 		while ((q = *p) != NULL) {
    721 			if ((q->isr_intr)(q->isr_arg))
    722 				break;
    723 			p = &q->isr_forw;
    724 		}
    725 		break;
    726 #endif
    727 #if 0
    728 /* now dealt with in locore.s for speed reasons */
    729 	case 5:
    730 		/* check RS232 RBF */
    731 		serintr (0);
    732 
    733 		custom.intreq = INTF_DSKSYNC;
    734 		break;
    735 #endif
    736 
    737 	case 4:
    738 #ifdef DRACO
    739 #include "drsc.h"
    740 		if (is_draco())
    741 #if NDRSC > 0
    742 			drsc_handler();
    743 #else
    744 			single_inst_bclr_b(*draco_intpen, DRIRQ_SCSI);
    745 #endif
    746 		else
    747 #endif
    748 		audio_handler();
    749 		break;
    750 	default:
    751 		printf("intrhand: unexpected sr 0x%x, intreq = 0x%x\n",
    752 		    sr, ireq);
    753 		break;
    754 	}
    755 #ifdef REALLYDEBUG
    756 	printf("intrhand: leaving.\n");
    757 #endif
    758 }
    759 
    760 bool
    761 cpu_intr_p(void)
    762 {
    763 
    764 	return intr_depth != 0;
    765 }
    766 
    767 #if defined(DEBUG) && !defined(PANICBUTTON)
    768 #define PANICBUTTON
    769 #endif
    770 
    771 #ifdef PANICBUTTON
    772 int panicbutton = 1;	/* non-zero if panic buttons are enabled */
    773 int crashandburn = 0;
    774 int candbdelay = 50;	/* give em half a second */
    775 void candbtimer(void);
    776 callout_t candbtimer_ch;
    777 
    778 void
    779 candbtimer(void)
    780 {
    781 	crashandburn = 0;
    782 }
    783 #endif
    784 
    785 #if 0
    786 /*
    787  * Level 7 interrupts can be caused by the keyboard or parity errors.
    788  */
    789 nmihand(struct frame frame)
    790 {
    791 	if (kbdnmi()) {
    792 #ifdef PANICBUTTON
    793 		static int innmihand = 0;
    794 
    795 		/*
    796 		 * Attempt to reduce the window of vulnerability for recursive
    797 		 * NMIs (e.g. someone holding down the keyboard reset button).
    798 		 */
    799 		if (innmihand == 0) {
    800 			innmihand = 1;
    801 			printf("Got a keyboard NMI\n");
    802 			innmihand = 0;
    803 		}
    804 		if (panicbutton) {
    805 			if (crashandburn) {
    806 				crashandburn = 0;
    807 				panic(panicstr ?
    808 				      "forced crash, nosync" : "forced crash");
    809 			}
    810 			crashandburn++;
    811 			callout_reset(&candbtimer_ch, candbdelay,
    812 			    candbtimer, NULL);
    813 		}
    814 #endif
    815 		return;
    816 	}
    817 	if (parityerror(&frame))
    818 		return;
    819 	/* panic?? */
    820 	printf("unexpected level 7 interrupt ignored\n");
    821 }
    822 #endif
    823 
    824 #ifdef MODULAR
    825 int _spllkm6(void);
    826 int _spllkm7(void);
    827 
    828 #ifdef LEV6_DEFER
    829 int _spllkm6(void) {
    830 	return spl4();
    831 };
    832 
    833 int _spllkm7(void) {
    834 	return spl4();
    835 };
    836 
    837 #else
    838 
    839 int _spllkm6(void) {
    840 	return spl6();
    841 };
    842 
    843 int _spllkm7(void) {
    844 	return spl7();
    845 };
    846 
    847 #endif
    848 
    849 #endif
    850 
    851 int ipl2spl_table[_NIPL] = {
    852 	[IPL_NONE] = PSL_IPL0|PSL_S,
    853 	[IPL_SOFTCLOCK] = PSL_IPL1|PSL_S,
    854 	[IPL_VM] = PSL_IPL4|PSL_S,
    855 #if defined(LEV6_DEFER)
    856 	[IPL_SCHED] = PSL_IPL4|PSL_S,
    857 	[IPL_HIGH] = PSL_IPL4|PSL_S,
    858 #else /* defined(LEV6_DEFER) */
    859 	[IPL_SCHED] = PSL_IPL6|PSL_S,
    860 	[IPL_HIGH] = PSL_IPL7|PSL_S,
    861 #endif /* defined(LEV6_DEFER) */
    862 };
    863 
    864 int
    865 mm_md_physacc(paddr_t pa, vm_prot_t prot)
    866 {
    867 
    868 	return (pa >= 0xfffffffc || pa < lowram) ? EFAULT : 0;
    869 }
    870