Home | History | Annotate | Line # | Download | only in atari
      1 /*	$NetBSD: machdep.c,v 1.191 2024/03/05 14:15:29 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 <sys/cdefs.h>
     42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.191 2024/03/05 14:15:29 thorpej Exp $");
     43 
     44 #include "opt_ddb.h"
     45 #include "opt_compat_netbsd.h"
     46 #include "opt_mbtype.h"
     47 #include "opt_modular.h"
     48 #include "opt_panicbutton.h"
     49 
     50 #include <sys/param.h>
     51 #include <sys/systm.h>
     52 #include <sys/signalvar.h>
     53 #include <sys/kernel.h>
     54 #include <sys/proc.h>
     55 #include <sys/buf.h>
     56 #include <sys/reboot.h>
     57 #include <sys/conf.h>
     58 #include <sys/file.h>
     59 #include <sys/device.h>
     60 #include <sys/kmem.h>
     61 #include <sys/mbuf.h>
     62 #include <sys/msgbuf.h>
     63 #include <sys/vnode.h>
     64 #include <sys/queue.h>
     65 #include <sys/mount.h>
     66 #include <sys/syscallargs.h>
     67 #include <sys/ksyms.h>
     68 #include <sys/module.h>
     69 #include <sys/intr.h>
     70 #include <sys/exec.h>
     71 #include <sys/exec_aout.h>
     72 #include <sys/cpu.h>
     73 #include <sys/exec_elf.h>
     74 #include <sys/bus.h>
     75 
     76 #include <uvm/uvm_extern.h>
     77 
     78 #include <sys/sysctl.h>
     79 
     80 #include <machine/db_machdep.h>
     81 #include <ddb/db_sym.h>
     82 #include <ddb/db_extern.h>
     83 
     84 #include <machine/reg.h>
     85 #include <machine/psl.h>
     86 #include <machine/pte.h>
     87 
     88 #include <dev/cons.h>
     89 #include <dev/mm.h>
     90 
     91 #include "ksyms.h"
     92 #include "nvr.h"
     93 
     94 #define	DEV_NVRAM	11	/* Nvram minor-number */
     95 
     96 static void bootsync(void);
     97 static void call_sicallbacks(void);
     98 static void identifycpu(void);
     99 void	straymfpint(int, u_short);
    100 void	straytrap(int, u_short);
    101 
    102 #ifdef _MILANHW_
    103 void	nmihandler(void);
    104 #endif
    105 
    106 struct vm_map *phys_map = NULL;
    107 
    108 void *	msgbufaddr;
    109 vaddr_t	msgbufpa;
    110 
    111 extern  int   freebufspace;
    112 extern	u_int lowram;
    113 
    114 /*
    115  * For the fpu emulation and the fpu driver
    116  */
    117 int	fputype = 0;
    118 
    119 /* the following is used externally (sysctl_hw) */
    120 char	machine[] = MACHINE;	/* from <machine/param.h> */
    121 
    122 /* Our exported CPU info; we can have only one. */
    123 struct cpu_info cpu_info_store;
    124 
    125  /*
    126  * Console initialization: called early on from main,
    127  * before vm init or startup.  Do enough configuration
    128  * to choose and initialize a console.
    129  */
    130 void
    131 consinit(void)
    132 {
    133 	int i;
    134 
    135 	/*
    136 	 * Initialize error message buffer. pmap_bootstrap() has
    137 	 * positioned this at the end of kernel memory segment - map
    138 	 * and initialize it now.
    139 	 */
    140 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
    141 		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
    142 		    msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0);
    143 	pmap_update(pmap_kernel());
    144 	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
    145 
    146 	/*
    147 	 * Initialize hardware that support various console types like
    148 	 * the grf and PCI busses.
    149 	 */
    150 	config_console();
    151 
    152 	/*
    153 	 * Now pick the best console candidate.
    154 	 */
    155 	cninit();
    156 
    157 #if NKSYMS || defined(DDB) || defined(MODULAR)
    158 	{
    159 		extern int end;
    160 		extern int *esym;
    161 
    162 		ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
    163 		    (void *)&end, esym);
    164 	}
    165 #endif
    166 #if defined (DDB)
    167 	if (boothowto & RB_KDB)
    168 		Debugger();
    169 #endif
    170 }
    171 
    172 /*
    173  * cpu_startup: allocate memory for variable-sized tables,
    174  * initialize CPU, and do autoconfiguration.
    175  */
    176 void
    177 cpu_startup(void)
    178 {
    179 	char pbuf[9];
    180 #ifdef DEBUG
    181 	extern int pmapdebug;
    182 	int opmapdebug = pmapdebug;
    183 #endif
    184 	vaddr_t minaddr, maxaddr;
    185 	extern vsize_t mem_size;	/* from pmap.c */
    186 
    187 #ifdef DEBUG
    188 	pmapdebug = 0;
    189 #endif
    190 
    191 	if (fputype != FPU_NONE)
    192 		m68k_make_fpu_idle_frame();
    193 
    194 	/*
    195 	 * Good {morning,afternoon,evening,night}.
    196 	 */
    197 	printf("%s%s", copyright, version);
    198 	identifycpu();
    199 
    200 	format_bytes(pbuf, sizeof(pbuf), mem_size);
    201 	printf("total memory = %s\n", pbuf);
    202 
    203 	minaddr = 0;
    204 
    205 	/*
    206 	 * Allocate a submap for physio
    207 	 */
    208 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
    209 	    VM_PHYS_SIZE, 0, false, NULL);
    210 
    211 #ifdef DEBUG
    212 	pmapdebug = opmapdebug;
    213 #endif
    214 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
    215 	printf("avail memory = %s\n", pbuf);
    216 }
    217 
    218 /*
    219  * Info for CTL_HW
    220  */
    221 static void
    222 identifycpu(void)
    223 {
    224 	const char *mach, *mmu, *fpu, *cpu;
    225 	uint32_t pcr;
    226 	char cputxt[30];
    227 
    228 	switch (machineid & ATARI_ANYMACH) {
    229 	case ATARI_TT:
    230 		mach = "Atari TT";
    231 		break;
    232 	case ATARI_FALCON:
    233 		mach = "Atari Falcon";
    234 		break;
    235 	case ATARI_HADES:
    236 		mach = "Atari Hades";
    237 		break;
    238 	case ATARI_MILAN:
    239 		mach = "Atari Milan";
    240 		break;
    241 	default:
    242 		mach = "Atari UNKNOWN";
    243 		break;
    244 	}
    245 
    246 	cpu     = "m68k";
    247 	fputype = fpu_probe();
    248 	fpu     = fpu_describe(fputype);
    249 
    250 	switch (cputype) {
    251 	case CPU_68060:
    252 		__asm(".word 0x4e7a,0x0808;"
    253 		    "movl %%d0,%0" : "=d"(pcr) : : "d0");
    254 		snprintf(cputxt, sizeof(cputxt), "MC68%s060 rev.%d",
    255 		    pcr & 0x10000 ? "LC/EC" : "", (pcr >> 8) & 0xff);
    256 		cpu = cputxt;
    257 		mmu = "/MMU";
    258 		break;
    259 	case CPU_68040:
    260 		cpu = "MC68040";
    261 		mmu = "/MMU";
    262 		break;
    263 	case CPU_68030:
    264 		cpu = "MC68030";
    265 		mmu = "/MMU";
    266 		break;
    267 	default: /* XXX */
    268 		cpu = "MC68020";
    269 		mmu = " MC68851 MMU";
    270 	}
    271 	cpu_setmodel("%s (%s CPU%s%sFPU)", mach, cpu, mmu, fpu);
    272 	printf("%s\n", cpu_getmodel());
    273 }
    274 
    275 /*
    276  * machine dependent system variables.
    277  */
    278 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    279 {
    280 
    281 	sysctl_createv(clog, 0, NULL, NULL,
    282 		       CTLFLAG_PERMANENT,
    283 		       CTLTYPE_NODE, "machdep", NULL,
    284 		       NULL, 0, NULL, 0,
    285 		       CTL_MACHDEP, CTL_EOL);
    286 
    287 	sysctl_createv(clog, 0, NULL, NULL,
    288 		       CTLFLAG_PERMANENT,
    289 		       CTLTYPE_STRUCT, "console_device", NULL,
    290 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    291 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    292 }
    293 
    294 static int waittime = -1;
    295 
    296 static void
    297 bootsync(void)
    298 {
    299 	if (waittime < 0) {
    300 		waittime = 0;
    301 		vfs_shutdown();
    302 	}
    303 }
    304 
    305 void
    306 cpu_reboot(int howto, char *bootstr)
    307 {
    308 	struct pcb *pcb = lwp_getpcb(curlwp);
    309 
    310 	/* take a snap shot before clobbering any registers */
    311 	if (pcb != NULL)
    312 		savectx(pcb);
    313 
    314 	boothowto = howto;
    315 	if ((howto & RB_NOSYNC) == 0)
    316 		bootsync();
    317 
    318 	/*
    319 	 * Call shutdown hooks. Do this _before_ anything might be
    320 	 * asked to the user in case nobody is there....
    321 	 */
    322 	doshutdownhooks();
    323 
    324 	pmf_system_shutdown(boothowto);
    325 
    326 	splhigh();			/* extreme priority */
    327 	if (howto & RB_HALT) {
    328 		printf("halted\n\n");
    329 		__asm("	stop	#0x2700");
    330 	} else {
    331 		if (howto & RB_DUMP)
    332 			dumpsys();
    333 
    334 		doboot();
    335 		/*NOTREACHED*/
    336 	}
    337 	panic("Boot() should never come here");
    338 	/*NOTREACHED*/
    339 }
    340 
    341 #define	BYTES_PER_DUMP	PAGE_SIZE	/* Must be a multiple of PAGE_SIZE */
    342 static vaddr_t	dumpspace;	/* Virt. space to map dumppages	*/
    343 
    344 /*
    345  * Reserve _virtual_ memory to map in the page to be dumped
    346  */
    347 vaddr_t
    348 reserve_dumppages(vaddr_t p)
    349 {
    350 
    351 	dumpspace = p;
    352 	return p + BYTES_PER_DUMP;
    353 }
    354 
    355 uint32_t	dumpmag  = 0x8fca0101;	/* magic number for savecore	*/
    356 int		dumpsize = 0;		/* also for savecore (pages)	*/
    357 long		dumplo   = 0;		/* (disk blocks)		*/
    358 
    359 void
    360 cpu_dumpconf(void)
    361 {
    362 	int	nblks, i;
    363 
    364 	for (i = dumpsize = 0; i < NMEM_SEGS; i++) {
    365 		if (boot_segs[i].start == boot_segs[i].end)
    366 			break;
    367 		dumpsize += boot_segs[i].end - boot_segs[i].start;
    368 	}
    369 	dumpsize = btoc(dumpsize);
    370 
    371 	if (dumpdev != NODEV) {
    372 		nblks = bdev_size(dumpdev);
    373 		if (nblks > 0) {
    374 			if (dumpsize > btoc(dbtob(nblks - dumplo)))
    375 				dumpsize = btoc(dbtob(nblks - dumplo));
    376 			else if (dumplo == 0)
    377 				dumplo = nblks - btodb(ctob(dumpsize));
    378 		}
    379 	}
    380 	dumplo -= cpu_dumpsize();
    381 
    382 	/*
    383 	 * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?)
    384 	 * in case the dump device includes a disk label.
    385 	 */
    386 	if (dumplo < btodb(PAGE_SIZE))
    387 		dumplo = btodb(PAGE_SIZE);
    388 }
    389 
    390 /*
    391  * Doadump comes here after turning off memory management and
    392  * getting on the dump stack, either when called above, or by
    393  * the auto-restart code.
    394  */
    395 void
    396 dumpsys(void)
    397 {
    398 	const struct bdevsw *bdev;
    399 	daddr_t	blkno;		/* Current block to write	*/
    400 	int	(*dump)(dev_t, daddr_t, void *, size_t);
    401 				/* Dumping function		*/
    402 	u_long	maddr;		/* PA being dumped		*/
    403 	int	segbytes;	/* Number of bytes in this seg.	*/
    404 	int	segnum;		/* Segment we are dumping	*/
    405 	int	nbytes;		/* Bytes left to dump		*/
    406 	int	i, n, error;
    407 
    408 	error = segnum = 0;
    409 	if (dumpdev == NODEV)
    410 		return;
    411 	bdev = bdevsw_lookup(dumpdev);
    412 	if (bdev == NULL)
    413 		return;
    414 	/*
    415 	 * For dumps during autoconfiguration,
    416 	 * if dump device has already configured...
    417 	 */
    418 	if (dumpsize == 0)
    419 		cpu_dumpconf();
    420 	if (dumplo <= 0) {
    421 		printf("\ndump to dev %u,%u not possible\n",
    422 		    major(dumpdev), minor(dumpdev));
    423 		return;
    424 	}
    425 	printf("\ndumping to dev %u,%u offset %ld\n",
    426 	    major(dumpdev), minor(dumpdev), dumplo);
    427 
    428 #if defined(DDB) || defined(PANICWAIT)
    429 	printf("Do you want to dump memory? [y]");
    430 	cnpollc(1);
    431 	i = cngetc();
    432 	cnpollc(0);
    433 	cnputc(i);
    434 	switch (i) {
    435 	case 'n':
    436 	case 'N':
    437 		return;
    438 	case '\n':
    439 		break;
    440 	default :
    441 		cnputc('\n');
    442 	}
    443 #endif /* defined(DDB) || defined(PANICWAIT) */
    444 
    445 	maddr    = 0;
    446 	segbytes = boot_segs[0].end;
    447 	blkno    = dumplo;
    448 	dump     = bdev->d_dump;
    449 	nbytes   = dumpsize * PAGE_SIZE;
    450 
    451 	printf("dump ");
    452 
    453 	error = cpu_dump(dump, &blkno);
    454 	if (!error) {
    455 		for (i = 0; i < nbytes; i += n, segbytes -= n) {
    456 			/*
    457 			 * Skip the hole
    458 			 */
    459 			if (segbytes == 0) {
    460 				segnum++;
    461 				maddr    = boot_segs[segnum].start;
    462 				segbytes = boot_segs[segnum].end -
    463 				    boot_segs[segnum].start;
    464 			}
    465 			/*
    466 			 * Print Mb's to go
    467 			 */
    468 			n = nbytes - i;
    469 			if (n && (n % (1024 * 1024)) == 0)
    470 				printf_nolog("%d ", n / (1024 * 1024));
    471 
    472 			/*
    473 			 * Limit transfer to BYTES_PER_DUMP
    474 			 */
    475 			if (n > BYTES_PER_DUMP)
    476 				n = BYTES_PER_DUMP;
    477 
    478 			/*
    479 			 * Map to a VA and write it
    480 			 */
    481 			if (maddr != 0) { /* XXX kvtop chokes on this	*/
    482 				(void)pmap_map(dumpspace, maddr, maddr + n,
    483 				    VM_PROT_READ);
    484 				error = (*dump)(dumpdev, blkno,
    485 				    (void *)dumpspace, n);
    486 				if (error)
    487 					break;
    488 			}
    489 
    490 			maddr += n;
    491 			blkno += btodb(n);
    492 		}
    493 	}
    494 	switch (error) {
    495 
    496 	case ENXIO:
    497 		printf("device bad\n");
    498 		break;
    499 
    500 	case EFAULT:
    501 		printf("device not ready\n");
    502 		break;
    503 
    504 	case EINVAL:
    505 		printf("area improper\n");
    506 		break;
    507 
    508 	case EIO:
    509 		printf("i/o error\n");
    510 		break;
    511 
    512 	default:
    513 		printf("succeeded\n");
    514 		break;
    515 	}
    516 	printf("\n\n");
    517 	delay(5000000);		/* 5 seconds */
    518 }
    519 
    520 void
    521 straytrap(int pc, u_short evec)
    522 {
    523 	static int prev_evec;
    524 
    525 	printf("unexpected trap (vector offset 0x%x) from 0x%x\n",
    526 	    evec & 0xFFF, pc);
    527 
    528 	if (prev_evec == evec) {
    529 		delay(1000000);
    530 		prev_evec = 0;
    531 	} else
    532 		prev_evec = evec;
    533 }
    534 
    535 void
    536 straymfpint(int pc, u_short evec)
    537 {
    538 
    539 	printf("unexpected mfp-interrupt (vector offset 0x%x) from 0x%x\n",
    540 	       evec & 0xFFF, pc);
    541 }
    542 
    543 int	*nofault;
    544 
    545 int
    546 badbaddr(void *addr, int size)
    547 {
    548 	int i;
    549 	label_t	faultbuf;
    550 
    551 	nofault = (int *) &faultbuf;
    552 	if (setjmp((label_t *)nofault)) {
    553 		nofault = (int *) 0;
    554 		return 1;
    555 	}
    556 	switch (size) {
    557 	case 1:
    558 		i = *(volatile uint8_t *)addr;
    559 		break;
    560 	case 2:
    561 		i = *(volatile uint16_t *)addr;
    562 		break;
    563 	case 4:
    564 		i = *(volatile uint32_t *)addr;
    565 		break;
    566 	default:
    567 		panic("badbaddr: unknown size");
    568 	}
    569 	__USE(i);
    570 	nofault = (int *)0;
    571 	return 0;
    572 }
    573 
    574 /*
    575  * this is a handy package to have asynchronously executed
    576  * function calls executed at very low interrupt priority.
    577  * Example for use is keyboard repeat, where the repeat
    578  * handler running at splclock() triggers such a (hardware
    579  * aided) software interrupt.
    580  * Note: the installed functions are currently called in a
    581  * LIFO fashion, might want to change this to FIFO
    582  * later.
    583  *
    584  * XXX: Some of functions which use this callback should be rewritten
    585  * XXX: to use MI softintr(9) directly.
    586  */
    587 struct si_callback {
    588 	struct si_callback *next;
    589 	void (*function)(void *rock1, void *rock2);
    590 	void *rock1, *rock2;
    591 };
    592 static void *si_callback_cookie;
    593 static struct si_callback *si_callbacks;
    594 static struct si_callback *si_free;
    595 #ifdef DIAGNOSTIC
    596 static int ncbd;	/* number of callback blocks dynamically allocated */
    597 #endif
    598 
    599 void
    600 init_sicallback(void)
    601 {
    602 
    603 	si_callback_cookie = softint_establish(SOFTINT_NET,
    604 	    (void (*)(void *))call_sicallbacks, NULL);
    605 }
    606 
    607 void
    608 add_sicallback(void (*function)(void *, void *), void *rock1, void *rock2)
    609 {
    610 	struct si_callback *si;
    611 	int s;
    612 
    613 	/*
    614 	 * this function may be called from high-priority interrupt handlers.
    615 	 * We may NOT block for  memory-allocation in here!.
    616 	 */
    617 	s = splhigh();
    618 	if ((si = si_free) != NULL)
    619 		si_free = si->next;
    620 	splx(s);
    621 
    622 	if (si == NULL) {
    623 		si = kmem_intr_alloc(sizeof(*si), KM_NOSLEEP);
    624 #ifdef DIAGNOSTIC
    625 		if (si)
    626 			++ncbd;		/* count # dynamically allocated */
    627 #endif
    628 		if (si == NULL)
    629 			return;
    630 	}
    631 
    632 	si->function = function;
    633 	si->rock1    = rock1;
    634 	si->rock2    = rock2;
    635 
    636 	s = splhigh();
    637 	si->next     = si_callbacks;
    638 	si_callbacks = si;
    639 	splx(s);
    640 
    641 	/*
    642 	 * and cause a software interrupt (spl1). This interrupt might
    643 	 * happen immediately, or after returning to a safe enough level.
    644 	 *
    645 	 * XXX:
    646 	 * According to <machine/scu.h> and lev1intr() handler in locore.s,
    647 	 * at least _ATARIHW_ machines (ATARITT and HADES?) seem to have
    648 	 * some hardware support which can initiate real hardware interrupt
    649 	 * at ipl 1 for software interrupt. But as per <machine/mtpr.h>,
    650 	 * this feature was not used at all on setsoft*() calls and
    651 	 * traditional hp300 derived ssir (simulated software interrupt
    652 	 * request) on VAX REI emulation in locore.s is used.
    653 	 */
    654 	softint_schedule(si_callback_cookie);
    655 }
    656 
    657 void
    658 rem_sicallback(void (*function)(void *rock1, void *rock2))
    659 {
    660 	struct si_callback *si, *psi, *nsi;
    661 	int s;
    662 
    663 	s = splhigh();
    664 	for (psi = 0, si = si_callbacks; si; ) {
    665 		nsi = si->next;
    666 
    667 		if (si->function != function)
    668 			psi = si;
    669 		else {
    670 			si->next = si_free;
    671 			si_free  = si;
    672 			if (psi != NULL)
    673 				psi->next = nsi;
    674 			else
    675 				si_callbacks = nsi;
    676 		}
    677 		si = nsi;
    678 	}
    679 	splx(s);
    680 }
    681 
    682 /* purge the list */
    683 static void
    684 call_sicallbacks(void)
    685 {
    686 	struct si_callback *si;
    687 	int s;
    688 	void *rock1, *rock2;
    689 	void (*function)(void *, void *);
    690 
    691 	do {
    692 		s = splhigh();
    693 		if ((si = si_callbacks) != NULL)
    694 			si_callbacks = si->next;
    695 		splx(s);
    696 
    697 		if (si != NULL) {
    698 			function = si->function;
    699 			rock1    = si->rock1;
    700 			rock2    = si->rock2;
    701 			s = splhigh();
    702 			if (si_callbacks)
    703 				softint_schedule(si_callback_cookie);
    704 			si->next = si_free;
    705 			si_free  = si;
    706 			splx(s);
    707 
    708 			/*
    709 			 * Raise spl for BASEPRI() checks to see
    710 			 * nested interrupts in some drivers using callbacks
    711 			 * since modern MI softint(9) doesn't seem to do it
    712 			 * in !__HAVE_FAST_SOFTINTS case.
    713 			 *
    714 			 * XXX: This is just a workaround hack.
    715 			 *      Each driver should raise spl in its handler
    716 			 *      to avoid nested interrupts if necessary.
    717 			 */
    718 			s = splsoftnet();	/* XXX */
    719 			function(rock1, rock2);
    720 			splx(s);
    721 		}
    722 	} while (si != NULL);
    723 #ifdef DIAGNOSTIC
    724 	if (ncbd) {
    725 #ifdef DEBUG
    726 		printf("call_sicallback: %d more dynamic structures\n", ncbd);
    727 #endif
    728 		ncbd = 0;
    729 	}
    730 #endif
    731 }
    732 
    733 #if defined(DEBUG) && !defined(PANICBUTTON)
    734 #define PANICBUTTON
    735 #endif
    736 
    737 #ifdef PANICBUTTON
    738 int panicbutton = 1;	/* non-zero if panic buttons are enabled */
    739 int crashandburn = 0;
    740 int candbdelay = 50;	/* give em half a second */
    741 
    742 void candbtimer(void);
    743 
    744 void
    745 candbtimer(void)
    746 {
    747 
    748 	crashandburn = 0;
    749 }
    750 #endif
    751 
    752 /*
    753  * should only get here, if no standard executable. This can currently
    754  * only mean, we're reading an old ZMAGIC file without MID, but since Atari
    755  * ZMAGIC always worked the `right' way (;-)) just ignore the missing
    756  * MID and proceed to new zmagic code ;-)
    757  */
    758 int
    759 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
    760 {
    761 	int error = ENOEXEC;
    762 #ifdef COMPAT_NOMID
    763 	struct exec *execp = epp->ep_hdr;
    764 #endif
    765 
    766 #ifdef COMPAT_NOMID
    767 	if (!((execp->a_midmag >> 16) & 0x0fff)
    768 	    && execp->a_midmag == ZMAGIC)
    769 		return exec_aout_prep_zmagic(l->l_proc, epp);
    770 #endif
    771 	return error;
    772 }
    773 
    774 #ifdef MODULAR
    775 /*
    776  * Push any modules loaded by the bootloader etc.
    777  */
    778 void
    779 module_init_md(void)
    780 {
    781 }
    782 #endif
    783 
    784 #ifdef _MILANHW_
    785 
    786 /*
    787  * Currently the only source of NMI interrupts on the Milan is the PLX9080.
    788  * On access errors to the PCI bus, an NMI is generated. This NMI is shorted
    789  * in locore in case of a PCI config cycle to a non-existing address to allow
    790  * for probes. On other occasions, it ShouldNotHappen(TM).
    791  * Note: The handler in locore clears the errors, to make further PCI access
    792  * possible.
    793  */
    794 void
    795 nmihandler(void)
    796 {
    797 	extern unsigned long	plx_status;
    798 
    799 	printf("nmihandler: plx_status = 0x%08lx\n", plx_status);
    800 }
    801 #endif
    802 
    803 int
    804 mm_md_physacc(paddr_t pa, vm_prot_t prot)
    805 {
    806 	struct memseg *ms;
    807 
    808 	for (ms = boot_segs; ms->start != ms->end; ms++) {
    809 		if ((pa >= ms->start) && (pa < ms->end))
    810 			return 0;
    811 	}
    812 	return EFAULT;
    813 }
    814 
    815 int
    816 mm_md_readwrite(dev_t dev, struct uio *uio)
    817 {
    818 	switch (minor(dev)) {
    819 	case DEV_NVRAM:
    820 #if NNVR > 0
    821 		return nvram_uio(uio);
    822 #else
    823 		return ENXIO;
    824 #endif
    825 	default:
    826 		return ENXIO;
    827 	}
    828 }
    829