xref: /netbsd/sys/arch/atari/atari/machdep.c (revision 6550d01e)
1 /*	$NetBSD: machdep.c,v 1.168 2010/10/16 17:10:42 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * the Systems Programming Group of the University of Utah Computer
9  * Science Department.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * from: Utah $Hdr: machdep.c 1.63 91/04/24$
36  *
37  *	@(#)machdep.c	7.16 (Berkeley) 6/3/91
38  */
39 /*
40  * Copyright (c) 1988 University of Utah.
41  *
42  * This code is derived from software contributed to Berkeley by
43  * the Systems Programming Group of the University of Utah Computer
44  * Science Department.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. All advertising materials mentioning features or use of this software
55  *    must display the following acknowledgement:
56  *	This product includes software developed by the University of
57  *	California, Berkeley and its contributors.
58  * 4. Neither the name of the University nor the names of its contributors
59  *    may be used to endorse or promote products derived from this software
60  *    without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  * from: Utah $Hdr: machdep.c 1.63 91/04/24$
75  *
76  *	@(#)machdep.c	7.16 (Berkeley) 6/3/91
77  */
78 
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.168 2010/10/16 17:10:42 tsutsui Exp $");
81 
82 #include "opt_ddb.h"
83 #include "opt_compat_netbsd.h"
84 #include "opt_mbtype.h"
85 #include "opt_modular.h"
86 #include "opt_panicbutton.h"
87 
88 #include <sys/param.h>
89 #include <sys/systm.h>
90 #include <sys/signalvar.h>
91 #include <sys/kernel.h>
92 #include <sys/proc.h>
93 #include <sys/buf.h>
94 #include <sys/reboot.h>
95 #include <sys/conf.h>
96 #include <sys/file.h>
97 #include <sys/device.h>
98 #include <sys/malloc.h>
99 #include <sys/mbuf.h>
100 #include <sys/msgbuf.h>
101 #include <sys/vnode.h>
102 #include <sys/queue.h>
103 #include <sys/mount.h>
104 #include <sys/syscallargs.h>
105 #include <sys/ksyms.h>
106 #include <sys/module.h>
107 #include <sys/intr.h>
108 #include <sys/exec.h>
109 #include <sys/exec_aout.h>
110 #include <sys/cpu.h>
111 #if defined(DDB) && defined(__ELF__)
112 #include <sys/exec_elf.h>
113 #endif
114 
115 #undef PS	/* XXX netccitt/pk.h conflict with machine/reg.h? */
116 
117 #define	MAXMEM	64*1024	/* XXX - from cmap.h */
118 #include <uvm/uvm_extern.h>
119 
120 #include <sys/sysctl.h>
121 
122 #include <machine/db_machdep.h>
123 #include <ddb/db_sym.h>
124 #include <ddb/db_extern.h>
125 
126 #include <machine/reg.h>
127 #include <machine/psl.h>
128 #include <machine/pte.h>
129 
130 #include <dev/cons.h>
131 
132 #include "ksyms.h"
133 
134 static void bootsync(void);
135 static void call_sicallbacks(void);
136 static void identifycpu(void);
137 void	straymfpint(int, u_short);
138 void	straytrap(int, u_short);
139 
140 #ifdef _MILANHW_
141 void	nmihandler(void);
142 #endif
143 
144 struct vm_map *phys_map = NULL;
145 
146 void *	msgbufaddr;
147 vaddr_t	msgbufpa;
148 
149 int	physmem = MAXMEM;	/* max supported memory, changes to actual */
150 /*
151  * safepri is a safe priority for sleep to set for a spin-wait
152  * during autoconfiguration or after a panic.
153  */
154 int	safepri = PSL_LOWIPL;
155 extern  int   freebufspace;
156 extern	u_int lowram;
157 
158 /*
159  * For the fpu emulation and the fpu driver
160  */
161 int	fputype = 0;
162 
163 /* the following is used externally (sysctl_hw) */
164 char	machine[] = MACHINE;	/* from <machine/param.h> */
165 
166 /* Our exported CPU info; we can have only one. */
167 struct cpu_info cpu_info_store;
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 	int i;
178 
179 	/*
180 	 * Initialize error message buffer. pmap_bootstrap() has
181 	 * positioned this at the end of kernel memory segment - map
182 	 * and initialize it now.
183 	 */
184 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
185 		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
186 		    msgbufpa + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0);
187 	pmap_update(pmap_kernel());
188 	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
189 
190 	/*
191 	 * Initialize hardware that support various console types like
192 	 * the grf and PCI busses.
193 	 */
194 	config_console();
195 
196 	/*
197 	 * Now pick the best console candidate.
198 	 */
199 	cninit();
200 
201 #if NKSYMS || defined(DDB) || defined(MODULAR)
202 	{
203 		extern int end;
204 		extern int *esym;
205 
206 #ifndef __ELF__
207 		ksyms_addsyms_elf(*(int *)&end, ((int *)&end) + 1, esym);
208 #else
209 		ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
210 		    (void *)&end, esym);
211 #endif
212 	}
213 #endif
214 #if defined (DDB)
215         if (boothowto & RB_KDB)
216                 Debugger();
217 #endif
218 }
219 
220 /*
221  * cpu_startup: allocate memory for variable-sized tables,
222  * initialize CPU, and do autoconfiguration.
223  */
224 void
225 cpu_startup(void)
226 {
227 	extern int iomem_malloc_safe;
228 	char pbuf[9];
229 #ifdef DEBUG
230 	extern int pmapdebug;
231 	int opmapdebug = pmapdebug;
232 #endif
233 	vaddr_t minaddr, maxaddr;
234 	extern vsize_t mem_size;	/* from pmap.c */
235 
236 #ifdef DEBUG
237 	pmapdebug = 0;
238 #endif
239 
240 	if (fputype != FPU_NONE)
241 		m68k_make_fpu_idle_frame();
242 
243 	/*
244 	 * Good {morning,afternoon,evening,night}.
245 	 */
246 	printf("%s%s", copyright, version);
247 	identifycpu();
248 
249 	format_bytes(pbuf, sizeof(pbuf), mem_size);
250 	printf("total memory = %s\n", pbuf);
251 
252 	minaddr = 0;
253 
254 	/*
255 	 * Allocate a submap for physio
256 	 */
257 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
258 	    VM_PHYS_SIZE, 0, false, NULL);
259 
260 #ifdef DEBUG
261 	pmapdebug = opmapdebug;
262 #endif
263 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
264 	printf("avail memory = %s\n", pbuf);
265 
266 	/*
267 	 * Alloc extent allocation to use malloc
268 	 */
269 	iomem_malloc_safe = 1;
270 }
271 
272 /*
273  * Set registers on exec.
274  */
275 void
276 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
277 {
278 	struct frame *frame = (struct frame *)l->l_md.md_regs;
279 	struct pcb *pcb = lwp_getpcb(l);
280 
281 	frame->f_sr = PSL_USERSET;
282 	frame->f_pc = pack->ep_entry & ~1;
283 	frame->f_regs[D0] = 0;
284 	frame->f_regs[D1] = 0;
285 	frame->f_regs[D2] = 0;
286 	frame->f_regs[D3] = 0;
287 	frame->f_regs[D4] = 0;
288 	frame->f_regs[D5] = 0;
289 	frame->f_regs[D6] = 0;
290 	frame->f_regs[D7] = 0;
291 	frame->f_regs[A0] = 0;
292 	frame->f_regs[A1] = 0;
293 	frame->f_regs[A2] = (int)l->l_proc->p_psstr;
294 	frame->f_regs[A3] = 0;
295 	frame->f_regs[A4] = 0;
296 	frame->f_regs[A5] = 0;
297 	frame->f_regs[A6] = 0;
298 	frame->f_regs[SP] = stack;
299 
300 	/* restore a null state frame */
301 	pcb->pcb_fpregs.fpf_null = 0;
302 	if (fputype)
303 		m68881_restore(&pcb->pcb_fpregs);
304 }
305 
306 /*
307  * Info for CTL_HW
308  */
309 char cpu_model[120];
310 
311 static void
312 identifycpu(void)
313 {
314        const char *mach, *mmu, *fpu, *cpu;
315 
316 	switch (machineid & ATARI_ANYMACH) {
317 	case ATARI_TT:
318 		mach = "Atari TT";
319 		break;
320 	case ATARI_FALCON:
321 		mach = "Atari Falcon";
322 		break;
323 	case ATARI_HADES:
324 		mach = "Atari Hades";
325 		break;
326 	case ATARI_MILAN:
327 		mach = "Atari Milan";
328 		break;
329 	default:
330 		mach = "Atari UNKNOWN";
331 		break;
332 	}
333 
334 	cpu     = "m68k";
335 	fputype = fpu_probe();
336 	fpu     = fpu_describe(fputype);
337 
338 	switch (cputype) {
339 
340 	case CPU_68060:
341 		{
342 			uint32_t	pcr;
343 			char		cputxt[30];
344 
345 			__asm(".word 0x4e7a,0x0808;"
346 			    "movl %%d0,%0" : "=d"(pcr) : : "d0");
347 			sprintf(cputxt, "68%s060 rev.%d",
348 			    pcr & 0x10000 ? "LC/EC" : "", (pcr >> 8) & 0xff);
349 			cpu = cputxt;
350 			mmu = "/MMU";
351 		}
352 		break;
353 	case CPU_68040:
354 		cpu = "m68040";
355 		mmu = "/MMU";
356 		break;
357 	case CPU_68030:
358 		cpu = "m68030";
359 		mmu = "/MMU";
360 		break;
361 	default: /* XXX */
362 		cpu = "m68020";
363 		mmu = " m68851 MMU";
364 	}
365 	sprintf(cpu_model, "%s (%s CPU%s%sFPU)", mach, cpu, mmu, fpu);
366 	printf("%s\n", cpu_model);
367 }
368 
369 /*
370  * machine dependent system variables.
371  */
372 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
373 {
374 
375 	sysctl_createv(clog, 0, NULL, NULL,
376 		       CTLFLAG_PERMANENT,
377 		       CTLTYPE_NODE, "machdep", NULL,
378 		       NULL, 0, NULL, 0,
379 		       CTL_MACHDEP, CTL_EOL);
380 
381 	sysctl_createv(clog, 0, NULL, NULL,
382 		       CTLFLAG_PERMANENT,
383 		       CTLTYPE_STRUCT, "console_device", NULL,
384 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
385 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
386 }
387 
388 static int waittime = -1;
389 
390 static void
391 bootsync(void)
392 {
393 
394 	if (waittime < 0) {
395 		waittime = 0;
396 
397 		vfs_shutdown();
398 
399 		/*
400 		 * If we've been adjusting the clock, the todr
401 		 * will be out of synch; adjust it now.
402 		 */
403 		resettodr();
404 	}
405 }
406 
407 void
408 cpu_reboot(int howto, char *bootstr)
409 {
410 	struct pcb *pcb = lwp_getpcb(curlwp);
411 
412 	/* take a snap shot before clobbering any registers */
413 	if (pcb != NULL)
414 		savectx(pcb);
415 
416 	boothowto = howto;
417 	if ((howto & RB_NOSYNC) == 0)
418 		bootsync();
419 
420 	/*
421 	 * Call shutdown hooks. Do this _before_ anything might be
422 	 * asked to the user in case nobody is there....
423 	 */
424 	doshutdownhooks();
425 
426 	pmf_system_shutdown(boothowto);
427 
428 	splhigh();			/* extreme priority */
429 	if (howto & RB_HALT) {
430 		printf("halted\n\n");
431 		__asm("	stop	#0x2700");
432 	} else {
433 		if (howto & RB_DUMP)
434 			dumpsys();
435 
436 		doboot();
437 		/*NOTREACHED*/
438 	}
439 	panic("Boot() should never come here");
440 	/*NOTREACHED*/
441 }
442 
443 #define	BYTES_PER_DUMP	PAGE_SIZE	/* Must be a multiple of PAGE_SIZE */
444 static vaddr_t	dumpspace;	/* Virt. space to map dumppages	*/
445 
446 /*
447  * Reserve _virtual_ memory to map in the page to be dumped
448  */
449 vaddr_t
450 reserve_dumppages(vaddr_t p)
451 {
452 
453 	dumpspace = p;
454 	return p + BYTES_PER_DUMP;
455 }
456 
457 uint32_t	dumpmag  = 0x8fca0101;	/* magic number for savecore	*/
458 int		dumpsize = 0;		/* also for savecore (pages)	*/
459 long		dumplo   = 0;		/* (disk blocks)		*/
460 
461 void
462 cpu_dumpconf(void)
463 {
464 	const struct bdevsw *bdev;
465 	int	nblks, i;
466 
467 	for (i = dumpsize = 0; i < NMEM_SEGS; i++) {
468 		if (boot_segs[i].start == boot_segs[i].end)
469 			break;
470 		dumpsize += boot_segs[i].end - boot_segs[i].start;
471 	}
472 	dumpsize = btoc(dumpsize);
473 
474 	if (dumpdev != NODEV) {
475 		bdev = bdevsw_lookup(dumpdev);
476 		if (bdev == NULL) {
477 			dumpdev = NODEV;
478 			return;
479 		}
480 		if (bdev->d_psize != NULL) {
481 			nblks = (*bdev->d_psize)(dumpdev);
482 			if (dumpsize > btoc(dbtob(nblks - dumplo)))
483 				dumpsize = btoc(dbtob(nblks - dumplo));
484 			else if (dumplo == 0)
485 				dumplo = nblks - btodb(ctob(dumpsize));
486 		}
487 	}
488 	dumplo -= cpu_dumpsize();
489 
490 	/*
491 	 * Don't dump on the first PAGE_SIZE (why PAGE_SIZE?)
492 	 * in case the dump device includes a disk label.
493 	 */
494 	if (dumplo < btodb(PAGE_SIZE))
495 		dumplo = btodb(PAGE_SIZE);
496 }
497 
498 /*
499  * Doadump comes here after turning off memory management and
500  * getting on the dump stack, either when called above, or by
501  * the auto-restart code.
502  */
503 void
504 dumpsys(void)
505 {
506 	const struct bdevsw *bdev;
507 	daddr_t	blkno;		/* Current block to write	*/
508 	int	(*dump)(dev_t, daddr_t, void *, size_t);
509 				/* Dumping function		*/
510 	u_long	maddr;		/* PA being dumped		*/
511 	int	segbytes;	/* Number of bytes in this seg.	*/
512 	int	segnum;		/* Segment we are dumping	*/
513 	int	nbytes;		/* Bytes left to dump		*/
514 	int	i, n, error;
515 
516 	error = segnum = 0;
517 	if (dumpdev == NODEV)
518 		return;
519 	bdev = bdevsw_lookup(dumpdev);
520 	if (bdev == NULL)
521 		return;
522 	/*
523 	 * For dumps during autoconfiguration,
524 	 * if dump device has already configured...
525 	 */
526 	if (dumpsize == 0)
527 		cpu_dumpconf();
528 	if (dumplo <= 0) {
529 		printf("\ndump to dev %u,%u not possible\n",
530 		    major(dumpdev), minor(dumpdev));
531 		return;
532 	}
533 	printf("\ndumping to dev %u,%u offset %ld\n",
534 	    major(dumpdev), minor(dumpdev), dumplo);
535 
536 #if defined(DDB) || defined(PANICWAIT)
537 	printf("Do you want to dump memory? [y]");
538 	cnputc(i = cngetc());
539 	switch (i) {
540 	case 'n':
541 	case 'N':
542 		return;
543 	case '\n':
544 		break;
545 	default :
546 		cnputc('\n');
547 	}
548 #endif /* defined(DDB) || defined(PANICWAIT) */
549 
550 	maddr    = 0;
551 	segbytes = boot_segs[0].end;
552 	blkno    = dumplo;
553 	dump     = bdev->d_dump;
554 	nbytes   = dumpsize * PAGE_SIZE;
555 
556 	printf("dump ");
557 
558 	error = cpu_dump(dump, &blkno);
559 	if (!error) {
560 		for (i = 0; i < nbytes; i += n, segbytes -= n) {
561 			/*
562 			 * Skip the hole
563 			 */
564 			if (segbytes == 0) {
565 				segnum++;
566 				maddr    = boot_segs[segnum].start;
567 				segbytes = boot_segs[segnum].end -
568 				    boot_segs[segnum].start;
569 			}
570 			/*
571 			 * Print Mb's to go
572 			 */
573 			n = nbytes - i;
574 			if (n && (n % (1024 * 1024)) == 0)
575 				printf_nolog("%d ", n / (1024 * 1024));
576 
577 			/*
578 			 * Limit transfer to BYTES_PER_DUMP
579 			 */
580 			if (n > BYTES_PER_DUMP)
581 				n = BYTES_PER_DUMP;
582 
583 			/*
584 			 * Map to a VA and write it
585 			 */
586 			if (maddr != 0) { /* XXX kvtop chokes on this	*/
587 				(void)pmap_map(dumpspace, maddr, maddr + n,
588 				    VM_PROT_READ);
589 				error = (*dump)(dumpdev, blkno,
590 				    (void *)dumpspace, n);
591 				if (error)
592 					break;
593 			}
594 
595 			maddr += n;
596 			blkno += btodb(n);
597 		}
598 	}
599 	switch (error) {
600 
601 	case ENXIO:
602 		printf("device bad\n");
603 		break;
604 
605 	case EFAULT:
606 		printf("device not ready\n");
607 		break;
608 
609 	case EINVAL:
610 		printf("area improper\n");
611 		break;
612 
613 	case EIO:
614 		printf("i/o error\n");
615 		break;
616 
617 	default:
618 		printf("succeeded\n");
619 		break;
620 	}
621 	printf("\n\n");
622 	delay(5000000);		/* 5 seconds */
623 }
624 
625 void
626 straytrap(int pc, u_short evec)
627 {
628 	static int prev_evec;
629 
630 	printf("unexpected trap (vector offset 0x%x) from 0x%x\n",
631 	    evec & 0xFFF, pc);
632 
633 	if (prev_evec == evec) {
634 		delay(1000000);
635 		prev_evec = 0;
636 	} else
637 		prev_evec = evec;
638 }
639 
640 void
641 straymfpint(int pc, u_short evec)
642 {
643 
644 	printf("unexpected mfp-interrupt (vector offset 0x%x) from 0x%x\n",
645 	       evec & 0xFFF, pc);
646 }
647 
648 int	*nofault;
649 
650 int
651 badbaddr(void *addr, int size)
652 {
653 	register int i;
654 	label_t	faultbuf;
655 
656 #ifdef lint
657 	i = *addr; if (i) return(0);
658 #endif
659 	nofault = (int *) &faultbuf;
660 	if (setjmp((label_t *)nofault)) {
661 		nofault = (int *) 0;
662 		return 1;
663 	}
664 	switch (size) {
665 	case 1:
666 		i = *(volatile uint8_t *)addr;
667 		break;
668 	case 2:
669 		i = *(volatile uint16_t *)addr;
670 		break;
671 	case 4:
672 		i = *(volatile uint32_t *)addr;
673 		break;
674 	default:
675 		panic("badbaddr: unknown size");
676 	}
677 	nofault = (int *)0;
678 	return 0;
679 }
680 
681 /*
682  * this is a handy package to have asynchronously executed
683  * function calls executed at very low interrupt priority.
684  * Example for use is keyboard repeat, where the repeat
685  * handler running at splclock() triggers such a (hardware
686  * aided) software interrupt.
687  * Note: the installed functions are currently called in a
688  * LIFO fashion, might want to change this to FIFO
689  * later.
690  *
691  * XXX: Some of functions which use this callback should be rewritten
692  * XXX: to use MI softintr(9) directly.
693  */
694 struct si_callback {
695 	struct si_callback *next;
696 	void (*function)(void *rock1, void *rock2);
697 	void *rock1, *rock2;
698 };
699 static void *si_callback_cookie;
700 static struct si_callback *si_callbacks;
701 static struct si_callback *si_free;
702 #ifdef DIAGNOSTIC
703 static int ncbd;	/* number of callback blocks dynamically allocated */
704 #endif
705 
706 void
707 init_sicallback(void)
708 {
709 
710 	si_callback_cookie = softint_establish(SOFTINT_NET,
711 	    (void (*)(void *))call_sicallbacks, NULL);
712 }
713 
714 void
715 add_sicallback(void (*function)(void *, void *), void *rock1, void *rock2)
716 {
717 	struct si_callback *si;
718 	int s;
719 
720 	/*
721 	 * this function may be called from high-priority interrupt handlers.
722 	 * We may NOT block for  memory-allocation in here!.
723 	 */
724 	s = splhigh();
725 	if ((si = si_free) != NULL)
726 		si_free = si->next;
727 	splx(s);
728 
729 	if (si == NULL) {
730 		si = malloc(sizeof(*si), M_TEMP, M_NOWAIT);
731 #ifdef DIAGNOSTIC
732 		if (si)
733 			++ncbd;		/* count # dynamically allocated */
734 #endif
735 		if (si == NULL)
736 			return;
737 	}
738 
739 	si->function = function;
740 	si->rock1    = rock1;
741 	si->rock2    = rock2;
742 
743 	s = splhigh();
744 	si->next     = si_callbacks;
745 	si_callbacks = si;
746 	splx(s);
747 
748 	/*
749 	 * and cause a software interrupt (spl1). This interrupt might
750 	 * happen immediately, or after returning to a safe enough level.
751 	 *
752 	 * XXX:
753 	 * According to <machine/scu.h> and lev1intr() hander in locore.s,
754 	 * at least _ATARIHW_ machines (ATARITT and HADES?) seem to have
755 	 * some hardware support which can initiate real hardware interrupt
756 	 * at ipl 1 for software interrupt. But as per <machine/mtpr.h>,
757 	 * this feature was not used at all on setsoft*() calls and
758 	 * traditional hp300 derived ssir (simulated software interrupt
759 	 * request) on VAX REI emulation in locore.s is used.
760 	 */
761 	softint_schedule(si_callback_cookie);
762 }
763 
764 void
765 rem_sicallback(void (*function)(void *rock1, void *rock2))
766 {
767 	struct si_callback *si, *psi, *nsi;
768 	int s;
769 
770 	s = splhigh();
771 	for (psi = 0, si = si_callbacks; si; ) {
772 		nsi = si->next;
773 
774 		if (si->function != function)
775 			psi = si;
776 		else {
777 			si->next = si_free;
778 			si_free  = si;
779 			if (psi != NULL)
780 				psi->next = nsi;
781 			else
782 				si_callbacks = nsi;
783 		}
784 		si = nsi;
785 	}
786 	splx(s);
787 }
788 
789 /* purge the list */
790 static void
791 call_sicallbacks(void)
792 {
793 	struct si_callback *si;
794 	int s;
795 	void *rock1, *rock2;
796 	void (*function)(void *, void *);
797 
798 	do {
799 		s = splhigh();
800 		if ((si = si_callbacks) != NULL)
801 			si_callbacks = si->next;
802 		splx(s);
803 
804 		if (si != NULL) {
805 			function = si->function;
806 			rock1    = si->rock1;
807 			rock2    = si->rock2;
808 			s = splhigh();
809 			if (si_callbacks)
810 				softint_schedule(si_callback_cookie);
811 			si->next = si_free;
812 			si_free  = si;
813 			splx(s);
814 
815 			/*
816 			 * Raise spl for BASEPRI() checks to see
817 			 * nested interrupts in some drivers using callbacks
818 			 * since modern MI softint(9) doesn't seem to do it
819 			 * in !__HAVE_FAST_SOFTINTS case.
820 			 *
821 			 * XXX: This is just a workaround hack.
822 			 *      Each driver should raise spl in its handler
823 			 *      to avoid nested interrupts if necessary.
824 			 */
825 			s = splsoftnet();	/* XXX */
826 			function(rock1, rock2);
827 			splx(s);
828 		}
829 	} while (si != NULL);
830 #ifdef DIAGNOSTIC
831 	if (ncbd) {
832 #ifdef DEBUG
833 		printf("call_sicallback: %d more dynamic structures\n", ncbd);
834 #endif
835 		ncbd = 0;
836 	}
837 #endif
838 }
839 
840 #if defined(DEBUG) && !defined(PANICBUTTON)
841 #define PANICBUTTON
842 #endif
843 
844 #ifdef PANICBUTTON
845 int panicbutton = 1;	/* non-zero if panic buttons are enabled */
846 int crashandburn = 0;
847 int candbdelay = 50;	/* give em half a second */
848 
849 void candbtimer(void);
850 
851 void
852 candbtimer(void)
853 {
854 
855 	crashandburn = 0;
856 }
857 #endif
858 
859 /*
860  * should only get here, if no standard executable. This can currently
861  * only mean, we're reading an old ZMAGIC file without MID, but since Atari
862  * ZMAGIC always worked the `right' way (;-)) just ignore the missing
863  * MID and proceed to new zmagic code ;-)
864  */
865 int
866 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
867 {
868 	int error = ENOEXEC;
869 #ifdef COMPAT_NOMID
870 	struct exec *execp = epp->ep_hdr;
871 #endif
872 
873 #ifdef COMPAT_NOMID
874 	if (!((execp->a_midmag >> 16) & 0x0fff)
875 	    && execp->a_midmag == ZMAGIC)
876 		return exec_aout_prep_zmagic(l->l_proc, epp);
877 #endif
878 	return error;
879 }
880 
881 #ifdef MODULAR
882 /*
883  * Push any modules loaded by the bootloader etc.
884  */
885 void
886 module_init_md(void)
887 {
888 }
889 #endif
890 
891 #ifdef _MILANHW_
892 
893 /*
894  * Currently the only source of NMI interrupts on the Milan is the PLX9080.
895  * On access errors to the PCI bus, an NMI is generated. This NMI is shorted
896  * in locore in case of a PCI config cycle to a non-existing address to allow
897  * for probes. On other occaisions, it ShouldNotHappen(TM).
898  * Note: The handler in locore clears the errors, to make further PCI access
899  * possible.
900  */
901 void
902 nmihandler(void)
903 {
904 	extern unsigned long	plx_status;
905 
906 	printf("nmihandler: plx_status = 0x%08lx\n", plx_status);
907 }
908 #endif
909