xref: /netbsd-src/sys/arch/amiga/amiga/machdep.c (revision f36002f244a49908fef9cba8789032bdbf48d572)
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
consinit(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
cpu_startup(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
identifycpu(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
bootsync(void)392 bootsync(void)
393 {
394 	if (waittime < 0) {
395 		waittime = 0;
396 		vfs_shutdown();
397 	}
398 }
399 
400 
401 void
cpu_reboot(register int howto,char * bootstr)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
cpu_dumpconf(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
reserve_dumppages(vm_offset_t p)551 reserve_dumppages(vm_offset_t p)
552 {
553 	dumpspace = p;
554 	return (p + BYTES_PER_DUMP);
555 }
556 
557 void
dumpsys(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
initcpu(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
straytrap(int pc,u_short evec)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
badaddr(register void * addr)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
badbaddr(register void * addr)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
add_isr(struct isr * isr)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
remove_isr(struct isr * isr)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
intrhand(int sr)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
cpu_intr_p(void)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
candbtimer(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
cpu_exec_aout_makecmds(struct lwp * l,struct exec_package * epp)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
module_init_md(void)1202 module_init_md(void)
1203 {
1204 }
1205 
1206 int _spllkm6(void);
1207 int _spllkm7(void);
1208 
1209 #ifdef LEV6_DEFER
_spllkm6(void)1210 int _spllkm6(void) {
1211 	return spl4();
1212 };
1213 
_spllkm7(void)1214 int _spllkm7(void) {
1215 	return spl4();
1216 };
1217 
1218 #else
1219 
_spllkm6(void)1220 int _spllkm6(void) {
1221 	return spl6();
1222 };
1223 
_spllkm7(void)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
mm_md_physacc(paddr_t pa,vm_prot_t prot)1246 mm_md_physacc(paddr_t pa, vm_prot_t prot)
1247 {
1248 
1249 	return (pa >= 0xfffffffc || pa < lowram) ? EFAULT : 0;
1250 }
1251