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