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